eric7/Plugins/VcsPlugins/vcsMercurial/GpgExtension/HgGpgSignaturesDialog.py

branch
eric7
changeset 8312
800c432b34c8
parent 8259
2bbec88047dd
child 8318
962bce857696
equal deleted inserted replaced
8311:4e8b98454baa 8312:800c432b34c8
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2011 - 2021 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a dialog showing signed changesets.
8 """
9
10 import re
11
12 from PyQt5.QtCore import pyqtSlot, Qt, QCoreApplication
13 from PyQt5.QtWidgets import (
14 QDialog, QDialogButtonBox, QHeaderView, QTreeWidgetItem
15 )
16
17 from .Ui_HgGpgSignaturesDialog import Ui_HgGpgSignaturesDialog
18
19
20 class HgGpgSignaturesDialog(QDialog, Ui_HgGpgSignaturesDialog):
21 """
22 Class implementing a dialog showing signed changesets.
23 """
24 def __init__(self, vcs, parent=None):
25 """
26 Constructor
27
28 @param vcs reference to the vcs object
29 @param parent reference to the parent widget (QWidget)
30 """
31 super().__init__(parent)
32 self.setupUi(self)
33 self.setWindowFlags(Qt.WindowType.Window)
34
35 self.buttonBox.button(
36 QDialogButtonBox.StandardButton.Close).setEnabled(False)
37 self.buttonBox.button(
38 QDialogButtonBox.StandardButton.Cancel).setDefault(True)
39
40 self.vcs = vcs
41 self.__hgClient = vcs.getClient()
42
43 self.show()
44 QCoreApplication.processEvents()
45
46 def closeEvent(self, e):
47 """
48 Protected slot implementing a close event handler.
49
50 @param e close event (QCloseEvent)
51 """
52 if self.__hgClient.isExecuting():
53 self.__hgClient.cancel()
54
55 e.accept()
56
57 def start(self):
58 """
59 Public slot to start the list command.
60 """
61 self.errorGroup.hide()
62
63 self.intercept = False
64 self.activateWindow()
65
66 args = self.vcs.initCommand("sigs")
67
68 out, err = self.__hgClient.runcommand(args)
69 if err:
70 self.__showError(err)
71 if out:
72 for line in out.splitlines():
73 self.__processOutputLine(line)
74 if self.__hgClient.wasCanceled():
75 break
76 self.__finish()
77
78 def __finish(self):
79 """
80 Private slot called when the process finished or the user pressed
81 the button.
82 """
83 self.buttonBox.button(
84 QDialogButtonBox.StandardButton.Close).setEnabled(True)
85 self.buttonBox.button(
86 QDialogButtonBox.StandardButton.Cancel).setEnabled(False)
87 self.buttonBox.button(
88 QDialogButtonBox.StandardButton.Close).setDefault(True)
89 self.buttonBox.button(
90 QDialogButtonBox.StandardButton.Close).setFocus(
91 Qt.FocusReason.OtherFocusReason)
92
93 if self.signaturesList.topLevelItemCount() == 0:
94 # no patches present
95 self.__generateItem("", "", self.tr("no signatures found"))
96 self.__resizeColumns()
97 self.__resort()
98
99 def on_buttonBox_clicked(self, button):
100 """
101 Private slot called by a button of the button box clicked.
102
103 @param button button that was clicked (QAbstractButton)
104 """
105 if button == self.buttonBox.button(
106 QDialogButtonBox.StandardButton.Close
107 ):
108 self.close()
109 elif button == self.buttonBox.button(
110 QDialogButtonBox.StandardButton.Cancel
111 ):
112 self.__hgClient.cancel()
113
114 def __resort(self):
115 """
116 Private method to resort the tree.
117 """
118 self.signaturesList.sortItems(
119 self.signaturesList.sortColumn(),
120 self.signaturesList.header().sortIndicatorOrder())
121
122 def __resizeColumns(self):
123 """
124 Private method to resize the list columns.
125 """
126 self.signaturesList.header().resizeSections(
127 QHeaderView.ResizeMode.ResizeToContents)
128 self.signaturesList.header().setStretchLastSection(True)
129
130 def __generateItem(self, revision, changeset, signature):
131 """
132 Private method to generate a patch item in the list of patches.
133
134 @param revision revision number (string)
135 @param changeset changeset of the bookmark (string)
136 @param signature signature of the changeset (string)
137 """
138 if revision == "" and changeset == "":
139 QTreeWidgetItem(self.signaturesList, [signature])
140 else:
141 revString = "{0:>7}:{1}".format(revision, changeset)
142 topItems = self.signaturesList.findItems(
143 revString, Qt.MatchFlag.MatchExactly)
144 if len(topItems) == 0:
145 # first signature for this changeset
146 topItm = QTreeWidgetItem(self.signaturesList, [
147 "{0:>7}:{1}".format(revision, changeset)])
148 topItm.setExpanded(True)
149 font = topItm.font(0)
150 font.setBold(True)
151 topItm.setFont(0, font)
152 else:
153 topItm = topItems[0]
154 QTreeWidgetItem(topItm, [signature])
155
156 def __processOutputLine(self, line):
157 """
158 Private method to process the lines of output.
159
160 @param line output line to be processed (string)
161 """
162 li = line.split()
163 if li[-1][0] in "1234567890":
164 # last element is a rev:changeset
165 rev, changeset = li[-1].split(":", 1)
166 del li[-1]
167 signature = " ".join(li)
168 self.__generateItem(rev, changeset, signature)
169
170 def __showError(self, out):
171 """
172 Private slot to show some error.
173
174 @param out error to be shown (string)
175 """
176 self.errorGroup.show()
177 self.errors.insertPlainText(out)
178 self.errors.ensureCursorVisible()
179
180 @pyqtSlot()
181 def on_signaturesList_itemSelectionChanged(self):
182 """
183 Private slot handling changes of the selection.
184 """
185 selectedItems = self.signaturesList.selectedItems()
186 if (
187 len(selectedItems) == 1 and
188 self.signaturesList.indexOfTopLevelItem(selectedItems[0]) != -1
189 ):
190 self.verifyButton.setEnabled(True)
191 else:
192 self.verifyButton.setEnabled(False)
193
194 @pyqtSlot()
195 def on_verifyButton_clicked(self):
196 """
197 Private slot to verify the signatures of the selected revision.
198 """
199 rev = (
200 self.signaturesList.selectedItems()[0].text(0)
201 .split(":")[0].strip()
202 )
203 self.vcs.getExtensionObject("gpg").hgGpgVerifySignatures(rev)
204
205 @pyqtSlot(int)
206 def on_categoryCombo_activated(self, index):
207 """
208 Private slot called, when a new filter category is selected.
209
210 @param index index of the selected entry
211 @type int
212 """
213 self.__filterSignatures()
214
215 @pyqtSlot(str)
216 def on_rxEdit_textChanged(self, txt):
217 """
218 Private slot called, when a filter expression is entered.
219
220 @param txt filter expression (string)
221 """
222 self.__filterSignatures()
223
224 def __filterSignatures(self):
225 """
226 Private method to filter the log entries.
227 """
228 searchRxText = self.rxEdit.text()
229 filterTop = self.categoryCombo.currentText() == self.tr("Revision")
230 searchRx = (
231 re.compile(
232 r"^\s*{0}".format(searchRxText[1:]), re.IGNORECASE)
233 if filterTop and searchRxText.startswith("^") else
234 re.compile(searchRxText, re.IGNORECASE)
235 )
236 for topIndex in range(self.signaturesList.topLevelItemCount()):
237 topLevelItem = self.signaturesList.topLevelItem(topIndex)
238 if filterTop:
239 topLevelItem.setHidden(
240 searchRx.search(topLevelItem.text(0)) is None)
241 else:
242 visibleChildren = topLevelItem.childCount()
243 for childIndex in range(topLevelItem.childCount()):
244 childItem = topLevelItem.child(childIndex)
245 if searchRx.search(childItem.text(0)) is None:
246 childItem.setHidden(True)
247 visibleChildren -= 1
248 else:
249 childItem.setHidden(False)
250 topLevelItem.setHidden(visibleChildren == 0)

eric ide

mercurial