eric6/Plugins/VcsPlugins/vcsMercurial/HgStatusDialog.py

changeset 7370
5fb53279f2df
parent 7360
9190402e4505
child 7533
88261c96484b
equal deleted inserted replaced
7369:dbeeed55df08 7370:5fb53279f2df
6 """ 6 """
7 Module implementing a dialog to show the output of the hg status command 7 Module implementing a dialog to show the output of the hg status command
8 process. 8 process.
9 """ 9 """
10 10
11
12 import os 11 import os
13 12
14 from PyQt5.QtCore import pyqtSlot, Qt, QProcess, QTimer, QSize 13 from PyQt5.QtCore import pyqtSlot, Qt, QSize
15 from PyQt5.QtGui import QTextCursor 14 from PyQt5.QtGui import QTextCursor
16 from PyQt5.QtWidgets import ( 15 from PyQt5.QtWidgets import (
17 QWidget, QDialogButtonBox, QMenu, QHeaderView, QTreeWidgetItem, QLineEdit 16 QWidget, QDialogButtonBox, QMenu, QHeaderView, QTreeWidgetItem
18 ) 17 )
19 18
20 from E5Gui.E5Application import e5App 19 from E5Gui.E5Application import e5App
21 from E5Gui import E5MessageBox 20 from E5Gui import E5MessageBox
22 21
25 from .HgDiffHighlighter import HgDiffHighlighter 24 from .HgDiffHighlighter import HgDiffHighlighter
26 from .HgDiffGenerator import HgDiffGenerator 25 from .HgDiffGenerator import HgDiffGenerator
27 26
28 import Preferences 27 import Preferences
29 import UI.PixmapCache 28 import UI.PixmapCache
30 from Globals import strToQByteArray
31 29
32 30
33 class HgStatusDialog(QWidget, Ui_HgStatusDialog): 31 class HgStatusDialog(QWidget, Ui_HgStatusDialog):
34 """ 32 """
35 Class implementing a dialog to show the output of the hg status command 33 Class implementing a dialog to show the output of the hg status command
62 self.diff = None 60 self.diff = None
63 self.vcs = vcs 61 self.vcs = vcs
64 self.vcs.committed.connect(self.__committed) 62 self.vcs.committed.connect(self.__committed)
65 self.__hgClient = self.vcs.getClient() 63 self.__hgClient = self.vcs.getClient()
66 self.__mq = mq 64 self.__mq = mq
67 if self.__hgClient:
68 self.process = None
69 else:
70 self.process = QProcess()
71 self.process.finished.connect(self.__procFinished)
72 self.process.readyReadStandardOutput.connect(self.__readStdout)
73 self.process.readyReadStandardError.connect(self.__readStderr)
74 65
75 self.statusList.headerItem().setText(self.__lastColumn, "") 66 self.statusList.headerItem().setText(self.__lastColumn, "")
76 self.statusList.header().setSortIndicator( 67 self.statusList.header().setSortIndicator(
77 self.__pathColumn, Qt.AscendingOrder) 68 self.__pathColumn, Qt.AscendingOrder)
78 69
210 """ 201 """
211 Protected slot implementing a close event handler. 202 Protected slot implementing a close event handler.
212 203
213 @param e close event (QCloseEvent) 204 @param e close event (QCloseEvent)
214 """ 205 """
215 if self.__hgClient: 206 if self.__hgClient.isExecuting():
216 if self.__hgClient.isExecuting(): 207 self.__hgClient.cancel()
217 self.__hgClient.cancel()
218 else:
219 if (
220 self.process is not None and
221 self.process.state() != QProcess.NotRunning
222 ):
223 self.process.terminate()
224 QTimer.singleShot(2000, self.process.kill)
225 self.process.waitForFinished(3000)
226 208
227 if self.__mq: 209 if self.__mq:
228 self.vcs.getPlugin().setPreferences( 210 self.vcs.getPlugin().setPreferences(
229 "MqStatusDialogGeometry", self.saveGeometry()) 211 "MqStatusDialogGeometry", self.saveGeometry())
230 self.vcs.getPlugin().setPreferences( 212 self.vcs.getPlugin().setPreferences(
351 while not os.path.isdir(os.path.join(repodir, self.vcs.adminDir)): 333 while not os.path.isdir(os.path.join(repodir, self.vcs.adminDir)):
352 repodir = os.path.dirname(repodir) 334 repodir = os.path.dirname(repodir)
353 if os.path.splitdrive(repodir)[1] == os.sep: 335 if os.path.splitdrive(repodir)[1] == os.sep:
354 return 336 return
355 337
356 if self.__hgClient: 338 self.refreshButton.setEnabled(False)
357 self.inputGroup.setEnabled(False) 339
358 self.inputGroup.hide() 340 out, err = self.__hgClient.runcommand(args)
359 self.refreshButton.setEnabled(False) 341 if err:
360 342 self.__showError(err)
361 out, err = self.__hgClient.runcommand(args) 343 if out:
362 if err: 344 for line in out.splitlines():
363 self.__showError(err) 345 self.__processOutputLine(line)
364 if out: 346 if self.__hgClient.wasCanceled():
365 for line in out.splitlines(): 347 break
366 self.__processOutputLine(line) 348 self.__finish()
367 if self.__hgClient.wasCanceled():
368 break
369 self.__finish()
370 else:
371 if self.process:
372 self.process.kill()
373
374 self.process.setWorkingDirectory(repodir)
375
376 self.process.start('hg', args)
377 procStarted = self.process.waitForStarted(5000)
378 if not procStarted:
379 self.inputGroup.setEnabled(False)
380 self.inputGroup.hide()
381 E5MessageBox.critical(
382 self,
383 self.tr('Process Generation Error'),
384 self.tr(
385 'The process {0} could not be started. '
386 'Ensure, that it is in the search path.'
387 ).format('hg'))
388 else:
389 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False)
390 self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(True)
391 self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True)
392
393 self.refreshButton.setEnabled(False)
394 349
395 def __finish(self): 350 def __finish(self):
396 """ 351 """
397 Private slot called when the process finished or the user pressed 352 Private slot called when the process finished or the user pressed
398 the button. 353 the button.
399 """ 354 """
400 if (
401 self.process is not None and
402 self.process.state() != QProcess.NotRunning
403 ):
404 self.process.terminate()
405 QTimer.singleShot(2000, self.process.kill)
406 self.process.waitForFinished(3000)
407
408 self.inputGroup.setEnabled(False)
409 self.inputGroup.hide()
410 self.refreshButton.setEnabled(True) 355 self.refreshButton.setEnabled(True)
411 356
412 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True) 357 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True)
413 self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False) 358 self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False)
414 self.buttonBox.button(QDialogButtonBox.Close).setDefault(True) 359 self.buttonBox.button(QDialogButtonBox.Close).setDefault(True)
434 @param button button that was clicked (QAbstractButton) 379 @param button button that was clicked (QAbstractButton)
435 """ 380 """
436 if button == self.buttonBox.button(QDialogButtonBox.Close): 381 if button == self.buttonBox.button(QDialogButtonBox.Close):
437 self.close() 382 self.close()
438 elif button == self.buttonBox.button(QDialogButtonBox.Cancel): 383 elif button == self.buttonBox.button(QDialogButtonBox.Cancel):
439 if self.__hgClient: 384 self.__hgClient.cancel()
440 self.__hgClient.cancel()
441 else:
442 self.__finish()
443 elif button == self.refreshButton: 385 elif button == self.refreshButton:
444 self.on_refreshButton_clicked() 386 self.on_refreshButton_clicked()
445
446 def __procFinished(self, exitCode, exitStatus):
447 """
448 Private slot connected to the finished signal.
449
450 @param exitCode exit code of the process (integer)
451 @param exitStatus exit status of the process (QProcess.ExitStatus)
452 """
453 self.__finish()
454
455 def __readStdout(self):
456 """
457 Private slot to handle the readyReadStandardOutput signal.
458
459 It reads the output of the process, formats it and inserts it into
460 the contents pane.
461 """
462 if self.process is not None:
463 self.process.setReadChannel(QProcess.StandardOutput)
464
465 while self.process.canReadLine():
466 line = str(self.process.readLine(), self.vcs.getEncoding(),
467 'replace')
468 self.__processOutputLine(line)
469 387
470 def __processOutputLine(self, line): 388 def __processOutputLine(self, line):
471 """ 389 """
472 Private method to process the lines of output. 390 Private method to process the lines of output.
473 391
475 """ 393 """
476 if line[0] in "ACIMR?!" and line[1] == " ": 394 if line[0] in "ACIMR?!" and line[1] == " ":
477 status, path = line.strip().split(" ", 1) 395 status, path = line.strip().split(" ", 1)
478 self.__generateItem(status, path) 396 self.__generateItem(status, path)
479 397
480 def __readStderr(self):
481 """
482 Private slot to handle the readyReadStandardError signal.
483
484 It reads the error output of the process and inserts it into the
485 error pane.
486 """
487 if self.process is not None:
488 s = str(self.process.readAllStandardError(),
489 self.vcs.getEncoding(), 'replace')
490 self.__showError(s)
491
492 def __showError(self, out): 398 def __showError(self, out):
493 """ 399 """
494 Private slot to show some error. 400 Private slot to show some error.
495 401
496 @param out error to be shown (string) 402 @param out error to be shown (string)
497 """ 403 """
498 self.errorGroup.show() 404 self.errorGroup.show()
499 self.errors.insertPlainText(out) 405 self.errors.insertPlainText(out)
500 self.errors.ensureCursorVisible() 406 self.errors.ensureCursorVisible()
501
502 if not self.__hgClient:
503 # show input in case the process asked for some input
504 self.inputGroup.setEnabled(True)
505 self.inputGroup.show()
506
507 def on_passwordCheckBox_toggled(self, isOn):
508 """
509 Private slot to handle the password checkbox toggled.
510
511 @param isOn flag indicating the status of the check box (boolean)
512 """
513 if isOn:
514 self.input.setEchoMode(QLineEdit.Password)
515 else:
516 self.input.setEchoMode(QLineEdit.Normal)
517
518 @pyqtSlot()
519 def on_sendButton_clicked(self):
520 """
521 Private slot to send the input to the subversion process.
522 """
523 inputTxt = self.input.text()
524 inputTxt += os.linesep
525
526 if self.passwordCheckBox.isChecked():
527 self.errors.insertPlainText(os.linesep)
528 self.errors.ensureCursorVisible()
529 else:
530 self.errors.insertPlainText(inputTxt)
531 self.errors.ensureCursorVisible()
532
533 self.process.write(strToQByteArray(inputTxt))
534
535 self.passwordCheckBox.setChecked(False)
536 self.input.clear()
537
538 def on_input_returnPressed(self):
539 """
540 Private slot to handle the press of the return key in the input field.
541 """
542 self.intercept = True
543 self.on_sendButton_clicked()
544
545 def keyPressEvent(self, evt):
546 """
547 Protected slot to handle a key press event.
548
549 @param evt the key press event (QKeyEvent)
550 """
551 if self.intercept:
552 self.intercept = False
553 evt.accept()
554 return
555 super(HgStatusDialog, self).keyPressEvent(evt)
556 407
557 @pyqtSlot() 408 @pyqtSlot()
558 def on_refreshButton_clicked(self): 409 def on_refreshButton_clicked(self):
559 """ 410 """
560 Private slot to refresh the status display. 411 Private slot to refresh the status display.

eric ide

mercurial