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

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

eric ide

mercurial