Continued with support for Mercurial queues extension.

Sun, 15 May 2011 18:07:16 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Sun, 15 May 2011 18:07:16 +0200
changeset 1035
2cd7817ac659
parent 1034
8a7fa049e9d3
child 1036
1922b6ce2a57

Continued with support for Mercurial queues extension.

Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesFoldDialog.py file | annotate | diff | comparison | revisions
Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesFoldDialog.ui file | annotate | diff | comparison | revisions
Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesHeaderDialog.py file | annotate | diff | comparison | revisions
Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesHeaderDialog.ui file | annotate | diff | comparison | revisions
Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesNewPatchDialog.py file | annotate | diff | comparison | revisions
Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesNewPatchDialog.ui file | annotate | diff | comparison | revisions
Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesRenamePatchDialog.py file | annotate | diff | comparison | revisions
Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesRenamePatchDialog.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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesFoldDialog.py	Sun May 15 18:07:16 2011 +0200
@@ -0,0 +1,138 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2011 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a dialog to enter data to fold patches.
+"""
+
+from PyQt4.QtCore import pyqtSlot, Qt
+from PyQt4.QtGui import QDialog, QDialogButtonBox, QTreeWidgetItem
+
+from .Ui_HgQueuesFoldDialog import Ui_HgQueuesFoldDialog
+
+import UI.PixmapCache
+
+
+class HgQueuesFoldDialog(QDialog, Ui_HgQueuesFoldDialog):
+    """
+    Class implementing a dialog to enter data to fold patches.
+    """
+    def __init__(self, patchesList, parent=None):
+        """
+        Constructor
+        
+        @param patchesList list of patches to select from (list of strings)
+        @param parent reference to the parent widget (QWidget)
+        """
+        QDialog.__init__(self, parent)
+        self.setupUi(self)
+        
+        self.addButton.setIcon(UI.PixmapCache.getIcon("1downarrow.png"))
+        self.removeButton.setIcon(UI.PixmapCache.getIcon("1uparrow.png"))
+        self.upButton.setIcon(UI.PixmapCache.getIcon("1uparrow.png"))
+        self.downButton.setIcon(UI.PixmapCache.getIcon("1downarrow.png"))
+        
+        for patch in patchesList:
+            name, summary = patch.split("@@")
+            QTreeWidgetItem(self.sourcePatches, [name, summary])
+        
+        self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False)
+    
+    def __updateOkButton(self):
+        """
+        Private slot to update the status of the OK button.
+        """
+        self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(
+            self.selectedPatches.topLevelItemCount() != 0)
+    
+    @pyqtSlot()
+    def on_addButton_clicked(self):
+        """
+        Private slot to add a patch to the list of selected patches.
+        """
+        row = self.sourcePatches.indexOfTopLevelItem(self.sourcePatches.currentItem())
+        itm = self.sourcePatches.takeTopLevelItem(row)
+        
+        curItm = self.selectedPatches.currentItem()
+        if curItm is not None:
+            row = self.selectedPatches.indexOfTopLevelItem(curItm) + 1
+            self.selectedPatches.insertTopLevelItem(row, itm)
+        else:
+            self.selectedPatches.addTopLevelItem(itm)
+        
+        self.__updateOkButton()
+    
+    @pyqtSlot()
+    def on_removeButton_clicked(self):
+        """
+        Private slot to remove a patch from the list of selected patches.
+        """
+        row = self.selectedPatches.indexOfTopLevelItem(self.selectedPatches.currentItem())
+        itm = self.selectedPatches.takeTopLevelItem(row)
+        self.sourcePatches.addTopLevelItem(itm)
+        self.sourcePatches.sortItems(0, Qt.AscendingOrder)
+        
+        self.__updateOkButton()
+    
+    @pyqtSlot()
+    def on_upButton_clicked(self):
+        """
+        Private slot to move a patch up in the list.
+        """
+        row = self.selectedPatches.indexOfTopLevelItem(self.selectedPatches.currentItem())
+        if row > 0:
+            targetRow = row - 1
+            itm = self.selectedPatches.takeTopLevelItem(row)
+            self.selectedPatches.insertTopLevelItem(targetRow, itm)
+            self.selectedPatches.setCurrentItem(itm)
+    
+    @pyqtSlot()
+    def on_downButton_clicked(self):
+        """
+        Private slot to move a patch down in the list.
+        """
+        row = self.selectedPatches.indexOfTopLevelItem(self.selectedPatches.currentItem())
+        if row < self.selectedPatches.topLevelItemCount() - 1:
+            targetRow = row + 1
+            itm = self.selectedPatches.takeTopLevelItem(row)
+            self.selectedPatches.insertTopLevelItem(targetRow, itm)
+            self.selectedPatches.setCurrentItem(itm)
+    
+    @pyqtSlot(QTreeWidgetItem, QTreeWidgetItem)
+    def on_sourcePatches_currentItemChanged(self, current, previous):
+        """
+        Private slot to react on changes of the current item of source patches.
+        
+        @param current reference to the new current item (QTreeWidgetItem)
+        @param previous reference to the previous current item (QTreeWidgetItem)
+        """
+        self.addButton.setEnabled(current is not None)
+    
+    @pyqtSlot(QTreeWidgetItem, QTreeWidgetItem)
+    def on_selectedPatches_currentItemChanged(self, current, previous):
+        """
+        Private slot to react on changes of the current item of selected patches.
+        
+        @param current reference to the new current item (QTreeWidgetItem)
+        @param previous reference to the previous current item (QTreeWidgetItem)
+        """
+        self.removeButton.setEnabled(current is not None)
+        
+        row = self.selectedPatches.indexOfTopLevelItem(current)
+        self.upButton.setEnabled(row > 0)
+        self.downButton.setEnabled(row < self.selectedPatches.topLevelItemCount() - 1)
+    
+    def getData(self):
+        """
+        Public method to retrieve the entered data.
+        
+        @return tuple of commit message and list of selected patches
+            (string, list of strings)
+        """
+        patchesList = []
+        for row in range(self.selectedPatches.topLevelItemCount()):
+            patchesList.append(self.selectedPatches.topLevelItem(row).text(0))
+        
+        return self.messageEdit.toPlainText(), patchesList
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesFoldDialog.ui	Sun May 15 18:07:16 2011 +0200
@@ -0,0 +1,288 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>HgQueuesFoldDialog</class>
+ <widget class="QDialog" name="HgQueuesFoldDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>450</width>
+    <height>600</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Fold Patches</string>
+  </property>
+  <property name="sizeGripEnabled">
+   <bool>true</bool>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="0" column="0">
+    <widget class="QLabel" name="label">
+     <property name="text">
+      <string>Message:</string>
+     </property>
+     <property name="alignment">
+      <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="1">
+    <widget class="QPlainTextEdit" name="messageEdit">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+       <horstretch>0</horstretch>
+       <verstretch>1</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="toolTip">
+      <string>Enter commit message for the folded patch</string>
+     </property>
+     <property name="tabChangesFocus">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="0" colspan="2">
+    <widget class="QTreeWidget" name="sourcePatches">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+       <horstretch>0</horstretch>
+       <verstretch>2</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="editTriggers">
+      <set>QAbstractItemView::NoEditTriggers</set>
+     </property>
+     <property name="alternatingRowColors">
+      <bool>true</bool>
+     </property>
+     <property name="rootIsDecorated">
+      <bool>false</bool>
+     </property>
+     <property name="itemsExpandable">
+      <bool>false</bool>
+     </property>
+     <property name="allColumnsShowFocus">
+      <bool>true</bool>
+     </property>
+     <property name="expandsOnDoubleClick">
+      <bool>false</bool>
+     </property>
+     <column>
+      <property name="text">
+       <string>Name</string>
+      </property>
+     </column>
+     <column>
+      <property name="text">
+       <string>Summary</string>
+      </property>
+     </column>
+    </widget>
+   </item>
+   <item row="2" column="0" colspan="2">
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <item>
+      <spacer name="horizontalSpacer">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QToolButton" name="addButton">
+       <property name="enabled">
+        <bool>false</bool>
+       </property>
+       <property name="toolTip">
+        <string>Press to add the selected entry to the list of selected patches</string>
+       </property>
+       <property name="text">
+        <string notr="true"/>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QToolButton" name="removeButton">
+       <property name="enabled">
+        <bool>false</bool>
+       </property>
+       <property name="toolTip">
+        <string>Press to remove the selected entry from the list of selected patches</string>
+       </property>
+       <property name="text">
+        <string notr="true"/>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <spacer name="horizontalSpacer_2">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+    </layout>
+   </item>
+   <item row="3" column="0" colspan="2">
+    <widget class="QTreeWidget" name="selectedPatches">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+       <horstretch>0</horstretch>
+       <verstretch>2</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="editTriggers">
+      <set>QAbstractItemView::NoEditTriggers</set>
+     </property>
+     <property name="alternatingRowColors">
+      <bool>true</bool>
+     </property>
+     <property name="rootIsDecorated">
+      <bool>false</bool>
+     </property>
+     <property name="itemsExpandable">
+      <bool>false</bool>
+     </property>
+     <property name="expandsOnDoubleClick">
+      <bool>false</bool>
+     </property>
+     <column>
+      <property name="text">
+       <string>Name</string>
+      </property>
+     </column>
+     <column>
+      <property name="text">
+       <string>Summary</string>
+      </property>
+     </column>
+    </widget>
+   </item>
+   <item row="3" column="2">
+    <layout class="QVBoxLayout" name="verticalLayout">
+     <item>
+      <spacer name="verticalSpacer">
+       <property name="orientation">
+        <enum>Qt::Vertical</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>20</width>
+         <height>40</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QToolButton" name="upButton">
+       <property name="enabled">
+        <bool>false</bool>
+       </property>
+       <property name="toolTip">
+        <string>Press to move the selected patch up</string>
+       </property>
+       <property name="text">
+        <string notr="true"/>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QToolButton" name="downButton">
+       <property name="enabled">
+        <bool>false</bool>
+       </property>
+       <property name="toolTip">
+        <string>Press to move the selected patch down</string>
+       </property>
+       <property name="text">
+        <string notr="true"/>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <spacer name="verticalSpacer_2">
+       <property name="orientation">
+        <enum>Qt::Vertical</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>20</width>
+         <height>40</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+    </layout>
+   </item>
+   <item row="4" column="0" colspan="3">
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <tabstops>
+  <tabstop>messageEdit</tabstop>
+  <tabstop>sourcePatches</tabstop>
+  <tabstop>addButton</tabstop>
+  <tabstop>removeButton</tabstop>
+  <tabstop>selectedPatches</tabstop>
+  <tabstop>upButton</tabstop>
+  <tabstop>downButton</tabstop>
+  <tabstop>buttonBox</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>HgQueuesFoldDialog</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>HgQueuesFoldDialog</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/HgQueuesHeaderDialog.py	Sun May 15 18:07:16 2011 +0200
@@ -0,0 +1,155 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2011 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a dialog to show the commit message of the current patch.
+"""
+
+import os
+
+from PyQt4.QtCore import QProcess, QTimer, Qt
+from PyQt4.QtGui import QDialog, QDialogButtonBox
+
+from E5Gui import E5MessageBox
+
+from .Ui_HgQueuesHeaderDialog import Ui_HgQueuesHeaderDialog
+
+import Preferences
+
+
+class HgQueuesHeaderDialog(QDialog, Ui_HgQueuesHeaderDialog):
+    """
+    Class implementing a dialog to show the commit message of the current patch.
+    """
+    def __init__(self, vcs, parent=None):
+        """
+        Constructor
+        
+        @param vcs reference to the vcs object
+        @param parent reference to the parent widget (QWidget)
+        """
+        QDialog.__init__(self, parent)
+        self.setupUi(self)
+        
+        self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False)
+        self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True)
+        
+        self.process = QProcess()
+        self.vcs = vcs
+        
+        self.process.finished.connect(self.__procFinished)
+        self.process.readyReadStandardOutput.connect(self.__readStdout)
+        self.process.readyReadStandardError.connect(self.__readStderr)
+    
+    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)
+        """
+        self.activateWindow()
+        
+        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
+        
+        args = []
+        args.append('qheader')
+        
+        self.process.kill()
+        self.process.setWorkingDirectory(repodir)
+        
+        self.process.start('hg', args)
+        procStarted = self.process.waitForStarted()
+        if not procStarted:
+            E5MessageBox.critical(self,
+                self.trUtf8('Process Generation Error'),
+                self.trUtf8(
+                    'The process {0} could not be started. '
+                    'Ensure, that it is in the search path.'
+                ).format('hg'))
+    
+    def __finish(self):
+        """
+        Private slot called when the process finished or the user pressed the button.
+        """
+        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.buttonBox.button(QDialogButtonBox.Close).setEnabled(True)
+        self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False)
+        self.buttonBox.button(QDialogButtonBox.Close).setDefault(True)
+        self.buttonBox.button(QDialogButtonBox.Close).setFocus(Qt.OtherFocusReason)
+        
+        self.process = None
+    
+    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.Close):
+            self.close()
+        elif button == self.buttonBox.button(QDialogButtonBox.Cancel):
+            self.__finish()
+    
+    def __procFinished(self, exitCode, exitStatus):
+        """
+        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 __readStdout(self):
+        """
+        Private slot to handle the readyReadStdout signal.
+        
+        It reads the output of the process, formats it and inserts it into
+        the contents pane.
+        """
+        if self.process is not None:
+            s = str(self.process.readAllStandardOutput(),
+                    Preferences.getSystem("IOEncoding"),
+                    'replace')
+            self.messageEdit.appendPlainText(s)
+    
+    def __readStderr(self):
+        """
+        Private slot to handle the readyReadStderr 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(),
+                    Preferences.getSystem("IOEncoding"),
+                    'replace')
+            self.messageEdit.appendPlainText(self.trUtf8("Error: "))
+            self.messageEdit.appendPlainText(s)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesHeaderDialog.ui	Sun May 15 18:07:16 2011 +0200
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>HgQueuesHeaderDialog</class>
+ <widget class="QDialog" name="HgQueuesHeaderDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>300</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Commit Message</string>
+  </property>
+  <property name="sizeGripEnabled">
+   <bool>true</bool>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QPlainTextEdit" name="messageEdit">
+     <property name="readOnly">
+      <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::Cancel|QDialogButtonBox::Close</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <tabstops>
+  <tabstop>messageEdit</tabstop>
+  <tabstop>buttonBox</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
--- a/Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesNewPatchDialog.py	Sat May 14 20:00:13 2011 +0200
+++ b/Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesNewPatchDialog.py	Sun May 15 18:07:16 2011 +0200
@@ -7,7 +7,7 @@
 Module implementing a dialog to get the data for a new patch.
 """
 
