Continued with Mercurial bookmark support.

Sat, 07 May 2011 20:31:28 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Sat, 07 May 2011 20:31:28 +0200
changeset 1018
949812411ab8
parent 1017
919147f2b518
child 1019
d8a9697f78d1

Continued with Mercurial bookmark support.

Plugins/VcsPlugins/vcsMercurial/BookmarksExtension/HgBookmarksInOutDialog.py file | annotate | diff | comparison | revisions
Plugins/VcsPlugins/vcsMercurial/BookmarksExtension/HgBookmarksInOutDialog.ui file | annotate | diff | comparison | revisions
Plugins/VcsPlugins/vcsMercurial/BookmarksExtension/ProjectHelper.py file | annotate | diff | comparison | revisions
Plugins/VcsPlugins/vcsMercurial/BookmarksExtension/bookmarks.py file | annotate | diff | comparison | revisions
Plugins/VcsPlugins/vcsMercurial/hg.py file | annotate | diff | comparison | revisions
eric5.e4p file | annotate | diff | comparison | revisions
icons/default/deleteBookmark.png file | annotate | diff | comparison | revisions
icons/default/listBookmarks.png file | annotate | diff | comparison | revisions
icons/default/moveBookmark.png file | annotate | diff | comparison | revisions
icons/default/renameBookmark.png file | annotate | diff | comparison | revisions
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/VcsPlugins/vcsMercurial/BookmarksExtension/HgBookmarksInOutDialog.py	Sat May 07 20:31:28 2011 +0200
@@ -0,0 +1,280 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2011 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a dialog to show a list of incoming or outgoing bookmarks.
+"""
+
+import os
+
+from PyQt4.QtCore import pyqtSlot, QProcess, Qt, QTimer
+from PyQt4.QtGui import QDialog, QDialogButtonBox, QHeaderView, QTreeWidgetItem, \
+    QLineEdit
+
+from E5Gui import E5MessageBox
+
+from .Ui_HgBookmarksInOutDialog import Ui_HgBookmarksInOutDialog
+
+import Preferences
+
+
+class HgBookmarksInOutDialog(QDialog, Ui_HgBookmarksInOutDialog):
+    """
+    Class implementing a dialog to show a list of incoming or outgoing bookmarks.
+    """
+    INCOMING = 0
+    OUTGOING = 1
+    
+    def __init__(self, vcs, mode, parent=None):
+        """
+        Constructor
+        
+        @param vcs reference to the vcs object
+        @param mode mode of the dialog (HgBookmarksInOutDialog.INCOMING,
+            HgBookmarksInOutDialog.OUTGOING)
+        @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)
+        
+        if mode not in [self.INCOMING, self.OUTGOING]:
+            raise ValueError("Bad value for mode")
+        if mode == self.INCOMING:
+            self.setWindowTitle(self.trUtf8("Mercurial Incoming Bookmarks"))
+        elif mode == self.OUTGOING:
+            self.setWindowTitle(self.trUtf8("Mercurial Outgoing Bookmarks"))
+        
+        self.process = QProcess()
+        self.vcs = vcs
+        self.mode = mode
+        
+        self.bookmarksList.headerItem().setText(self.bookmarksList.columnCount(), "")
+        self.bookmarksList.header().setSortIndicator(3, Qt.AscendingOrder)
+        
+        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 bookmarks command.
+        
+        @param path name of directory to be listed (string)
+        """
+        self.errorGroup.hide()
+        
+        self.intercept = False
+        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 = []
+        if self.mode == self.INCOMING:
+            args.append('incoming')
+        elif self.mode == self.OUTGOING:
+            args.append('outgoing')
+        else:
+            raise ValueError("Bad value for mode")
+        args.append('--bookmarks')
+        
+        self.process.kill()
+        self.process.setWorkingDirectory(repodir)
+        
+        self.process.start('hg', args)
+        procStarted = self.process.waitForStarted()
+        if not procStarted:
+            self.inputGroup.setEnabled(False)
+            self.inputGroup.hide()
+            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'))
+        else:
+            self.inputGroup.setEnabled(True)
+            self.inputGroup.show()
+    
+    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.inputGroup.setEnabled(False)
+        self.inputGroup.hide()
+        
+        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
+        
+        if self.bookmarksList.topLevelItemCount() == 0:
+            # no bookmarks defined
+            self.__generateItem(self.trUtf8("no bookmarks found"), "")
+        self.bookmarksList.doItemsLayout()
+        self.__resizeColumns()
+        self.__resort()
+    
+    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 __resort(self):
+        """
+        Private method to resort the tree.
+        """
+        self.bookmarksList.sortItems(self.bookmarksList.sortColumn(),
+            self.bookmarksList.header().sortIndicatorOrder())
+    
+    def __resizeColumns(self):
+        """
+        Private method to resize the list columns.
+        """
+        self.bookmarksList.header().resizeSections(QHeaderView.ResizeToContents)
+        self.bookmarksList.header().setStretchLastSection(True)
+    
+    def __generateItem(self, changeset, name):
+        """
+        Private method to generate a bookmark item in the bookmarks list.
+        
+        @param changeset changeset of the bookmark (string)
+        @param name name of the bookmark (string)
+        """
+        itm = QTreeWidgetItem(self.bookmarksList, [
+            name,
+            changeset])
+        itm.setTextAlignment(1, Qt.AlignRight)
+    
+    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.
+        """
+        self.process.setReadChannel(QProcess.StandardOutput)
+        
+        while self.process.canReadLine():
+            s = str(self.process.readLine(),
+                    Preferences.getSystem("IOEncoding"),
+                    'replace')
+            if s.startswith(" "):
+                l = s.strip().split()
+                changeset = l[-1]
+                del l[-1]
+                name = " ".join(l)
+                self.__generateItem(changeset, name)
+    
+    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:
+            self.errorGroup.show()
+            s = str(self.process.readAllStandardError(),
+                    Preferences.getSystem("IOEncoding"),
+                    'replace')
+            self.errors.insertPlainText(s)
+            self.errors.ensureCursorVisible()
+    
+    def on_passwordCheckBox_toggled(self, isOn):
+        """
+        Private slot to handle the password checkbox toggled.
+        
+        @param isOn flag indicating the status of the check box (boolean)
+        """
+        if isOn:
+            self.input.setEchoMode(QLineEdit.Password)
+        else:
+            self.input.setEchoMode(QLineEdit.Normal)
+    
+    @pyqtSlot()
+    def on_sendButton_clicked(self):
+        """
+        Private slot to send the input to the subversion process.
+        """
+        input = self.input.text()
+        input += os.linesep
+        
+        if self.passwordCheckBox.isChecked():
+            self.errors.insertPlainText(os.linesep)
+            self.errors.ensureCursorVisible()
+        else:
+            self.errors.insertPlainText(input)
+            self.errors.ensureCursorVisible()
+        
+        self.process.write(input)
+        
+        self.passwordCheckBox.setChecked(False)
+        self.input.clear()
+    
+    def on_input_returnPressed(self):
+        """
+        Private slot to handle the press of the return key in the input field.
+        """
+        self.intercept = True
+        self.on_sendButton_clicked()
+    
+    def keyPressEvent(self, evt):
+        """
+        Protected slot to handle a key press event.
+        
+        @param evt the key press event (QKeyEvent)
+        """
+        if self.intercept:
+            self.intercept = False
+            evt.accept()
+            return
+        QDialog.keyPressEvent(self, evt)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/VcsPlugins/vcsMercurial/BookmarksExtension/HgBookmarksInOutDialog.ui	Sat May 07 20:31:28 2011 +0200
@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>HgBookmarksInOutDialog</class>
+ <widget class="QDialog" name="HgBookmarksInOutDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>520</width>
+    <height>494</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string/>
+  </property>
+  <property name="sizeGripEnabled">
+   <bool>true</bool>
+  </property>
+  <layout class="QVBoxLayout">
+   <item>
+    <widget class="QTreeWidget" name="bookmarksList">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+       <horstretch>0</horstretch>
+       <verstretch>2</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="focusPolicy">
+      <enum>Qt::NoFocus</enum>
+     </property>
+     <property name="whatsThis">
+      <string>&lt;b&gt;Bookmarks List&lt;/b&gt;
+&lt;p&gt;This shows a list of the bookmarks.&lt;/p&gt;</string>
+     </property>
+     <property name="alternatingRowColors">
+      <bool>true</bool>
+     </property>
+     <property name="rootIsDecorated">
+      <bool>false</bool>
+     </property>
+     <property name="itemsExpandable">
+      <bool>false</bool>
+     </property>
+     <property name="sortingEnabled">
+      <bool>true</bool>
+     </property>
+     <column>
+      <property name="text">
+       <string>Name</string>
+      </property>
+     </column>
+     <column>
+      <property name="text">
+       <string>Changeset</string>
+      </property>
+     </column>
+    </widget>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="errorGroup">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
+       <horstretch>0</horstretch>
+       <verstretch>1</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="title">
+      <string>Errors</string>
+     </property>
+     <layout class="QVBoxLayout">
+      <item>
+       <widget class="QTextEdit" name="errors">
+        <property name="focusPolicy">
+         <enum>Qt::NoFocus</enum>
+        </property>
+        <property name="readOnly">
+         <bool>true</bool>
+        </property>
+        <property name="acceptRichText">
+         <bool>false</bool>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="inputGroup">
+     <property name="title">
+      <string>Input</string>
+     </property>
+     <layout class="QGridLayout">
+      <item row="1" column="1">
+       <spacer>
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeType">
+         <enum>QSizePolicy::Expanding</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>327</width>
+          <height>29</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item row="1" column="2">
+       <widget class="QPushButton" name="sendButton">
+        <property name="toolTip">
+         <string>Press to send the input to the hg process</string>
+        </property>
+        <property name="text">
+         <string>&amp;Send</string>
+        </property>
+        <property name="shortcut">
+         <string>Alt+S</string>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="0" colspan="3">
+       <widget class="QLineEdit" name="input">
+        <property name="toolTip">
+         <string>Enter data to be sent to the hg process</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="0">
+       <widget class="QCheckBox" name="passwordCheckBox">
+        <property name="toolTip">
+         <string>Select to switch the input field to password mode</string>
+        </property>
+        <property name="text">
+         <string>&amp;Password Mode</string>
+        </property>
+        <property name="shortcut">
+         <string>Alt+P</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::Close</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <pixmapfunction>qPixmapFromMimeSource</pixmapfunction>
+ <tabstops>
+  <tabstop>input</tabstop>
+  <tabstop>passwordCheckBox</tabstop>
+  <tabstop>sendButton</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
--- a/Plugins/VcsPlugins/vcsMercurial/BookmarksExtension/ProjectHelper.py	Sat May 07 17:56:31 2011 +0200
+++ b/Plugins/VcsPlugins/vcsMercurial/BookmarksExtension/ProjectHelper.py	Sat May 07 20:31:28 2011 +0200
@@ -12,6 +12,8 @@
 
 from E5Gui.E5Action import E5Action
 
