#coding:utf-8

#!/usr/bin/python3
#
#  Copyright (c) 2007-2009 Canonical Ltd.
#
#  Author: Oliver Grawert <ogra@ubuntu.com>
#
#  Modifications 2013 from papoteur <papoteur@mageialinux-online.org>
#  and Geiger David <david.david@mageialinux-online.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.
#
#  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 St, Fifth Floor, Boston, MA 02110-1301, USA.

#  Requires python3-parted

# ensure we're using the latest build, if called from our build environment
import sys
import imp

sys.path.insert(0,'../../../build/swig/python3')
imp.reload(sys)
###########
# imports #
###########
import yui
#import locale
import time

####################################
# LOCALE (important for TERMINAL!) #
####################################
# set the locale to de/utf-8
#locale.setlocale(locale.LC_ALL, "")
#log = yui.YUILog.instance()
#log.setLogFileName("debug.log")
#log.enableDebugLogging( True )

import os, re
import io
import gettext
from gettext import gettext as _
from subprocess import call, Popen, PIPE
import dbus


class NoUDisks2(Exception):
    pass


class UDisks2(object):

    BLOCK = 'org.freedesktop.UDisks2.Block'
    DRIVE = 'org.freedesktop.UDisks2.Drive'

    def __init__(self):
        self.bus = dbus.SystemBus()
        try:
            self.bus.get_object('org.freedesktop.UDisks2',
                        '/org/freedesktop/UDisks2')
        except dbus.exceptions.DBusException as e:
            if getattr(e, '_dbus_error_name', None) == 'org.freedesktop.DBus.Error.ServiceUnknown':
                raise NoUDisks2()
            raise

    def find_devices(self):
        proxy = self.bus.get_object("org.freedesktop.UDisks2", "/org/freedesktop/UDisks2")
        iface = dbus.Interface(proxy, "org.freedesktop.UDisks2")
        _udisks2_obj_manager = dbus.Interface(iface, "org.freedesktop.DBus.ObjectManager")
        objects=_udisks2_obj_manager.GetManagedObjects()
        re_drive = re.compile('(?P<path>.*?/drives/(?P<id>.*))')
        re_block = re.compile('(?P<path>.*?/block_devices/(?P<id>.*))')
        devs= [m.groupdict() for m in
                     [re_drive.match(path) for path in (objects.keys())]
                 if m]
        blocks = [m.groupdict() for m in
                     [re_block.match(path) for path in (objects.keys())]
                 if m]
        list=[]

        for dev in devs:
            dev_obj =objects[dev['path']][self.DRIVE]
            if (dev_obj['ConnectionBus'] == 'usb' or dev_obj['ConnectionBus'] == 'sdio') and \
                 (dev_obj['Removable'] == 1 or dev_obj['MediaRemovable'] == 1 ):
               item=[]
               vend = dev_obj['Vendor']
               name = dev_obj['Model']
               for block in blocks:
                   if dev['path'] == objects[block['path']][self.BLOCK]['Drive']:
                       dev_name = block['path'].split('/')[-1]
                       path = ''.join([i for i in dev_name if not i.isdigit()])
                       path = '/dev/' + path
                       break
               size = dev_obj['Size']
               item.append(vend+" "+name)
               item.append(path)
               item.append(size)
               list.append(item)
        return list

class Info(object):
    def __init__(self,title,richtext,text):
        self.title=title
        self.richtext=richtext
        self.text=text

       