-from PyQt4.QtCore import pyqtSlot, QDate
+from PyQt4.QtCore import pyqtSlot, QDateTime
 from PyQt4.QtGui import QDialog, QDialogButtonBox
 
 from .Ui_HgQueuesNewPatchDialog import Ui_HgQueuesNewPatchDialog
@@ -17,25 +17,47 @@
     """
     Class implementing a dialog to get the data for a new patch.
     """
-    def __init__(self, parent=None):
+    NEW_MODE = 0
+    REFRESH_MODE = 1
+    
+    def __init__(self, mode, message="", parent=None):
         """
         Constructor
         
+        @param mode mode of the dialog (HgQueuesNewPatchDialog.NEW_MODE,
+            HgQueuesNewPatchDialog.REFRESH_MODE)
+        @param message text to set as the commit message (string)
         @param parent reference to the parent widget (QWidget)
         """
         QDialog.__init__(self, parent)
         self.setupUi(self)
         
-        self.dateEdit.setDate(QDate.currentDate())
+        self.__mode = mode
+        if self.__mode == HgQueuesNewPatchDialog.REFRESH_MODE:
+            self.nameLabel.hide()
+            self.nameEdit.hide()
+        elif self.__mode == HgQueuesNewPatchDialog.NEW_MODE:
+            # nothing special here
+            pass
+        else:
+            raise ValueError("invalid value for mode")
         
