Plugins/VcsPlugins/vcsSubversion/SvnLogBrowserDialog.py

changeset 945
8cd4d08fa9f6
parent 791
9ec2ac20e54e
child 1080
dfd96566f584
equal deleted inserted replaced
944:1b59c4ba121e 945:8cd4d08fa9f6
19 from .Ui_SvnLogBrowserDialog import Ui_SvnLogBrowserDialog 19 from .Ui_SvnLogBrowserDialog import Ui_SvnLogBrowserDialog
20 20
21 import UI.PixmapCache 21 import UI.PixmapCache
22 22
23 import Preferences 23 import Preferences
24
24 25
25 class SvnLogBrowserDialog(QDialog, Ui_SvnLogBrowserDialog): 26 class SvnLogBrowserDialog(QDialog, Ui_SvnLogBrowserDialog):
26 """ 27 """
27 Class implementing a dialog to browse the log history. 28 Class implementing a dialog to browse the log history.
28 """ 29 """
29 def __init__(self, vcs, parent = None): 30 def __init__(self, vcs, parent=None):
30 """ 31 """
31 Constructor 32 Constructor
32 33
33 @param vcs reference to the vcs object 34 @param vcs reference to the vcs object
34 @param parent parent widget (QWidget) 35 @param parent parent widget (QWidget)
80 # path copied from followed by copied from revision 81 # path copied from followed by copied from revision
81 self.rx_flags2 = QRegExp(' ([ADM]) (.*)\\s*') 82 self.rx_flags2 = QRegExp(' ([ADM]) (.*)\\s*')
82 # three blanks followed by A or D or M followed by path 83 # three blanks followed by A or D or M followed by path
83 84
84 self.flags = { 85 self.flags = {
85 'A' : self.trUtf8('Added'), 86 'A': self.trUtf8('Added'),
86 'D' : self.trUtf8('Deleted'), 87 'D': self.trUtf8('Deleted'),
87 'M' : self.trUtf8('Modified'), 88 'M': self.trUtf8('Modified'),
88 } 89 }
89 90
90 self.buf = [] # buffer for stdout 91 self.buf = [] # buffer for stdout
91 self.diff = None 92 self.diff = None
92 self.__started = False 93 self.__started = False
115 116
116 def __resortLog(self): 117 def __resortLog(self):
117 """ 118 """
118 Private method to resort the log tree. 119 Private method to resort the log tree.
119 """ 120 """
120 self.logTree.sortItems(self.logTree.sortColumn(), 121 self.logTree.sortItems(self.logTree.sortColumn(),
121 self.logTree.header().sortIndicatorOrder()) 122 self.logTree.header().sortIndicatorOrder())
122 123
123 def __resizeColumnsFiles(self): 124 def __resizeColumnsFiles(self):
124 """ 125 """
125 Private method to resize the changed files tree columns. 126 Private method to resize the changed files tree columns.
130 def __resortFiles(self): 131 def __resortFiles(self):
131 """ 132 """
132 Private method to resort the changed files tree. 133 Private method to resort the changed files tree.
133 """ 134 """
134 sortColumn = self.filesTree.sortColumn() 135 sortColumn = self.filesTree.sortColumn()
135 self.filesTree.sortItems(1, 136 self.filesTree.sortItems(1,
136 self.filesTree.header().sortIndicatorOrder()) 137 self.filesTree.header().sortIndicatorOrder())
137 self.filesTree.sortItems(sortColumn, 138 self.filesTree.sortItems(sortColumn,
138 self.filesTree.header().sortIndicatorOrder()) 139 self.filesTree.header().sortIndicatorOrder())
139 140
140 def __generateLogItem(self, author, date, message, revision, changedPaths): 141 def __generateLogItem(self, author, date, message, revision, changedPaths):
141 """ 142 """
142 Private method to generate a log tree entry. 143 Private method to generate a log tree entry.
144 @param author author info (string) 145 @param author author info (string)
145 @param date date info (string) 146 @param date date info (string)
146 @param message text of the log message (list of strings) 147 @param message text of the log message (list of strings)
147 @param revision revision info (string) 148 @param revision revision info (string)
148 @param changedPaths list of dictionary objects containing 149 @param changedPaths list of dictionary objects containing
149 info about the changed files/directories 150 info about the changed files/directories
150 @return reference to the generated item (QTreeWidgetItem) 151 @return reference to the generated item (QTreeWidgetItem)
151 """ 152 """
152 msg = [] 153 msg = []
153 for line in message: 154 for line in message:
154 msg.append(line.strip()) 155 msg.append(line.strip())
155 156
156 itm = QTreeWidgetItem(self.logTree, [ 157 itm = QTreeWidgetItem(self.logTree, [
157 "{0:7}".format(revision), 158 "{0:7}".format(revision),
158 author, 159 author,
159 date, 160 date,
160 " ".join(msg), 161 " ".join(msg),
161 ]) 162 ])
162 163
163 itm.setData(0, self.__messageRole, message) 164 itm.setData(0, self.__messageRole, message)
164 itm.setData(0, self.__changesRole, changedPaths) 165 itm.setData(0, self.__changesRole, changedPaths)
165 166
185 @param copyFrom path the file was copied from (None, string) 186 @param copyFrom path the file was copied from (None, string)
186 @param copyRev revision the file was copied from (None, string) 187 @param copyRev revision the file was copied from (None, string)
187 @return reference to the generated item (QTreeWidgetItem) 188 @return reference to the generated item (QTreeWidgetItem)
188 """ 189 """
189 itm = QTreeWidgetItem(self.filesTree, [ 190 itm = QTreeWidgetItem(self.filesTree, [
190 self.flags[action], 191 self.flags[action],
191 path, 192 path,
192 copyFrom, 193 copyFrom,
193 copyRev, 194 copyRev,
194 ]) 195 ])
195 196
196 itm.setTextAlignment(3, Qt.AlignRight) 197 itm.setTextAlignment(3, Qt.AlignRight)
197 198
198 return itm 199 return itm
199 200
200 def __getLogEntries(self, startRev = None): 201 def __getLogEntries(self, startRev=None):
201 """ 202 """
202 Private method to retrieve log entries from the repository. 203 Private method to retrieve log entries from the repository.
203 204
204 @param startRev revision number to start from (integer, string) 205 @param startRev revision number to start from (integer, string)
205 """ 206 """
297 Private method to process the buffered output of the svn log command. 298 Private method to process the buffered output of the svn log command.
298 """ 299 """
299 ioEncoding = Preferences.getSystem("IOEncoding") 300 ioEncoding = Preferences.getSystem("IOEncoding")
300 301
301 noEntries = 0 302 noEntries = 0
302 log = {"message" : []} 303 log = {"message": []}
303 changedPaths = [] 304 changedPaths = []
304 for s in self.buf: 305 for s in self.buf:
305 if self.rx_rev1.exactMatch(s): 306 if self.rx_rev1.exactMatch(s):
306 log["revision"] = self.rx_rev.cap(1) 307 log["revision"] = self.rx_rev.cap(1)
307 log["author"] = self.rx_rev.cap(2) 308 log["author"] = self.rx_rev.cap(2)
308 log["date"] = self.rx_rev.cap(3) 309 log["date"] = self.rx_rev.cap(3)
309 # number of lines is ignored 310 # number of lines is ignored
310 elif self.rx_rev2.exactMatch(s): 311 elif self.rx_rev2.exactMatch(s):
311 log["revision"] = self.rx_rev2.cap(1) 312 log["revision"] = self.rx_rev2.cap(1)
312 log["author"] = self.rx_rev2.cap(2) 313 log["author"] = self.rx_rev2.cap(2)
313 log["date"] = self.rx_rev2.cap(3) 314 log["date"] = self.rx_rev2.cap(3)
314 # number of lines is ignored 315 # number of lines is ignored
315 elif self.rx_flags1.exactMatch(s): 316 elif self.rx_flags1.exactMatch(s):
316 changedPaths.append({\ 317 changedPaths.append({\
317 "action" : 318 "action":
318 str(self.rx_flags1.cap(1).strip(), ioEncoding, 'replace'), 319 str(self.rx_flags1.cap(1).strip(), ioEncoding, 'replace'),
319 "path" : 320 "path":
320 str(self.rx_flags1.cap(2).strip(), ioEncoding, 'replace'), 321 str(self.rx_flags1.cap(2).strip(), ioEncoding, 'replace'),
321 "copyfrom_path" : 322 "copyfrom_path":
322 str(self.rx_flags1.cap(3).strip(), ioEncoding, 'replace'), 323 str(self.rx_flags1.cap(3).strip(), ioEncoding, 'replace'),
323 "copyfrom_revision" : 324 "copyfrom_revision":
324 str(self.rx_flags1.cap(4).strip(), ioEncoding, 'replace'), 325 str(self.rx_flags1.cap(4).strip(), ioEncoding, 'replace'),
325 }) 326 })
326 elif self.rx_flags2.exactMatch(s): 327 elif self.rx_flags2.exactMatch(s):
327 changedPaths.append({\ 328 changedPaths.append({\
328 "action" : 329 "action":
329 str(self.rx_flags2.cap(1).strip(), ioEncoding, 'replace'), 330 str(self.rx_flags2.cap(1).strip(), ioEncoding, 'replace'),
330 "path" : 331 "path":
331 str(self.rx_flags2.cap(2).strip(), ioEncoding, 'replace'), 332 str(self.rx_flags2.cap(2).strip(), ioEncoding, 'replace'),
332 "copyfrom_path" : "", 333 "copyfrom_path": "",
333 "copyfrom_revision" : "", 334 "copyfrom_revision": "",
334 }) 335 })
335 elif self.rx_sep1.exactMatch(s) or self.rx_sep2.exactMatch(s): 336 elif self.rx_sep1.exactMatch(s) or self.rx_sep2.exactMatch(s):
336 if len(log) > 1: 337 if len(log) > 1:
337 self.__generateLogItem(log["author"], log["date"], 338 self.__generateLogItem(log["author"], log["date"],
338 log["message"], log["revision"], changedPaths) 339 log["message"], log["revision"], changedPaths)
339 dt = QDate.fromString(log["date"], Qt.ISODate) 340 dt = QDate.fromString(log["date"], Qt.ISODate)
340 if not self.__maxDate.isValid() and not self.__minDate.isValid(): 341 if not self.__maxDate.isValid() and not self.__minDate.isValid():
341 self.__maxDate = dt 342 self.__maxDate = dt
342 self.__minDate = dt 343 self.__minDate = dt
344 if self.__maxDate < dt: 345 if self.__maxDate < dt:
345 self.__maxDate = dt 346 self.__maxDate = dt
346 if self.__minDate > dt: 347 if self.__minDate > dt:
347 self.__minDate = dt 348 self.__minDate = dt
348 noEntries += 1 349 noEntries += 1
349 log = {"message" : []} 350 log = {"message": []}
350 changedPaths = [] 351 changedPaths = []
351 else: 352 else:
352 if s.strip().endswith(":") or not s.strip(): 353 if s.strip().endswith(":") or not s.strip():
353 continue 354 continue
354 else: 355 else:
376 self.__filterLogsEnabled = True 377 self.__filterLogsEnabled = True
377 self.__filterLogs() 378 self.__filterLogs()
378 379
379 def __readStdout(self): 380 def __readStdout(self):
380 """ 381 """
381 Private slot to handle the readyReadStandardOutput signal. 382 Private slot to handle the readyReadStandardOutput signal.
382 383
383 It reads the output of the process and inserts it into a buffer. 384 It reads the output of the process and inserts it into a buffer.
384 """ 385 """
385 self.process.setReadChannel(QProcess.StandardOutput) 386 self.process.setReadChannel(QProcess.StandardOutput)
386 387
387 while self.process.canReadLine(): 388 while self.process.canReadLine():
388 line = str(self.process.readLine(), 389 line = str(self.process.readLine(),
389 Preferences.getSystem("IOEncoding"), 390 Preferences.getSystem("IOEncoding"),
390 'replace') 391 'replace')
391 self.buf.append(line) 392 self.buf.append(line)
392 393
393 def __readStderr(self): 394 def __readStderr(self):
394 """ 395 """
397 It reads the error output of the process and inserts it into the 398 It reads the error output of the process and inserts it into the
398 error pane. 399 error pane.
399 """ 400 """
400 if self.process is not None: 401 if self.process is not None:
401 self.errorGroup.show() 402 self.errorGroup.show()
402 s = str(self.process.readAllStandardError(), 403 s = str(self.process.readAllStandardError(),
403 Preferences.getSystem("IOEncoding"), 404 Preferences.getSystem("IOEncoding"),
404 'replace') 405 'replace')
405 self.errors.insertPlainText(s) 406 self.errors.insertPlainText(s)
406 self.errors.ensureCursorVisible() 407 self.errors.ensureCursorVisible()
407 408
408 def __diffRevisions(self, rev1, rev2): 409 def __diffRevisions(self, rev1, rev2):
445 446
446 self.filesTree.clear() 447 self.filesTree.clear()
447 changes = current.data(0, self.__changesRole) 448 changes = current.data(0, self.__changesRole)
448 if len(changes) > 0: 449 if len(changes) > 0:
449 for change in changes: 450 for change in changes:
450 self.__generateFileItem(change["action"], change["path"], 451 self.__generateFileItem(change["action"], change["path"],
451 change["copyfrom_path"], change["copyfrom_revision"]) 452 change["copyfrom_path"], change["copyfrom_revision"])
452 self.__resizeColumnsFiles() 453 self.__resizeColumnsFiles()
453 self.__resortFiles() 454 self.__resortFiles()
454 455
455 self.diffPreviousButton.setEnabled( 456 self.diffPreviousButton.setEnabled(
586 @pyqtSlot(bool) 587 @pyqtSlot(bool)
587 def on_stopCheckBox_clicked(self, checked): 588 def on_stopCheckBox_clicked(self, checked):
588 """ 589 """
589 Private slot called, when the stop on copy/move checkbox is clicked 590 Private slot called, when the stop on copy/move checkbox is clicked
590 """ 591 """
591 self.vcs.getPlugin().setPreferences("StopLogOnCopy", 592 self.vcs.getPlugin().setPreferences("StopLogOnCopy",
592 self.stopCheckBox.isChecked()) 593 self.stopCheckBox.isChecked())
593 self.nextButton.setEnabled(True) 594 self.nextButton.setEnabled(True)
594 self.limitSpinBox.setEnabled(True) 595 self.limitSpinBox.setEnabled(True)
595 596
596 def on_passwordCheckBox_toggled(self, isOn): 597 def on_passwordCheckBox_toggled(self, isOn):

eric ide

mercurial