def error(self, pkg, errormsg): InstallProgress.error(self, pkg, errormsg) logging.error("got an error from dpkg for pkg: '%s': '%s'" % (pkg, errormsg)) # we do not report followup errors from earlier failures if gettext.dgettext( 'dpkg', "dependency problems - leaving unconfigured") in errormsg: return False summary = _("Could not install '%s'") % pkg msg = _("The upgrade will continue but the '%s' package may not " "be in a working state. Please consider submitting a " "bug report about it.") % pkg msg = "<big><b>%s</b></big><br />%s" % (summary, msg) dialogue = QDialog(self.parent.window_main) loadUi("dialog_error.ui", dialogue) self.parent.translate_widget_children(dialogue) dialogue.label_error.setText(msg) if errormsg != None: dialogue.textview_error.setText(errormsg) dialogue.textview_error.show() else: dialogue.textview_error.hide() dialogue.connect(dialogue.button_bugreport, SIGNAL("clicked()"), self.parent.reportBug) dialogue.exec_()
def show_info(parent, title, msg): dlg = QDialog(parent) dlg.setWindowTitle(title) vlayout = QVBoxLayout(dlg) label = QLabel(msg) label.setTextInteractionFlags(Qt.LinksAccessibleByMouse) label.setOpenExternalLinks(True) scroll_area = QScrollArea() scroll_area.setWidget(label) button_box = QDialogButtonBox(QDialogButtonBox.Ok) dlg.connect(button_box, SIGNAL('accepted()'), dlg.accept) vlayout.addWidget(scroll_area) vlayout.addWidget(button_box) return dlg.exec_()
def warningYesNoOptions(parent, msg, options = ()): dlg = QDialog(parent) dlg.setWindowTitle(_('Question')) layout = QVBoxLayout() dlg.setLayout(layout) label = QLabel(msg) layout.addWidget(label) for opt in options: layout.addWidget(opt['widget']) buttonBox = QDialogButtonBox(QDialogButtonBox.Yes | QDialogButtonBox.No) buttonBox.button(QDialogButtonBox.No).setDefault(True) layout.addWidget(buttonBox) dlg.connect(buttonBox, SIGNAL('accepted()'), dlg.accept) dlg.connect(buttonBox, SIGNAL('rejected()'), dlg.reject) ret = dlg.exec_() return (ret, {opt['id']:opt['retFunc']() for opt in options})
def warningYesNoOptions(parent, msg, options=()): dlg = QDialog(parent) dlg.setWindowTitle(_('Question')) layout = QVBoxLayout() dlg.setLayout(layout) label = QLabel(msg) layout.addWidget(label) for opt in options: layout.addWidget(opt['widget']) buttonBox = QDialogButtonBox(QDialogButtonBox.Yes | QDialogButtonBox.No) buttonBox.button(QDialogButtonBox.No).setDefault(True) layout.addWidget(buttonBox) dlg.connect(buttonBox, SIGNAL('accepted()'), dlg.accept) dlg.connect(buttonBox, SIGNAL('rejected()'), dlg.reject) ret = dlg.exec_() return (ret, {opt['id']: opt['retFunc']() for opt in options})
class CustomParticles(ParticleDistribution): def __init__(self, numParticles = 10, particlesPath = None, storageFilename = None): ParticleDistribution.__init__(self, "CustomParticles") self.dialog = QDialog() self.ui = Ui_ParticleSettingsDialog() self.ui.setupUi(self.dialog) self.dialog.connect(self.ui.addParticleButton, SIGNAL("clicked()"), self.treeAddParticle) self.dialog.connect(self.ui.removeParticleButton, SIGNAL("clicked()"), self.treeRemoveParticle) if storageFilename is None: self.particles = Particles(0) else: self.particles = read_set_from_file(particlesPath + storageFilename, "hdf5") self.numParticles = len(self.particles) self.storageFilename = storageFilename self.particlesPath = particlesPath self.ui.pathText.setText(self.storageFilename) def setStoragePath(self, path): self.particlesPath = path def __getstate__(self): write_set_to_file(self.particles, self.particlesPath + self.storageFilename, "hdf5") pickleDict = self.__dict__.copy() del pickleDict["particles"] del pickleDict["dialog"] del pickleDict["ui"] return pickleDict def getParticleList(self): return self.particles.copy() def __setstate__(self, state): self.__dict__ = dict(self.__dict__, **state) self.dialog = QDialog() self.ui = Ui_ParticleSettingsDialog() self.ui.setupUi(self.dialog) particles = read_set_from_file(self.particlesPath + self.storageFilename, "hdf5") self.particles = Particles(len(particles)) self.numParticles = len(particles) try: positionUnit = eval(self.positionUnit) massUnit = eval(self.massUnit) radiusUnit = eval(self.radiusUnit) velUnit = eval(self.velUnit) except: positionUnit = AU massUnit = MSun radiusUnit = AU velUnit = km/s for i in range(len(particles)): self.particles[i].position = particles[i].position.as_quantity_in(positionUnit) self.particles[i].mass = particles[i].mass.as_quantity_in(massUnit) self.particles[i].velocity = particles[i].velocity.as_quantity_in(velUnit) self.particles[i].radius = particles[i].radius.as_quantity_in(radiusUnit) self.ui.pathText.setText(self.storageFilename) @pyqtSlot() def treeAddParticle(self): item = QTreeWidgetItem( ("0.0", "0.0", "0.0", "AU", "0.0", "0.0", "0.0", "km/s", "0.0", "MSun", "0.0", "km" )) item.setFlags(item.flags() | Qt.ItemIsEditable) self.ui.particlesTree.addTopLevelItem(item) def treeRemoveParticle(self): item = self.ui.particlesTree.currentItem() index = self.ui.particlesTree.indexFromItem(item) self.ui.particlesTree.takeTopLevelItem(index.row()) def setupDialog(self): for particle in self.particles: pos = particle.position.number vel = particle.velocity.number mass = particle.mass.number radius = particle.radius.number item = QTreeWidgetItem(( str(pos[0]), str(pos[1]), str(pos[2]), str(particle.position.unit), str(vel[0]), str(vel[1]), str(vel[2]), str(particle.velocity.unit), str(mass), str(particle.mass.unit), str(radius), str(particle.radius.unit) )) item.setFlags(item.flags() | Qt.ItemIsEditable) self.ui.particlesTree.addTopLevelItem(item) def showSettingsDialog(self): self.setupDialog() result = self.dialog.exec_() self.storageFilename = str(self.ui.pathText.text()) allGood = False if result == QDialog.Accepted: allGood = True i = 0 it = QTreeWidgetItemIterator(self.ui.particlesTree) newParticles = Particles(self.ui.particlesTree.topLevelItemCount()) while it.value() is not None: posX, pXGood = it.value().data(0, Qt.DisplayRole).toFloat() posY, pYGood = it.value().data(1, Qt.DisplayRole).toFloat() posZ, pZGood = it.value().data(2, Qt.DisplayRole).toFloat() posUnit = str(it.value().data(3, Qt.DisplayRole).toString()) try: eval(posUnit) posUnitGood = True except: posUnitGood = False velX, vXGood = it.value().data(4, Qt.DisplayRole).toFloat() velY, vYGood = it.value().data(5, Qt.DisplayRole).toFloat() velZ, vZGood = it.value().data(6, Qt.DisplayRole).toFloat() velUnit = str(it.value().data(7, Qt.DisplayRole).toString()) try: eval(velUnit) velUnitGood = True except: velUnitGood = False mass, massGood = it.value().data(8, Qt.DisplayRole).toFloat() massUnit = str(it.value().data(9, Qt.DisplayRole).toString()) try: eval(massUnit) massUnitGood = True except: massUnitGood = False radius, radiusGood = it.value().data(10, Qt.DisplayRole).toFloat() radiusUnit = str(it.value().data(11, Qt.DisplayRole).toString()) radiusUnitGood = (radiusUnit in units.__dict__) checks = (pXGood, pYGood, pZGood, posUnitGood, vXGood, vYGood, vZGood, velUnitGood, massGood, massUnitGood) allGood = reduce(lambda x,y: x and y, checks, allGood) if allGood: newParticles[i].position = [posX, posY, posZ] | eval(posUnit) newParticles[i].velocity = [velX, velY, velZ] | eval(velUnit) newParticles[i].mass = mass | eval(massUnit) newParticles[i].radius = radius | eval(radiusUnit) it += 1 i += 1 if(allGood): del self.particles self.particles = newParticles self.positionUnit = posUnit self.massUnit = massUnit self.radiusUnit = radiusUnit self.velUnit = velUnit self.numParticles = len(self.particles) self.ui.particlesTree.clear()
def tsplot(self, widget): # self.calcThermo() import cyclePlotter from PyQt4.QtCore import SIGNAL from PyQt4.QtGui import QDialog, QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QSplitter from matplotlib.backends.backend_qt4 import NavigationToolbar2QT as NavigationToolbar # plot=TsPlotter.TsPlotter("Tt0",self.T_tinf,0.0,self.p_tinf) tsplot = cyclePlotter.TsPlotter("", 0, 0, 0) tsplot.pyl.clear() tsplot.pWidget.format_labels() hsplot = cyclePlotter.HsPlotter("", 0, 0, 0, 0) hsplot.pyl.clear() hsplot.pWidget.format_labels() def calcPlot(): tsplot.pyl.clear() tsplot.pWidget.format_labels() tsplot.addnewStart("T_t0", self.T_tinf, 0.0, self.p_tinf) tsplot.isotherme("T_t2", self.hpc.p_t1) # Radialverdichter tsplot.polytrope("T_t3", self.hpc.eta_pol, pend=self.hpc.p_t3) # Brennkammer tsplot.isobare("T_t4", self.combc.T_t3) # h-Turbine tsplot.polytrope("T_t5", self.hpt.eta_pol, Tend=self.hpt.T_t3) # Düse tsplot.isotherme("T_t8", self.hn.p_t3) # Entspannung tsplot.isentrope("T_t9", pend=self.p_tinf) tsplot.isobare("", self.T_tinf) tsplot.pWidget.draw() hsplot.pyl.clear() hsplot.pWidget.format_labels() hsplot.addnewStart("H_t0", self.mflow, self.T_tinf, 0.0, self.p_tinf) hsplot.isotherme("H_t2", self.mflow, self.hpc.p_t1) # Radialverdichter hsplot.polytrope("H_t3", self.mflow, self.hpc.eta_pol, pend=self.hpc.p_t3) # Brennkammer hsplot.isobare("H_t4", self.mflow, self.combc.T_t3) # h-Turbine hsplot.polytrope("H_t5", self.mflow, self.hpt.eta_pol, Tend=self.hpt.T_t3) # Düse hsplot.isotherme("H_t8", self.mflow, self.hn.p_t3) # Entspannung hsplot.isentrope("H_t9", self.mflow, pend=self.p_tinf) hsplot.isobare("", self.mflow, self.T_tinf) hsplot.pWidget.draw() toolbar1 = NavigationToolbar(tsplot.pWidget, tsplot.pWidget) toolbar2 = NavigationToolbar(hsplot.pWidget, hsplot.pWidget) l = QVBoxLayout() plotb = QPushButton("Update Plot") sp = QSplitter() w1 = QWidget() l1 = QVBoxLayout() l1.addWidget(tsplot.pWidget) l1.addWidget(toolbar1) w1.setLayout(l1) w2 = QWidget() l2 = QVBoxLayout() l2.addWidget(hsplot.pWidget) l2.addWidget(toolbar2) w2.setLayout(l2) sp.addWidget(w1) sp.addWidget(w2) l.addWidget(sp) l.addWidget(plotb) w = QDialog() w.setLayout(l) # w.show() w.connect(plotb, SIGNAL("clicked()"), calcPlot) widget.addTab(w, "Cycle Plot")
denominatorSpinBox = QSpinBox() denominatorLabel.setBuddy(denominatorSpinBox) denominatorSpinBox.setRange(3, 60) denominatorSpinBox.setValue(slider.fraction()[1]) denominatorSpinBox.setAlignment(Qt.AlignRight|Qt.AlignVCenter) numeratorLabel = QLabel("Numerator") numeratorLCD = QLCDNumber() numeratorLCD.setSegmentStyle(QLCDNumber.Flat) layout = QGridLayout() layout.addWidget(sliderLabel, 0, 0) layout.addWidget(slider, 0, 1, 1, 5) layout.addWidget(numeratorLabel, 1, 0) layout.addWidget(numeratorLCD, 1, 1) layout.addWidget(denominatorLabel, 1, 2) layout.addWidget(denominatorSpinBox, 1, 3) form.setLayout(layout) def valueChanged(denominator): numerator = int(slider.decimal() * denominator) slider.setFraction(numerator, denominator) numeratorLCD.display(numerator) form.connect(slider, SIGNAL("valueChanged(int,int)"), numeratorLCD, SLOT("display(int)")) form.connect(denominatorSpinBox, SIGNAL("valueChanged(int)"), valueChanged) form.setWindowTitle("Fraction Slider") form.show() app.exec_()
class DistUpgradeViewKDE(DistUpgradeView): """KDE frontend of the distUpgrade tool""" def __init__(self, datadir=None, logdir=None): DistUpgradeView.__init__(self) # silence the PyQt4 logger logger = logging.getLogger("PyQt4") logger.setLevel(logging.INFO) if not datadir or datadir == '.': localedir = os.path.join(os.getcwd(), "mo") else: localedir = "/usr/share/locale/ubuntu-release-upgrader" # FIXME: i18n must be somewhere relative do this dir try: gettext.bindtextdomain("ubuntu-release-upgrader", localedir) gettext.textdomain("ubuntu-release-upgrader") except Exception as e: logging.warning("Error setting locales (%s)" % e) #about = KAboutData("adept_manager","Upgrader","0.1","Dist Upgrade Tool for Kubuntu",KAboutData.License_GPL,"(c) 2007 Canonical Ltd", #"http://wiki.kubuntu.org/KubuntuUpdateManager", "*****@*****.**") #about.addAuthor("Jonathan Riddell", None,"*****@*****.**") #about.addAuthor("Michael Vogt", None,"*****@*****.**") #KCmdLineArgs.init(["./dist-upgrade.py"],about) # we test for DISPLAY here, QApplication does not throw a # exception when run without DISPLAY but dies instead if not "DISPLAY" in os.environ: raise Exception("No DISPLAY in os.environ found") self.app = QApplication(["ubuntu-release-upgrader"]) if os.path.exists( "/usr/share/icons/oxygen/48x48/apps/system-software-update.png" ): messageIcon = QPixmap( "/usr/share/icons/oxygen/48x48/apps/system-software-update.png" ) else: messageIcon = QPixmap( "/usr/share/icons/hicolor/48x48/apps/adept_manager.png") self.app.setWindowIcon(QIcon(messageIcon)) self.window_main = UpgraderMainWindow() self.window_main.setParent(self) self.window_main.show() self.prev_step = 0 # keep a record of the latest step self._opCacheProgress = KDEOpProgress( self.window_main.progressbar_cache, self.window_main.progress_text) self._acquireProgress = KDEAcquireProgressAdapter(self) self._cdromProgress = KDECdromProgressAdapter(self) self._installProgress = KDEInstallProgressAdapter(self) # reasonable fault handler sys.excepthook = self._handleException self.window_main.showTerminalButton.setEnabled(False) self.app.connect(self.window_main.showTerminalButton, SIGNAL("clicked()"), self.showTerminal) #kdesu requires us to copy the xauthority file before it removes it when Adept is killed fd, copyXauth = tempfile.mkstemp("", "adept") if 'XAUTHORITY' in os.environ and os.environ['XAUTHORITY'] != copyXauth: shutil.copy(os.environ['XAUTHORITY'], copyXauth) os.environ["XAUTHORITY"] = copyXauth # Note that with kdesudo this needs --nonewdcop ## create a new DCOP-Client: #client = DCOPClient() ## connect the client to the local DCOP-server: #client.attach() #for qcstring_app in client.registeredApplications(): # app = str(qcstring_app) # if app.startswith("adept"): # adept = DCOPApp(qcstring_app, client) # adeptInterface = adept.object("MainApplication-Interface") # adeptInterface.quit() # This works just as well subprocess.call(["killall", "adept_manager"]) subprocess.call(["killall", "adept_updater"]) # init gettext gettext.bindtextdomain("ubuntu-release-upgrader", localedir) gettext.textdomain("ubuntu-release-upgrader") self.translate_widget_children() self.window_main.label_title.setText( self.window_main.label_title.text().replace("Ubuntu", "Kubuntu")) # setup terminal text in hidden by default spot self.window_main.konsole_frame.hide() self.konsole_frame_layout = QHBoxLayout(self.window_main.konsole_frame) self.window_main.konsole_frame.setMinimumSize(600, 400) self.terminal_text = DumbTerminal(self._installProgress, self.window_main.konsole_frame) self.konsole_frame_layout.addWidget(self.terminal_text) self.terminal_text.show() # for some reason we need to start the main loop to get everything displayed # this app mostly works with processEvents but run main loop briefly to keep it happily displaying all widgets QTimer.singleShot(10, self.exitMainLoop) self.app.exec_() def exitMainLoop(self): print("exitMainLoop") self.app.exit() def translate_widget_children(self, parentWidget=None): if parentWidget == None: parentWidget = self.window_main if isinstance(parentWidget, QDialog) or isinstance( parentWidget, QWidget): if str(parentWidget.windowTitle()) == "Error": parentWidget.setWindowTitle( gettext.dgettext("kdelibs", "Error")) else: parentWidget.setWindowTitle(_(str(parentWidget.windowTitle()))) if parentWidget.children() != None: for widget in parentWidget.children(): self.translate_widget(widget) self.translate_widget_children(widget) def translate_widget(self, widget): if isinstance(widget, QLabel) or isinstance(widget, QPushButton): if str(widget.text()) == "&Cancel": kdelibs = gettext.translation("kdelibs", gettext.textdomain("kdelibs"), fallback=True) widget.setText(unicode_gettext(kdelibs, "&Cancel")) elif str(widget.text()) == "&Close": kdelibs = gettext.translation("kdelibs", gettext.textdomain("kdelibs"), fallback=True) widget.setText(unicode_gettext(kdelibs, "&Close")) elif str(widget.text()) != "": widget.setText(_(str(widget.text())).replace("_", "&")) def _handleException(self, exctype, excvalue, exctb): """Crash handler.""" if (issubclass(exctype, KeyboardInterrupt) or issubclass(exctype, SystemExit)): return # we handle the exception here, hand it to apport and run the # apport gui manually after it because we kill u-m during the upgrade # to prevent it from popping up for reboot notifications or FF restart # notifications or somesuch lines = traceback.format_exception(exctype, excvalue, exctb) logging.error("not handled exception in KDE frontend:\n%s" % "\n".join(lines)) # we can't be sure that apport will run in the middle of a upgrade # so we still show a error message here apport_crash(exctype, excvalue, exctb) if not run_apport(): tbtext = ''.join( traceback.format_exception(exctype, excvalue, exctb)) dialog = QDialog(self.window_main) loadUi("dialog_error.ui", dialog) self.translate_widget_children(self.dialog) #FIXME make URL work #dialog.connect(dialog.beastie_url, SIGNAL("leftClickedURL(const QString&)"), self.openURL) dialog.crash_detail.setText(tbtext) dialog.exec_() sys.exit(1) def openURL(self, url): """start konqueror""" #need to run this else kdesu can't run Konqueror #subprocess.call(['su', 'ubuntu', 'xhost', '+localhost']) QDesktopServices.openUrl(QUrl(url)) def reportBug(self): """start konqueror""" #need to run this else kdesu can't run Konqueror #subprocess.call(['su', 'ubuntu', 'xhost', '+localhost']) QDesktopServices.openUrl( QUrl( "https://launchpad.net/ubuntu/+source/ubuntu-release-upgrader/+filebug" )) def showTerminal(self): if self.window_main.konsole_frame.isVisible(): self.window_main.konsole_frame.hide() self.window_main.showTerminalButton.setText(_("Show Terminal >>>")) else: self.window_main.konsole_frame.show() self.window_main.showTerminalButton.setText(_("<<< Hide Terminal")) self.window_main.resize(self.window_main.sizeHint()) def getAcquireProgress(self): return self._acquireProgress def getInstallProgress(self, cache): self._installProgress._cache = cache return self._installProgress def getOpCacheProgress(self): return self._opCacheProgress def getCdromProgress(self): return self._cdromProgress def update_status(self, msg): self.window_main.label_status.setText(msg) def hideStep(self, step): image = getattr(self.window_main, "image_step%i" % step) label = getattr(self.window_main, "label_step%i" % step) image.hide() label.hide() def abort(self): step = self.prev_step if step > 0: image = getattr(self.window_main, "image_step%i" % step) if os.path.exists( "/usr/share/icons/oxygen/16x16/actions/dialog-cancel.png"): cancelIcon = QPixmap( "/usr/share/icons/oxygen/16x16/actions/dialog-cancel.png") elif os.path.exists( "/usr/lib/kde4/share/icons/oxygen/16x16/actions/dialog-cancel.png" ): cancelIcon = QPixmap( "/usr/lib/kde4/share/icons/oxygen/16x16/actions/dialog-cancel.png" ) else: cancelIcon = QPixmap( "/usr/share/icons/crystalsvg/16x16/actions/cancel.png") image.setPixmap(cancelIcon) image.show() def setStep(self, step): if os.path.exists( "/usr/share/icons/oxygen/16x16/actions/dialog-ok.png"): okIcon = QPixmap( "/usr/share/icons/oxygen/16x16/actions/dialog-ok.png") elif os.path.exists( "/usr/lib/kde4/share/icons/oxygen/16x16/actions/dialog-ok.png" ): okIcon = QPixmap( "/usr/lib/kde4/share/icons/oxygen/16x16/actions/dialog-ok.png") else: okIcon = QPixmap( "/usr/share/icons/crystalsvg/16x16/actions/ok.png") if os.path.exists( "/usr/share/icons/oxygen/16x16/actions/arrow-right.png"): arrowIcon = QPixmap( "/usr/share/icons/oxygen/16x16/actions/arrow-right.png") elif os.path.exists( "/usr/lib/kde4/share/icons/oxygen/16x16/actions/arrow-right.png" ): arrowIcon = QPixmap( "/usr/lib/kde4/share/icons/oxygen/16x16/actions/arrow-right.png" ) else: arrowIcon = QPixmap( "/usr/share/icons/crystalsvg/16x16/actions/1rightarrow.png") if self.prev_step: image = getattr(self.window_main, "image_step%i" % self.prev_step) label = getattr(self.window_main, "label_step%i" % self.prev_step) image.setPixmap(okIcon) image.show() ##arrow.hide() self.prev_step = step # show the an arrow for the current step and make the label bold image = getattr(self.window_main, "image_step%i" % step) label = getattr(self.window_main, "label_step%i" % step) image.setPixmap(arrowIcon) image.show() label.setText("<b>" + label.text() + "</b>") def information(self, summary, msg, extended_msg=None): msg = "<big><b>%s</b></big><br />%s" % (summary, msg) dialogue = QDialog(self.window_main) loadUi("dialog_error.ui", dialogue) self.translate_widget_children(dialogue) dialogue.label_error.setText(msg) if extended_msg != None: dialogue.textview_error.setText(extended_msg) dialogue.textview_error.show() else: dialogue.textview_error.hide() dialogue.button_bugreport.hide() dialogue.setWindowTitle(_("Information")) if os.path.exists( "/usr/share/icons/oxygen/48x48/status/dialog-information.png"): messageIcon = QPixmap( "/usr/share/icons/oxygen/48x48/status/dialog-information.png") elif os.path.exists( "/usr/lib/kde4/share/icons/oxygen/48x48/status/dialog-information.png" ): messageIcon = QPixmap( "/usr/lib/kde4/share/icons/oxygen/48x48/status/dialog-information.png" ) else: messageIcon = QPixmap( "/usr/share/icons/crystalsvg/32x32/actions/messagebox_info.png" ) dialogue.image.setPixmap(messageIcon) dialogue.exec_() def error(self, summary, msg, extended_msg=None): msg = "<big><b>%s</b></big><br />%s" % (summary, msg) dialogue = QDialog(self.window_main) loadUi("dialog_error.ui", dialogue) self.translate_widget_children(dialogue) dialogue.label_error.setText(msg) if extended_msg != None: dialogue.textview_error.setText(extended_msg) dialogue.textview_error.show() else: dialogue.textview_error.hide() dialogue.button_close.show() self.app.connect(dialogue.button_bugreport, SIGNAL("clicked()"), self.reportBug) if os.path.exists( "/usr/share/icons/oxygen/48x48/status/dialog-error.png"): messageIcon = QPixmap( "/usr/share/icons/oxygen/48x48/status/dialog-error.png") elif os.path.exists( "/usr/lib/kde4/share/icons/oxygen/48x48/status/dialog-error.png" ): messageIcon = QPixmap( "/usr/lib/kde4/share/icons/oxygen/48x48/status/dialog-error.png" ) else: messageIcon = QPixmap( "/usr/share/icons/crystalsvg/32x32/actions/messagebox_critical.png" ) dialogue.image.setPixmap(messageIcon) dialogue.exec_() return False def confirmChanges(self, summary, changes, demotions, downloadSize, actions=None, removal_bold=True): """show the changes dialogue""" # FIXME: add a whitelist here for packages that we expect to be # removed (how to calc this automatically?) DistUpgradeView.confirmChanges(self, summary, changes, demotions, downloadSize) self.changesDialogue = QDialog(self.window_main) loadUi("dialog_changes.ui", self.changesDialogue) self.changesDialogue.treeview_details.hide() self.changesDialogue.connect(self.changesDialogue.show_details_button, SIGNAL("clicked()"), self.showChangesDialogueDetails) self.translate_widget_children(self.changesDialogue) self.changesDialogue.show_details_button.setText(_("Details") + " >>>") self.changesDialogue.resize(self.changesDialogue.sizeHint()) if os.path.exists( "/usr/share/icons/oxygen/48x48/status/dialog-warning.png"): warningIcon = QPixmap( "/usr/share/icons/oxygen/48x48/status/dialog-warning.png") elif os.path.exists( "/usr/lib/kde4/share/icons/oxygen/48x48/status/dialog-warning.png" ): warningIcon = QPixmap( "/usr/lib/kde4/share/icons/oxygen/48x48/status/dialog-warning.png" ) else: warningIcon = QPixmap( "/usr/share/icons/crystalsvg/32x32/actions/messagebox_warning.png" ) self.changesDialogue.question_pixmap.setPixmap(warningIcon) if actions != None: cancel = actions[0].replace("_", "") self.changesDialogue.button_cancel_changes.setText(cancel) confirm = actions[1].replace("_", "") self.changesDialogue.button_confirm_changes.setText(confirm) summaryText = "<big><b>%s</b></big>" % summary self.changesDialogue.label_summary.setText(summaryText) self.changesDialogue.label_changes.setText(self.confirmChangesMessage) # fill in the details self.changesDialogue.treeview_details.clear() self.changesDialogue.treeview_details.setHeaderLabels(["Packages"]) self.changesDialogue.treeview_details.header().hide() for demoted in self.demotions: self.changesDialogue.treeview_details.insertTopLevelItem( 0, QTreeWidgetItem(self.changesDialogue.treeview_details, [_("No longer supported %s") % demoted.name])) for rm in self.toRemove: self.changesDialogue.treeview_details.insertTopLevelItem( 0, QTreeWidgetItem(self.changesDialogue.treeview_details, [_("Remove %s") % rm.name])) for rm in self.toRemoveAuto: self.changesDialogue.treeview_details.insertTopLevelItem( 0, QTreeWidgetItem( self.changesDialogue.treeview_details, [_("Remove (was auto installed) %s") % rm.name])) for inst in self.toInstall: self.changesDialogue.treeview_details.insertTopLevelItem( 0, QTreeWidgetItem(self.changesDialogue.treeview_details, [_("Install %s") % inst.name])) for up in self.toUpgrade: self.changesDialogue.treeview_details.insertTopLevelItem( 0, QTreeWidgetItem(self.changesDialogue.treeview_details, [_("Upgrade %s") % up.name])) #FIXME resize label, stop it being shrinkable res = self.changesDialogue.exec_() if res == QDialog.Accepted: return True return False def showChangesDialogueDetails(self): if self.changesDialogue.treeview_details.isVisible(): self.changesDialogue.treeview_details.hide() self.changesDialogue.show_details_button.setText( _("Details") + " >>>") else: self.changesDialogue.treeview_details.show() self.changesDialogue.show_details_button.setText("<<< " + _("Details")) self.changesDialogue.resize(self.changesDialogue.sizeHint()) def askYesNoQuestion(self, summary, msg, default='No'): answer = QMessageBox.question(self.window_main, summary, "<font>" + msg, QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if answer == QMessageBox.Yes: return True return False def confirmRestart(self): messageBox = QMessageBox( QMessageBox.Question, _("Restart required"), _("<b><big>Restart the system to complete the upgrade</big></b>"), QMessageBox.NoButton, self.window_main) yesButton = messageBox.addButton(QMessageBox.Yes) noButton = messageBox.addButton(QMessageBox.No) yesButton.setText(_("_Restart Now").replace("_", "&")) noButton.setText(gettext.dgettext("kdelibs", "&Close")) answer = messageBox.exec_() if answer == QMessageBox.Yes: return True return False def processEvents(self): QApplication.processEvents() def pulseProgress(self, finished=False): # FIXME: currently we do nothing here because this is # run in a different python thread and QT explodes if the UI is # touched from a non QThread pass def on_window_main_delete_event(self): #FIXME make this user friendly text = _("""<b><big>Cancel the running upgrade?</big></b> The system could be in an unusable state if you cancel the upgrade. You are strongly advised to resume the upgrade.""" ) text = text.replace("\n", "<br />") cancel = QMessageBox.warning(self.window_main, _("Cancel Upgrade?"), text, QMessageBox.Yes, QMessageBox.No) if cancel == QMessageBox.Yes: return True return False
class KDEInstallProgressAdapter(InstallProgress): """methods for updating the progress bar while installing packages""" # timeout with no status change when the terminal is expanded # automatically TIMEOUT_TERMINAL_ACTIVITY = 240 def __init__(self, parent): InstallProgress.__init__(self) self._cache = None self.label_status = parent.window_main.label_status self.progress = parent.window_main.progressbar_cache self.progress_text = parent.window_main.progress_text self.parent = parent try: self._terminal_log = open("/var/log/dist-upgrade/term.log", "wb") except Exception as e: # if something goes wrong (permission denied etc), use stdout logging.error("Can not open terminal log: '%s'" % e) if sys.version >= '3': self._terminal_log = sys.stdout.buffer else: self._terminal_log = sys.stdout # some options for dpkg to make it die less easily apt_pkg.config.set("DPkg::StopOnError", "False") def start_update(self): InstallProgress.start_update(self) self.finished = False # FIXME: add support for the timeout # of the terminal (to display something useful then) # -> longer term, move this code into python-apt self.label_status.setText(_("Applying changes")) self.progress.setValue(0) self.progress_text.setText(" ") # do a bit of time-keeping self.start_time = 0.0 self.time_ui = 0.0 self.last_activity = 0.0 self.parent.window_main.showTerminalButton.setEnabled(True) def error(self, pkg, errormsg): InstallProgress.error(self, pkg, errormsg) logging.error("got an error from dpkg for pkg: '%s': '%s'" % (pkg, errormsg)) # we do not report followup errors from earlier failures if gettext.dgettext( 'dpkg', "dependency problems - leaving unconfigured") in errormsg: return False summary = _("Could not install '%s'") % pkg msg = _("The upgrade will continue but the '%s' package may not " "be in a working state. Please consider submitting a " "bug report about it.") % pkg msg = "<big><b>%s</b></big><br />%s" % (summary, msg) dialogue = QDialog(self.parent.window_main) loadUi("dialog_error.ui", dialogue) self.parent.translate_widget_children(dialogue) dialogue.label_error.setText(msg) if errormsg != None: dialogue.textview_error.setText(errormsg) dialogue.textview_error.show() else: dialogue.textview_error.hide() dialogue.connect(dialogue.button_bugreport, SIGNAL("clicked()"), self.parent.reportBug) dialogue.exec_() def conffile(self, current, new): """ask question in case conffile has been changed by user""" logging.debug("got a conffile-prompt from dpkg for file: '%s'" % current) start = time.time() prim = _("Replace the customized configuration file\n'%s'?") % current sec = _("You will lose any changes you have made to this " "configuration file if you choose to replace it with " "a newer version.") markup = "<span weight=\"bold\" size=\"larger\">%s </span> \n\n%s" % ( prim, sec) self.confDialogue = QDialog(self.parent.window_main) loadUi("dialog_conffile.ui", self.confDialogue) self.confDialogue.label_conffile.setText(markup) self.confDialogue.textview_conffile.hide() #FIXME, below to be tested #self.confDialogue.resize(self.confDialogue.minimumSizeHint()) self.confDialogue.connect(self.confDialogue.show_difference_button, SIGNAL("clicked()"), self.showConffile) # workaround silly dpkg if not os.path.exists(current): current = current + ".dpkg-dist" # now get the diff if os.path.exists("/usr/bin/diff"): cmd = ["/usr/bin/diff", "-u", current, new] diff = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0] diff = diff.decode("UTF-8", "replace") self.confDialogue.textview_conffile.setText(diff) else: self.confDialogue.textview_conffile.setText( _("The 'diff' command was not found")) result = self.confDialogue.exec_() self.time_ui += time.time() - start # if replace, send this to the terminal if result == QDialog.Accepted: os.write(self.master_fd, "y\n") else: os.write(self.master_fd, "n\n") def showConffile(self): if self.confDialogue.textview_conffile.isVisible(): self.confDialogue.textview_conffile.hide() self.confDialogue.show_difference_button.setText( _("Show Difference >>>")) else: self.confDialogue.textview_conffile.show() self.confDialogue.show_difference_button.setText( _("<<< Hide Difference")) def fork(self): """pty voodoo""" (self.child_pid, self.master_fd) = pty.fork() if self.child_pid == 0: os.environ["TERM"] = "dumb" if ("DEBIAN_FRONTEND" not in os.environ or os.environ["DEBIAN_FRONTEND"] == "kde"): os.environ["DEBIAN_FRONTEND"] = "noninteractive" os.environ["APT_LISTCHANGES_FRONTEND"] = "none" logging.debug(" fork pid is: %s" % self.child_pid) return self.child_pid def status_change(self, pkg, percent, status): """update progress bar and label""" # start the timer when the first package changes its status if self.start_time == 0.0: #print("setting start time to %s" % self.start_time) self.start_time = time.time() self.progress.setValue(self.percent) self.label_status.setText(utf8(status.strip())) # start showing when we gathered some data if percent > 1.0: self.last_activity = time.time() self.activity_timeout_reported = False delta = self.last_activity - self.start_time # time wasted in conffile questions (or other ui activity) delta -= self.time_ui time_per_percent = (float(delta) / percent) eta = (100.0 - self.percent) * time_per_percent # only show if we have some sensible data (60sec < eta < 2days) if eta > 61.0 and eta < (60 * 60 * 24 * 2): self.progress_text.setText( _("About %s remaining") % FuzzyTimeToStr(eta)) else: self.progress_text.setText(" ") def finish_update(self): self.label_status.setText("") def update_interface(self): """ no mainloop in this application, just call processEvents lots here it's also important to sleep for a minimum amount of time """ # log the output of dpkg (on the master_fd) to the terminal log while True: try: (rlist, wlist, xlist) = select.select([self.master_fd], [], [], 0) if len(rlist) > 0: line = os.read(self.master_fd, 255) self._terminal_log.write(line) self.parent.terminal_text.insertWithTermCodes( utf8(line, errors="replace")) else: break except Exception as e: print(e) logging.debug("error reading from self.master_fd '%s'" % e) break # now update the GUI try: InstallProgress.update_interface(self) except ValueError as e: logging.error( "got ValueError from InstallProgress.update_interface. Line was '%s' (%s)" % (self.read, e)) # reset self.read so that it can continue reading and does not loop self.read = "" # check about terminal activity if self.last_activity > 0 and \ (self.last_activity + self.TIMEOUT_TERMINAL_ACTIVITY) < time.time(): if not self.activity_timeout_reported: #FIXME bug 95465, I can't recreate this, so here's a hacky fix try: logging.warning( "no activity on terminal for %s seconds (%s)" % (self.TIMEOUT_TERMINAL_ACTIVITY, self.label_status.text())) except UnicodeEncodeError: logging.warning("no activity on terminal for %s seconds" % (self.TIMEOUT_TERMINAL_ACTIVITY)) self.activity_timeout_reported = True self.parent.window_main.konsole_frame.show() QApplication.processEvents() time.sleep(0.02) def wait_child(self): while True: self.update_interface() (pid, res) = os.waitpid(self.child_pid, os.WNOHANG) if pid == self.child_pid: break # we need the full status here (not just WEXITSTATUS) return res
def login(video): if gui is "PyQt4": #A login with Qt4 GUI global mail, passw #Objects login = QDialog() login_mailtext = QLabel("Email:") login_mail = QLineEdit(mail) login_passtext = QLabel("Password:"******"Ok") login_cancel = QPushButton("Cancel") login_grid = QGridLayout() #Connection to grid login_grid.addWidget(login_mailtext,0,0) login_grid.addWidget(login_mail,0,1) login_grid.addWidget(login_passtext,1,0) login_grid.addWidget(login_passw,1,1) login_grid.addWidget(login_Ok,2,0) login_grid.addWidget(login_cancel,2,1) login.setLayout(login_grid) #Method def accept(): global mail, passw mail = login_mail.text() passw = login_passw.text() if mail != "" and passw != "": login.close() return work(video) #Signals login.connect(login_Ok, SIGNAL("clicked()"), accept) login.connect(login_cancel, SIGNAL("clicked()"), SLOT("close()") ) #Options and execution login_passw.setEchoMode(2) login.setWindowTitle("NicoLogin") login.show() login.exec_() elif gui is "Gtk": #A login with GTK GUI #Method def accept(widget): global mail, passw mail = login_mail.get_text() passw = login_passw.get_text() if mail != "" and passw != "": login.destroy() return work(video) def close(widget): login.destroy() #Objects login = gtk.Window() layout = gtk.Table(2,3,True) login_mailtext = gtk.Label() login_mail = gtk.Entry() login_passtext = gtk.Label() login_passw = gtk.Entry() login_Ok = gtk.Button("Ok") login_cancel = gtk.Button("Cancel") #Grid layout.attach(login_mailtext,0,1,0,1) layout.attach(login_mail,1,2,0,1) layout.attach(login_passtext,0,1,1,2) layout.attach(login_passw,1,2,1,2) layout.attach(login_Ok,0,1,2,3) layout.attach(login_cancel,1,2,2,3) #Options and Run login_Ok.connect("clicked",accept) login_cancel.connect("clicked",close) login.connect("destroy", gtk.main_quit) login_mailtext.set_text("Email:") login_mail.set_text(mail) login_passtext.set_text("Password:"******"Tk": #A login with Tk GUI #Method def accept(*args): global mail, passw mail = login_mail.get() passw = login_passw.get() if mail != "" and passw != "": login.destroy() return work(video) #Objects login = Tk.Toplevel() login_mailtext = Tk.Label(login, text="Email:") login_passtext = Tk.Label(login, text="Password:"******"*") login_Ok = Tk.Button(login, text="Ok", command=accept) login_cancel = Tk.Button(login, text="Cancel", command=login.destroy) #Connection to grid login_mailtext.grid(row=0) login_passtext.grid(row=1) login_mail.grid(row=0, column=1) login_passw.grid(row=1, column=1) login_Ok.grid(row=2) login_cancel.grid(row=2, column=1) #Options and execution login_mail.focus() login.bind("<Return>", accept) login.mainloop() else: #A login without GUI while mail == "" or passw == "": mail = raw_input("\nEmail: ") passw = getpass.getpass(prompt="Password: ") return work(video) return False