-        self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False)
+        if message:
+            self.messageEdit.setPlainText(message)
+        
+        self.dateTimeEdit.setDateTime(QDateTime.currentDateTime())
+        
+        self.__updateUI()
     
     def __updateUI(self):
         """
         Private slot to update the UI.
         """
-        enable = self.nameEdit.text() != "" and \
-                 self.messageEdit.toPlainText() != ""
+        if self.__mode == HgQueuesNewPatchDialog.REFRESH_MODE:
+            enable = self.messageEdit.toPlainText() != ""
+        else:
+            enable = self.nameEdit.text() != "" and \
+                     self.messageEdit.toPlainText() != ""
         if self.userGroup.isChecked():
             enable = enable and \
                 (self.currentUserCheckBox.isChecked() or \
@@ -61,6 +83,33 @@
         """
         self.__updateUI()
     
+    @pyqtSlot(bool)
+    def on_userGroup_toggled(self, checked):
+        """
+        Private slot to handle changes of the user group state.
+        
+        @param checked flag giving the checked state (boolean)
+        """
+        self.__updateUI()
+    
+    @pyqtSlot(bool)
+    def on_currentUserCheckBox_toggled(self, checked):
+        """
+        Private slot to handle changes of the currentuser state.
+        
+        @param checked flag giving the checked state (boolean)
+        """
+        self.__updateUI()
+    
+    @pyqtSlot(str)
+    def on_userEdit_textChanged(self, txt):
+        """
+        Private slot to handle changes of the user name.
+        
+        @param txt text of the edit (string)
+        """
+        self.__updateUI()
+    
     def getData(self):
         """
         Public method to retrieve the entered data.
@@ -77,6 +126,6 @@
                     self.userEdit.text())
         dateData = (self.dateGroup.isChecked(), 
                     self.currentDateCheckBox.isChecked(), 
-                    self.dateEdit.date().toString("yyyy-MM-dd"))
+                    self.dateTimeEdit.dateTime().toString("yyyy-MM-dd hh:mm"))
         return (self.nameEdit.text(), self.messageEdit.toPlainText(), 
             userData, dateData)
--- a/Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesNewPatchDialog.ui	Sat May 14 20:00:13 2011 +0200
+++ b/Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesNewPatchDialog.ui	Sun May 15 18:07:16 2011 +0200
@@ -18,7 +18,7 @@
   </property>
   <layout class="QGridLayout" name="gridLayout_3">
    <item row="0" column="0">
-    <widget class="QLabel" name="label">
+    <widget class="QLabel" name="nameLabel">
      <property name="text">
       <string>Name:</string>
      </property>
@@ -126,12 +126,12 @@
        </widget>
       </item>
       <item row="1" column="1">
-       <widget class="QDateEdit" name="dateEdit">
+       <widget class="QDateTimeEdit" name="dateTimeEdit">
         <property name="toolTip">
-         <string>Enter the date to be used for the patch</string>
+         <string>Enter the date and time to be used for the patch</string>
         </property>
         <property name="displayFormat">
-         <string notr="true">yyyy-MM-dd</string>
+         <string notr="true">yyyy-MM-dd hh:mm</string>
         </property>
         <property name="calendarPopup">
          <bool>true</bool>
@@ -171,7 +171,7 @@
   <tabstop>userEdit</tabstop>
   <tabstop>dateGroup</tabstop>
   <tabstop>currentDateCheckBox</tabstop>
-  <tabstop>dateEdit</tabstop>
+  <tabstop>dateTimeEdit</tabstop>
   <tabstop>buttonBox</tabstop>
  </tabstops>
  <resources/>
@@ -243,22 +243,6 @@
   <connection>
    <sender>currentDateCheckBox</sender>
    <signal>toggled(bool)</signal>
-   <receiver>dateEdit</receiver>
-   <slot>setDisabled(bool)</slot>
-   <hints>
-    <hint type="sourcelabel">
-     <x>55</x>
-     <y>269</y>
-    </hint>
-    <hint type="destinationlabel">
-     <x>82</x>
-     <y>294</y>
-    </hint>
-   </hints>
-  </connection>
-  <connection>
-   <sender>currentDateCheckBox</sender>
-   <signal>toggled(bool)</signal>
    <receiver>label_4</receiver>
    <slot>setDisabled(bool)</slot>
    <hints>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesRenamePatchDialog.py	Sun May 15 18:07:16 2011 +0200