+import UI.PixmapCache
+
 
 class BookmarksProjectHelper(QObject):
     """
@@ -50,6 +52,7 @@
         Public method to generate the action objects.
         """
         self.hgBookmarksListAct = E5Action(self.trUtf8('List bookmarks'),
+                UI.PixmapCache.getIcon("listBookmarks.png"),
                 self.trUtf8('List bookmarks...'),
                 0, 0, self, 'mercurial_list_bookmarks')
         self.hgBookmarksListAct.setStatusTip(self.trUtf8(
@@ -63,6 +66,7 @@
         self.actions.append(self.hgBookmarksListAct)
     
         self.hgBookmarkDefineAct = E5Action(self.trUtf8('Define bookmark'),
+                UI.PixmapCache.getIcon("addBookmark.png"),
                 self.trUtf8('Define bookmark...'),
                 0, 0, self, 'mercurial_define_bookmark')
         self.hgBookmarkDefineAct.setStatusTip(self.trUtf8(
@@ -76,6 +80,7 @@
         self.actions.append(self.hgBookmarkDefineAct)
     
         self.hgBookmarkDeleteAct = E5Action(self.trUtf8('Delete bookmark'),
+                UI.PixmapCache.getIcon("deleteBookmark.png"),
                 self.trUtf8('Delete bookmark...'),
                 0, 0, self, 'mercurial_delete_bookmark')
         self.hgBookmarkDeleteAct.setStatusTip(self.trUtf8(
@@ -89,6 +94,7 @@
         self.actions.append(self.hgBookmarkDeleteAct)
     
         self.hgBookmarkRenameAct = E5Action(self.trUtf8('Rename bookmark'),
+                UI.PixmapCache.getIcon("renameBookmark.png"),
                 self.trUtf8('Rename bookmark...'),
                 0, 0, self, 'mercurial_rename_bookmark')
         self.hgBookmarkRenameAct.setStatusTip(self.trUtf8(
@@ -102,6 +108,7 @@
         self.actions.append(self.hgBookmarkRenameAct)
     
         self.hgBookmarkMoveAct = E5Action(self.trUtf8('Move bookmark'),
+                UI.PixmapCache.getIcon("moveBookmark.png"),
                 self.trUtf8('Move bookmark...'),
                 0, 0, self, 'mercurial_move_bookmark')
         self.hgBookmarkMoveAct.setStatusTip(self.trUtf8(
@@ -113,6 +120,66 @@
         ))
         self.hgBookmarkMoveAct.triggered[()].connect(self.__hgBookmarkMove)
         self.actions.append(self.hgBookmarkMoveAct)
+        
+        self.hgBookmarkIncomingAct = E5Action(self.trUtf8('Show incoming bookmarks'),
+                UI.PixmapCache.getIcon("vcsUpdate.png"),
+                self.trUtf8('Show incoming bookmarks'),
+                0, 0, self, 'mercurial_incoming_bookmarks')
+        self.hgBookmarkIncomingAct.setStatusTip(self.trUtf8(
+            'Show a list of incoming bookmarks'
+        ))
+        self.hgBookmarkIncomingAct.setWhatsThis(self.trUtf8(
+            """<b>Show incoming bookmarks</b>"""
+            """<p>This shows a list of new bookmarks available at the remote"""
+            """ repository.</p>"""
+        ))
+        self.hgBookmarkIncomingAct.triggered[()].connect(self.__hgBookmarkIncoming)
+        self.actions.append(self.hgBookmarkIncomingAct)
+        
+        self.hgBookmarkPullAct = E5Action(self.trUtf8('Pull bookmark'),
+                UI.PixmapCache.getIcon("vcsUpdate.png"),
+                self.trUtf8('Pull bookmark'),
+                0, 0, self, 'mercurial_pull_bookmark')
+        self.hgBookmarkPullAct.setStatusTip(self.trUtf8(
+            'Pull a bookmark from a remote repository'
+        ))
+        self.hgBookmarkPullAct.setWhatsThis(self.trUtf8(
+            """<b>Pull bookmark</b>"""
+            """<p>This pulls a bookmark from a remote repository into the """
+            """local repository.</p>"""
+        ))
+        self.hgBookmarkPullAct.triggered[()].connect(self.__hgBookmarkPull)
+        self.actions.append(self.hgBookmarkPullAct)
+        
+        self.hgBookmarkOutgoingAct = E5Action(self.trUtf8('Show outgoing bookmarks'),
+                UI.PixmapCache.getIcon("vcsCommit.png"),
+                self.trUtf8('Show outgoing bookmarks'),
+                0, 0, self, 'mercurial_outgoing_bookmarks')
+        self.hgBookmarkOutgoingAct.setStatusTip(self.trUtf8(
+            'Show a list of outgoing bookmarks'
+        ))
+        self.hgBookmarkOutgoingAct.setWhatsThis(self.trUtf8(
+            """<b>Show outgoing bookmarks</b>"""
+            """<p>This shows a list of new bookmarks available at the local"""
+            """ repository.</p>"""
+        ))
+        self.hgBookmarkOutgoingAct.triggered[()].connect(self.__hgBookmarkOutgoing)
+        self.actions.append(self.hgBookmarkOutgoingAct)
+        
+        self.hgBookmarkPushAct = E5Action(self.trUtf8('Push bookmark'),
+                UI.PixmapCache.getIcon("vcsCommit.png"),
+                self.trUtf8('Push bookmark'),
+                0, 0, self, 'mercurial_push_bookmark')
+        self.hgBookmarkPushAct.setStatusTip(self.trUtf8(
+            'Push a bookmark to a remote repository'
+        ))
+        self.hgBookmarkPushAct.setWhatsThis(self.trUtf8(
+            """<b>Push bookmark</b>"""
+            """<p>This pushes a bookmark from the local repository to a """
+            """remote repository.</p>"""
+        ))
+        self.hgBookmarkPushAct.triggered[()].connect(self.__hgBookmarkPush)
+        self.actions.append(self.hgBookmarkPushAct)
     
     def initMenu(self, mainMenu):
         """
@@ -129,6 +196,12 @@
         menu.addAction(self.hgBookmarkMoveAct)
         menu.addSeparator()
         menu.addAction(self.hgBookmarksListAct)
+        menu.addSeparator()
+        menu.addAction(self.hgBookmarkIncomingAct)
+        menu.addAction(self.hgBookmarkPullAct)
+        menu.addSeparator()
+        menu.addAction(self.hgBookmarkOutgoingAct)
+        menu.addAction(self.hgBookmarkPushAct)
         
         return menu
     
@@ -166,3 +239,31 @@
         """
         self.vcs.getExtensionObject("bookmarks")\
             .hgBookmarkMove(self.project.getProjectPath())
+    
+    def __hgBookmarkIncoming(self):
+        """
+        Private slot used to show a list of incoming bookmarks.
+        """
+        self.vcs.getExtensionObject("bookmarks")\
+            .hgBookmarkIncoming(self.project.getProjectPath())
+    
+    def __hgBookmarkOutgoing(self):
+        """
+        Private slot used to show a list of outgoing bookmarks.
+        """
+        self.vcs.getExtensionObject("bookmarks")\
+            .hgBookmarkOutgoing(self.project.getProjectPath())
+    
+    def __hgBookmarkPull(self):
+        """
+        Private slot used to pull a bookmark from a remote repository.
+        """
+        self.vcs.getExtensionObject("bookmarks")\
+            .hgBookmarkPull(self.project.getProjectPath())
+    
+    def __hgBookmarkPush(self):
+        """
+        Private slot used to push a bookmark to a remote repository.
+        """
+        self.vcs.getExtensionObject("bookmarks")\
+            .hgBookmarkPush(self.project.getProjectPath())
--- a/Plugins/VcsPlugins/vcsMercurial/BookmarksExtension/bookmarks.py	Sat May 07 17:56:31 2011 +0200
+++ b/Plugins/VcsPlugins/vcsMercurial/BookmarksExtension/bookmarks.py	Sat May 07 20:31:28 2011 +0200
@@ -17,6 +17,7 @@
 from .HgBookmarksListDialog import HgBookmarksListDialog
 from .HgBookmarkDialog import HgBookmarkDialog
 from .HgBookmarkRenameDialog import HgBookmarkRenameDialog
+from .HgBookmarksInOutDialog import HgBookmarksInOutDialog
 
 import Preferences
 
@@ -34,6 +35,7 @@
         self.vcs = vcs
         
         self.bookmarksListDlg = None
+        self.bookmarksInOutDlg = None
         self.bookmarksList = []
     
     def shutdown(self):
@@ -42,6 +44,8 @@
         """
         if self.bookmarksListDlg is not None:
             self.bookmarksListDlg.close()
+        if self.bookmarksInOutDlg is not None:
+            self.bookmarksInOutDlg.close()
     
     def hgListBookmarks(self, path):
         """
@@ -93,10 +97,8 @@
         
         @param name file/directory name (string)
         """
-        dname, fname = self.vcs.splitPath(name)
-        
         # find the root of the repo
-        repodir = str(dname)
+        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:
@@ -127,10 +129,8 @@
         
         @param name file/directory name (string)
         """
-        dname, fname = self.vcs.splitPath(name)
-        
         # find the root of the repo
-        repodir = str(dname)
+        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:
@@ -159,10 +159,8 @@
         
         @param name file/directory name (string)
         """
-        dname, fname = self.vcs.splitPath(name)
-        
         # find the root of the repo
-        repodir = str(dname)
+        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:
@@ -189,10 +187,8 @@
         
         @param name file/directory name (string)
         """
-        dname, fname = self.vcs.splitPath(name)
-        
         # find the root of the repo
-        repodir = str(dname)
+        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:
@@ -217,3 +213,124 @@
             res = dia.startProcess(args, repodir)
             if res:
                 dia.exec_()
+    
+    def hgBookmarkIncoming(self, name):
+        """
+        Public method to show a list of incoming bookmarks.
+        
+        @param name file/directory name (string)
+        """
+        self.bookmarksInOutDlg = HgBookmarksInOutDialog(
+            self.vcs, HgBookmarksInOutDialog.INCOMING)
+        self.bookmarksInOutDlg.show()
+        self.bookmarksInOutDlg.start(name)
+    
+    def hgBookmarkOutgoing(self, name):
+        """
+        Public method to show a list of outgoing bookmarks.
+        
+        @param name file/directory name (string)
+        """
+        self.bookmarksInOutDlg = HgBookmarksInOutDialog(
+            self.vcs, HgBookmarksInOutDialog.OUTGOING)
+        self.bookmarksInOutDlg.show()
+        self.bookmarksInOutDlg.start(name)
+    
+    def __getInOutBookmarks(self, repodir, incoming):
+        """
+        Public method to get the list of incoming or outgoing bookmarks.
+        
+        @param repodir directory name of the repository (string)
+        @param incoming flag indicating to get incoming bookmarks (boolean)
+        @return list of bookmarks (list of string)
+        """
+        bookmarksList = []
+        
+        ioEncoding = Preferences.getSystem("IOEncoding")
+        process = QProcess()
+        args = []
+        if incoming:
+            args.append('incoming')
+        else:
+            args.append('outgoing')
+        args.append('--bookmarks')
+        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 line.startswith(" "):
+                        l = line.strip().split()
+                        del l[-1]
+                        name = " ".join(l)
+                        bookmarksList.append(name)
+        
+        return bookmarksList
+    
+    def hgBookmarkPull(self, name):
+        """
+        Public method to pull a bookmark from a remote repository.
+        
+        @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
+        
+        bookmarks = self.__getInOutBookmarks(repodir, True)
+        
+        bookmark, ok = QInputDialog.getItem(
+            None,
+            self.trUtf8("Pull Bookmark"),
+            self.trUtf8("Select the bookmark to be pulled:"),
+            [""] + sorted(bookmarks),
+            0, True)
+        if ok and bookmark:
+            args = []
+            args.append('pull')
+            args.append('--bookmark')
+            args.append(bookmark)
+        
+        dia = HgDialog(self.trUtf8('Pulling bookmark from a remote Mercurial repository'))
+        res = dia.startProcess(args, repodir)
+        if res:
+            dia.exec_()
+    
+    def hgBookmarkPush(self, name):
+        """
+        Public method to push a bookmark to a remote repository.
+        
+        @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
+        
+        bookmarks = self.__getInOutBookmarks(repodir, False)
+        
+        bookmark, ok = QInputDialog.getItem(
+            None,
+            self.trUtf8("Push Bookmark"),
+            self.trUtf8("Select the bookmark to be push:"),
+            [""] + sorted(bookmarks),
+            0, True)
+        if ok and bookmark:
+            args = []
+            args.append('push')
+            args.append('--bookmark')
+            args.append(bookmark)
+        
+        dia = HgDialog(self.trUtf8('Pushing bookmark to a remote Mercurial repository'))
+        res = dia.startProcess(args, repodir)
+        if res:
+            dia.exec_()
--- a/Plugins/VcsPlugins/vcsMercurial/hg.py	Sat May 07 17:56:31 2011 +0200
+++ b/Plugins/VcsPlugins/vcsMercurial/hg.py	Sat May 07 20:31:28 2011 +0200
@@ -109,6 +109,7 @@
             self.adminDir = '.hg'
         
         self.log = None
+        self.logBrowser = None
         self.diff = None
         self.status = None
         self.tagbranchList = None
@@ -149,6 +150,8 @@
         """
         if self.log is not None:
             self.log.close()
+        if self.logBrowser is not None:
+            self.logBrowser.close()
         if self.diff is not None:
             self.diff.close()
         if self.status is not None:
--- a/eric5.e4p	Sat May 07 17:56:31 2011 +0200
+++ b/eric5.e4p	Sat May 07 20:31:28 2011 +0200
@@ -882,6 +882,7 @@
     <Source>Plugins/VcsPlugins/vcsMercurial/BookmarksExtension/HgBookmarksListDialog.py</Source>
     <Source>Plugins/VcsPlugins/vcsMercurial/BookmarksExtension/HgBookmarkDialog.py</Source>
     <Source>Plugins/VcsPlugins/vcsMercurial/BookmarksExtension/HgBookmarkRenameDialog.py</Source>
+    <Source>Plugins/VcsPlugins/vcsMercurial/BookmarksExtension/HgBookmarksInOutDialog.py</Source>
   </Sources>
   <Forms>
     <Form>PyUnit/UnittestDialog.ui</Form>
@@ -1124,6 +1125,7 @@
     <Form>Plugins/VcsPlugins/vcsMercurial/BookmarksExtension/HgBookmarksListDialog.ui</Form>
     <Form>Plugins/VcsPlugins/vcsMercurial/BookmarksExtension/HgBookmarkDialog.ui</Form>
     <Form>Plugins/VcsPlugins/vcsMercurial/BookmarksExtension/HgBookmarkRenameDialog.ui</Form>
+    <Form>Plugins/VcsPlugins/vcsMercurial/BookmarksExtension/HgBookmarksInOutDialog.ui</Form>
   </Forms>
   <Translations>
     <Translation>i18n/eric5_cs.qm</Translation>
Binary file icons/default/deleteBookmark.png has changed
Binary file icons/default/listBookmarks.png has changed
Binary file icons/default/moveBookmark.png has changed
Binary file icons/default/renameBookmark.png has changed

eric ide

mercurial