diff options
Diffstat (limited to 'liveusb/gui.py')
-rwxr-xr-x | liveusb/gui.py | 270 |
1 files changed, 270 insertions, 0 deletions
diff --git a/liveusb/gui.py b/liveusb/gui.py new file mode 100755 index 0000000..9de97e5 --- /dev/null +++ b/liveusb/gui.py @@ -0,0 +1,270 @@ +# -*- coding: utf-8 -*- +# +# Copyright © 2008 Red Hat, Inc. All rights reserved. +# Copyright © 2008 Kushal Das <kushal@fedoraproject.org> +# 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 <lmacken@redhat.com> +# Kushal Das <kushal@fedoraproject.org> +# Aurelien Lefebvre <alefebvre@mandriva.com> + +import os +import sys +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.hal.connect_to_signal('DeviceAdded', + self.populate_devices) + self.live.hal.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, 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:\)")) + + + if not self.live.is_hybrid(self.live.iso): + self.status(_("The selected iso isn't hybrid")) + self.live.iso = None + else: + 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() |