@@ -0,0 +1,84 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2011 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a dialog to enter the data to rename a patch.
+"""
+
+from PyQt4.QtCore import pyqtSlot
+from PyQt4.QtGui import QDialog, QDialogButtonBox
+
+from .Ui_HgQueuesRenamePatchDialog import Ui_HgQueuesRenamePatchDialog
+
+
+class HgQueuesRenamePatchDialog(QDialog, Ui_HgQueuesRenamePatchDialog):
+    """
+    Class implementing a dialog to enter the data to rename a patch.
+    """
+    def __init__(self, currentPatch, patchesList, parent=None):
+        """
+        Constructor
+        
+        @param currentPatch name of the current patch (string)
+        @param patchesList list of patches to select from (list of strings)
+        @param parent reference to the parent widget (QWidget)
+        """
+        QDialog.__init__(self, parent)
+        self.setupUi(self)
+        
+        self.currentButton.setText(
+            self.trUtf8("Current Patch ({0})").format(currentPatch))
+        self.nameCombo.addItems([""] + patchesList)
+        
+        self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False)
+    
+    def __updateUI(self):
+        """
+        Private slot to update the UI.
+        """
+        enable = self.nameEdit.text() != ""
+        if self.namedButton.isChecked():
+            enable = enable and self.nameCombo.currentText() != ""
+        
+        self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(enable)
+    
+    @pyqtSlot(str)
+    def on_nameEdit_textChanged(self, txt):
+        """
+        Private slot to handle changes of the new name.
+        
+        @param txt text of the edit (string)
+        """
+        self.__updateUI()
+    
+    @pyqtSlot(bool)
+    def on_namedButton_toggled(self, checked):
+        """
+        Private slot to handle changes of the selection method.
+        
+        @param checked state of the check box (boolean)
+        """
+        self.__updateUI()
+    
+    @pyqtSlot(str)
+    def on_nameCombo_currentIndexChanged(self, txt):
+        """
+        Private slot to handle changes of the selected patch name.
+        
+        @param txt selected patch name (string)
+        """
+        self.__updateUI()
+    
+    def getData(self):
+        """
+        Public method to retrieve the entered data.
+        
+        @return tuple of new name and selected patch (string, string)
+        """
+        selectedPatch = ""
+        if self.namedButton.isChecked():
+            selectedPatch = self.nameCombo.currentText()
+        
+        return self.nameEdit.text(), selectedPatch
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesRenamePatchDialog.ui	Sun May 15 18:07:16 2011 +0200
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>HgQueuesRenamePatchDialog</class>
+ <widget class="QDialog" name="HgQueuesRenamePatchDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>174</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Rename Patch</string>
+  </property>
+  <property name="sizeGripEnabled">
+   <bool>true</bool>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout_2">
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <item>
+      <widget class="QLabel" name="label">
+       <property name="text">
+        <string>New Name:</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QLineEdit" name="nameEdit">
+       <property name="toolTip">
+        <string>Enter the new name for the selected patch</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="groupBox">
+     <property name="title">
+      <string>Patch</string>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout">
+      <item>
+       <widget class="QRadioButton" name="currentButton">
+        <property name="toolTip">
+         <string>Select to rename the current patch</string>
+        </property>
+        <property name="text">
+         <string notr="true">Current Patch</string>
+        </property>
+        <property name="checked">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QRadioButton" name="namedButton">
+        <property name="toolTip">
+         <string>Select to rename the selected named patch</string>
+        </property>
+        <property name="text">
+         <string>Named Patch</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QComboBox" name="nameCombo">
+        <property name="enabled">
+         <bool>false</bool>
+        </property>
+        <property name="toolTip">
+         <string>Select the patch to be renamed</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <tabstops>
+  <tabstop>nameEdit</tabstop>
+  <tabstop>currentButton</tabstop>
+  <tabstop>namedButton</tabstop>
+  <tabstop>nameCombo</tabstop>
+  <tabstop>buttonBox</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>HgQueuesRenamePatchDialog</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>HgQueuesRenamePatchDialog</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>
+  <connection>
+   <sender>namedButton</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>nameCombo</receiver>
+   <slot>setEnabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>59</x>
+     <y>106</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>63</x>
+     <y>136</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
--- a/Plugins/VcsPlugins/vcsMercurial/QueuesExtension/ProjectHelper.py	Sat May 14 20:00:13 2011 +0200
+++ b/Plugins/VcsPlugins/vcsMercurial/QueuesExtension/ProjectHelper.py	Sun May 15 18:07:16 2011 +0200
@@ -12,6 +12,8 @@
 
 from E5Gui.E5Action import E5Action
 
+from .queues import Queues
+
 
 class QueuesProjectHelper(QObject):
     """
@@ -75,6 +77,22 @@
         self.hgQueueRefreshAct.triggered[()].connect(self.__hgQueueRefreshPatch)
         self.actions.append(self.hgQueueRefreshAct)
         
+        self.hgQueueRefreshMessageAct = E5Action(
+                self.trUtf8('Update Current Patch (with Message)'),
+                self.trUtf8('Update Current Patch (with Message)'),
+                0, 0, self, 'mercurial_queues_refresh_message')
+        self.hgQueueRefreshMessageAct.setStatusTip(self.trUtf8(
+            'Update the current patch and edit commit message'
+        ))
+        self.hgQueueRefreshMessageAct.setWhatsThis(self.trUtf8(
+            """<b>Update Current Patch (with Message)</b>"""
+            """<p>This updates the current patch after giving the chance to change"""
+            """ the current commit message.</p>"""
+        ))
+        self.hgQueueRefreshMessageAct.triggered[()].connect(
+            self.__hgQueueRefreshPatchMessage)
+        self.actions.append(self.hgQueueRefreshMessageAct)
+        
         self.hgQueueDiffAct = E5Action(self.trUtf8('Show Current Patch'),
                 self.trUtf8('Show Current Patch...'),
                 0, 0, self, 'mercurial_queues_show')
@@ -90,6 +108,19 @@
         self.hgQueueDiffAct.triggered[()].connect(self.__hgQueueShowPatch)
         self.actions.append(self.hgQueueDiffAct)
         
+        self.hgQueueHeaderAct = E5Action(self.trUtf8('Show Current Message'),
+                self.trUtf8('Show Current Message...'),
+                0, 0, self, 'mercurial_queues_show_message')
+        self.hgQueueHeaderAct.setStatusTip(self.trUtf8(
+            'Show the commit message of the current patch'
+        ))
+        self.hgQueueHeaderAct.setWhatsThis(self.trUtf8(
+            """<b>Show Current Message</b>"""
+            """<p>This shows the commit message of the current patch.</p>"""
+        ))
+        self.hgQueueHeaderAct.triggered[()].connect(self.__hgQueueShowHeader)
+        self.actions.append(self.hgQueueHeaderAct)
+        
         self.hgQueueListAct = E5Action(self.trUtf8('List Patches'),
                 self.trUtf8('List Patches...'),
                 0, 0, self, 'mercurial_queues_list')