class IsoDumper(object):

    def get_devices(self):
        self.list=self.u.find_devices()
        while len(self.list)==0:
            if self.nodevDialog():
                self.list = self.u.find_devices()
            else:
                return False
                break
        self.devicelist.addItem("",False)
        if len(self.list)>0:
            for name, path, size in self.list:
              if size != 0 :
                # convert in Mbytes
                sizeM=str(int(size)/(1024*1024))
                self.devicelist.addItem(str(name+' ('+path.lstrip()+') '+sizeM+_('Mb')),False)
            return True


    def update_list(self ):
        self.devicelist.deleteAllItems()
        self.get_devices()
        self.img_name = ""
        self.ima.setLabel(self.ChooseImage)
        self.backup_select.setLabel(self.ChooseImage)
        self.dialog.recalcLayout()
        self.restore()

    def device_selected(self):
        selitem = self.devicelist.selectedItem()
        if selitem != None:
            self.dev = selitem.label()
            for name, path, size in self.list:
                if self.dev.startswith(name):
                    self.deviceSize=size
                    self.device_name=name.rstrip().replace(' ', '')
                    self.logger(_('Target Device: ')+ self.dev)
                    self.formatbt.setEnabled()
                    self.ima.setEnabled()
                    self.backup_select.setEnabled()
                    break
            

    def backup_sel(self):
        if self.backup_bname.get_current_folder_uri() == None :
            self.backup_bname.set_current_folder_uri('file:///home/'+self.user)
            self.backup_bname.set_current_name(self.device_name+".img")
        self.choose.run()

    def backup_choosed(self):
            # Add .img if not specified
            if not self.backup_img_name.lower().endswith('.img'):
                self.backup_img_name=self.backup_img_name+".img"
            head, tail = os.path.split(self.backup_img_name)
            self.backup_dest=self.backup_img_name
            self.backup_select.setLabel(tail)
            self.dialog.recalcLayout()
            self.backupbt.setEnabled()
            #self.backup_select.set_tooltip_text(self.backup_img_name)
            self.logger(_('Backup to: ')+ self.backup_img_name)

    def do_format(self,format_type,name)            :
        target = self.dev.split('(')[1].split(')')[0]
        info = Info(_("Formatting confirmation"),True,self.warning)
        if self.ask_YesOrNo(info):
            rc=self.raw_format(target, format_type, name)
            self.operation=False
            if rc == 0:
                message = _('The device was formatted successfully.')
                self.logger(message)
                self.success()
            elif rc == 5:
                message = _("An error occurred while creating a partition.")
                self.logger(message)
                self.emergency(message)
            elif rc == 127:
                message = _('Authentication error.')
                self.logger(message)
                self.emergency(message)
            else:
                message = _('An error occurred.')
                self.emergency(message)

    def restore(self):
        self.backup_select.setDisabled()
        self.backupbt.setDisabled()
        self.formatbt.setDisabled()
        self.ima.setDisabled()
        self.writebt.setDisabled()
        self.devicelist.setEnabled()
        self.progress.setLabel("")
        self.progress.setValue(0)
        self.progress.setDisabled()
        self.refreshbt.setEnabled()

    def raw_format(self, usb_path, fstype, label):
        self.operation=True
        if os.geteuid() > 0:
            launcher='pkexec'
            self.process = Popen([launcher,'/usr/bin/python3', '-u', '/usr/lib/isodumper/raw_format.py','-d',usb_path,'-f',fstype, '-l', label, '-u', str(os.geteuid()), '-g', str(os.getgid())], shell=False, stdout=PIPE, preexec_fn=os.setsid)
        else:
            self.process = Popen(['/usr/bin/python3', '-u', '/usr/lib/isodumper/raw_format.py','-d',usb_path,'-f',fstype, '-l', label, '-u', str(os.geteuid()), '-g', str(os.getgid())], shell=False, stdout=PIPE, preexec_fn=os.setsid)
        working=True
        while working:
            time.sleep(0.5)
            self.process.poll()
            rc=self.process.returncode
            if rc is None:
                working=True
            else:
                self.process = None
                working= False
        return rc

    def backup_go(self):
        dest = self.backup_img_name
        if os.path.exists(dest):
            info = Info(_("Backup confirmation"),True,_("Do you want to overwrite the file?"))
            if not(self.ask_YesOrNo(info)):
                self.returncode = 1
                return True
        st = os.statvfs(os.path.dirname(dest))
        free = st.f_bavail * st.f_frsize
        if free<self.deviceSize :
            sizeM=str(self.deviceSize/(1024*1024))
            message=_("The destination directory is too small to receive the backup (%s Mb needed)")%(sizeM)
            self.logger(message)
            self.emergency(message)
        else:
            self.returncode=0
            source = self.dev.split('(')[1].split(')')[0]
            self.logger(_('Backup to:')+' '+dest)
            self.raw_write(source, dest, self.deviceSize)
            if self.returncode==0:
            	self.success()
                

    def do_write(self):
        self.returncode = 0
        self.writebt.setDisabled()
        self.devicelist.setDisabled()
        self.formatbt.setDisabled()
        self.backupbt.setDisabled()
        self.backup_select.setDisabled()
        self.progress.setEnabled()
        source = self.img_name
        target = self.dev.split('(')[1].split(')')[0]
