Continued with support for Mercurial queues extension.

Sat, 21 May 2011 16:17:31 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Sat, 21 May 2011 16:17:31 +0200
changeset 1046
5dd14be5d6a1
parent 1044
11aca34cce20
child 1047
b41a36b201e4

Continued with support for Mercurial queues extension.

Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesDefineGuardsDialog.py file | annotate | diff | comparison | revisions
Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesDefineGuardsDialog.ui file | annotate | diff | comparison | revisions
Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesListAllGuardsDialog.py file | annotate | diff | comparison | revisions
Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesListAllGuardsDialog.ui file | annotate | diff | comparison | revisions
Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesListGuardsDialog.py file | annotate | diff | comparison | revisions
Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesListGuardsDialog.ui file | annotate | diff | comparison | revisions
Plugins/VcsPlugins/vcsMercurial/QueuesExtension/ProjectHelper.py file | annotate | diff | comparison | revisions
Plugins/VcsPlugins/vcsMercurial/QueuesExtension/queues.py file | annotate | diff | comparison | revisions
eric5.e4p file | annotate | diff | comparison | revisions
icons/default/minus.png file | annotate | diff | comparison | revisions
icons/default/plus.png file | annotate | diff | comparison | revisions
--- /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."""))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesDefineGuardsDialog.ui	Sat May 21 16:17:31 2011 +0200
@@ -0,0 +1,204 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>HgQueuesDefineGuardsDialog</class>
+ <widget class="QDialog" name="HgQueuesDefineGuardsDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>434</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Define Guards</string>
+  </property>
+  <property name="sizeGripEnabled">
+   <bool>true</bool>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QLabel" name="label">
+     <property name="text">
+      <string>Select patch (leave empty for current patch):</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QComboBox" name="patchSelector">
+     <property name="toolTip">
+      <string>Select the patch to show the guards of</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="Line" name="line">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout_3">
+     <item>
+      <widget class="QLabel" name="label_3">
+       <property name="text">
+        <string>Patch:</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QLabel" name="patchNameLabel">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="toolTip">
+        <string>Shows the name of the patch</string>
+       </property>
+       <property name="text">
+        <string/>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <widget class="QListWidget" name="guardsList">
+     <property name="toolTip">
+      <string>This shows the list of guards to be defined for the selected patch</string>
+     </property>
+     <property name="alternatingRowColors">
+      <bool>true</bool>
+     </property>
+     <property name="selectionMode">
+      <enum>QAbstractItemView::ExtendedSelection</enum>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <item>
+      <widget class="QRadioButton" name="plusButton">
+       <property name="toolTip">
+        <string>Select to define a positive guard</string>
+       </property>
+       <property name="text">
+        <string/>
+       </property>
+       <property name="checked">
+        <bool>true</bool>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QRadioButton" name="minusButton">
+       <property name="toolTip">
+        <string>Select to define a negative guard</string>
+       </property>
+       <property name="text">
+        <string/>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QComboBox" name="guardCombo">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="toolTip">
+        <string>Enter the guard name</string>
+       </property>
+       <property name="editable">
+        <bool>true</bool>
+       </property>
+       <property name="insertPolicy">
+        <enum>QComboBox::InsertAlphabetically</enum>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="addButton">
+       <property name="toolTip">
+        <string>Press to add the guard to the list or change it</string>
+       </property>
+       <property name="text">
+        <string>Add/Change</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <widget class="QPushButton" name="removeButton">
+     <property name="toolTip">
+      <string>Press to remove the selected guards from the list</string>
+     </property>
+     <property name="text">
+      <string>Remove</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Apply|QDialogButtonBox::Close</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <tabstops>
+  <tabstop>patchSelector</tabstop>
+  <tabstop>guardsList</tabstop>
+  <tabstop>plusButton</tabstop>
+  <tabstop>minusButton</tabstop>
+  <tabstop>guardCombo</tabstop>
+  <tabstop>addButton</tabstop>
+  <tabstop>removeButton</tabstop>
+  <tabstop>buttonBox</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>HgQueuesDefineGuardsDialog</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>222</x>
+     <y>419</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>HgQueuesDefineGuardsDialog</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>290</x>
+     <y>425</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesListAllGuardsDialog.py	Sat May 21 16:17:31 2011 +0200
@@ -0,0 +1,104 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2011 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a dialog to show all guards for all patches.
+"""
+
+import os
+
+from PyQt4.QtCore import QProcess, QTimer
+from PyQt4.QtGui import QDialog, QTreeWidgetItem
+
+from .Ui_HgQueuesListAllGuardsDialog import Ui_HgQueuesListAllGuardsDialog
+
+import Preferences
+import UI.PixmapCache
+
+
+class HgQueuesListAllGuardsDialog(QDialog, Ui_HgQueuesListAllGuardsDialog):
+    """
+    Class implementing a dialog to show all guards for all patches.
+    """
+    def __init__(self, vcs, parent=None):
+        """
+        Constructor
+        
+        @param parent reference to the parent widget (QWidget)
+        """
+        QDialog.__init__(self, parent)
+        self.setupUi(self)
+        
+        self.process = QProcess()
+        self.vcs = vcs
+    
+    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)
+        
+        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
+        
+        
+        ioEncoding = Preferences.getSystem("IOEncoding")
+        process = QProcess()
+        args = []
+        args.append("qguard")
+        args.append("--list")
+        
+        process.setWorkingDirectory(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')
+                if output:
+                    guardsDict = {}
+                    for line in output.splitlines():
+                        if line:
+                            patchName, guards = line.strip().split(":", 1)
+                            guardsDict[patchName] = guards.strip().split()
+                    for patchName in sorted(guardsDict.keys()):
+                        patchItm = QTreeWidgetItem(self.guardsTree, [patchName])
+                        patchItm.setExpanded(True)
+                        for guard in guardsDict[patchName]:
+                            if guard.startswith("+"):
+                                icon = UI.PixmapCache.getIcon("plus.png")
+                                guard = guard[1:]
+                            elif guard.startswith("-"):
+                                icon = UI.PixmapCache.getIcon("minus.png")
+                                guard = guard[1:]
+                            else:
+                                icon = None
+                                guard = self.trUtf8("Unguarded")
+                            itm = QTreeWidgetItem(patchItm, [guard])
+                            if icon:
+                                itm.setIcon(0, icon)
+                else:
+                    QTreeWidgetItem(self.guardsTree, [self.trUtf8("no patches found")])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesListAllGuardsDialog.ui	Sat May 21 16:17:31 2011 +0200
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>HgQueuesListAllGuardsDialog</class>
+ <widget class="QDialog" name="HgQueuesListAllGuardsDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>400</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>List All Guards</string>
+  </property>
+  <property name="sizeGripEnabled">
+   <bool>true</bool>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QTreeWidget" name="guardsTree">
+     <property name="toolTip">
+      <string>Show all guards of all patches</string>
+     </property>
+     <property name="alternatingRowColors">
+      <bool>true</bool>
+     </property>
+     <property name="selectionMode">
+      <enum>QAbstractItemView::NoSelection</enum>
+     </property>
+     <property name="headerHidden">
+      <bool>true</bool>
+     </property>
+     <column>
+      <property name="text">
+       <string notr="true">1</string>
+      </property>
+     </column>
+    </widget>
+   </item>
+   <item>
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Close</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <tabstops>
+  <tabstop>guardsTree</tabstop>
+  <tabstop>buttonBox</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>HgQueuesListAllGuardsDialog</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>248</x>
+     <y>254</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>HgQueuesListAllGuardsDialog</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>316</x>
+     <y>260</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesListGuardsDialog.py	Sat May 21 16:17:31 2011 +0200
@@ -0,0 +1,114 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2011 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a dialog to show the guards of a selected patch.
+"""
+
+import os
+
+from PyQt4.QtCore import pyqtSlot, QProcess, QTimer
+from PyQt4.QtGui import QDialog, QListWidgetItem
+
+from .Ui_HgQueuesListGuardsDialog import Ui_HgQueuesListGuardsDialog
+
+import Preferences
+import UI.PixmapCache
+
+
+class HgQueuesListGuardsDialog(QDialog, Ui_HgQueuesListGuardsDialog):
+    """
+    Class implementing a dialog to show the guards of a selected patch.
+    """
+    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.patchSelector.addItems([""] + patchesList)
+    
+    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)
+        
+        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("")
+    
+    @pyqtSlot(str)
+    def on_patchSelector_activated(self, patch):
+        """
+        Private slot to get the list of guards for the given patch name.
+        
+        @param patch selected patch name (empty for current patch)
+        """
+        self.guardsList.clear()
+        self.patchNameLabel.setText("")
+        
+        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:]
+                        elif guard.startswith("-"):
+                            icon = UI.PixmapCache.getIcon("minus.png")
+                            guard = guard[1:]
+                        else:
+                            icon = None
+                            guard = self.trUtf8("Unguarded")
+                        itm = QListWidgetItem(guard, self.guardsList)
+                        if icon:
+                            itm.setIcon(icon)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesListGuardsDialog.ui	Sat May 21 16:17:31 2011 +0200
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>HgQueuesListGuardsDialog</class>
+ <widget class="QDialog" name="HgQueuesListGuardsDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>400</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>List Guards</string>
+  </property>
+  <property name="sizeGripEnabled">
+   <bool>true</bool>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QLabel" name="label">
+     <property name="text">
+      <string>Select patch (leave empty for current patch):</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QComboBox" name="patchSelector">
+     <property name="toolTip">
+      <string>Select the patch to show the guards of</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="Line" name="line">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <item>
+      <widget class="QLabel" name="label_2">
+       <property name="text">
+        <string>Patch:</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QLabel" name="patchNameLabel">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="toolTip">
+        <string>Shows the name of the patch</string>
+       </property>
+       <property name="text">
+        <string/>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <widget class="QListWidget" name="guardsList">
+     <property name="toolTip">
+      <string>This shows the list of guards defined for the selected patch</string>
+     </property>
+     <property name="alternatingRowColors">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Close</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <tabstops>
+  <tabstop>patchSelector</tabstop>
+  <tabstop>guardsList</tabstop>
+  <tabstop>buttonBox</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>HgQueuesListGuardsDialog</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>248</x>
+     <y>254</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>HgQueuesListGuardsDialog</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>316</x>
+     <y>260</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
--- a/Plugins/VcsPlugins/vcsMercurial/QueuesExtension/ProjectHelper.py	Fri May 20 19:07:30 2011 +0200
+++ b/Plugins/VcsPlugins/vcsMercurial/QueuesExtension/ProjectHelper.py	Sat May 21 16:17:31 2011 +0200
@@ -189,6 +189,7 @@
         
         self.__initPushPopActions()
         self.__initPushPopForceActions()
+        self.__initGuardsActions()
     
     def __initPushPopActions(self):
         """
@@ -394,6 +395,107 @@
         self.hgQueueGotoForceAct.triggered[()].connect(self.__hgQueueGotoPatchForced)
         self.actions.append(self.hgQueueGotoForceAct)
     
+    
+    def __initGuardsActions(self):
+        """
+        Public method to generate the guards action objects.
+        """
+        self.hgQueueDefineGuardsAct = E5Action(self.trUtf8('Define Guards'),
+                self.trUtf8('Define Guards...'),
+                0, 0, self, 'mercurial_queues_guards_define')
+        self.hgQueueDefineGuardsAct.setStatusTip(self.trUtf8(
+            'Define guards for the current or a named patch'
+        ))
+        self.hgQueueDefineGuardsAct.setWhatsThis(self.trUtf8(
+            """<b>Define Guards</b>"""
+            """<p>This opens a dialog to define guards for the current"""
+            """ or a named patch.</p>"""
+        ))
+        self.hgQueueDefineGuardsAct.triggered[()].connect(self.__hgQueueGuardsDefine)
+        self.actions.append(self.hgQueueDefineGuardsAct)
+        
+        self.hgQueueDropAllGuardsAct = E5Action(self.trUtf8('Drop All Guards'),
+                self.trUtf8('Drop All Guards...'),
+                0, 0, self, 'mercurial_queues_guards_drop_all')
+        self.hgQueueDropAllGuardsAct.setStatusTip(self.trUtf8(
+            'Drop all guards of the current or a named patch'
+        ))
+        self.hgQueueDropAllGuardsAct.setWhatsThis(self.trUtf8(
+            """<b>Drop All Guards</b>"""
+            """<p>This drops all guards of the current or a named patch.</p>"""
+        ))
+        self.hgQueueDropAllGuardsAct.triggered[()].connect(self.__hgQueueGuardsDropAll)
+        self.actions.append(self.hgQueueDropAllGuardsAct)
+        
+        self.hgQueueListGuardsAct = E5Action(self.trUtf8('List Guards'),
+                self.trUtf8('List Guards...'),
+                0, 0, self, 'mercurial_queues_guards_list')
+        self.hgQueueListGuardsAct.setStatusTip(self.trUtf8(
+            'List guards of the current or a named patch'
+        ))
+        self.hgQueueListGuardsAct.setWhatsThis(self.trUtf8(
+            """<b>List Guards</b>"""
+            """<p>This lists the guards of the current or a named patch.</p>"""
+        ))
+        self.hgQueueListGuardsAct.triggered[()].connect(self.__hgQueueGuardsList)
+        self.actions.append(self.hgQueueListGuardsAct)
+        
+        self.hgQueueListAllGuardsAct = E5Action(self.trUtf8('List All Guards'),
+                self.trUtf8('List All Guards...'),
+                0, 0, self, 'mercurial_queues_guards_list_all')
+        self.hgQueueListAllGuardsAct.setStatusTip(self.trUtf8(
+            'List all guards of all patches'
+        ))
+        self.hgQueueListAllGuardsAct.setWhatsThis(self.trUtf8(
+            """<b>List All Guards</b>"""
+            """<p>This lists all guards of all patches.</p>"""
+        ))
+        self.hgQueueListAllGuardsAct.triggered[()].connect(self.__hgQueueGuardsListAll)
+        self.actions.append(self.hgQueueListAllGuardsAct)
+        
+        self.hgQueueActivateGuardsAct = E5Action(self.trUtf8('Set Active Guards'),
+                self.trUtf8('Set Active Guards...'),
+                0, 0, self, 'mercurial_queues_guards_set_active')
+        self.hgQueueActivateGuardsAct.setStatusTip(self.trUtf8(
+            'Set the list of active guards'
+        ))
+        self.hgQueueActivateGuardsAct.setWhatsThis(self.trUtf8(
+            """<b>Set Active Guards</b>"""
+            """<p>This opens a dialog to set the active guards.</p>"""
+        ))
+        self.hgQueueActivateGuardsAct.triggered[()].connect(self.__hgQueueGuardsSetActive)
+        self.actions.append(self.hgQueueActivateGuardsAct)
+        
+        self.hgQueueDeactivateGuardsAct = E5Action(self.trUtf8('Deactivate Guards'),
+                self.trUtf8('Deactivate Guards...'),
+                0, 0, self, 'mercurial_queues_guards_deactivate')
+        self.hgQueueDeactivateGuardsAct.setStatusTip(self.trUtf8(
+            'Deactivate all active guards'
+        ))
+        self.hgQueueDeactivateGuardsAct.setWhatsThis(self.trUtf8(
+            """<b>Deactivate Guards</b>"""
+            """<p>This deactivates all active guards.</p>"""
+        ))
+        self.hgQueueDeactivateGuardsAct.triggered[()].connect(
+            self.__hgQueueGuardsDeactivate)
+        self.actions.append(self.hgQueueDeactivateGuardsAct)
+        
+        self.hgQueueIdentifyActiveGuardsAct = E5Action(
+                self.trUtf8('Identify Active Guards'),
+                self.trUtf8('Identify Active Guards...'),
+                0, 0, self, 'mercurial_queues_guards_identify_active')
+        self.hgQueueIdentifyActiveGuardsAct.setStatusTip(self.trUtf8(
+            'Show a list of active guards and affected patches'
+        ))
+        self.hgQueueIdentifyActiveGuardsAct.setWhatsThis(self.trUtf8(
+            """<b>Identify Active Guards</b>"""
+            """<p>This opens a dialog show a list of active guards and the"""
+            """ patches directly affected by them.</p>"""
+        ))
+        self.hgQueueIdentifyActiveGuardsAct.triggered[()].connect(
+            self.__hgQueueGuardsIdentifyActive)
+        self.actions.append(self.hgQueueIdentifyActiveGuardsAct)
+    
     def initMenu(self, mainMenu):
         """
         Public method to generate the VCS menu.
@@ -425,6 +527,18 @@
         pushPopForceMenu.addSeparator()
         pushPopForceMenu.addAction(self.hgQueueGotoForceAct)
         
+        guardsMenu = QMenu(self.trUtf8("Guards"), menu)
+        guardsMenu.addAction(self.hgQueueDefineGuardsAct)
+        guardsMenu.addAction(self.hgQueueDropAllGuardsAct)
+        guardsMenu.addSeparator()
+        guardsMenu.addAction(self.hgQueueListGuardsAct)
+        guardsMenu.addAction(self.hgQueueListAllGuardsAct)
+        guardsMenu.addSeparator()
+        guardsMenu.addAction(self.hgQueueActivateGuardsAct)
+        guardsMenu.addAction(self.hgQueueDeactivateGuardsAct)
+        guardsMenu.addSeparator()
+        guardsMenu.addAction(self.hgQueueIdentifyActiveGuardsAct)
+        
         menu.addAction(self.hgQueueNewAct)
         menu.addAction(self.hgQueueRefreshAct)
         menu.addAction(self.hgQueueRefreshMessageAct)
@@ -442,6 +556,8 @@
         menu.addAction(self.hgQueueDeleteAct)
         menu.addSeparator()
         menu.addAction(self.hgQueueFoldAct)
+        menu.addSeparator()
+        menu.addMenu(guardsMenu)
         
         return menu
     
@@ -636,3 +752,49 @@
         """
         self.vcs.getExtensionObject("mq")\
             .hgQueueFoldUnappliedPatches(self.project.getProjectPath())
+    
+    def __hgQueueGuardsDefine(self):
+        """
+        Private slot used to define guards for the current or a named patch.
+        """
+        self.vcs.getExtensionObject("mq")\
+            .hgQueueGuardsDefine(self.project.getProjectPath())
+    
+    def __hgQueueGuardsDropAll(self):
+        """
+        Private slot used to drop all guards of the current or a named patch.
+        """
+        self.vcs.getExtensionObject("mq")\
+            .hgQueueGuardsDropAll(self.project.getProjectPath())
+    
+    def __hgQueueGuardsList(self):
+        """
+        Private slot used to list the guards for the current or a named patch.
+        """
+        self.vcs.getExtensionObject("mq")\
+            .hgQueueGuardsList(self.project.getProjectPath())
+    
+    def __hgQueueGuardsListAll(self):
+        """
+        Private slot used to list all guards of all patches.
+        """
+        self.vcs.getExtensionObject("mq")\
+            .hgQueueGuardsListAll(self.project.getProjectPath())
+    
+    def __hgQueueGuardsSetActive(self):
+        """
+        Private slot used to set the active guards.
+        """
+        pass
+    
+    def __hgQueueGuardsDeactivate(self):
+        """
+        Private slot used to deactivate all active guards.
+        """
+        pass
+    
+    def __hgQueueGuardsIdentifyActive(self):
+        """
+        Private slot used to list all active guards and their patches.
+        """
+        pass
--- a/Plugins/VcsPlugins/vcsMercurial/QueuesExtension/queues.py	Fri May 20 19:07:30 2011 +0200
+++ b/Plugins/VcsPlugins/vcsMercurial/QueuesExtension/queues.py	Sat May 21 16:17:31 2011 +0200
@@ -21,6 +21,9 @@
 from .HgQueuesRenamePatchDialog import HgQueuesRenamePatchDialog
 from .HgQueuesFoldDialog import HgQueuesFoldDialog
 from .HgQueuesHeaderDialog import HgQueuesHeaderDialog
+from .HgQueuesListGuardsDialog import HgQueuesListGuardsDialog
+from .HgQueuesListAllGuardsDialog import HgQueuesListAllGuardsDialog
+from .HgQueuesDefineGuardsDialog import HgQueuesDefineGuardsDialog
 
 import Preferences
 
@@ -47,6 +50,10 @@
         
         self.qdiffDialog = None
         self.qheaderDialog = None
+        self.queuesListDialog = None
+        self.queuesListGuardsDialog = None
+        self.queuesListAllGuardsDialog = None
+        self.queuesDefineGuardsDialog = None
     
     def shutdown(self):
         """
@@ -56,6 +63,14 @@
             self.qdiffDialog.close()
         if self.qheaderDialog is not None:
             self.qheaderDialog.close()
+        if self.queuesListDialog is not None:
+            self.queuesListDialog.close()
+        if self.queuesListGuardsDialog is not None:
+            self.queuesListGuardsDialog.close()
+        if self.queuesListAllGuardsDialog is not None:
+            self.queuesListAllGuardsDialog.close()
+        if self.queuesDefineGuardsDialog is not None:
+            self.queuesDefineGuardsDialog.close()
     
     def __getPatchesList(self, repodir, listType, withSummary=False):
         """
@@ -471,3 +486,103 @@
             E5MessageBox.information(None,
                 self.trUtf8("Fold Patches"),
                 self.trUtf8("""No patches available to be folded."""))
+    
+    def hgQueueGuardsList(self, name):
+        """
+        Public method to list the guards for the current or a named patch.
+        
+        @param name file/directory name (string)
+        """
+        # find the root of the repo
+        repodir = self.vcs.splitPath(name)[0]
+        while not os.path.isdir(os.path.join(repodir, self.vcs.adminDir)):
+            repodir = os.path.dirname(repodir)
+            if repodir == os.sep:
+                return
+        
+        patchnames = sorted(
+            self.__getPatchesList(repodir, Queues.SERIES_LIST))
+        if patchnames:
+            self.queuesListGuardsDialog = HgQueuesListGuardsDialog(self.vcs, patchnames)
+            self.queuesListGuardsDialog.show()
+            self.queuesListGuardsDialog.start(name)
+        else:
+            E5MessageBox.information(None,
+                self.trUtf8("List Guards"),
+                self.trUtf8("""No patches available to list guards for."""))
+    
+    def hgQueueGuardsListAll(self, name):
+        """
+        Public method to list all guards of all patches.
+        
+        @param name file/directory name (string)
+        """
+        self.queuesListAllGuardsDialog = HgQueuesListAllGuardsDialog(self.vcs)
+        self.queuesListAllGuardsDialog.show()
+        self.queuesListAllGuardsDialog.start(name)
+    
+    def hgQueueGuardsDefine(self, name):
+        """
+        Public method to define guards for the current or a named patch.
+        
+        @param name file/directory name (string)
+        """
+        # find the root of the repo
+        repodir = self.vcs.splitPath(name)[0]
+        while not os.path.isdir(os.path.join(repodir, self.vcs.adminDir)):
+            repodir = os.path.dirname(repodir)
+            if repodir == os.sep:
+                return
+        
+        patchnames = sorted(
+            self.__getPatchesList(repodir, Queues.SERIES_LIST))
+        if patchnames:
+            self.queuesDefineGuardsDialog = HgQueuesDefineGuardsDialog(
+                self.vcs, patchnames)
+            self.queuesDefineGuardsDialog.show()
+            self.queuesDefineGuardsDialog.start(name)
+        else:
+            E5MessageBox.information(None,
+                self.trUtf8("Define Guards"),
+                self.trUtf8("""No patches available to define guards for."""))
+    
+    def hgQueueGuardsDropAll(self, name):
+        """
+        Public method to drop all guards of the current or a named patch.
+        
+        @param name file/directory name (string)
+        """
+        # find the root of the repo
+        repodir = self.vcs.splitPath(name)[0]
+        while not os.path.isdir(os.path.join(repodir, self.vcs.adminDir)):
+            repodir = os.path.dirname(repodir)
+            if repodir == os.sep:
+                return
+        
+        patchnames = sorted(
+            self.__getPatchesList(repodir, Queues.SERIES_LIST))
+        if patchnames:
+            patch, ok = QInputDialog.getItem(
+                None,
+                self.trUtf8("Drop All Guards"),
+                self.trUtf8("Select the patch to drop guards for"
+                            " (leave empty for the current patch):"),
+                [""] + patchnames,
+                0, False)
+            if ok:
+                process = QProcess()
+                args = []
+                args.append("qguard")
+                if patch:
+                    args.append(patch)
+                args.append("--none")
+                
+                process.setWorkingDirectory(repodir)
+                process.start('hg', args)
+                procStarted = process.waitForStarted()
+                if procStarted:
+                    process.waitForFinished(30000)
+        else:
+            E5MessageBox.information(None,
+                self.trUtf8("Drop All Guards"),
+                self.trUtf8("""No patches available to define guards for."""))
--- a/eric5.e4p	Fri May 20 19:07:30 2011 +0200
+++ b/eric5.e4p	Sat May 21 16:17:31 2011 +0200
@@ -891,6 +891,9 @@
     <Source>Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesRenamePatchDialog.py</Source>
     <Source>Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesFoldDialog.py</Source>
     <Source>Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesHeaderDialog.py</Source>
+    <Source>Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesListGuardsDialog.py</Source>
+    <Source>Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesListAllGuardsDialog.py</Source>
+    <Source>Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesDefineGuardsDialog.py</Source>
   </Sources>
   <Forms>
     <Form>PyUnit/UnittestDialog.ui</Form>
@@ -1139,6 +1142,9 @@
     <Form>Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesRenamePatchDialog.ui</Form>
     <Form>Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesFoldDialog.ui</Form>
     <Form>Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesHeaderDialog.ui</Form>
+    <Form>Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesListGuardsDialog.ui</Form>
+    <Form>Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesListAllGuardsDialog.ui</Form>
+    <Form>Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesDefineGuardsDialog.ui</Form>
   </Forms>
   <Translations>
     <Translation>i18n/eric5_cs.qm</Translation>
Binary file icons/default/minus.png has changed
Binary file icons/default/plus.png has changed

eric ide

mercurial