@@ -111,12 +142,51 @@
         ))
         self.hgQueueFinishAct.setWhatsThis(self.trUtf8(
             """<b>Finish Applied Patches</b>"""
-            """<p>This finishes the applied patches) by moving them out of"""
+            """<p>This finishes the applied patches by moving them out of"""
             """ mq control into regular repository history.</p>"""
         ))
         self.hgQueueFinishAct.triggered[()].connect(self.__hgQueueFinishAppliedPatches)
         self.actions.append(self.hgQueueFinishAct)
         
+        self.hgQueueRenameAct = E5Action(self.trUtf8('Rename Patch'),
+                self.trUtf8('Rename Patch'),
+                0, 0, self, 'mercurial_queues_rename')
+        self.hgQueueRenameAct.setStatusTip(self.trUtf8(
+            'Rename a patch'
+        ))
+        self.hgQueueRenameAct.setWhatsThis(self.trUtf8(
+            """<b>Rename Patch</b>"""
+            """<p>This renames the current or a named patch.</p>"""
+        ))
+        self.hgQueueRenameAct.triggered[()].connect(self.__hgQueueRenamePatch)
+        self.actions.append(self.hgQueueRenameAct)
+        
+        self.hgQueueDeleteAct = E5Action(self.trUtf8('Delete Patch'),
+                self.trUtf8('Delete Patch'),
+                0, 0, self, 'mercurial_queues_delete')
+        self.hgQueueDeleteAct.setStatusTip(self.trUtf8(
+            'Delete unapplied patch'
+        ))
+        self.hgQueueDeleteAct.setWhatsThis(self.trUtf8(
+            """<b>Delete Patch</b>"""
+            """<p>This deletes an unapplied patch.</p>"""
+        ))
+        self.hgQueueDeleteAct.triggered[()].connect(self.__hgQueueDeletePatch)
+        self.actions.append(self.hgQueueDeleteAct)
+        
+        self.hgQueueFoldAct = E5Action(self.trUtf8('Fold Patches'),
+                self.trUtf8('Fold Patches'),
+                0, 0, self, 'mercurial_queues_fold')
+        self.hgQueueFoldAct.setStatusTip(self.trUtf8(
+            'Fold unapplied patches into the current patch'
+        ))
+        self.hgQueueFoldAct.setWhatsThis(self.trUtf8(
+            """<b>Fold Patches</b>"""
+            """<p>This folds unapplied patches into the current patch.</p>"""
+        ))
+        self.hgQueueFoldAct.triggered[()].connect(self.__hgQueueFoldUnappliedPatches)
+        self.actions.append(self.hgQueueFoldAct)
+        
         self.__initPushPopActions()
         self.__initPushPopForceActions()
     
@@ -203,6 +273,20 @@
         ))
         self.hgQueuePopUntilAct.triggered[()].connect(self.__hgQueuePopPatches)
         self.actions.append(self.hgQueuePopUntilAct)
+        
+        self.hgQueueGotoAct = E5Action(self.trUtf8('Go to Patch'),
+                self.trUtf8('Go to Patch'),
+                0, 0, self, 'mercurial_queues_goto')
+        self.hgQueueGotoAct.setStatusTip(self.trUtf8(
+            'Push or pop patches until named patch is at top of stack'
+        ))
+        self.hgQueueGotoAct.setWhatsThis(self.trUtf8(
+            """<b>Go to Patch</b>"""
+            """<p>This pushes or pops patches until a named patch is at the"""
+            """ top of the stack.</p>"""
+        ))
+        self.hgQueueGotoAct.triggered[()].connect(self.__hgQueueGotoPatch)
+        self.actions.append(self.hgQueueGotoAct)
     
     def __initPushPopForceActions(self):
         """
@@ -294,6 +378,21 @@
         ))
         self.hgQueuePopUntilForceAct.triggered[()].connect(self.__hgQueuePopPatchesForced)
         self.actions.append(self.hgQueuePopUntilForceAct)
+        
+        self.hgQueueGotoForceAct = E5Action(self.trUtf8('Go to Patch'),
+                self.trUtf8('Go to Patch'),
+                0, 0, self, 'mercurial_queues_goto_force')
+        self.hgQueueGotoForceAct.setStatusTip(self.trUtf8(
+            'Push or pop patches until named patch is at top of stack overwriting'
+            ' any local changes'
+        ))
+        self.hgQueueGotoForceAct.setWhatsThis(self.trUtf8(
+            """<b>Go to Patch</b>"""
+            """<p>This pushes or pops patches until a named patch is at the"""
+            """ top of the stack overwriting any local changes.</p>"""
+        ))
+        self.hgQueueGotoForceAct.triggered[()].connect(self.__hgQueueGotoPatchForced)
+        self.actions.append(self.hgQueueGotoForceAct)
     
     def initMenu(self, mainMenu):
         """
@@ -308,28 +407,41 @@
         pushPopMenu.addAction(self.hgQueuePushAct)
         pushPopMenu.addAction(self.hgQueuePushUntilAct)
         pushPopMenu.addAction(self.hgQueuePushAllAct)
+        pushPopMenu.addSeparator()
         pushPopMenu.addAction(self.hgQueuePopAct)
         pushPopMenu.addAction(self.hgQueuePopUntilAct)
         pushPopMenu.addAction(self.hgQueuePopAllAct)
+        pushPopMenu.addSeparator()
+        pushPopMenu.addAction(self.hgQueueGotoAct)
         
         pushPopForceMenu = QMenu(self.trUtf8("Push/Pop (force)"), menu)
         pushPopForceMenu.addAction(self.hgQueuePushForceAct)
         pushPopForceMenu.addAction(self.hgQueuePushUntilForceAct)
         pushPopForceMenu.addAction(self.hgQueuePushAllForceAct)
+        pushPopForceMenu.addSeparator()
         pushPopForceMenu.addAction(self.hgQueuePopForceAct)
         pushPopForceMenu.addAction(self.hgQueuePopUntilForceAct)
         pushPopForceMenu.addAction(self.hgQueuePopAllForceAct)
+        pushPopForceMenu.addSeparator()
+        pushPopForceMenu.addAction(self.hgQueueGotoForceAct)
         
         menu.addAction(self.hgQueueNewAct)
         menu.addAction(self.hgQueueRefreshAct)
+        menu.addAction(self.hgQueueRefreshMessageAct)
         menu.addAction(self.hgQueueFinishAct)
         menu.addSeparator()
         menu.addAction(self.hgQueueDiffAct)
+        menu.addAction(self.hgQueueHeaderAct)
         menu.addSeparator()
         menu.addAction(self.hgQueueListAct)
         menu.addSeparator()
         menu.addMenu(pushPopMenu)
         menu.addMenu(pushPopForceMenu)
+        menu.addSeparator()
+        menu.addAction(self.hgQueueRenameAct)
+        menu.addAction(self.hgQueueDeleteAct)
+        menu.addSeparator()
+        menu.addAction(self.hgQueueFoldAct)
         
         return menu
     
@@ -347,6 +459,13 @@
         self.vcs.getExtensionObject("mq")\
             .hgQueueRefreshPatch(self.project.getProjectPath())
     
