1# -*- coding: utf-8 -*-
2
3# Copyright (c) 2010 - 2021 Detlev Offenbach <detlev@die-offenbachs.de>
4#
5
6"""
7Module implementing the Mercurial version control plugin.
8"""
9
10import os
11import contextlib
12
13from PyQt5.QtCore import QObject, QCoreApplication, QByteArray
14
15from E5Gui.E5Application import e5App
16
17import Preferences
18from Preferences.Shortcuts import readShortcuts
19
20from VcsPlugins.vcsMercurial.HgUtilities import getConfigPath, getHgExecutable
21
22import Utilities
23import UI.Info
24
25# Start-Of-Header
26name = "Mercurial Plugin"
27author = "Detlev Offenbach <detlev@die-offenbachs.de>"
28autoactivate = False
29deactivateable = True
30version = UI.Info.VersionOnly
31pluginType = "version_control"
32pluginTypename = "Mercurial"
33className = "VcsMercurialPlugin"
34packageName = "__core__"
35shortDescription = "Implements the Mercurial version control interface."
36longDescription = (
37    """This plugin provides the Mercurial version control interface."""
38)
39pyqtApi = 2
40# End-Of-Header
41
42error = ""
43
44
45def exeDisplayData():
46    """
47    Public method to support the display of some executable info.
48
49    @return dictionary containing the data to query the presence of
50        the executable
51    """
52    data = {
53        "programEntry": True,
54        "header": QCoreApplication.translate(
55            "VcsMercurialPlugin", "Version Control - Mercurial"),
56        "exe": getHgExecutable(),
57        "versionCommand": 'version',
58        "versionStartsWith": 'Mercurial',
59        "versionPosition": -1,
60        "version": "",
61        "versionCleanup": (0, -1),
62    }
63
64    return data
65
66
67def getVcsSystemIndicator():
68    """
69    Public function to get the indicators for this version control system.
70
71    @return dictionary with indicator as key and a tuple with the vcs name
72        (string) and vcs display string (string)
73    """
74    global pluginTypename
75    data = {}
76    exe = getHgExecutable()
77    if Utilities.isinpath(exe):
78        data[".hg"] = (pluginTypename, displayString())
79        data["_hg"] = (pluginTypename, displayString())
80    return data
81
82
83def displayString():
84    """
85    Public function to get the display string.
86
87    @return display string (string)
88    """
89    exe = getHgExecutable()
90    if Utilities.isinpath(exe):
91        return QCoreApplication.translate('VcsMercurialPlugin', 'Mercurial')
92    else:
93        return ""
94
95mercurialCfgPluginObject = None
96
97
98def createConfigurationPage(configDlg):
99    """
100    Module function to create the configuration page.
101
102    @param configDlg reference to the configuration dialog (QDialog)
103    @return reference to the configuration page
104    """
105    global mercurialCfgPluginObject
106    from VcsPlugins.vcsMercurial.ConfigurationPage.MercurialPage import (
107        MercurialPage
108    )
109    if mercurialCfgPluginObject is None:
110        mercurialCfgPluginObject = VcsMercurialPlugin(None)
111    page = MercurialPage(mercurialCfgPluginObject)
112    return page
113
114
115def getConfigData():
116    """
117    Module function returning data as required by the configuration dialog.
118
119    @return dictionary with key "zzz_mercurialPage" containing the relevant
120        data
121    """
122    return {
123        "zzz_mercurialPage":
124        [QCoreApplication.translate("VcsMercurialPlugin", "Mercurial"),
125            os.path.join("VcsPlugins", "vcsMercurial", "icons",
126                         "preferences-mercurial.svg"),
127            createConfigurationPage, "vcsPage", None],
128    }
129
130
131def prepareUninstall():
132    """
133    Module function to prepare for an uninstallation.
134    """
135    if not e5App().getObject("PluginManager").isPluginLoaded(
136            "PluginVcsMercurial"):
137        Preferences.Prefs.settings.remove("Mercurial")
138
139
140def clearPrivateData():
141    """
142    Module function to clear the private data of the plug-in.
143    """
144    for key in ["RepositoryUrlHistory"]:
145        VcsMercurialPlugin.setPreferences(key, [])
146
147
148class VcsMercurialPlugin(QObject):
149    """
150    Class implementing the Mercurial version control plugin.
151    """
152    MercurialDefaults = {
153        "StopLogOnCopy": True,  # used in log browser
154        "LogLimit": 20,
155        "CommitMessages": 20,
156        "Commits": [],
157        "CommitAuthorsLimit": 20,
158        "CommitAuthors": [],
159        "PullUpdate": False,
160        "PreferUnbundle": False,
161        "ServerPort": 8000,
162        "ServerStyle": "",
163        "CleanupPatterns": "*.orig *.rej *~",
164        "CreateBackup": False,
165        "InternalMerge": False,
166        "Encoding": "utf-8",
167        "EncodingMode": "strict",
168        "ConsiderHidden": False,
169        "LogMessageColumnWidth": 30,
170        "LogBrowserShowFullLog": True,
171        "LogBrowserGeometry": QByteArray(),
172        "LogBrowserSplitterStates": [QByteArray(), QByteArray(),
173                                     QByteArray()],
174        # mainSplitter, detailsSplitter, diffSplitter
175        "StatusDialogGeometry": QByteArray(),
176        "StatusDialogSplitterState": QByteArray(),
177        "MqStatusDialogGeometry": QByteArray(),
178        "MqStatusDialogSplitterState": QByteArray(),
179        "RepositoryUrlHistory": [],
180    }
181
182    def __init__(self, ui):
183        """
184        Constructor
185
186        @param ui reference to the user interface object (UI.UserInterface)
187        """
188        super().__init__(ui)
189        self.__ui = ui
190
191        from VcsPlugins.vcsMercurial.ProjectHelper import HgProjectHelper
192        self.__projectHelperObject = HgProjectHelper(None, None)
193        with contextlib.suppress(KeyError):
194            e5App().registerPluginObject(
195                pluginTypename, self.__projectHelperObject, pluginType)
196        readShortcuts(pluginName=pluginTypename)
197
198    def getProjectHelper(self):
199        """
200        Public method to get a reference to the project helper object.
201
202        @return reference to the project helper object
203        """
204        return self.__projectHelperObject
205
206    def initToolbar(self, ui, toolbarManager):
207        """
208        Public slot to initialize the VCS toolbar.
209
210        @param ui reference to the main window (UserInterface)
211        @param toolbarManager reference to a toolbar manager object
212            (E5ToolBarManager)
213        """
214        if self.__projectHelperObject:
215            self.__projectHelperObject.initToolbar(ui, toolbarManager)
216
217    def activate(self):
218        """
219        Public method to activate this plugin.
220
221        @return tuple of reference to instantiated viewmanager and
222            activation status (boolean)
223        """
224        from VcsPlugins.vcsMercurial.hg import Hg
225        self.__object = Hg(self, self.__ui)
226
227        tb = self.__ui.getToolbar("vcs")[1]
228        tb.setVisible(False)
229        tb.setEnabled(False)
230
231        tb = self.__ui.getToolbar("mercurial")[1]
232        tb.setVisible(Preferences.getVCS("ShowVcsToolbar"))
233        tb.setEnabled(True)
234
235        return self.__object, True
236
237    def deactivate(self):
238        """
239        Public method to deactivate this plugin.
240        """
241        self.__object = None
242
243        tb = self.__ui.getToolbar("mercurial")[1]
244        tb.setVisible(False)
245        tb.setEnabled(False)
246
247        tb = self.__ui.getToolbar("vcs")[1]
248        tb.setVisible(Preferences.getVCS("ShowVcsToolbar"))
249        tb.setEnabled(True)
250
251    @classmethod
252    def getPreferences(cls, key):
253        """
254        Class method to retrieve the various settings.
255
256        @param key the key of the value to get
257        @return the requested setting
258        """
259        if key in ["StopLogOnCopy", "PullUpdate", "PreferUnbundle",
260                   "CreateBackup", "InternalMerge", "ConsiderHidden",
261                   "LogBrowserShowFullLog"]:
262            return Preferences.toBool(Preferences.Prefs.settings.value(
263                "Mercurial/" + key, cls.MercurialDefaults[key]))
264        elif key in ["LogLimit", "CommitMessages", "CommitAuthorsLimit",
265                     "ServerPort", "LogMessageColumnWidth"]:
266            return int(Preferences.Prefs.settings.value(
267                "Mercurial/" + key, cls.MercurialDefaults[key]))
268        elif key in ["Commits", "CommitAuthors", "RepositoryUrlHistory"]:
269            return Preferences.toList(Preferences.Prefs.settings.value(
270                "Mercurial/" + key, cls.MercurialDefaults[key]))
271        elif key in ["LogBrowserGeometry", "StatusDialogGeometry",
272                     "StatusDialogSplitterState", "MqStatusDialogGeometry",
273                     "MqStatusDialogSplitterState"]:
274            # QByteArray values
275            v = Preferences.Prefs.settings.value("Mercurial/" + key)
276            if v is not None:
277                return v
278            else:
279                return cls.MercurialDefaults[key]
280        elif key in ["LogBrowserSplitterStates"]:
281            # list of QByteArray values
282            states = Preferences.Prefs.settings.value("Mercurial/" + key)
283            if states is not None:
284                return states
285            else:
286                return cls.MercurialDefaults[key]
287        else:
288            return Preferences.Prefs.settings.value(
289                "Mercurial/" + key, cls.MercurialDefaults[key])
290
291    @classmethod
292    def setPreferences(cls, key, value):
293        """
294        Class method to store the various settings.
295
296        @param key the key of the setting to be set
297        @param value the value to be set
298        """
299        Preferences.Prefs.settings.setValue("Mercurial/" + key, value)
300
301    def getGlobalOptions(self):
302        """
303        Public method to build a list of global options.
304
305        @return list of global options (list of string)
306        """
307        args = []
308        if (
309            self.getPreferences("Encoding") !=
310            self.MercurialDefaults["Encoding"]
311        ):
312            args.append("--encoding")
313            args.append(self.getPreferences("Encoding"))
314        if (
315            self.getPreferences("EncodingMode") !=
316            self.MercurialDefaults["EncodingMode"]
317        ):
318            args.append("--encodingmode")
319            args.append(self.getPreferences("EncodingMode"))
320        if self.getPreferences("ConsiderHidden"):
321            args.append("--hidden")
322        return args
323
324    def getConfigPath(self):
325        """
326        Public method to get the filename of the config file.
327
328        @return filename of the config file (string)
329        """
330        return getConfigPath()
331
332    def prepareUninstall(self):
333        """
334        Public method to prepare for an uninstallation.
335        """
336        e5App().unregisterPluginObject(pluginTypename)
337
338    def prepareUnload(self):
339        """
340        Public method to prepare for an unload.
341        """
342        if self.__projectHelperObject:
343            self.__projectHelperObject.removeToolbar(
344                self.__ui, e5App().getObject("ToolbarManager"))
345        e5App().unregisterPluginObject(pluginTypename)
346