#        self.logger(_('Image: ')+source)
#        self.logger(_('Target Device: ')+self.dev)
        b = os.path.getsize(source)
        if b > (self.deviceSize):
            message = _('The device is too small to contain the ISO file.')
            self.logger(message)
            self.emergency(message)
        else:
            info = Info(_("Writing confirmation"),True,self.warning)
            if self.ask_YesOrNo(info):
                if self.deviceSize> 1024*1024*1024*32 :
                    info = Info(_("Warning"),True,_('The device is bigger than 32 Gbytes. Are you sure you want use it?'))
                    if self.ask_YesOrNo(info):
                        pass
                    else:
                        self.emergency(message)
                        return
                self.ima.setDisabled()
                self.writebt.setDisabled()
                self.do_umount(target)
                if self.returncode != 1:
                    # Writing step
                    #Dump mode
                    self.returncode=0
                    b=os.path.getsize(source)
                    self.raw_write(source, target, b)
                    if self.returncode == 0:
                        self.check_write(target, b)
                        self.success()
                else:
                    self.restore()
            else:
                self.restore()
    def do_umount(self, target):
        mounts = self.get_mounted(target)
        if mounts:
            self.logger(_('Unmounting all partitions of ')+target+':')
        for mount in mounts:
            self.logger(_('Trying to unmount ')+mount[0]+'...')
            try:
                retcode = call('umount '+mount[0], shell=True)
                if retcode == 32:
                    message = _('Partition %s is busy')%mount[0]
                    self.logger(message)
                    self.emergency(message)
                elif retcode< 0:
                    message = _('Error, umount ')+mount[0]+_(' was terminated by signal ')+str(retcode)
                    self.logger(message)
                    self.emergency(message)
                elif retcode == 0:
                        self.logger(mount[0]+_(' successfully unmounted'))
                else:
                        message = _('Error, umount ')+mount[0]+_(' returned ')+str(retcode)
                        self.logger(message)
                        self.emergency(message)
            except OSError as e:
                message = _('Execution failed: ')+str(e)
                self.logger(message)
                self.emergency(message)

    def get_mounted(self, target):
        try:
            lines = [line.strip("\n").split(" ") for line in open ("/etc/mtab", "r").readlines()]
            return [mount for mount in lines if mount[0].startswith(target)]
        except:
             message = _('Could not read mtab !')
             self.logger(message)
             self.emergency(message)

    def raw_write(self, source, target, b):
        self.operation=True
        bs=4096*128
        try:
            ifc=io.open(source, "rb",1)
        except:
             message = _('Reading error.')+ source
             self.logger(message)
             self.emergency(message)
             return
        else:
            try:
                ofc= io.open(target, 'wb',0)
            except:
                 message = _("You don't have permission to write to the device") +" "+ target
                 self.logger(message)
                 self.emergency(message)
                 self.close()
            else:
                self.progress.setLabel(_('Writing ')+source.split('/')[-1]+_(' to ')+target.split('/')[-1])
                self.logger(_('Executing copy from ')+source+_(' to ')+target)
                steps=list(range(0, b+1, int(b/100)))
                steps.append(b)
                indice=1
                written=0
                ncuts=int(b/bs)
                while ncuts <= 100:
                    bs=int(bs/2)
                    ncuts=int(b/bs)
                for i in range(0,int(ncuts)+1):
                    try:
                        buf=ifc.read(bs)
                    except:
                        message = _("Reading error.")
                        self.logger(message)
                        self.emergency(message)
                        return
                    try:
                        ofc.write(buf)
                    except:
                        message = _("Writing error.")
                        self.logger(message)
                        self.emergency(message)
                        return
                    written+=len(buf)
                    if written > steps[indice]:
                        if indice%1==0:
                            self.logger(_('Wrote: ')+str(indice)+'% '+str(written)+' bytes')
                        self.progress.setValue(indice)
                        self.dialog.pollEvent()
                        indice +=1
                        try:
                            os.fsync(ofc)
                        except:
                           message = _("Writing error.")
                           self.logger(message)
                           self.emergency(message)
                           return
                self.progress.setValue(100)
                self.logger(_('Image ')+source.split('/')[-1]+_(' successfully written to ')+target)
                self.logger(_('Bytes written: ')+str(written))
                try:
                    ofc.close()
                except:
                   message = _("Writing error.")
                   self.logger(message)
                   self.emergency(message)
            ifc.close()

    def check_write(self, target, b):
        import hashlib
        self.progress.setEnabled()
        self.progress.setLabel(_('Checking ')+target.split('/')[-1])
        self.progress.setValue(0)
        steps=list(range(0, b+1, int(b/100)))
        steps.append(b)
        indice=0
        checked=0
        sha1func=hashlib.sha1()
        md5func=hashlib.md5()
        ncuts=int(b/1024)
        try:
        	with open(target, 'rb') as f:
        		for x in range(0,ncuts):
        			block = f.read(1024)
        			sha1func.update(block)
        			md5func.update(block)
        			if checked > steps[indice]:
        				self.progress.setValue(indice)
        				self.dialog.pollEvent()
        				indice +=1
        			checked+=1024                         
        		block = f.read(b-ncuts*1024)
        		sha1func.update(block)
        		md5func.update(block)
        		sha1sumcalc=sha1func.hexdigest()
        		md5sumcalc=md5func.hexdigest()
        	self.logger(_('SHA1 sum: ')+sha1sumcalc)
        	self.logger(_('MD5  sum: ')+md5sumcalc)
        	f.close()
        except:
        	pass
        self.progress.setValue(100)

    def success(self):
        self.operation=False
        self.final_unsensitive()
        info = Info(_("Success"),True,_("The operation completed successfully.\n\
 You are free to unplug it now, a logfile \n\
(/home/-user- or /root)/.isodumper/isodumper.log will be saved when\n\
 you close the application."))
        if self.ask_OK(info) :
           return


    def confirm_close(self, *args):
        if self.operation==False:    # no writing , backup nor format running
            self.close()
        else:   # writing , backup or format running
            info = Info(_("Warning"),True,_("Writing is in progress. Exiting during writing \n\
            will make the device or the backup unusable.\n\
            Are you sure you want to quit during writing?"))
            if self.ask_YesOrNo(info) :
                return True
            else:
                return False

    def emergency(self,message):
        self.operation=False
        self.returncode=1
        self.final_unsensitive()
        info = Info(_("Error"),True,message)
        self.ask_OK(info)

    def final_unsensitive(self):
        self.ima.setDisabled()
        self.devicelist.setDisabled()
        self.writebt.setDisabled()
        self.progress.setDisabled()
        self.backup_select.setDisabled()

    def wip_unsensitive(self):
        self.ima.setDisabled()
        self.devicelist.setDisabled()
        self.writebt.setDisabled()
        self.backup_select.setDisabled()
        self.backupbt.setDisabled()
        self.refreshbt.setDisabled()
		
    def close(self):
        self.write_logfile()
        self.dialog.destroy()
        #exit(0)

    def write_logfile(self):
        import pwd
        pw = pwd.getpwnam(self.user)
        uid = pw.pw_uid
        gid=pw.pw_gid
        if (self.user != 'root') and (self.user !=''):
            logpath='/home/'+self.user+'/.isodumper'
            os.setgid(gid)
            os.setuid(uid)
            if not(os.path.isdir(logpath)):
                os.mkdir(logpath)
        else:
            logpath='/root'
        logfile=open(logpath+'/isodumper.log',"w", encoding="utf-8")
        logfile.write(self.logview.logText())
        logfile.close()

        print((self.logview.logText()))

    def logger(self, text):
        self.logview.appendLines(text+"\n")

    def activate_devicelist(self):
        self.devicelist.setEnabled()
        self.logger(_('Image ')+": "+ self.img_name)
