Wed, 24 Jul 2013 19:58:04 +0200
Started implementing support for the Mercurial archive function.
--- a/E5Gui/E5Completers.py Wed Jul 24 19:43:44 2013 +0200 +++ b/E5Gui/E5Completers.py Wed Jul 24 19:58:04 2013 +0200 @@ -12,6 +12,7 @@ from Globals import isWindowsPlatform +# TODO: replace obsoleted QDirModel by QFileSystemModel class E5FileCompleter(QCompleter): """
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/VcsPlugins/vcsMercurial/HgArchiveDialog.py Wed Jul 24 19:58:04 2013 +0200 @@ -0,0 +1,145 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2013 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing a dialog to enter the archive data. +""" + +from PyQt4.QtCore import pyqtSlot, QFileInfo +from PyQt4.QtGui import QDialog, QDialogButtonBox + +from E5Gui.E5Completers import E5FileCompleter, E5DirCompleter +from E5Gui import E5FileDialog + +from .Ui_HgArchiveDialog import Ui_HgArchiveDialog + +import Utilities + + +class HgArchiveDialog(QDialog, Ui_HgArchiveDialog): + """ + Class implementing a dialog to enter the archive data. + """ + def __init__(self, vcs, parent=None): + """ + Constructor + + @param vcs reference to the Mercurial object (Hg) + @param parent reference to the parent widget (QWidget) + """ + super().__init__(parent) + self.setupUi(self) + + self.__archiveFileCompleter = E5FileCompleter() + self.__archiveDirCompleter = E5DirCompleter() + self.__activeCompleter = self.__archiveFileCompleter + self.archiveEdit.setCompleter(self.__activeCompleter) + + self.typeComboBox.addItem(self.trUtf8("Detect Automatically"), "") + self.typeComboBox.addItem(self.trUtf8("Directory of Files"), "files") + self.typeComboBox.addItem(self.trUtf8("Uncompressed TAR-Archive"), "tar") + self.typeComboBox.addItem(self.trUtf8("Bzip2 compressed TAR-Archive"), "tbz2") + self.typeComboBox.addItem(self.trUtf8("Gzip compressed TAR-Archive"), "tgz") + self.typeComboBox.addItem(self.trUtf8("Uncompressed ZIP-Archive"), "uzip") + self.typeComboBox.addItem(self.trUtf8("Compressed ZIP-Archive"), "zip") + + self.__unixFileFilters = [ + self.trUtf8("Bzip2 compressed TAR-Archive (*.tar.bz2)"), + self.trUtf8("Gzip compressed TAR-Archive (*.tar.gz)"), + self.trUtf8("Uncompressed TAR-Archive (*.tar)"), + ] + self.__windowsFileFilters = [ + self.trUtf8("Compressed ZIP-Archive (*.zip)"), + self.trUtf8("Uncompressed ZIP-Archive (*.uzip)") + ] + if Utilities.isWindowsPlatform(): + self.__fileFilters = ";;".join( + self.__windowsFileFilters + self.__unixFileFilters) + else: + self.__fileFilters = ";;".join( + self.__unixFileFilters + self.__windowsFileFilters) + self.__fileFilters += ";;" + self.trUtf8("All Files (*)") + + self.subReposCheckBox.setEnabled(vcs.hasSubrepositories()) + + self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False) + + self.__projectPath = \ + vcs.getPlugin().getProjectHelper().getProject().getProjectPath() + + @pyqtSlot(str) + def on_archiveEdit_textChanged(self, archive): + """ + Private slot to handle changes of the archive name. + """ + self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(archive != "") + + @pyqtSlot() + def on_archiveButton_clicked(self): + """ + Private slot to select the archive name via a file selection dialog. + """ + type_ = self.typeComboBox.itemData(self.typeComboBox.currentIndex()) + + archive = Utilities.fromNativeSeparators(self.archiveEdit.text()) + if not archive: + archive = self.__projectPath + + if type_ == "files": + archive = E5FileDialog.getExistingDirectory( + self, + self.trUtf8("Select Archive Directory"), + archive, + E5FileDialog.Options(E5FileDialog.ShowDirsOnly)) + else: + archive, selectedFilter = E5FileDialog.getSaveFileNameAndFilter( + self, + self.trUtf8("Select Archive File"), + archive, + self.__fileFilters, + None, + E5FileDialog.Options(E5FileDialog.DontConfirmOverwrite)) + if archive: + ext = QFileInfo(archive).suffix() + if not ext: + ex = selectedFilter.split("(*")[1].split(")")[0] + if ex: + archive += ex + + if archive: + self.archiveEdit.setText(Utilities.toNativeSeparators(archive)) + + @pyqtSlot(int) + def on_typeComboBox_activated(self, index): + """ + Private slot to react on changes of the selected archive type. + + @param index index of the selected type (integer) + """ + type_ = self.typeComboBox.itemData(index) + if type_ == "files": + if self.__activeCompleter != self.__archiveDirCompleter: + self.__activeCompleter = self.__archiveDirCompleter + self.archiveEdit.setCompleter(self.__activeCompleter) + else: + # TODO: add name filter to completer based upon selected type + if self.__activeCompleter != self.__archiveFileCompleter: + self.__activeCompleter = self.__archiveFileCompleter + self.archiveEdit.setCompleter(self.__activeCompleter) + + def getData(self): + """ + Public method to retrieve the data. + + @return tuple giving the archive name (string), the archive type (string), + the directory prefix 8string) and a flag indicating to recurse into + subrepositories (boolean) + """ + return ( + self.archiveEdit.text(), + self.typeComboBox.itemData(self.typeComboBox.currentIndex()), + self.prefixEdit.text(), + self.subReposCheckBox.isChecked(), + )
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/VcsPlugins/vcsMercurial/HgArchiveDialog.ui Wed Jul 24 19:58:04 2013 +0200 @@ -0,0 +1,137 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>HgArchiveDialog</class> + <widget class="QDialog" name="HgArchiveDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>145</height> + </rect> + </property> + <property name="windowTitle"> + <string>Mercurial Archive</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>Archive:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLineEdit" name="archiveEdit"> + <property name="toolTip"> + <string>Enter the file name of the archive</string> + </property> + </widget> + </item> + <item row="0" column="2"> + <widget class="QPushButton" name="archiveButton"> + <property name="toolTip"> + <string>Press to select the archive file name via a file selection dialog</string> + </property> + <property name="text"> + <string>...</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Type:</string> + </property> + </widget> + </item> + <item row="1" column="1" colspan="2"> + <widget class="QComboBox" name="typeComboBox"> + <property name="toolTip"> + <string>Select the archive type</string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Prefix:</string> + </property> + </widget> + </item> + <item row="2" column="1" colspan="2"> + <widget class="QLineEdit" name="prefixEdit"> + <property name="toolTip"> + <string>Enter the directory prefix for the files in the archive</string> + </property> + </widget> + </item> + <item row="3" column="0" colspan="3"> + <widget class="QCheckBox" name="subReposCheckBox"> + <property name="toolTip"> + <string>Select to recurse into subrepositories</string> + </property> + <property name="text"> + <string>Include Subrepositories</string> + </property> + </widget> + </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>archiveEdit</tabstop> + <tabstop>archiveButton</tabstop> + <tabstop>typeComboBox</tabstop> + <tabstop>prefixEdit</tabstop> + <tabstop>subReposCheckBox</tabstop> + <tabstop>buttonBox</tabstop> + </tabstops> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>HgArchiveDialog</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>HgArchiveDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui>
--- a/Plugins/VcsPlugins/vcsMercurial/ProjectHelper.py Wed Jul 24 19:43:44 2013 +0200 +++ b/Plugins/VcsPlugins/vcsMercurial/ProjectHelper.py Wed Jul 24 19:58:04 2013 +0200 @@ -917,6 +917,20 @@ )) self.hgRemoveSubreposAct.triggered[()].connect(self.__hgRemoveSubrepositories) self.actions.append(self.hgRemoveSubreposAct) + + self.hgArchiveAct = E5Action(self.trUtf8('Create unversioned archive'), + UI.PixmapCache.getIcon("vcsExport.png"), + self.trUtf8('Create unversioned archive...'), + 0, 0, self, 'mercurial_archive') + self.hgArchiveAct.setStatusTip(self.trUtf8( + 'Create an unversioned archive from the repository' + )) + self.hgArchiveAct.setWhatsThis(self.trUtf8( + """<b>Create unversioned archive...</b>""" + """<p>This creates an unversioned archive from the repository.</p>""" + )) + self.hgArchiveAct.triggered[()].connect(self.__hgArchive) + self.actions.append(self.hgArchiveAct) def initMenu(self, menu): """ @@ -953,6 +967,8 @@ specialsMenu = QMenu(self.trUtf8("Specials"), menu) specialsMenu.setTearOffEnabled(True) + specialsMenu.addAction(self.hgArchiveAct) + specialsMenu.addSeparator() specialsMenu.addAction(self.hgPushForcedAct) specialsMenu.addSeparator() specialsMenu.addAction(self.hgServeAct) @@ -1432,3 +1448,9 @@ Private slot to show a working directory summary. """ self.vcs.hgSummary() + + def __hgArchive(self): + """ + Private slot to create an unversioned archive from the repository. + """ + self.vcs.hgArchive()
--- a/Plugins/VcsPlugins/vcsMercurial/hg.py Wed Jul 24 19:43:44 2013 +0200 +++ b/Plugins/VcsPlugins/vcsMercurial/hg.py Wed Jul 24 19:58:04 2013 +0200 @@ -2739,6 +2739,39 @@ self.checkVCSStatus() return res + def hgArchive(self): + """ + Public method to create an unversioned archive from the repository. + """ + # find the root of the repo + repodir = self.__projectHelper.getProject().getProjectPath() + while not os.path.isdir(os.path.join(repodir, self.adminDir)): + repodir = os.path.dirname(repodir) + if os.path.splitdrive(repodir)[1] == os.sep: + return + + from .HgArchiveDialog import HgArchiveDialog + dlg = HgArchiveDialog(self) + if dlg.exec_() == QDialog.Accepted: + archive, type_, prefix, subrepos = dlg.getData() + + args = [] + args.append("archive") + if type_: + args.append("--type") + args.append(type_) + if prefix: + args.append("--prefix") + args.append(prefix) + if subrepos: + args.append("--subrepos") + args.append(archive) + + dia = HgDialog(self.trUtf8("Create Unversioned Archive"), self) + res = dia.startProcess(args, repodir) + if res: + dia.exec_() + ############################################################################ ## Methods to deal with subrepositories are below. ############################################################################
--- a/eric5.e4p Wed Jul 24 19:43:44 2013 +0200 +++ b/eric5.e4p Wed Jul 24 19:58:04 2013 +0200 @@ -1106,6 +1106,7 @@ <Source>ThirdParty/Jasy/jasy/js/tokenize/Lang.py</Source> <Source>Plugins/VcsPlugins/vcsMercurial/ConfigurationPage/MercurialUserDataDialog.py</Source> <Source>Plugins/VcsPlugins/vcsMercurial/HgSummaryDialog.py</Source> + <Source>Plugins/VcsPlugins/vcsMercurial/HgArchiveDialog.py</Source> </Sources> <Forms> <Form>PyUnit/UnittestDialog.ui</Form> @@ -1426,6 +1427,7 @@ <Form>Plugins/WizardPlugins/QRegularExpressionWizard/QRegularExpressionWizardRepeatDialog.ui</Form> <Form>Plugins/VcsPlugins/vcsMercurial/ConfigurationPage/MercurialUserDataDialog.ui</Form> <Form>Plugins/VcsPlugins/vcsMercurial/HgSummaryDialog.ui</Form> + <Form>Plugins/VcsPlugins/vcsMercurial/HgArchiveDialog.ui</Form> </Forms> <Translations> <Translation>i18n/eric5_cs.ts</Translation>