Thu, 10 Jan 2019 14:21:05 +0100
Updated copyright for 2019.
# -*- coding: utf-8 -*- # Copyright (c) 2012 - 2019 Detlev Offenbach <detlev@die-offenbachs.de> # """ Module implementing a dialog showing the available routes. """ from __future__ import unicode_literals try: str = unicode except NameError: pass import os from PyQt5.QtCore import QProcess, QTimer, pyqtSlot, Qt, QCoreApplication from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QLineEdit, \ QTreeWidgetItem from E5Gui import E5MessageBox from .Ui_PyramidRoutesDialog import Ui_PyramidRoutesDialog import Preferences from Globals import strToQByteArray class PyramidRoutesDialog(QDialog, Ui_PyramidRoutesDialog): """ Class implementing a dialog showing the available routes. """ def __init__(self, project, parent=None): """ Constructor @param project reference to the project object (ProjectPyramid.Project.Project) @param parent reference to the parent widget (QWidget) """ super(PyramidRoutesDialog, self).__init__(parent) self.setupUi(self) self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False) self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True) self.__project = project self.proc = None self.buffer = "" self.show() QCoreApplication.processEvents() def finish(self): """ Public slot called when the process finished or the user pressed the button. """ if self.proc is not None and \ self.proc.state() != QProcess.NotRunning: self.proc.terminate() QTimer.singleShot(2000, self.proc.kill) self.proc.waitForFinished(3000) self.inputGroup.setEnabled(False) self.inputGroup.hide() self.proc = None self.__processBuffer() self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True) self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False) self.buttonBox.button(QDialogButtonBox.Close).setDefault(True) self.buttonBox.button(QDialogButtonBox.Close).setFocus( Qt.OtherFocusReason) def on_buttonBox_clicked(self, button): """ Private slot called by a button of the button box clicked. @param button button that was clicked (QAbstractButton) """ if button == self.buttonBox.button(QDialogButtonBox.Close): self.close() elif button == self.buttonBox.button(QDialogButtonBox.Cancel): self.finish() def __procFinished(self, exitCode, exitStatus): """ Private slot connected to the finished signal. @param exitCode exit code of the process (integer) @param exitStatus exit status of the process (QProcess.ExitStatus) """ self.normal = (exitStatus == QProcess.NormalExit) and (exitCode == 0) self.finish() def __processBuffer(self): """ Private slot to process the output buffer of the proutes command. """ self.routes.clear() if not self.buffer: QTreeWidgetItem(self.routes, [self.tr("No routes found.")]) self.routes.setHeaderHidden(True) else: lines = self.buffer.splitlines() row = 0 headers = [] while row < len(lines): if lines[row].strip().startswith("---"): headerLine = lines[row - 1] headers = headerLine.split() break row += 1 if headers: self.routes.setHeaderLabels(headers) self.routes.setHeaderHidden(False) row += 1 splitCount = len(headers) - 1 while row < len(lines): line = lines[row].strip() parts = line.split(None, splitCount) QTreeWidgetItem(self.routes, parts) row += 1 for column in range(len(headers)): self.routes.resizeColumnToContents(column) def start(self, projectPath): """ Public slot used to start the process. @param projectPath path to the Pyramid project (string) @return flag indicating a successful start of the process """ QTreeWidgetItem(self.routes, [self.tr("Getting routes...")]) self.routes.setHeaderHidden(True) self.errorGroup.hide() self.normal = False self.intercept = False self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False) self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(True) self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True) self.buttonBox.button(QDialogButtonBox.Cancel).setFocus( Qt.OtherFocusReason) self.proc = QProcess() self.proc.finished.connect(self.__procFinished) self.proc.readyReadStandardOutput.connect(self.__readStdout) self.proc.readyReadStandardError.connect(self.__readStderr) cmd = self.__project.getPyramidCommand("proutes") args = [] args.append("development.ini") if projectPath: self.proc.setWorkingDirectory(projectPath) self.proc.start(cmd, args) procStarted = self.proc.waitForStarted() if not procStarted: self.buttonBox.setFocus() self.inputGroup.setEnabled(False) E5MessageBox.critical( self, self.tr('Process Generation Error'), self.tr( 'The process {0} could not be started. ' 'Ensure, that it is in the search path.' ).format(cmd)) else: self.inputGroup.setEnabled(True) self.inputGroup.show() return procStarted def __readStdout(self): """ Private slot to handle the readyReadStandardOutput signal. It reads the output of the process and appends it to a buffer for delayed processing. """ if self.proc is not None: out = str(self.proc.readAllStandardOutput(), Preferences.getSystem("IOEncoding"), 'replace') self.buffer += out def __readStderr(self): """ Private slot to handle the readyReadStandardError signal. It reads the error output of the process and inserts it into the error pane. """ if self.proc is not None: err = str(self.proc.readAllStandardError(), Preferences.getSystem("IOEncoding"), 'replace') self.errorGroup.show() self.errors.insertPlainText(err) self.errors.ensureCursorVisible() QCoreApplication.processEvents() def on_passwordCheckBox_toggled(self, isOn): """ Private slot to handle the password checkbox toggled. @param isOn flag indicating the status of the check box (boolean) """ if isOn: self.input.setEchoMode(QLineEdit.Password) else: self.input.setEchoMode(QLineEdit.Normal) @pyqtSlot() def on_sendButton_clicked(self): """ Private slot to send the input to the subversion process. """ inputTxt = self.input.text() inputTxt += os.linesep if self.passwordCheckBox.isChecked(): self.errors.insertPlainText(os.linesep) self.errors.ensureCursorVisible() self.proc.write(strToQByteArray(inputTxt)) self.passwordCheckBox.setChecked(False) self.input.clear() def on_input_returnPressed(self): """ Private slot to handle the press of the return key in the input field. """ self.intercept = True self.on_sendButton_clicked() def keyPressEvent(self, evt): """ Protected slot to handle a key press event. @param evt the key press event (QKeyEvent) """ if self.intercept: self.intercept = False evt.accept() return super(PyramidRoutesDialog, self).keyPressEvent(evt)