#        self.chooser.set_tooltip_text(self.img_name)

    def help_dialog(self):
        info = Info(_("IsoDumper"),True,_("Mageia IsoDumper<BR />\
----------------<BR />\
This GUI program is primarily for safely writing a bootable ISO image to a USB flash drive, \
an operation devious & potentially hazardous when done by hand. As a bonus, it can also back up the\
entire previous<BR />contents of the flash drive onto the hard disc, and restore the flash drive \
to its previous state subsequently.<BR />\
It gives also a feature for formatting the USB device.<BR />\
<BR />\
IsoDumper can be launched either from the menus, or a user or root console with the command 'isodumper'.<BR />\
For normal users, the root password is solicited; this is necessary for the program's operation. <BR />\
The flash drive can be inserted beforehand or once the program is started. In the latter case, a \
dialogue will say that there is no flash drive inserted, and allow a 'retry' to find it once it is. <BR />\
(You may have to close any automatically opened File Manager window).<BR />\
<BR />\
The fields of the main window are as follows:<BR />\
- Device to work on: the device of the USB flash drive, a drop-down list to choose from.<BR />\
- Write Image: to choose the source ISO image *.iso (or flash drive backup file *.img) to write out.<BR />\
- Write to device: This button launches the operation - with a prior warning dialogue. <BR />\
The operation is shown in the progress bar beneath.<BR />\
- Backup to: define the name and placement of the backup image file. The current flash drive \
will be backed up to a disc file. Note that the entire flash drive is preserved, regardless of its \
actual contents; ensure that you have the necessary free disc space (the same size as the USB device). \
This backup file can be used later to restore the flash drive by selecting it as the source *.img file to write out.<BR />\
- Backup the device: launch the backup operation.<BR />\
- Format the device:  create an unique partition on the entire volume in the specified format in FAT, \
NTFS or ext. You can specify a volume name and the format in a new dialog box.<BR />"))
        if self.ask_OK(info) :
           return

    def __init__(self,user):
        APP="isodumper"
        DIR="/usr/share/locale"
        self.RELEASE="v0.59"

        gettext.bindtextdomain(APP, DIR)
        gettext.textdomain(APP)

        # for the localisation of log file
        self.user = user

        # define size of the selected device
        self.deviceSize=0

        # Operation running
        self.operation=False
        
        self.ChooseImage = _("Choose an image")
        self.warning = _("Warning\nThis will destroy all data on the target device,\n\
        are you sure you want to proceed?\n\
        If you say ok here, please <b>do not unplug</b>\
        the device during the following operation.")
        """
        Init/Constructor for the 'widgets'
        """
        yui.YUI.app().setApplicationTitle(_("IsoDumper")+" "+self.RELEASE)
        yui.YUI.app().setApplicationIcon("/usr/share/icons/isodumper.png")
        self.atelier = yui.YUI.widgetFactory()
        self.dialog = self.atelier.createPopupDialog()
        # create the main gui
        # +---+-----------------+
        # +   banner            +
        # +---+-----------------+
        # |  devicelist         |
        # +---+-----+------+----+
        # + L | ima | writebt |
        # +---+-----+------+----+
        # + L | backup_select | backupbt |
        # +---+-----+------+----+
        # + F       | formatbt  |
        # +----------------+----+
        # | progress            |
        # +---------------------+
        # | report              |
        # +---------------------+
        # | refreshbt | aboutbt  | helpbt | quitbt  |
        # +---------------------+
        self.ancrage = self.atelier.createReplacePoint(self.dialog)
        self.box = self.atelier.createVBox(self.ancrage)
        self.bannerbox = self.atelier.createHBox(self.box)
        self.banner=self.atelier.createImage(self.bannerbox,"/usr/share/isodumper/header.svg")
        self.devicebox = self.atelier.createHBox(self.box)
        self.devicebox.setWeight(1,10)
        self.devicelist=self.atelier.createComboBox(self.devicebox,_("Device to work on:"),False)
        self.devicelist.setNotify()
        self.devicelist.setStretchable(0,True)
        self.writebox = self.atelier.createHBox(self.box)
        self.atelier.createLabel(self.writebox,_("Write Image:"))
        #   add file picker for image file
        self.ima=self.atelier.createPushButton(self.writebox,self.ChooseImage)
        self.ima.setStretchable(0,True)
        self.ima.setDisabled()
        self.atelier.createHStretch(self.writebox)
        self.writebt = self.atelier.createPushButton(self.writebox, _("&Write to device" ))
        self.writebt.setDisabled()
        self.backupbox = self.atelier.createHBox(self.box)
        self.atelier.createLabel(self.backupbox,_("Backup to:"))
        #   add file picker for backup file name
        self.backup_select=self.atelier.createPushButton(self.backupbox,self.ChooseImage)
        self.backup_select.setStretchable(0,True)
        self.backup_select.setDisabled()
        self.atelier.createHStretch(self.backupbox)
        self.backupbt = self.atelier.createPushButton(self.backupbox, _("&Backup the device" ))
        self.backupbt.setDisabled()
        self.formatbox = self.atelier.createHBox(self.box)
        #self.formatbox.setWeight(1,10)
        self.atelier.createLabel(self.formatbox,_("Format the device in FAT, NTFS or ext:"))
        self.atelier.createHStretch(self.formatbox)
        self.formatbt = self.atelier.createPushButton(self.formatbox, _("&Format the device" ))
        self.formatbt.setDisabled()
        self.progressbox = self.atelier.createHBox(self.box)
        self.progressbox.setWeight(1,10)
        self.progress = self.atelier.createProgressBar(self.progressbox,_("Progress"),100)
        self.progress.setStretchable(0,True)
        self.reportbox = self.atelier.createHBox(self.box)
        #self.reportbox.setWeight(1,10)
        self.logview = self.atelier.createLogView(self.reportbox,_("Report"), 10)
        self.logview.setStretchable(0,True)
        #self.reportbox.setWeight(1,20)
        self.buttonsbox = self.atelier.createHBox(self.box)
        #self.buttonsbox.setWeight(1,10)
        self.refreshbt = self.atelier.createPushButton(self.buttonsbox, _("&Refresh" ))
        self.refreshbt.setStretchable(0,True)
        self.aboutbt = self.atelier.createPushButton(self.buttonsbox, _("&About" ))
        self.aboutbt.setStretchable(0,True)
        self.helpbt = self.atelier.createPushButton(self.buttonsbox, _("&Help" ))
        self.helpbt.setStretchable(0,True)
        self.quitbt = self.atelier.createPushButton(self.buttonsbox, _("&Quit" ))
        self.quitbt.setStretchable(0,True)
        self.u = None
        try:
            self.u = UDisks2()
        except :
           message = _('UDisks2 is not available on your system')
           self.logger(message)
           self.emergency(message)
        if not self.get_devices():
            self.dialog.destroy()
            yui.YUILoader.deleteUI()
            exit()
        self.device_selected()
        self.dialog.recalcLayout()
        self.ancrage.showChild()

    def ask_format(self):
        self.ima.setDisabled()
        self.formatbt.setDisabled()
        self.backup_select.setDisabled()
        self.writebt.setDisabled()
        self.devicelist.setDisabled()
        atelier =  yui.YUI.widgetFactory()       
        dialog = atelier.createPopupDialog()
