Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesDefineGuardsDialog.py

changeset 1046
5dd14be5d6a1
child 1047
b41a36b201e4
diff -r 11aca34cce20 -r 5dd14be5d6a1 Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesDefineGuardsDialog.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesDefineGuardsDialog.py	Sat May 21 16:17:31 2011 +0200
@@ -0,0 +1,317 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2011 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a dialog to define guards for patches.
+"""
+
+import os
+
+from PyQt4.QtCore import pyqtSlot, Qt, QProcess, QTimer
+from PyQt4.QtGui import QDialog, QDialogButtonBox, QAbstractButton, QListWidgetItem
+
+from E5Gui import E5MessageBox
+
+from .Ui_HgQueuesDefineGuardsDialog import Ui_HgQueuesDefineGuardsDialog
+
+import Preferences
+import UI.PixmapCache
+
+
+class HgQueuesDefineGuardsDialog(QDialog, Ui_HgQueuesDefineGuardsDialog):
+    """
+    Class implementing a dialog to define guards for patches.
+    """
+    def __init__(self, vcs, patchesList, parent=None):
+        """
+        Constructor
+        
+        @param vcs reference to the vcs object
+        @param patchesList list of patches (list of strings)
+        @param parent reference to the parent widget (QWidget)
+        """
+        QDialog.__init__(self, parent)
+        self.setupUi(self)
+        
+        self.process = QProcess()
+        self.vcs = vcs
+        
+        self.__patches = patchesList[:]
+        self.patchSelector.addItems([""] + self.__patches)
+        
+        self.plusButton.setIcon(UI.PixmapCache.getIcon("plus.png"))
+        self.minusButton.setIcon(UI.PixmapCache.getIcon("minus.png"))
+        
+        self.__dirtyList = False
+        self.__currentPatch = ""
+    
+    def closeEvent(self, e):
+        """
+        Private slot implementing a close event handler.
+        
+        @param e close event (QCloseEvent)
+        """
+        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)
+        
+        if self.__dirtyList:
+            res = E5MessageBox.question(self,
+                self.trUtf8("Unsaved Changes"),
+                self.trUtf8("""The guards list has been changed."""
+                            """ Shall the changes be applied?"""),
+                E5MessageBox.StandardButtons(
+                    E5MessageBox.Apply | \
+                    E5MessageBox.Discard),
+                E5MessageBox.Apply)
+            if res == E5MessageBox.Apply:
+                self.__applyGuards()
+            else:
+                self.__dirtyList = False
+        
+        e.accept()
+    
+    def start(self, path):
+        """
+        Public slot to start the list command.
+        
+        @param path name of directory to be listed (string)
+        """
+        dname, fname = self.vcs.splitPath(path)
+        
+        # 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 repodir == os.sep:
+                return
+        
+        self.__repodir = repodir
+        self.on_patchSelector_activated("")
+    
+    def __getGuards(self):
+        """
+        Private method to get a list of all guards defined.
+        
+        @return list of guards (list of strings)
+        """
+        guardsList = []
+        
+        ioEncoding = Preferences.getSystem("IOEncoding")
+        process = QProcess()
+        args = []
+        args.append("qselect")
+        args.append("--series")
+        
+        process.setWorkingDirectory(self.__repodir)
+        process.start('hg', args)
+        procStarted = process.waitForStarted()
+        if procStarted:
+            finished = process.waitForFinished(30000)
+            if finished and process.exitCode() == 0:
+                output = \
+                    str(process.readAllStandardOutput(), ioEncoding, 'replace')
+                for guard in output.splitlines():
+                    guard = guard.strip()[1:]
+                    if guard not in guardsList:
+                        guardsList.append(guard)
+        
+        return sorted(guardsList)
+    
+    @pyqtSlot(str)
+    def on_patchSelector_activated(self, patch):
+        """
+        Private slot to get the list of guards defined for the given patch name.
+        
+        @param patch selected patch name (empty for current patch)
+        """
+        if self.__dirtyList:
+            res = E5MessageBox.question(self,
+                self.trUtf8("Unsaved Changes"),
+                self.trUtf8("""The guards list has been changed."""
+                            """ Shall the changes be applied?"""),
+                E5MessageBox.StandardButtons(
+                    E5MessageBox.Apply | \
+                    E5MessageBox.Discard),
+                E5MessageBox.Apply)
+            if res == E5MessageBox.Apply:
+                self.__applyGuards()
+            else:
+                self.__dirtyList = False
+        
+        self.guardsList.clear()
+        self.patchNameLabel.setText("")
+        
+        self.guardCombo.clear()
+        guardsList = self.__getGuards()
+        self.guardCombo.addItems(guardsList)
+        self.guardCombo.setEditText("")
+        
+        ioEncoding = Preferences.getSystem("IOEncoding")
+        process = QProcess()
+        args = []
+        args.append("qguard")
+        if patch:
+            args.append(patch)
+        
+        process.setWorkingDirectory(self.__repodir)
+        process.start('hg', args)
+        procStarted = process.waitForStarted()
+        if procStarted:
+            finished = process.waitForFinished(30000)
+            if finished and process.exitCode() == 0:
+                output = \
+                    str(process.readAllStandardOutput(), ioEncoding, 'replace').strip()
+                if output:
+                    patchName, guards = output.split(":", 1)
+                    self.patchNameLabel.setText(patchName)
+                    guardsList = guards.strip().split()
+                    for guard in guardsList:
+                        if guard.startswith("+"):
+                            icon = UI.PixmapCache.getIcon("plus.png")
+                            guard = guard[1:]
+                            sign = "+"
+                        elif guard.startswith("-"):
+                            icon = UI.PixmapCache.getIcon("minus.png")
+                            guard = guard[1:]
+                            sign = "-"
+                        else:
+                            continue
+                        itm = QListWidgetItem(icon, guard, self.guardsList)
+                        itm.setData(Qt.UserRole, sign)
+        
+        self.on_guardsList_itemSelectionChanged()
+    
+    @pyqtSlot()
+    def on_guardsList_itemSelectionChanged(self):
+        """
+        Private slot to handle changes of the selection of guards.
+        """
+        self.removeButton.setEnabled(
+            len(self.guardsList.selectedItems()) > 0)
+    
+    def __getGuard(self, guard):
+        """
+        Private method to get a reference to a named guard.
+        
+        @param guard name of the guard (string)
+        @return reference to the guard item (QListWidgetItem)
+        """
+        items = self.guardsList.findItems(guard, Qt.MatchCaseSensitive)
+        if items:
+            return items[0]
+        else:
+            return None
+    
+    @pyqtSlot(str)
+    def on_guardCombo_editTextChanged(self, txt):
+        """
+        Private slot to handle changes of the text of the guard combo.
+        
+        @param txt contents of the guard combo line edit (string)
+        """
+        self.addButton.setEnabled(txt != "")
+    
+    @pyqtSlot()
+    def on_addButton_clicked(self):
+        """
+        Private slot to add a guard definition to the list or change it.
+        """
+        guard = self.guardCombo.currentText()
+        if self.plusButton.isChecked():
+            sign = "+"
+            icon = UI.PixmapCache.getIcon("plus.png")
+        else:
+            sign = "-"
+            icon = UI.PixmapCache.getIcon("minus.png")
+        
+        guardItem = self.__getGuard(guard)
+        if guardItem:
+            # guard already exists, remove it first
+            row = self.guardsList.row(guardItem)
+            itm = self.guardsList.takeItem(row)
+            del itm
+        
+        itm = QListWidgetItem(icon, guard, self.guardsList)
+        itm.setData(Qt.UserRole, sign)
+        self.guardsList.sortItems()
+        
+        self.__dirtyList = True
+    
+    @pyqtSlot()
+    def on_removeButton_clicked(self):
+        """
+        Private slot to remove guard definitions from the list.
+        """
+        res = E5MessageBox.yesNo(self,
+            self.trUtf8("Remove Guards"),
+            self.trUtf8("""Do you really want to remove the selected guards?"""))
+        if res:
+            for guardItem in self.guardsList.selectedItems():
+                row = self.guardsList.row(guardItem)
+                itm = self.guardsList.takeItem(row)
+                del itm
+        
+        self.__dirtyList = True
+    
+    @pyqtSlot(QAbstractButton)
+    def on_buttonBox_clicked(self, button):
+        """
+        Private slot called by a button of the button box clicked.
+        
+        @param button button that was clicked (QAbstractButton)
+        """
+        if button == self.buttonBox.button(QDialogButtonBox.Apply):
+            self.__applyGuards()
+        elif button == self.buttonBox.button(QDialogButtonBox.Close):
+            self.close()
+    
+    @pyqtSlot()
+    def __applyGuards(self):
+        """
+        Private slot to apply the defined guards to the current patch.
+        """
+        if self.__dirtyList:
+            guardsList = []
+            for row in range(self.guardsList.count()):
+                itm = self.guardsList.item(row)
+                guard = itm.data(Qt.UserRole) + itm.text()
+                guardsList.append(guard)
+            
+            ioEncoding = Preferences.getSystem("IOEncoding")
+            process = QProcess()
+            args = []
+            args.append("qguard")
+            args.append(self.patchNameLabel.text())
+            if guardsList:
+                args.append("--")
+                args.extend(guardsList)
+            else:
+                args.append("--none")
+            
+            process.setWorkingDirectory(self.__repodir)
+            process.start('hg', args)
+            procStarted = process.waitForStarted()
+            if procStarted:
+                finished = process.waitForFinished(30000)
+                if finished:
+                    if process.exitCode() == 0:
+                        self.__dirtyList = False
+                        self.on_patchSelector_activated(self.patchNameLabel.text())
+                    else:
+                        error = \
+                            str(process.readAllStandardError(), ioEncoding, 'replace')
+                        E5MessageBox.warning(self,
+                            self.trUtf8("Apply Guard Definitions"),
+                            self.trUtf8("""<p>The defined guards could not be"""
+                                        """ applied.</p><p>Reason: {0}</p>""")\
+                                .format(error))
+                        
+                else:
+                    E5MessageBox.warning(self,
+                        self.trUtf8("Apply Guard Definitions"),
+                        self.trUtf8("""The Mercurial process did not finish in time."""))

eric ide

mercurial