ProjectPyramid/PyramidRoutesDialog.py

changeset 13
227a115ab2a1
child 34
d20f7218d53c
equal deleted inserted replaced
12:a8d87f7de3e1 13:227a115ab2a1
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2012 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a dialog showing the available routes.
8 """
9
10 import os
11
12 from PyQt4.QtCore import QProcess, QTimer, pyqtSlot, Qt, QCoreApplication
13 from PyQt4.QtGui import QDialog, QDialogButtonBox, QLineEdit, QTreeWidgetItem
14
15 from E5Gui import E5MessageBox
16
17 from .Ui_PyramidRoutesDialog import Ui_PyramidRoutesDialog
18
19 import Preferences
20
21
22 class PyramidRoutesDialog(QDialog, Ui_PyramidRoutesDialog):
23 """
24 Class implementing a dialog showing the available routes.
25 """
26 def __init__(self, project, parent=None):
27 """
28 Constructor
29
30 @param project reference to the project object (ProjectPyramid.Project.Project)
31 @param parent reference to the parent widget (QWidget)
32 """
33 super().__init__(parent)
34 self.setupUi(self)
35
36 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False)
37 self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True)
38
39 self.__project = project
40 self.proc = None
41 self.buffer = ""
42
43 self.show()
44 QCoreApplication.processEvents()
45
46 def finish(self):
47 """
48 Public slot called when the process finished or the user pressed the button.
49 """
50 if self.proc is not None and \
51 self.proc.state() != QProcess.NotRunning:
52 self.proc.terminate()
53 QTimer.singleShot(2000, self.proc.kill)
54 self.proc.waitForFinished(3000)
55
56 self.inputGroup.setEnabled(False)
57 self.inputGroup.hide()
58
59 self.proc = None
60
61 self.__processBuffer()
62
63 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True)
64 self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False)
65 self.buttonBox.button(QDialogButtonBox.Close).setDefault(True)
66 self.buttonBox.button(QDialogButtonBox.Close).setFocus(Qt.OtherFocusReason)
67
68 def on_buttonBox_clicked(self, button):
69 """
70 Private slot called by a button of the button box clicked.
71
72 @param button button that was clicked (QAbstractButton)
73 """
74 if button == self.buttonBox.button(QDialogButtonBox.Close):
75 self.close()
76 elif button == self.buttonBox.button(QDialogButtonBox.Cancel):
77 self.finish()
78
79 def __procFinished(self, exitCode, exitStatus):
80 """
81 Private slot connected to the finished signal.
82
83 @param exitCode exit code of the process (integer)
84 @param exitStatus exit status of the process (QProcess.ExitStatus)
85 """
86 self.normal = (exitStatus == QProcess.NormalExit) and (exitCode == 0)
87 self.finish()
88
89 def __processBuffer(self):
90 """
91 Private slot to process the output buffer of the proutes command.
92 """
93 self.routes.clear()
94
95 if not self.buffer:
96 QTreeWidgetItem(self.routes, [self.trUtf8("No routes found.")])
97 self.routes.setHeaderHidden(True)
98 else:
99 lines = self.buffer.splitlines()
100 row = 0
101 headers = []
102 while row < len(lines):
103 if lines[row].strip().startswith("---"):
104 headerLine = lines[row - 1]
105 headers = headerLine.split()
106 break
107 row += 1
108 if headers:
109 self.routes.setHeaderLabels(headers)
110 self.routes.setHeaderHidden(False)
111 row += 1
112 splitCount = len(headers) - 1
113 while row < len(lines):
114 line = lines[row].strip()
115 parts = line.split(None, splitCount)
116 QTreeWidgetItem(self.routes, parts)
117 row += 1
118 for column in range(len(headers)):
119 self.routes.resizeColumnToContents(column)
120
121 def start(self, projectPath):
122 """
123 Public slot used to start the process.
124
125 @param command command to start (string)
126 @param projectPath path to the Pyramid project (string)
127 @return flag indicating a successful start of the process
128 """
129 QTreeWidgetItem(self.routes, [self.trUtf8("Getting routes...")])
130 self.routes.setHeaderHidden(True)
131
132 self.errorGroup.hide()
133 self.normal = False
134 self.intercept = False
135
136 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False)
137 self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(True)
138 self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True)
139 self.buttonBox.button(QDialogButtonBox.Cancel).setFocus(Qt.OtherFocusReason)
140
141 self.proc = QProcess()
142
143 self.proc.finished.connect(self.__procFinished)
144 self.proc.readyReadStandardOutput.connect(self.__readStdout)
145 self.proc.readyReadStandardError.connect(self.__readStderr)
146
147 cmd = self.__project.getPyramidCommand("proutes")
148 args = []
149 args.append("development.ini")
150
151 if projectPath:
152 self.proc.setWorkingDirectory(projectPath)
153 self.proc.start(cmd, args)
154 procStarted = self.proc.waitForStarted()
155 if not procStarted:
156 self.buttonBox.setFocus()
157 self.inputGroup.setEnabled(False)
158 E5MessageBox.critical(self,
159 self.trUtf8('Process Generation Error'),
160 self.trUtf8(
161 'The process {0} could not be started. '
162 'Ensure, that it is in the search path.'
163 ).format(cmd))
164 else:
165 self.inputGroup.setEnabled(True)
166 self.inputGroup.show()
167 return procStarted
168
169 def __readStdout(self):
170 """
171 Private slot to handle the readyReadStandardOutput signal.
172
173 It reads the output of the process and appends it to a buffer for
174 delayed processing.
175 """
176 if self.proc is not None:
177 out = str(self.proc.readAllStandardOutput(),
178 Preferences.getSystem("IOEncoding"),
179 'replace')
180 self.buffer += out
181
182 def __readStderr(self):
183 """
184 Private slot to handle the readyReadStandardError signal.
185
186 It reads the error output of the process and inserts it into the
187 error pane.
188 """
189 if self.proc is not None:
190 err = str(self.proc.readAllStandardError(),
191 Preferences.getSystem("IOEncoding"),
192 'replace')
193 self.errorGroup.show()
194 self.errors.insertPlainText(err)
195 self.errors.ensureCursorVisible()
196
197 QCoreApplication.processEvents()
198
199 def on_passwordCheckBox_toggled(self, isOn):
200 """
201 Private slot to handle the password checkbox toggled.
202
203 @param isOn flag indicating the status of the check box (boolean)
204 """
205 if isOn:
206 self.input.setEchoMode(QLineEdit.Password)
207 else:
208 self.input.setEchoMode(QLineEdit.Normal)
209
210 @pyqtSlot()
211 def on_sendButton_clicked(self):
212 """
213 Private slot to send the input to the subversion process.
214 """
215 input = self.input.text()
216 input += os.linesep
217
218 if self.passwordCheckBox.isChecked():
219 self.errors.insertPlainText(os.linesep)
220 self.errors.ensureCursorVisible()
221
222 self.proc.write(input)
223
224 self.passwordCheckBox.setChecked(False)
225 self.input.clear()
226
227 def on_input_returnPressed(self):
228 """
229 Private slot to handle the press of the return key in the input field.
230 """
231 self.intercept = True
232 self.on_sendButton_clicked()
233
234 def keyPressEvent(self, evt):
235 """
236 Protected slot to handle a key press event.
237
238 @param evt the key press event (QKeyEvent)
239 """
240 if self.intercept:
241 self.intercept = False
242 evt.accept()
243 return
244 super().keyPressEvent(evt)

eric ide

mercurial