Plugins/VcsPlugins/vcsMercurial/HgDiffDialog.py

changeset 4130
c5af9f10a061
parent 4111
82e21ab01491
child 4152
d90464d2ccaa
--- a/Plugins/VcsPlugins/vcsMercurial/HgDiffDialog.py	Tue Feb 24 18:31:14 2015 +0100
+++ b/Plugins/VcsPlugins/vcsMercurial/HgDiffDialog.py	Tue Feb 24 18:55:07 2015 +0100
@@ -13,17 +13,16 @@
 except NameError:
     pass
 
-import os
-
-from PyQt5.QtCore import pyqtSlot, QProcess, QTimer, QFileInfo, Qt
+from PyQt5.QtCore import pyqtSlot, QFileInfo, Qt
 from PyQt5.QtGui import QTextCursor, QCursor
-from PyQt5.QtWidgets import QWidget, QDialogButtonBox, QLineEdit, QApplication
+from PyQt5.QtWidgets import QWidget, QDialogButtonBox, QApplication
 
 from E5Gui import E5MessageBox, E5FileDialog
 from E5Gui.E5Application import e5App
 
 from .Ui_HgDiffDialog import Ui_HgDiffDialog
 from .HgDiffHighlighter import HgDiffHighlighter
+from .HgDiffGenerator import HgDiffGenerator
 
 import Utilities
 import Preferences
@@ -54,19 +53,14 @@
         
         self.searchWidget.attachTextEdit(self.contents)
         
-        self.process = QProcess()
-        self.vcs = vcs
-        self.__hgClient = self.vcs.getClient()
-        
         font = Preferences.getEditorOtherFonts("MonospacedFont")
         self.contents.setFontFamily(font.family())
         self.contents.setFontPointSize(font.pointSize())
         
         self.highlighter = HgDiffHighlighter(self.contents.document())
         
-        self.process.finished.connect(self.__procFinished)
-        self.process.readyReadStandardOutput.connect(self.__readStdout)
-        self.process.readyReadStandardError.connect(self.__readStderr)
+        self.__diffGenerator = HgDiffGenerator(vcs, self)
+        self.__diffGenerator.finished.connect(self.__generatorFinished)
     
     def closeEvent(self, e):
         """
@@ -74,30 +68,9 @@
         
         @param e close event (QCloseEvent)
         """
-        if self.__hgClient:
-            if self.__hgClient.isExecuting():
-                self.__hgClient.cancel()
-        else:
-            if self.process is not None and \
-               self.process.state() != QProcess.NotRunning:
-                self.process.terminate()
-                QTimer.singleShot(2000, self.process.kill)
-                self.process.waitForFinished(3000)
-        
+        self.__diffGenerator.stopProcess()
         e.accept()
     
-    def __getVersionArg(self, version):
-        """
-        Private method to get a hg revision argument for the given revision.
-        
-        @param version revision (integer or string)
-        @return version argument (string)
-        """
-        if version == "WORKING":
-            return None
-        else:
-            return str(version)
-    
     def start(self, fn, versions=None, bundle=None, qdiff=False,
               refreshable=False):
         """
@@ -113,126 +86,50 @@
         self.refreshButton.setVisible(refreshable)
         
         self.errorGroup.hide()
-        self.inputGroup.show()
-        self.inputGroup.setEnabled(True)
-        self.intercept = False
         self.filename = fn
         
         self.contents.clear()
-        self.paras = 0
-        
         self.filesCombo.clear()
         
         if qdiff:
-            args = self.vcs.initCommand("qdiff")
             self.setWindowTitle(self.tr("Patch Contents"))
-        else:
-            args = self.vcs.initCommand("diff")
-            
-            if self.vcs.hasSubrepositories():
-                args.append("--subrepos")
-            
-            if bundle:
-                args.append('--repository')
-                args.append(bundle)
-            elif self.vcs.bundleFile and os.path.exists(self.vcs.bundleFile):
-                args.append('--repository')
-                args.append(self.vcs.bundleFile)
-            
-            if versions is not None:
-                self.raise_()
-                self.activateWindow()
-                
-                rev1 = self.__getVersionArg(versions[0])
-                rev2 = None
-                if len(versions) == 2:
-                    rev2 = self.__getVersionArg(versions[1])
-                
-                if rev1 is not None or rev2 is not None:
-                    args.append('-r')
-                    if rev1 is not None and rev2 is not None:
-                        args.append('{0}:{1}'.format(rev1, rev2))
-                    elif rev2 is None:
-                        args.append(rev1)
-                    elif rev1 is None:
-                        args.append(':{0}'.format(rev2))
         
-        if isinstance(fn, list):
-            dname, fnames = self.vcs.splitPathList(fn)
-            self.vcs.addArguments(args, fn)
-        else:
-            dname, fname = self.vcs.splitPath(fn)
-            args.append(fn)
-        
-        self.__oldFile = ""
-        self.__oldFileLine = -1
-        self.__fileSeparators = []
+        self.raise_()
+        self.activateWindow()
         
         QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
-        if self.__hgClient:
-            self.inputGroup.setEnabled(False)
-            self.inputGroup.hide()
-            
-            out, err = self.__hgClient.runcommand(args)
-            
-            if err:
-                self.__showError(err)
-            if out:
-                for line in out.splitlines(True):
-                    self.__processOutputLine(line)
-                    if self.__hgClient.wasCanceled():
-                        break
-            
-            self.__finish()
-        else:
-            # find the root of the repo
-            repodir = dname
-            while not os.path.isdir(os.path.join(repodir, self.vcs.adminDir)):
-                repodir = os.path.dirname(repodir)
-                if os.path.splitdrive(repodir)[1] == os.sep:
-                    return
-            
-            self.process.kill()
-            
-            self.process.setWorkingDirectory(repodir)
-            
-            self.process.start('hg', args)
-            procStarted = self.process.waitForStarted(5000)
-            if not procStarted:
-                QApplication.restoreOverrideCursor()
-                self.inputGroup.setEnabled(False)
-                self.inputGroup.hide()
-                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('hg'))
+        procStarted = self.__diffGenerator.start(
+            fn, versions=versions, bundle=bundle, qdiff=qdiff)
+        if not procStarted:
+            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('hg'))
     
-    def __procFinished(self, exitCode, exitStatus):
+    def __generatorFinished(self):
         """
         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.__finish()