+    def __hgQueueRefreshPatchMessage(self):
+        """
+        Private slot used to refresh the current patch and it's commit message. 
+        """
+        self.vcs.getExtensionObject("mq")\
+            .hgQueueRefreshPatch(self.project.getProjectPath(), editMessage=True)
+    
     def __hgQueueShowPatch(self):
         """
         Private slot used to show the contents of the current patch. 
@@ -354,13 +473,20 @@
         self.vcs.getExtensionObject("mq")\
             .hgQueueShowPatch(self.project.getProjectPath())
     
+    def __hgQueueShowHeader(self):
+        """
+        Private slot used to show the commit message of the current patch. 
+        """
+        self.vcs.getExtensionObject("mq")\
+            .hgQueueShowHeader(self.project.getProjectPath())
+    
     def __hgQueuePushPatch(self):
         """
         Private slot used to push the next patch onto the stack. 
         """
         self.vcs.getExtensionObject("mq")\
             .hgQueuePushPopPatches(self.project.getProjectPath(), 
-                pop=False, all=False, named=False)
+                operation=Queues.PUSH, all=False, named=False)
     
     def __hgQueuePushPatchForced(self):
         """
@@ -369,7 +495,7 @@
         """
         self.vcs.getExtensionObject("mq")\
             .hgQueuePushPopPatches(self.project.getProjectPath(), 
-                pop=False, all=False, named=False, force=True)
+                operation=Queues.PUSH, all=False, named=False, force=True)
     
     def __hgQueuePushAllPatches(self):
         """
@@ -377,7 +503,7 @@
         """
         self.vcs.getExtensionObject("mq")\
             .hgQueuePushPopPatches(self.project.getProjectPath(), 
-                pop=False, all=True, named=False)
+                operation=Queues.PUSH, all=True, named=False)
     
     def __hgQueuePushAllPatchesForced(self):
         """
@@ -386,7 +512,7 @@
         """
         self.vcs.getExtensionObject("mq")\
             .hgQueuePushPopPatches(self.project.getProjectPath(), 
-                pop=False, all=True, named=False, force=True)
+                operation=Queues.PUSH, all=True, named=False, force=True)
     
     def __hgQueuePushPatches(self):
         """
@@ -395,7 +521,7 @@
         """
         self.vcs.getExtensionObject("mq")\
             .hgQueuePushPopPatches(self.project.getProjectPath(), 
-                pop=False, all=False, named=True)
+                operation=Queues.PUSH, all=False, named=True)
     
     def __hgQueuePushPatchesForced(self):
         """
@@ -404,7 +530,7 @@
         """
         self.vcs.getExtensionObject("mq")\
             .hgQueuePushPopPatches(self.project.getProjectPath(), 
-                pop=False, all=False, named=True, force=True)
+                operation=Queues.PUSH, all=False, named=True, force=True)
     
     def __hgQueuePopPatch(self):
         """
@@ -412,7 +538,7 @@
         """
         self.vcs.getExtensionObject("mq")\
             .hgQueuePushPopPatches(self.project.getProjectPath(), 
-                pop=True, all=False, named=False)
+                operation=Queues.POP, all=False, named=False)
     
     def __hgQueuePopPatchForced(self):
         """
@@ -421,7 +547,7 @@
         """
         self.vcs.getExtensionObject("mq")\
             .hgQueuePushPopPatches(self.project.getProjectPath(), 
-                pop=True, all=False, named=False)
+                operation=Queues.POP, all=False, named=False, force=True)
     
     def __hgQueuePopAllPatches(self):
         """
@@ -429,7 +555,7 @@
         """
         self.vcs.getExtensionObject("mq")\
             .hgQueuePushPopPatches(self.project.getProjectPath(), 
-                pop=True, all=True, named=False)
+                operation=Queues.POP, all=True, named=False)
     
     def __hgQueuePopAllPatchesForced(self):
         """
@@ -438,7 +564,7 @@
         """
         self.vcs.getExtensionObject("mq")\
             .hgQueuePushPopPatches(self.project.getProjectPath(), 
-                pop=True, all=True, named=False, force=True)
+                operation=Queues.POP, all=True, named=False, force=True)
     
     def __hgQueuePopPatches(self):
         """
@@ -447,7 +573,7 @@
         """
         self.vcs.getExtensionObject("mq")\
             .hgQueuePushPopPatches(self.project.getProjectPath(), 
-                pop=True, all=False, named=True)
+                operation=Queues.POP, all=False, named=True)
     
     def __hgQueuePopPatchesForced(self):
         """
@@ -456,18 +582,57 @@
         """
         self.vcs.getExtensionObject("mq")\
             .hgQueuePushPopPatches(self.project.getProjectPath(), 
-                pop=True, all=False, named=True)
+                operation=Queues.POP, all=False, named=True, force=True)
+    
+    def __hgQueueGotoPatch(self):
+        """
+        Private slot used to push or pop patches until the a named one
+        is at the top of the stack.
+        """
+        self.vcs.getExtensionObject("mq")\
+            .hgQueuePushPopPatches(self.project.getProjectPath(), 
+                operation=Queues.GOTO, all=False, named=True)
+    
+    def __hgQueueGotoPatchForced(self):
+        """
+        Private slot used to push or pop patches until the a named one
+        is at the top of the stack overwriting local changes.
+        """
+        self.vcs.getExtensionObject("mq")\
+            .hgQueuePushPopPatches(self.project.getProjectPath(), 
+                operation=Queues.GOTO, all=False, named=True, force=True)
     
     def __hgQueueListPatches(self):
         """
-        Private slot used to show a list of applied and unapplied patches. 
+        Private slot used to show a list of applied and unapplied patches.
         """
         self.vcs.getExtensionObject("mq")\
             .hgQueueListPatches(self.project.getProjectPath())
     
     def __hgQueueFinishAppliedPatches(self):
         """
-        Private slot used to finish all applied patches. 
+        Private slot used to finish all applied patches.
         """
         self.vcs.getExtensionObject("mq")\
             .hgQueueFinishAppliedPatches(self.project.getProjectPath())
+    
+    def __hgQueueRenamePatch(self):
+        """
+        Private slot used to rename a patch.
+        """
+        self.vcs.getExtensionObject("mq")\
+            .hgQueueRenamePatch(self.project.getProjectPath())
+    
+    def __hgQueueDeletePatch(self):
+        """
+        Private slot used to delete a patch.
+        """
+        self.vcs.getExtensionObject("mq")\
+            .hgQueueDeletePatch(self.project.getProjectPath())
+    
+    def __hgQueueFoldUnappliedPatches(self):
+        """
+        Private slot used to fold patches into the current patch.
+        """
+        self.vcs.getExtensionObject("mq")\
+            .hgQueueFoldUnappliedPatches(self.project.getProjectPath())
--- a/Plugins/VcsPlugins/vcsMercurial/QueuesExtension/queues.py	Sat May 14 20:00:13 2011 +0200
+++ b/Plugins/VcsPlugins/vcsMercurial/QueuesExtension/queues.py	Sun May 15 18:07:16 2011 +0200
@@ -18,6 +18,9 @@
 
 from .HgQueuesNewPatchDialog import HgQueuesNewPatchDialog
 from .HgQueuesListDialog import HgQueuesListDialog
+from .HgQueuesRenamePatchDialog import HgQueuesRenamePatchDialog
+from .HgQueuesFoldDialog import HgQueuesFoldDialog
+from .HgQueuesHeaderDialog import HgQueuesHeaderDialog
 
 import Preferences
 
@@ -30,6 +33,10 @@
     UNAPPLIED_LIST = 1
     SERIES_LIST = 2
     
+    POP = 0
+    PUSH = 1
+    GOTO = 2
+    
     def __init__(self, vcs):
         """
         Constructor