#        dialog.setTitle(_("Choose format"))
        vb=atelier.createVBox(dialog)
        label = atelier.createInputField(vb,_("Label for the device:"))
        cr = atelier.createRadioButtonGroup(vb)
        vb_c = atelier.createVBox(cr)
        vb_c1 = atelier.createHBox(vb_c)
        format_fat = atelier.createRadioButton(atelier.createLeft(vb_c1),_("FAT 32 (Windows)"))
        vb_c2 = atelier.createHBox(vb_c)
        format_ntfs = atelier.createRadioButton(atelier.createLeft(vb_c2),_("NTFS (Windows)"))
        vb_c3 = atelier.createHBox(vb_c)
        format_ext = atelier.createRadioButton(atelier.createLeft(vb_c3),_("ext4 (Linux)"))
        bb = atelier.createHBox(vb)
        executebt = atelier.createPushButton(bb,_("Execute"))
        cancelbt = atelier.createPushButton(bb,_("Cancel"))
        dialog.open()
        returncode = True
        while True:
            event = dialog.waitForEvent()
            if event.eventType() == yui.YEvent.CancelEvent:
                returncode = False
                break
            if event.widget() == executebt:
                if format_fat.value():
                    format_type = 'fat32'
                    format_label = label.value().upper()[:11]
                    break
                if format_ntfs.value():
                    format_type = 'ntfs'
                    format_label = label.value()[:32]
                    break
                if format_ext.value():
                    format_type = 'ext4'
                    format_label = label.value()
                    break
            if event.widget() == cancelbt:
                self.restore()
                returncode = False
                break
        dialog.destroy()
        if returncode:
            return True,format_type,format_label
        else:
            return False," "," "
        

    def ask_OK(self, info):
        yui.YUI.widgetFactory
        mgafactory = yui.YMGAWidgetFactory.getYMGAWidgetFactory(yui.YExternalWidgets.externalWidgetFactory("mga"))
        dlg = mgafactory.createDialogBox(yui.YMGAMessageBox.B_ONE)
        dlg.setTitle(info.title)
        dlg.setText(info.text, info.richtext)
        dlg.setButtonLabel("OK", yui.YMGAMessageBox.B_ONE)
        dlg.setMinSize(60, 10);
        return dlg.show() == yui.YMGAMessageBox.B_ONE

    def ask_YesOrNo(self, info):
        yui.YUI.widgetFactory
        mgafactory = yui.YMGAWidgetFactory.getYMGAWidgetFactory(yui.YExternalWidgets.externalWidgetFactory("mga"))
        dlg = mgafactory.createDialogBox(yui.YMGAMessageBox.B_TWO)
        dlg.setTitle(info.title)
        dlg.setText(info.text, info.richtext)
        dlg.setButtonLabel("Yes", yui.YMGAMessageBox.B_ONE)
        dlg.setButtonLabel("No",  yui.YMGAMessageBox.B_TWO)
        dlg.setMinSize(60, 8);
        return dlg.show() == yui.YMGAMessageBox.B_ONE

    def aboutDialog(self):
        yui.YUI.widgetFactory;
        mgafactory = yui.YMGAWidgetFactory.getYMGAWidgetFactory(yui.YExternalWidgets.externalWidgetFactory("mga"))
        dlg = mgafactory.createAboutDialog("Isodumper", self.RELEASE, "GPLv2",
                                        "Oliver Grawert<BR />Papoteur<BR />Pictures : Timothée Giet", _("A tool for writing ISO images to  a device")+"<BR />http://gitweb.mageia.org/software/isodumper", "")
        dlg.show();
        
    def nodevDialog(self):
        yui.YUI.widgetFactory
        mgafactory = yui.YMGAWidgetFactory.getYMGAWidgetFactory(yui.YExternalWidgets.externalWidgetFactory("mga"))
        dlg = mgafactory.createDialogBox(yui.YMGAMessageBox.B_TWO)
        dlg.setTitle("IsoDumper")
        dlg.setText(_("Warning\nNo target devices were found.\nYou need to plug in a USB Key to which the image can be written."))
        dlg.setButtonLabel(_("&Refresh"), yui.YMGAMessageBox.B_ONE)
        dlg.setButtonLabel(_("Cancel"),  yui.YMGAMessageBox.B_TWO)
        dlg.setMinSize(60, 8);
        return dlg.show() == yui.YMGAMessageBox.B_ONE

    def handleevent(self):
        self.traitement=None
        while True:
            event = self.dialog.waitForEvent()
            if event.eventType() == yui.YEvent.CancelEvent:
                self.close()
                break
            if event.widget() == self.quitbt:
                self.close()
                break
            if event.widget() == self.ima:
                    self.img_name=yui.YUI.app().askForExistingFile('file:///home/'+self.user,"*.iso *.img",self.ChooseImage)
                    self.ima.setLabel(os.path.basename(self.img_name))
                    self.dialog.recalcLayout()
                    self.writebt.setEnabled()
                    self.activate_devicelist()
            if event.widget() == self.writebt:
                    self.wip_unsensitive()
                    self.do_write()
                    self.restore()
            if event.widget() == self.backupbt:
                self.wip_unsensitive()
                self.backup_go()
                self.restore()
            if event.widget() == self.backup_select:
                self.backup_img_name=yui.YUI.app().askForSaveFileName('file:///home/'+self.user,"*.img",_("Backup to:"))
                if self.backup_img_name != '':
                        self.backup_choosed()
            if event.widget() == self.formatbt:
                    self.wip_unsensitive()
                    code,format_type,name = self.ask_format()
                    if code:
                        self.do_format(format_type,name)
                    self.restore()
            if event.widget() == self.devicelist:
                self.device_selected()
            try:
                if event.widget() == self.refreshbt:
                    self.update_list()
            except:
                pass
            try:
                if event.widget() == self.helpbt:
                    self.help_dialog()
            except:
                pass
            try:
                if event.widget() == self.quitbt:
                    self.confirm_close()
            except:
                pass
            if event.widget() == self.aboutbt:
                self.aboutDialog()

if __name__ == "__main__":
    import sys
    user=sys.argv[1]
    app = IsoDumper(user)
    try:
       app.handleevent()
    except:
       yui.YDialog.deleteAllDialogs()
    finally:
       # next line seems to be a workaround to prevent the qt-app from crashing
       # see https://github.com/libyui/libyui-qt/issues/41
       yui.YUILoader.deleteUI()