eric6/Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesDefineGuardsDialog.py

changeset 6942
2602857055c5
parent 6735
31e263d49c04
child 7192
a22eee00b052
equal deleted inserted replaced
6941:f99d60d6b59b 6942:2602857055c5
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2011 - 2019 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a dialog to define guards for patches.
8 """
9
10 from __future__ import unicode_literals
11 try:
12 str = unicode
13 except NameError:
14 pass
15
16 import os
17
18 from PyQt5.QtCore import pyqtSlot, Qt, QProcess, QCoreApplication
19 from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QAbstractButton, \
20 QListWidgetItem
21
22 from E5Gui import E5MessageBox
23
24 from .Ui_HgQueuesDefineGuardsDialog import Ui_HgQueuesDefineGuardsDialog
25
26 import UI.PixmapCache
27
28
29 class HgQueuesDefineGuardsDialog(QDialog, Ui_HgQueuesDefineGuardsDialog):
30 """
31 Class implementing a dialog to define guards for patches.
32 """
33 def __init__(self, vcs, extension, patchesList, parent=None):
34 """
35 Constructor
36
37 @param vcs reference to the vcs object
38 @param extension reference to the extension module (Queues)
39 @param patchesList list of patches (list of strings)
40 @param parent reference to the parent widget (QWidget)
41 """
42 super(HgQueuesDefineGuardsDialog, self).__init__(parent)
43 self.setupUi(self)
44 self.setWindowFlags(Qt.Window)
45
46 self.vcs = vcs
47 self.extension = extension
48 self.__hgClient = vcs.getClient()
49
50 self.__patches = patchesList[:]
51 self.patchSelector.addItems([""] + self.__patches)
52
53 self.plusButton.setIcon(UI.PixmapCache.getIcon("plus.png"))
54 self.minusButton.setIcon(UI.PixmapCache.getIcon("minus.png"))
55
56 self.__dirtyList = False
57 self.__currentPatch = ""
58
59 self.show()
60 QCoreApplication.processEvents()
61
62 def closeEvent(self, e):
63 """
64 Protected slot implementing a close event handler.
65
66 @param e close event (QCloseEvent)
67 """
68 if self.__hgClient:
69 if self.__hgClient.isExecuting():
70 self.__hgClient.cancel()
71
72 if self.__dirtyList:
73 res = E5MessageBox.question(
74 self,
75 self.tr("Unsaved Changes"),
76 self.tr("""The guards list has been changed."""
77 """ Shall the changes be applied?"""),
78 E5MessageBox.StandardButtons(
79 E5MessageBox.Apply |
80 E5MessageBox.Discard),
81 E5MessageBox.Apply)
82 if res == E5MessageBox.Apply:
83 self.__applyGuards()
84 else:
85 self.__dirtyList = False
86
87 e.accept()
88
89 def start(self, path):
90 """
91 Public slot to start the list command.
92
93 @param path name of directory to be listed (string)
94 """
95 dname, fname = self.vcs.splitPath(path)
96
97 # find the root of the repo
98 repodir = dname
99 while not os.path.isdir(os.path.join(repodir, self.vcs.adminDir)):
100 repodir = os.path.dirname(repodir)
101 if os.path.splitdrive(repodir)[1] == os.sep:
102 return
103
104 self.__repodir = repodir
105 self.on_patchSelector_activated("")
106
107 @pyqtSlot(str)
108 def on_patchSelector_activated(self, patch):
109 """
110 Private slot to get the list of guards defined for the given patch
111 name.
112
113 @param patch selected patch name (empty for current patch)
114 """
115 if self.__dirtyList:
116 res = E5MessageBox.question(
117 self,
118 self.tr("Unsaved Changes"),
119 self.tr("""The guards list has been changed."""
120 """ Shall the changes be applied?"""),
121 E5MessageBox.StandardButtons(
122 E5MessageBox.Apply |
123 E5MessageBox.Discard),
124 E5MessageBox.Apply)
125 if res == E5MessageBox.Apply:
126 self.__applyGuards()
127 else:
128 self.__dirtyList = False
129
130 self.guardsList.clear()
131 self.patchNameLabel.setText("")
132
133 self.guardCombo.clear()
134 guardsList = self.extension.getGuardsList(self.__repodir)
135 self.guardCombo.addItems(guardsList)
136 self.guardCombo.setEditText("")
137
138 args = self.vcs.initCommand("qguard")
139 if patch:
140 args.append(patch)
141
142 output = ""
143 if self.__hgClient:
144 output = self.__hgClient.runcommand(args)[0]
145 else:
146 process = QProcess()
147 process.setWorkingDirectory(self.__repodir)
148 process.start('hg', args)
149 procStarted = process.waitForStarted(5000)
150 if procStarted:
151 finished = process.waitForFinished(30000)
152 if finished and process.exitCode() == 0:
153 output = str(process.readAllStandardOutput(),
154 self.vcs.getEncoding(), 'replace').strip()
155
156 if output:
157 patchName, guards = output.split(":", 1)
158 self.patchNameLabel.setText(patchName)
159 guardsList = guards.strip().split()
160 for guard in guardsList:
161 if guard.startswith("+"):
162 icon = UI.PixmapCache.getIcon("plus.png")
163 guard = guard[1:]
164 sign = "+"
165 elif guard.startswith("-"):
166 icon = UI.PixmapCache.getIcon("minus.png")
167 guard = guard[1:]
168 sign = "-"
169 else:
170 continue
171 itm = QListWidgetItem(icon, guard, self.guardsList)
172 itm.setData(Qt.UserRole, sign)
173
174 self.on_guardsList_itemSelectionChanged()
175
176 @pyqtSlot()
177 def on_guardsList_itemSelectionChanged(self):
178 """
179 Private slot to handle changes of the selection of guards.
180 """
181 self.removeButton.setEnabled(
182 len(self.guardsList.selectedItems()) > 0)
183
184 def __getGuard(self, guard):
185 """
186 Private method to get a reference to a named guard.
187
188 @param guard name of the guard (string)
189 @return reference to the guard item (QListWidgetItem)
190 """
191 items = self.guardsList.findItems(guard, Qt.MatchCaseSensitive)
192 if items:
193 return items[0]
194 else:
195 return None
196
197 @pyqtSlot(str)
198 def on_guardCombo_editTextChanged(self, txt):
199 """
200 Private slot to handle changes of the text of the guard combo.
201
202 @param txt contents of the guard combo line edit (string)
203 """
204 self.addButton.setEnabled(txt != "")
205
206 @pyqtSlot()
207 def on_addButton_clicked(self):
208 """
209 Private slot to add a guard definition to the list or change it.
210 """
211 guard = self.guardCombo.currentText()
212 if self.plusButton.isChecked():
213 sign = "+"
214 icon = UI.PixmapCache.getIcon("plus.png")
215 else:
216 sign = "-"
217 icon = UI.PixmapCache.getIcon("minus.png")
218
219 guardItem = self.__getGuard(guard)
220 if guardItem:
221 # guard already exists, remove it first
222 row = self.guardsList.row(guardItem)
223 itm = self.guardsList.takeItem(row)
224 del itm
225
226 itm = QListWidgetItem(icon, guard, self.guardsList)
227 itm.setData(Qt.UserRole, sign)
228 self.guardsList.sortItems()
229
230 self.__dirtyList = True
231
232 @pyqtSlot()
233 def on_removeButton_clicked(self):
234 """
235 Private slot to remove guard definitions from the list.
236 """
237 res = E5MessageBox.yesNo(
238 self,
239 self.tr("Remove Guards"),
240 self.tr(
241 """Do you really want to remove the selected guards?"""))
242 if res:
243 for guardItem in self.guardsList.selectedItems():
244 row = self.guardsList.row(guardItem)
245 itm = self.guardsList.takeItem(row) # __IGNORE_WARNING__
246 del itm
247
248 self.__dirtyList = True
249
250 @pyqtSlot(QAbstractButton)
251 def on_buttonBox_clicked(self, button):
252 """
253 Private slot called by a button of the button box clicked.
254
255 @param button button that was clicked (QAbstractButton)
256 """
257 if button == self.buttonBox.button(QDialogButtonBox.Apply):
258 self.__applyGuards()
259 elif button == self.buttonBox.button(QDialogButtonBox.Close):
260 self.close()
261
262 @pyqtSlot()
263 def __applyGuards(self):
264 """
265 Private slot to apply the defined guards to the current patch.
266 """
267 if self.__dirtyList:
268 guardsList = []
269 for row in range(self.guardsList.count()):
270 itm = self.guardsList.item(row)
271 guard = itm.data(Qt.UserRole) + itm.text()
272 guardsList.append(guard)
273
274 args = self.vcs.initCommand("qguard")
275 args.append(self.patchNameLabel.text())
276 if guardsList:
277 args.append("--")
278 args.extend(guardsList)
279 else:
280 args.append("--none")
281
282 error = ""
283 if self.__hgClient:
284 error = self.__hgClient.runcommand(args)[1]
285 else:
286 process = QProcess()
287 process.setWorkingDirectory(self.__repodir)
288 process.start('hg', args)
289 procStarted = process.waitForStarted(5000)
290 if procStarted:
291 finished = process.waitForFinished(30000)
292 if finished:
293 if process.exitCode() != 0:
294 error = str(process.readAllStandardError(),
295 self.vcs.getEncoding(), 'replace')
296 else:
297 E5MessageBox.warning(
298 self,
299 self.tr("Apply Guard Definitions"),
300 self.tr(
301 """The Mercurial process did not finish"""
302 """ in time."""))
303
304 if error:
305 E5MessageBox.warning(
306 self,
307 self.tr("Apply Guard Definitions"),
308 self.tr("""<p>The defined guards could not be"""
309 """ applied.</p><p>Reason: {0}</p>""")
310 .format(error))
311 else:
312 self.__dirtyList = False
313 self.on_patchSelector_activated(
314 self.patchNameLabel.text())

eric ide

mercurial