@@ -39,6 +46,7 @@
         self.vcs = vcs
         
         self.qdiffDialog = None
+        self.qheaderDialog = None
     
     def shutdown(self):
         """
@@ -46,6 +54,107 @@
         """
         if self.qdiffDialog is not None:
             self.qdiffDialog.close()
+        if self.qheaderDialog is not None:
+            self.qheaderDialog.close()
+    
+    def __getPatchesList(self, repodir, listType, withSummary=False):
+        """
+        Public method to get a list of patches of a given type.
+        
+        @param repodir directory name of the repository (string)
+        @param listType type of patches list to get
+            (Queues.APPLIED_LIST, Queues.UNAPPLIED_LIST, Queues.SERIES_LIST)
+        @param withSummary flag indicating to get a summary as well (boolean)
+        @return list of patches (list of string)
+        """
+        patchesList = []
+        
+        ioEncoding = Preferences.getSystem("IOEncoding")
+        process = QProcess()
+        args = []
+        if listType == Queues.APPLIED_LIST:
+            args.append("qapplied")
+        elif listType == Queues.UNAPPLIED_LIST:
+            args.append("qunapplied")
+        elif listType == Queues.SERIES_LIST:
+            args.append("qseries")
+        else:
+            raise ValueError("illegal value for listType")
+        if withSummary:
+            args.append("--summary")
+        
+        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')
+                for line in output.splitlines():
+                    if withSummary:
+                        l = line.strip().split(": ")
+                        if len(l) == 1:
+                            patch, summary = l[0][:-1], ""
+                        else:
+                            patch, summary = l[0], l[1]
+                        patchesList.append("{0}@@{1}".format(patch, summary))
+                    else:
+                        patchesList.append(line.strip())
+        
+        return patchesList
+    
+    def __getCurrentPatch(self, repodir):
+        """
+        Public method to get the name of the current patch.
+        
+        @param repodir directory name of the repository (string)
+        @return name of the current patch (string)
+        """
+        currentPatch = ""
+        
+        ioEncoding = Preferences.getSystem("IOEncoding")
+        process = QProcess()
+        args = []
+        args.append("qtop")
+        
+        process.setWorkingDirectory(repodir)
+        process.start('hg', args)
+        procStarted = process.waitForStarted()
+        if procStarted:
+            finished = process.waitForFinished(30000)
+            if finished and process.exitCode() == 0:
+                currentPatch = str(
+                    process.readAllStandardOutput(),
+                    ioEncoding, 'replace').strip()
+        
+        return currentPatch
+    
+    def __getCommitMessage(self, repodir):
+        """
+        Public method to get the commit message of the current patch.
+        
+        @param repodir directory name of the repository (string)
+        @return name of the current patch (string)
+        """
+        message = ""
+        
+        ioEncoding = Preferences.getSystem("IOEncoding")
+        process = QProcess()
+        args = []
+        args.append("qheader")
+        
+        process.setWorkingDirectory(repodir)
+        process.start('hg', args)
+        procStarted = process.waitForStarted()
+        if procStarted:
+            finished = process.waitForFinished(30000)
+            if finished and process.exitCode() == 0:
+                message = str(
+                    process.readAllStandardOutput(),
+                    ioEncoding, 'replace')
+        
+        return message
     
     def hgQueueNewPatch(self, name):
         """
@@ -60,7 +169,7 @@
             if repodir == os.sep:
                 return
         
-        dlg = HgQueuesNewPatchDialog()
+        dlg = HgQueuesNewPatchDialog(HgQueuesNewPatchDialog.NEW_MODE)
         if dlg.exec_() == QDialog.Accepted:
             name, message, (userData, currentUser, userName), \
             (dateData, currentDate, dateStr) = dlg.getData()
@@ -90,11 +199,13 @@
                 dia.exec_()
                 self.vcs.checkVCSStatus()
     
-    def hgQueueRefreshPatch(self, name):
+    def hgQueueRefreshPatch(self, name, editMessage=False):
         """
-        Public method to create a new named patch.
+        Public method to refresh the current patch.
         
         @param name file/directory name (string)
+        @param editMessage flag indicating to edit the current
+            commit message (boolean)
         """
         # find the root of the repo
         repodir = self.vcs.splitPath(name)[0]
@@ -106,6 +217,31 @@
         args = []
         args.append("qrefresh")
         
+        if editMessage:
+            currentMessage = self.__getCommitMessage(repodir)
+            dlg = HgQueuesNewPatchDialog(HgQueuesNewPatchDialog.REFRESH_MODE,
+                                         currentMessage)
+            if dlg.exec_() == QDialog.Accepted:
+                name, message, (userData, currentUser, userName), \
+                (dateData, currentDate, dateStr) = dlg.getData()
+                if message != "" and message != currentMessage:
+                    args.append("--message")
+                    args.append(message)
+                if userData:
+                    if currentUser:
+                        args.append("--currentuser")
+                    else:
+                        args.append("--user")
+                        args.append(userName)
+                if dateData:
+                    if currentDate:
+                        args.append("--currentdate")
+                    else:
+                        args.append("--date")
+                        args.append(dateStr)
+            else:
+                return
+        
         dia = HgDialog(self.trUtf8('Update Current Patch'))
         res = dia.startProcess(args, repodir)
         if res:
@@ -114,7 +250,7 @@
     
     def hgQueueShowPatch(self, name):
         """
-        Public method to create a new named patch.
+        Public method to show the contents of the current patch.
         
         @param name file/directory name (string)
         """
@@ -123,12 +259,24 @@
         QApplication.processEvents()
         self.qdiffDialog.start(name, qdiff=True)
     
-    def hgQueuePushPopPatches(self, name, pop=False, all=False, named=False, force=False):
+    def hgQueueShowHeader(self, name):
+        """
+        Public method to show the commit message of the current patch.
+        
+        @param name file/directory name (string)
+        """
+        self.qheaderDialog = HgQueuesHeaderDialog(self.vcs)
+        self.qheaderDialog.show()
+        QApplication.processEvents()
+        self.qheaderDialog.start(name)
+    
+    def hgQueuePushPopPatches(self, name, operation, all=False, named=False, force=False):
         """
         Public method to push patches onto the stack or pop patches off the stack.
         
         @param name file/directory name (string)
