Sun, 15 May 2011 18:07:16 +0200
Continued with support for Mercurial queues extension.
--- /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>