-    
-    def __finish(self):
-        """
-        Private slot called when the process finished or the user pressed
-        the button.
         """
         QApplication.restoreOverrideCursor()
-        self.inputGroup.setEnabled(False)
-        self.inputGroup.hide()
         self.refreshButton.setEnabled(True)
         
-        if self.paras == 0:
-            self.contents.setPlainText(self.tr('There is no difference.'))
+        diff, errors, fileSeparators = self.__diffGenerator.getResult()
         
-        self.buttonBox.button(QDialogButtonBox.Save).setEnabled(self.paras > 0)
+        if diff:
+            self.contents.setPlainText("".join(diff))
+        else:
+            self.contents.setPlainText(
+                self.tr('There is no difference.'))
+        
+        if errors:
+            self.errorGroup.show()
+            self.errors.setPlainText("".join(errors))
+            self.errors.ensureCursorVisible()
+        
+        self.buttonBox.button(QDialogButtonBox.Save).setEnabled(bool(diff))
         self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True)
         self.buttonBox.button(QDialogButtonBox.Close).setDefault(True)
         self.buttonBox.button(QDialogButtonBox.Close).setFocus(
@@ -245,7 +142,7 @@
         
         self.filesCombo.addItem(self.tr("<Start>"), 0)
         self.filesCombo.addItem(self.tr("<End>"), -1)
-        for oldFile, newFile, pos in sorted(self.__fileSeparators):
+        for oldFile, newFile, pos in sorted(fileSeparators):
             if not oldFile:
                 self.filesCombo.addItem(newFile, pos)
             elif oldFile != newFile:
@@ -254,99 +151,6 @@
             else:
                 self.filesCombo.addItem(oldFile, pos)
     
-    def __appendText(self, txt):
-        """
-        Private method to append text to the end of the contents pane.
-        
-        @param txt text to insert (string)
-        """
-        tc = self.contents.textCursor()
-        tc.movePosition(QTextCursor.End)
-        self.contents.setTextCursor(tc)
-        self.contents.insertPlainText(txt)
-    
-    def __extractFileName(self, line):
-        """
-        Private method to extract the file name out of a file separator line.
-        
-        @param line line to be processed (string)
-        @return extracted file name (string)
-        """
-        f = line.split(None, 1)[1]
-        f = f.rsplit(None, 6)[0]
-        if f == "/dev/null":
-            f = "__NULL__"
-        else:
-            f = f.split("/", 1)[1]
-        return f
-    
-    def __processFileLine(self, line):
-        """
-        Private slot to process a line giving the old/new file.
-        
-        @param line line to be processed (string)
-        """
-        if line.startswith('---'):
-            self.__oldFileLine = self.paras
-            self.__oldFile = self.__extractFileName(line)
-        else:
-            newFile = self.__extractFileName(line)
-            if self.__oldFile == "__NULL__":
-                self.__fileSeparators.append(
-                    (newFile, newFile, self.__oldFileLine))
-            else:
-                self.__fileSeparators.append(
-                    (self.__oldFile, newFile, self.__oldFileLine))
-    
-    def __processOutputLine(self, line):
-        """
-        Private method to process the lines of output.
-        
-        @param line output line to be processed (string)
-        """
-        if line.startswith("--- ") or \
-           line.startswith("+++ "):
-            self.__processFileLine(line)
-        
-        self.__appendText(line)
-        self.paras += 1
-    
-    def __readStdout(self):
-        """
-        Private slot to handle the readyReadStandardOutput signal.
-        
-        It reads the output of the process, formats it and inserts it into
-        the contents pane.
-        """
-        self.process.setReadChannel(QProcess.StandardOutput)
-        
-        while self.process.canReadLine():
-            line = str(self.process.readLine(), self.vcs.getEncoding(),
-                       'replace')
-            self.__processOutputLine(line)
-    
-    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.process is not None:
-            s = str(self.process.readAllStandardError(),
-                    self.vcs.getEncoding(), 'replace')
-            self.__showError(s)
-    
-    def __showError(self, out):
-        """
-        Private slot to show some error.
-        
-        @param out error to be shown (string)
-        """
-        self.errorGroup.show()
-        self.errors.insertPlainText(out)
-        self.errors.ensureCursorVisible()
-    
     def on_buttonBox_clicked(self, button):
         """
         Private slot called by a button of the button box clicked.
@@ -463,53 +267,3 @@
         self.refreshButton.setEnabled(False)
         
         self.start(self.filename, refreshable=True)
-    
-    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.
-        """
-        input = self.input.text()
-        input += os.linesep
-        
-        if self.passwordCheckBox.isChecked():
-            self.errors.insertPlainText(os.linesep)
-            self.errors.ensureCursorVisible()
-        else:
-            self.errors.insertPlainText(input)
-            self.errors.ensureCursorVisible()
-        
-        self.process.write(input)
-        
-        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(HgDiffDialog, self).keyPressEvent(evt)

eric ide

mercurial