eric6/Plugins/VcsPlugins/vcsMercurial/HisteditExtension/HgHisteditPlanEditor.py

changeset 6942
2602857055c5
parent 6645
ad476851d7e0
child 7229
53054eb5b15a
equal deleted inserted replaced
6941:f99d60d6b59b 6942:2602857055c5
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2016 - 2019 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a dialog to edit the history modification plan.
8 """
9
10 from __future__ import unicode_literals
11
12 from PyQt5.QtCore import pyqtSlot, QCoreApplication
13 from PyQt5.QtWidgets import QDialog, QTreeWidgetItem, QComboBox
14
15 from E5Gui import E5MessageBox
16
17 from Ui_HgHisteditPlanEditor import Ui_HgHisteditPlanEditor
18
19 import UI.PixmapCache
20
21
22 class HgHisteditPlanActionComboBox(QComboBox):
23 """
24 Class implementing a combo box to select the action in the plan tree.
25 """
26 def __init__(self, item, column):
27 """
28 Constructor
29
30 @param item reference to the item
31 @type QTreeWidgetItem
32 @param column column number inside the tree widget item
33 @type int
34 """
35 super(HgHisteditPlanActionComboBox, self).__init__()
36
37 self.__item = item
38 self.__column = column
39
40 self.addItems(["pick", "drop", "mess", "fold", "roll", "edit"])
41 txt = self.__item.text(self.__column)
42 index = self.findText(txt)
43 if index > -1:
44 self.setCurrentIndex(index)
45
46 self.currentIndexChanged.connect(self.__changeItem)
47
48 @pyqtSlot(int)
49 def __changeItem(self, index):
50 """
51 Private slot to handle the selection of a plan action.
52
53 This method sets the text of the associated item for the specified
54 cell in order to be able to retrieve it with a call of the text()
55 method of the item.
56
57 @param index index of the selected action
58 @type int
59 """
60 self.__item.setText(self.__column, self.currentText())
61 self.__item.treeWidget().setCurrentItem(self.__item)
62
63 def showPopup(self):
64 """
65 Public method to show the list of items of the combo box.
66
67 This is reimplemented in order to set the associated item as the
68 current item of the tree widget.
69 """
70 self.__item.treeWidget().setCurrentItem(self.__item)
71 super(HgHisteditPlanActionComboBox, self).showPopup()
72
73
74 class HgHisteditPlanEditor(QDialog, Ui_HgHisteditPlanEditor):
75 """
76 Class implementing a dialog to edit the history modification plan.
77 """
78 def __init__(self, fileName, parent=None):
79 """
80 Constructor
81
82 @param fileName name of the file containing the history edit plan
83 to be edited
84 @type str
85 @param parent reference to the parent widget
86 @type QWidget
87 """
88 super(HgHisteditPlanEditor, self).__init__(parent)
89 self.setupUi(self)
90
91 self.upButton.setIcon(UI.PixmapCache.getIcon("1uparrow.png"))
92 self.downButton.setIcon(UI.PixmapCache.getIcon("1downarrow.png"))
93
94 self.planTreeWidget.headerItem().setText(
95 self.planTreeWidget.columnCount(), "")
96
97 self.__fileName = fileName
98 self.__readFile()
99
100 self.__updateButtons()
101
102 def __readFile(self):
103 """
104 Private method to read the file containing the edit plan and
105 populate the dialog.
106 """
107 try:
108 f = open(self.__fileName, "r")
109 txt = f.read()
110 f.close()
111 except (IOError, OSError) as err:
112 E5MessageBox.critical(
113 self,
114 self.tr("Edit Plan"),
115 self.tr("""<p>The file <b>{0}</b> could not be read.</p>"""
116 """<p>Reason: {1}</p>""").format(
117 self.__fileName, str(err)))
118 self.on_buttonBox_rejected()
119 return
120
121 infoLines = []
122 for line in txt.splitlines():
123 if line.startswith("#"):
124 infoLines.append(line[1:].lstrip())
125 else:
126 self.__createPlanItem(line)
127 self.infoEdit.setPlainText("\n".join(infoLines))
128
129 self.__resizeSections()
130
131 def __addActionCombo(self, item):
132 """
133 Private method to add an edit action combo to an item.
134
135 @param item reference to the tree widget item
136 @type QTreeWidgetItem
137 """
138 actionCombo = HgHisteditPlanActionComboBox(item, 0)
139 self.planTreeWidget.setItemWidget(item, 0, actionCombo)
140 item.setSizeHint(0, actionCombo.sizeHint())
141
142 def __createPlanItem(self, text):
143 """
144 Private method to create an edit plan tree item.
145
146 @param text line of text to be parsed
147 @type str
148 """
149 if not text.lstrip():
150 return
151
152 parts = text.split(" ", 3)
153 action = parts[0]
154 try:
155 rev = int(parts[2])
156 if len(parts) > 3:
157 summary = parts[3]
158 else:
159 summary = ""
160 except ValueError:
161 rev = -1
162 summary = " ".join(parts[2:])
163 if rev > -1:
164 revision = "{0:>7}:{1}".format(rev, parts[1])
165 else:
166 revision = parts[1]
167
168 itm = QTreeWidgetItem(self.planTreeWidget, [
169 action,
170 revision,
171 summary,
172 ])
173 self.__addActionCombo(itm)
174
175 def __resizeSections(self):
176 """
177 Private method to resize the tree widget sections.
178 """
179 for column in range(self.planTreeWidget.columnCount()):
180 self.planTreeWidget.resizeColumnToContents(column)
181 self.planTreeWidget.header().setStretchLastSection(True)
182
183 def __updateButtons(self):
184 """
185 Private method to set the enabled state of the up and down buttons.
186 """
187 if self.planTreeWidget.currentItem() is None:
188 self.upButton.setEnabled(False)
189 self.downButton.setEnabled(False)
190 else:
191 row = self.planTreeWidget.indexOfTopLevelItem(
192 self.planTreeWidget.currentItem())
193 self.upButton.setEnabled(row > 0)
194 self.downButton.setEnabled(
195 row < self.planTreeWidget.topLevelItemCount() - 1)
196
197 @pyqtSlot(QTreeWidgetItem, QTreeWidgetItem)
198 def on_planTreeWidget_currentItemChanged(self, current, previous):
199 """
200 Private slot handling the change of the current edit plan item.
201
202 @param current reference to the current edit plan item
203 @type QTreeWidgetItem
204 @param previous reference to the previous current edit plan item
205 @type QTreeWidgetItem
206 """
207 self.__updateButtons()
208
209 @pyqtSlot()
210 def on_upButton_clicked(self):
211 """
212 Private slot to move the current entry up one line.
213 """
214 row = self.planTreeWidget.indexOfTopLevelItem(
215 self.planTreeWidget.currentItem())
216 if row > 0:
217 targetRow = row - 1
218 itm = self.planTreeWidget.takeTopLevelItem(row)
219 self.planTreeWidget.insertTopLevelItem(targetRow, itm)
220 self.__addActionCombo(itm)
221 self.planTreeWidget.setCurrentItem(itm)
222
223 @pyqtSlot()
224 def on_downButton_clicked(self):
225 """
226 Private slot to move the current entry down one line.
227 """
228 row = self.planTreeWidget.indexOfTopLevelItem(
229 self.planTreeWidget.currentItem())
230 if row < self.planTreeWidget.topLevelItemCount() - 1:
231 targetRow = row + 1
232 itm = self.planTreeWidget.takeTopLevelItem(row)
233 self.planTreeWidget.insertTopLevelItem(targetRow, itm)
234 self.__addActionCombo(itm)
235 self.planTreeWidget.setCurrentItem(itm)
236
237 @pyqtSlot()
238 def on_buttonBox_accepted(self):
239 """
240 Private slot called by the buttonBox accepted signal.
241 """
242 text = self.__assembleEditPlan()
243 try:
244 f = open(self.__fileName, "w")
245 f.write(text)
246 f.close()
247 except (IOError, OSError) as err:
248 E5MessageBox.critical(
249 self,
250 self.tr("Edit Plan"),
251 self.tr("""<p>The file <b>{0}</b> could not be read.</p>"""
252 """<p>Reason: {1}</p>""").format(
253 self.__fileName, str(err)))
254 self.on_buttonBox_rejected()
255 return
256
257 self.close()
258 QCoreApplication.exit(0)
259
260 @pyqtSlot()
261 def on_buttonBox_rejected(self):
262 """
263 Private slot called by the buttonBox rejected signal.
264 """
265 self.close()
266 QCoreApplication.exit(1)
267
268 def __assembleEditPlan(self):
269 """
270 Private method to assemble the edit plan into text suitable for the
271 histedit file.
272
273 @return assembled edit plan text
274 @rtype str
275 """
276 lines = []
277 for row in range(self.planTreeWidget.topLevelItemCount()):
278 itm = self.planTreeWidget.topLevelItem(row)
279 if ":" in itm.text(1):
280 rev, changeset = itm.text(1).split(":", 1)
281 rev = "{0} {1}".format(changeset.strip(), rev.strip())
282 else:
283 rev = itm.text(1).strip()
284
285 lines.append("{0} {1} {2}".format(itm.text(0).strip(), rev,
286 itm.text(2)))
287
288 return "\n".join(lines)

eric ide

mercurial