src/eric7/Plugins/VcsPlugins/vcsMercurial/HisteditExtension/HgHisteditPlanEditor.py

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

eric ide

mercurial