#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()