# -*- coding: utf-8 -*- # # Copyright © 2008 Red Hat, Inc. All rights reserved. # Copyright © 2008 Kushal Das # Copyright © 2009 Mandriva. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, modify, # copy, or redistribute it subject to the terms and conditions of the GNU # General Public License v.2. This program is distributed in the hope that it # will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the # implied warranties 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 Street, Fifth # Floor, Boston, MA 02110-1301, USA. Any Red Hat trademarks that are # incorporated in the source code or documentation are not subject to the GNU # General Public License and may only be used or replicated with the express # permission of Red Hat, Inc. # # Author(s): Luke Macken # Kushal Das # Aurelien Lefebvre import logging from datetime import datetime from PyQt4 import QtCore, QtGui from liveusb import LiveUSBCreator, LiveUSBError, LiveUSBInterface, _ try: import dbus.mainloop.qt dbus.mainloop.qt.DBusQtMainLoop(set_as_default=True) except: pass class LiveUSBApp(QtGui.QApplication): """ Main application class """ def __init__(self, opts, args): QtGui.QApplication.__init__(self, args) self.mywindow = LiveUSBDialog(opts) self.mywindow.show() try: self.exec_() finally: self.mywindow.terminate() class ProgressThread(QtCore.QThread): def set_data(self): self.emit(QtCore.SIGNAL("maxprogress(int)"), 100) self.emit(QtCore.SIGNAL("progress(int)"), 0) def run(self): return def update(self, value): # Never update to 100% if value > 99: tunned_value = 99 else: tunned_value = value self.emit(QtCore.SIGNAL("progress(int)"), tunned_value) def terminate(self): self.emit(QtCore.SIGNAL("progress(int)"), 100) QtCore.QThread.terminate(self) class LiveUSBThread(QtCore.QThread): def __init__(self, live, progress, parent=None): QtCore.QThread.__init__(self, parent) self.progress = progress self.parent = parent self.live = live def status(self, text): self.emit(QtCore.SIGNAL("status(PyQt_PyObject)"), text) def run(self): handler = LiveUSBLogHandler(self.status) self.live.log.addHandler(handler) now = datetime.now() try: if not self.live.drive: raise Exception("No drive selected") if not self.live.iso: raise Exception("No ISO selected") # Setup the progress bar self.progress.set_data() self.progress.start() self.live.build_disk(self.progress) duration = str(datetime.now() - now).split('.')[0] self.status(_("Complete! (%s)" % duration)) self.progress.terminate() except LiveUSBError, e: self.status(e.message) # except Exception, e: # self.status(_("LiveUSB creation failed!")) def __del__(self): self.wait() class LiveUSBLogHandler(logging.Handler): def __init__(self, cb): logging.Handler.__init__(self) self.cb = cb def emit(self, record): if record.levelname in ('INFO', 'ERROR'): self.cb(record.msg) class LiveUSBDialog(QtGui.QDialog, LiveUSBInterface): """ Our main dialog class """ def __init__(self, opts): self.in_process = False QtGui.QDialog.__init__(self) LiveUSBInterface.__init__(self) self.opts = opts self.setupUi(self) self.live = LiveUSBCreator(opts=opts) self.populate_devices() self.progress_thread = ProgressThread() self.live_thread = LiveUSBThread(live=self.live, progress=self.progress_thread, parent=self) self.connect_slots() self.confirmed = False # Intercept all liveusb INFO log messages, and display them in the gui self.handler = LiveUSBLogHandler(lambda x: self.textEdit.append(x)) self.live.log.addHandler(self.handler) if not self.opts.verbose: self.live.log.removeHandler(self.live.handler) def populate_devices(self, *args, **kw): if self.in_process: return self.driveBox.clear() self.textEdit.clear() try: self.live.detect_removable_drives() for device, info in self.live.drives.items(): driveInfo = info['name'] if info.has_key('model') and info['model']: driveInfo += " - %s" % info['model'] if info.has_key('capacity') and info['capacity']: driveInfo += " (%s Mb)" % str(int(info['capacity'])/1000000) self.driveBox.addItem(driveInfo) self.check_startbutton_state() except LiveUSBError, e: self.textEdit.setPlainText(e.message) self.check_startbutton_state() def connect_slots(self): self.connect(self.isoBttn, QtCore.SIGNAL("clicked()"), self.selectfile) self.connect(self.startButton, QtCore.SIGNAL("clicked()"), self.begin) self.connect(self.live_thread, QtCore.SIGNAL("status(PyQt_PyObject)"), self.status) self.connect(self.live_thread, QtCore.SIGNAL("finished()"), lambda: self.enable_widgets(True)) self.connect(self.live_thread, QtCore.SIGNAL("terminated()"), lambda: self.enable_widgets(True)) self.connect(self.live_thread, QtCore.SIGNAL("progress(int)"), self.progress) self.connect(self.live_thread, QtCore.SIGNAL("maxprogress(int)"), self.maxprogress) self.connect(self.progress_thread, QtCore.SIGNAL("progress(int)"), self.progress) self.connect(self.progress_thread, QtCore.SIGNAL("maxprogress(int)"), self.maxprogress) if hasattr(self, 'refreshDevicesButton'): self.connect(self.refreshDevicesButton, QtCore.SIGNAL("clicked()"), self.populate_devices) # If we have access to HAL & DBus, intercept some useful signals # if hasattr(self.live, 'hal'): # self.live.i.connect_to_signal('DeviceAdded', # self.populate_devices) # self.live.hal.connect_to_signal('DeviceRemoved', # self.populate_devices) # If we have access to UDisk & DBus, intercept some useful signals if hasattr(self.live, 'iface'): self.live.iface.connect_to_signal('DeviceAdded', self.populate_devices) self.live.iface.connect_to_signal('DeviceRemoved', self.populate_devices) def progress(self, value): self.progressBar.setValue(value) def maxprogress(self, value): self.progressBar.setMaximum(value) def status(self, text): if isinstance(text, Exception): text = text.message self.textEdit.append(text) def enable_widgets(self, enabled=True): if(enabled == False): self.startButton.setEnabled(enabled) else: self.check_startbutton_state() self.driveBox.setEnabled(enabled) self.isoBttn.setEnabled(enabled) if hasattr(self, 'refreshDevicesButton'): self.refreshDevicesButton.setEnabled(enabled) self.in_process = not enabled def get_selected_drive(self): return str(self.driveBox.currentText()).split()[0] def begin(self): """ Begin the liveusb creation process. This method is called when the "Create LiveUSB" button is clicked. """ r = QtGui.QMessageBox.warning(self, _("Warning"), _("All the data on the USB stick are going to be eaten"), QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel); if(r == QtGui.QMessageBox.Cancel): return; self.enable_widgets(False) self.live.drive = self.get_selected_drive() # Remove the log handler, because our live thread will register its own self.live.log.removeHandler(self.handler) self.live_thread.start() def selectfile(self): isofile = QtGui.QFileDialog.getOpenFileName(self, _("Select Live ISO"), "..", "ISO (*.iso)" ) if isofile: try: self.live.set_iso(isofile) except Exception as e: self.live.log.error(e.message.encode('utf8')) self.status(_("Unable to encode the filename of your livecd. " "You may have better luck if you move your ISO " "to the root of your drive (ie: C:\)")) flag= False if not self.live.is_hybrid(self.live.iso): self.status(_("The selected iso isn't hybrid")) r = QtGui.QMessageBox.warning(self, _("Warning"), _("The selected iso seems not to be hybrid. Do you want to use it?"), QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel); if(r == QtGui.QMessageBox.Cancel): self.live.iso = None else: flag= True else: flag = True if flag: self.status("Iso " + _("selected")) self.check_startbutton_state() def check_startbutton_state(self): if self.live.drives != {} and self.live.iso: self.startButton.setEnabled(True) else: self.startButton.setEnabled(False) def terminate(self): """ Terminate any processes that we have spawned """ self.live.terminate()