-        @keyparam pop flag indicating a pop action (boolean)
+        @param operation operation type to be performed (Queues.POP,
+            Queues.PUSH, Queues.GOTO)
         @keyparam all flag indicating to push/pop all (boolean)
         @keyparam named flag indicating to push/pop until a named patch
             is at the top of the stack (boolean)
@@ -142,20 +290,26 @@
                 return
         
         args = []
-        if pop:
+        if operation == Queues.POP:
             args.append("qpop")
             title = self.trUtf8("Pop Patches")
             listType = Queues.APPLIED_LIST
-        else:
+        elif operation == Queues.PUSH:
             args.append("qpush")
             title = self.trUtf8("Push Patches")
             listType = Queues.UNAPPLIED_LIST
+        elif operation == Queues.GOTO:
+            args.append("qgoto")
+            title = self.trUtf8("Go to Patch")
+            listType = Queues.SERIES_LIST
+        else:
+            raise ValueError("illegal value for operation")
         if force:
             args.append("--force")
-        if all:
+        if all and operation in (Queues.POP, Queues.PUSH):
             args.append("--all")
-        elif named:
-            patchnames = self.__getUnAppliedPatches(repodir, listType)
+        elif named or operation == Queues.GOTO:
+            patchnames = self.__getPatchesList(repodir, listType)
             if patchnames:
                 patch, ok = QInputDialog.getItem(
                     None,
@@ -179,45 +333,9 @@
             dia.exec_()
             self.vcs.checkVCSStatus()
     
-    def __getUnAppliedPatches(self, repodir, listType):
-        """
-        Public method to get the list of applied or unapplied patches.
-        
-        @param repodir directory name of the repository (string)
-        @param listType type of patcheslist to get
-            (Queues.APPLIED_LIST, Queues.UNAPPLIED_LIST, Queues.SERIES_LIST)
-        @return list of patches (list of string)
-        """
-        patchesList = []
-        
-        ioEncoding = Preferences.getSystem("IOEncoding")
-        process = QProcess()
-        args = []
-        if listType == Queues.APPLIED_LIST:
-            args.append("qapplied")
-        elif listType == Queues.UNAPPLIED_LIST:
-            args.append("qunapplied")
-        elif listType == Queues.SERIES_LIST:
-            args.append("qseries")
-        else:
-            raise ValueError("Illegal value for listType.")
-        
-        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')
-                for line in output.splitlines():
-                    patchesList.append(line.strip())
-        
-        return patchesList
-    
     def hgQueueListPatches(self, name):
         """
-        Public method to create a new named patch.
+        Public method to show a list of all patches.
         
         @param name file/directory name (string)
         """
@@ -227,7 +345,7 @@
     
     def hgQueueFinishAppliedPatches(self, name):
         """
-        Public method to create a new named patch.
+        Public method to finish all applied patches.
         
         @param name file/directory name (string)
         """
@@ -247,3 +365,109 @@
         if res:
             dia.exec_()
             self.vcs.checkVCSStatus()
+    
+    def hgQueueRenamePatch(self, name):
+        """
+        Public method to rename the current or a selected 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
+        
+        args = []
+        args.append("qrename")
+        patchnames = sorted(self.__getPatchesList(repodir, Queues.SERIES_LIST))
+        if patchnames:
+            currentPatch = self.__getCurrentPatch(repodir)
+            if currentPatch:
+                dlg = HgQueuesRenamePatchDialog(currentPatch, patchnames)
+                if dlg.exec_() == QDialog.Accepted:
+                    newName, selectedPatch = dlg.getData()
+                    if selectedPatch:
+                        args.append(selectedPatch)
+                    args.append(newName)
+                    
+                    dia = HgDialog(self.trUtf8("Rename Patch"))
+                    res = dia.startProcess(args, repodir)
+                    if res:
+                        dia.exec_()
+    
+    def hgQueueDeletePatch(self, name):
+        """
+        Public method to delete a selected unapplied 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
+        
+        args = []
+        args.append("qdelete")
+        patchnames = sorted(self.__getPatchesList(repodir, Queues.UNAPPLIED_LIST))
+        if patchnames:
+            patch, ok = QInputDialog.getItem(
+                None,
+                self.trUtf8("Select Patch"),
+                self.trUtf8("Select the patch to be deleted:"),
+                patchnames,
+                0, False)
+            if ok and patch:
+                args.append(patch)
+                
+                dia = HgDialog(self.trUtf8("Delete Patch"))
+                res = dia.startProcess(args, repodir)
+                if res:
+                    dia.exec_()
+        else:
+            E5MessageBox.information(None,
+                self.trUtf8("Select Patch"),
+                self.trUtf8("""No patches to select from."""))
+    
+    def hgQueueFoldUnappliedPatches(self, name):
+        """
+        Public method to fold patches into the current 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
+        
+        args = []
+        args.append("qfold")
+        patchnames = sorted(
+            self.__getPatchesList(repodir, Queues.UNAPPLIED_LIST, withSummary=True))
+        if patchnames:
+            dlg = HgQueuesFoldDialog(patchnames)
+            if dlg.exec_() == QDialog.Accepted:
+                message, patchesList = dlg.getData()
+                if message:
+                    args.append("--message")
+                    args.append(message)
+                if patchesList:
+                    args.extend(patchesList)
+                    
+                    dia = HgDialog(self.trUtf8("Fold Patches"))
+                    res = dia.startProcess(args, repodir)
+                    if res:
+                        dia.exec_()
+                else:
+                    E5MessageBox.information(None,
+                        self.trUtf8("Fold Patches"),
+                        self.trUtf8("""No patches selected."""))
+        else:
+            E5MessageBox.information(None,
+                self.trUtf8("Fold Patches"),
+                self.trUtf8("""No patches available to be folded."""))
--- a/eric5.e4p	Sat May 14 20:00:13 2011 +0200
+++ b/eric5.e4p	Sun May 15 18:07:16 2011 +0200
@@ -888,6 +888,10 @@
     <Source>Plugins/VcsPlugins/vcsMercurial/QueuesExtension/ProjectHelper.py</Source>
     <Source>Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesNewPatchDialog.py</Source>
     <Source>Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesListDialog.py</Source>
+    <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/HgQueuesMessageDialog.py</Source>
   </Sources>
   <Forms>
     <Form>PyUnit/UnittestDialog.ui</Form>
@@ -1133,6 +1137,10 @@
     <Form>Plugins/VcsPlugins/vcsMercurial/BookmarksExtension/HgBookmarksInOutDialog.ui</Form>
     <Form>Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesNewPatchDialog.ui</Form>
     <Form>Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesListDialog.ui</Form>
+    <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/HgQueuesMessageDialog.ui</Form>
   </Forms>
   <Translations>
     <Translation>i18n/eric5_cs.qm</Translation>

eric ide

mercurial