eric6/Plugins/VcsPlugins/vcsSubversion/SvnPropListDialog.py

changeset 6942
2602857055c5
parent 6645
ad476851d7e0
child 7192
a22eee00b052
equal deleted inserted replaced
6941:f99d60d6b59b 6942:2602857055c5
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2003 - 2019 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a dialog to show the output of the svn proplist command
8 process.
9 """
10
11 from __future__ import unicode_literals
12 try:
13 str = unicode
14 except NameError:
15 pass
16
17 from PyQt5.QtCore import pyqtSlot, QTimer, QProcess, QProcessEnvironment, \
18 QRegExp, Qt
19 from PyQt5.QtWidgets import QWidget, QHeaderView, QDialogButtonBox, \
20 QTreeWidgetItem
21
22 from E5Gui import E5MessageBox
23
24 from .Ui_SvnPropListDialog import Ui_SvnPropListDialog
25
26 import Preferences
27
28
29 class SvnPropListDialog(QWidget, Ui_SvnPropListDialog):
30 """
31 Class implementing a dialog to show the output of the svn proplist command
32 process.
33 """
34 def __init__(self, vcs, parent=None):
35 """
36 Constructor
37
38 @param vcs reference to the vcs object
39 @param parent parent widget (QWidget)
40 """
41 super(SvnPropListDialog, self).__init__(parent)
42 self.setupUi(self)
43
44 self.refreshButton = \
45 self.buttonBox.addButton(self.tr("Refresh"),
46 QDialogButtonBox.ActionRole)
47 self.refreshButton.setToolTip(
48 self.tr("Press to refresh the properties display"))
49 self.refreshButton.setEnabled(False)
50 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False)
51 self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True)
52
53 self.process = QProcess()
54 env = QProcessEnvironment.systemEnvironment()
55 env.insert("LANG", "C")
56 self.process.setProcessEnvironment(env)
57 self.vcs = vcs
58
59 self.propsList.headerItem().setText(self.propsList.columnCount(), "")
60 self.propsList.header().setSortIndicator(0, Qt.AscendingOrder)
61
62 self.process.finished.connect(self.__procFinished)
63 self.process.readyReadStandardOutput.connect(self.__readStdout)
64 self.process.readyReadStandardError.connect(self.__readStderr)
65
66 self.rx_path = QRegExp(r"Properties on '([^']+)':\s*")
67 self.rx_prop = QRegExp(r" (.*) *: *(.*)[\r\n]")
68
69 def __resort(self):
70 """
71 Private method to resort the tree.
72 """
73 self.propsList.sortItems(
74 self.propsList.sortColumn(),
75 self.propsList.header().sortIndicatorOrder())
76
77 def __resizeColumns(self):
78 """
79 Private method to resize the list columns.
80 """
81 self.propsList.header().resizeSections(QHeaderView.ResizeToContents)
82 self.propsList.header().setStretchLastSection(True)
83
84 def __generateItem(self, path, propName, propValue):
85 """
86 Private method to generate a properties item in the properties list.
87
88 @param path file/directory name the property applies to (string)
89 @param propName name of the property (string)
90 @param propValue value of the property (string)
91 """
92 QTreeWidgetItem(self.propsList, [path, propName, propValue.strip()])
93
94 def closeEvent(self, e):
95 """
96 Protected slot implementing a close event handler.
97
98 @param e close event (QCloseEvent)
99 """
100 if self.process is not None and \
101 self.process.state() != QProcess.NotRunning:
102 self.process.terminate()
103 QTimer.singleShot(2000, self.process.kill)
104 self.process.waitForFinished(3000)
105
106 e.accept()
107
108 def start(self, fn, recursive=False):
109 """
110 Public slot to start the svn status command.
111
112 @param fn filename(s) (string or list of string)
113 @param recursive flag indicating a recursive list is requested
114 """
115 self.errorGroup.hide()
116
117 self.propsList.clear()
118 self.lastPath = None
119 self.lastProp = None
120 self.propBuffer = ""
121
122 self.__args = fn
123 self.__recursive = recursive
124
125 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False)
126 self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(True)
127 self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True)
128 self.refreshButton.setEnabled(False)
129
130 self.process.kill()
131
132 args = []
133 args.append('proplist')
134 self.vcs.addArguments(args, self.vcs.options['global'])
135 args.append('--verbose')
136 if recursive:
137 args.append('--recursive')
138 if isinstance(fn, list):
139 dname, fnames = self.vcs.splitPathList(fn)
140 self.vcs.addArguments(args, fnames)
141 else:
142 dname, fname = self.vcs.splitPath(fn)
143 args.append(fname)
144
145 self.process.setWorkingDirectory(dname)
146
147 self.process.start('svn', args)
148 procStarted = self.process.waitForStarted(5000)
149 if not procStarted:
150 E5MessageBox.critical(
151 self,
152 self.tr('Process Generation Error'),
153 self.tr(
154 'The process {0} could not be started. '
155 'Ensure, that it is in the search path.'
156 ).format('svn'))
157
158 def __finish(self):
159 """
160 Private slot called when the process finished or the user pressed the
161 button.
162 """
163 if self.process is not None and \
164 self.process.state() != QProcess.NotRunning:
165 self.process.terminate()
166 QTimer.singleShot(2000, self.process.kill)
167 self.process.waitForFinished(3000)
168
169 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True)
170 self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False)
171 self.buttonBox.button(QDialogButtonBox.Close).setDefault(True)
172
173 self.refreshButton.setEnabled(True)
174
175 if self.lastProp:
176 self.__generateItem(self.lastPath, self.lastProp, self.propBuffer)
177
178 self.__resort()
179 self.__resizeColumns()
180
181 def on_buttonBox_clicked(self, button):
182 """
183 Private slot called by a button of the button box clicked.
184
185 @param button button that was clicked (QAbstractButton)
186 """
187 if button == self.buttonBox.button(QDialogButtonBox.Close):
188 self.close()
189 elif button == self.buttonBox.button(QDialogButtonBox.Cancel):
190 self.__finish()
191 elif button == self.refreshButton:
192 self.on_refreshButton_clicked()
193
194 @pyqtSlot()
195 def on_refreshButton_clicked(self):
196 """
197 Private slot to refresh the status display.
198 """
199 self.start(self.__args, recursive=self.__recursive)
200
201 def __procFinished(self, exitCode, exitStatus):
202 """
203 Private slot connected to the finished signal.
204
205 @param exitCode exit code of the process (integer)
206 @param exitStatus exit status of the process (QProcess.ExitStatus)
207 """
208 if self.lastPath is None:
209 self.__generateItem('', 'None', '')
210
211 self.__finish()
212
213 def __readStdout(self):
214 """
215 Private slot to handle the readyReadStandardOutput signal.
216
217 It reads the output of the process, formats it and inserts it into
218 the contents pane.
219 """
220 self.process.setReadChannel(QProcess.StandardOutput)
221
222 while self.process.canReadLine():
223 s = str(self.process.readLine(),
224 Preferences.getSystem("IOEncoding"),
225 'replace')
226 if self.rx_path.exactMatch(s):
227 if self.lastProp:
228 self.__generateItem(
229 self.lastPath, self.lastProp, self.propBuffer)
230 self.lastPath = self.rx_path.cap(1)
231 self.lastProp = None
232 self.propBuffer = ""
233 elif self.rx_prop.exactMatch(s):
234 if self.lastProp:
235 self.__generateItem(
236 self.lastPath, self.lastProp, self.propBuffer)
237 self.lastProp = self.rx_prop.cap(1)
238 self.propBuffer = self.rx_prop.cap(2)
239 else:
240 self.propBuffer += ' '
241 self.propBuffer += s
242
243 def __readStderr(self):
244 """
245 Private slot to handle the readyReadStandardError signal.
246
247 It reads the error output of the process and inserts it into the
248 error pane.
249 """
250 if self.process is not None:
251 self.errorGroup.show()
252 s = str(self.process.readAllStandardError(),
253 Preferences.getSystem("IOEncoding"),
254 'replace')
255 self.errors.insertPlainText(s)
256 self.errors.ensureCursorVisible()

eric ide

mercurial