eric7/VCS/StatusWidget.py

branch
eric7
changeset 8620
84f7f7867b5f
parent 8619
2dc55ddafc68
child 8621
8c9f41115c04
equal deleted inserted replaced
8619:2dc55ddafc68 8620:84f7f7867b5f
5 5
6 """ 6 """
7 Module implementing a VCS Status widget for the sidebar/toolbar. 7 Module implementing a VCS Status widget for the sidebar/toolbar.
8 """ 8 """
9 9
10 import contextlib
11 import os
12
10 from PyQt6.QtCore import pyqtSlot, Qt 13 from PyQt6.QtCore import pyqtSlot, Qt
11 from PyQt6.QtWidgets import ( 14 from PyQt6.QtWidgets import (
12 QWidget, QVBoxLayout, QHBoxLayout, QLabel, QSizePolicy, QListView, 15 QWidget, QVBoxLayout, QHBoxLayout, QLabel, QSizePolicy, QListView,
13 QListWidget, QListWidgetItem, QToolButton 16 QListWidget, QListWidgetItem, QToolButton, QAbstractItemView
14 ) 17 )
15 18
19 from EricWidgets.EricApplication import ericApp
20 from EricWidgets import EricMessageBox
21
22 import Preferences
16 import UI.PixmapCache 23 import UI.PixmapCache
17 24
18 25
19 class StatusWidget(QWidget): 26 class StatusWidget(QWidget):
20 """ 27 """
21 Class implementing a VCS Status widget for the sidebar/toolbox. 28 Class implementing a VCS Status widget for the sidebar/toolbox.
22 """ 29 """
30 StatusDataRole = Qt.ItemDataRole.UserRole + 1
31
23 def __init__(self, project, parent=None): 32 def __init__(self, project, parent=None):
24 """ 33 """
25 Constructor 34 Constructor
26 35
27 @param project reference to the project object 36 @param project reference to the project object
44 self.__infoLabel = QLabel(self) 53 self.__infoLabel = QLabel(self)
45 self.__infoLabel.setSizePolicy( 54 self.__infoLabel.setSizePolicy(
46 QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Preferred) 55 QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Preferred)
47 self.__topLayout.addWidget(self.__infoLabel) 56 self.__topLayout.addWidget(self.__infoLabel)
48 57
58 self.__commitToggleButton = QToolButton(self)
59 self.__commitToggleButton.setIcon(UI.PixmapCache.getIcon("check"))
60 self.__commitToggleButton.setToolTip(
61 self.tr("Press to toggle the commit markers"))
62 self.__commitToggleButton.clicked.connect(self.__toggleCheckMark)
63 self.__topLayout.addWidget(self.__commitToggleButton)
64
65 self.__commitButton = QToolButton(self)
66 self.__commitButton.setIcon(UI.PixmapCache.getIcon("vcsCommit"))
67 self.__commitButton.setToolTip(
68 self.tr("Press to commit the marked entries"))
69 self.__commitButton.clicked.connect(self.__commit)
70 self.__topLayout.addWidget(self.__commitButton)
71
72 self.__addButton = QToolButton(self)
73 self.__addButton.setIcon(UI.PixmapCache.getIcon("vcsAdd"))
74 self.__addButton.setToolTip(
75 self.tr("Press to add the selected, untracked entries"))
76 self.__addButton.clicked.connect(self.__addUntracked)
77 self.__topLayout.addWidget(self.__addButton)
78
49 self.__reloadButton = QToolButton(self) 79 self.__reloadButton = QToolButton(self)
50 self.__reloadButton.setIcon(UI.PixmapCache.getIcon("reload")) 80 self.__reloadButton.setIcon(UI.PixmapCache.getIcon("reload"))
81 self.__reloadButton.setToolTip(
82 self.tr("Press to reload the status list"))
51 self.__reloadButton.clicked.connect(self.__reload) 83 self.__reloadButton.clicked.connect(self.__reload)
52 self.__topLayout.addWidget(self.__reloadButton) 84 self.__topLayout.addWidget(self.__reloadButton)
53 85
54 self.__layout.addLayout(self.__topLayout) 86 self.__layout.addLayout(self.__topLayout)
55 87
56 self.__statusList = QListWidget(self) 88 self.__statusList = QListWidget(self)
57 self.__statusList.setAlternatingRowColors(True) 89 self.__statusList.setAlternatingRowColors(True)
58 self.__statusList.setSortingEnabled(True) 90 self.__statusList.setSortingEnabled(True)
59 self.__statusList.setViewMode(QListView.ViewMode.ListMode) 91 self.__statusList.setViewMode(QListView.ViewMode.ListMode)
60 self.__statusList.setTextElideMode(Qt.TextElideMode.ElideLeft) 92 self.__statusList.setTextElideMode(Qt.TextElideMode.ElideLeft)
93 self.__statusList.setSelectionMode(
94 QAbstractItemView.SelectionMode.ExtendedSelection)
61 self.__layout.addWidget(self.__statusList) 95 self.__layout.addWidget(self.__statusList)
62 96
63 self.setLayout(self.__layout) 97 self.setLayout(self.__layout)
98
99 self.__statusIcons = {
100 "A": "vcs-added", # added
101 "M": "vcs-modified", # modified
102 "O": "vcs-removed", # removed
103 "R": "vcs-renamed", # renamed
104 "U": "vcs-update-required", # update needed
105 "Z": "vcs-conflicting", # conflict
106 "?": "vcs-untracked", # not tracked
107 "!": "vcs-missing", # missing
108 }
109 self.__statusTexts = {
110 "A": self.tr("added"),
111 "M": self.tr("modified"),
112 "O": self.tr("removed"),
113 "R": self.tr("renamed"),
114 "U": self.tr("needs update"),
115 "Z": self.tr("conflict"),
116 "?": self.tr("not tracked"),
117 "!": self.tr("missing"),
118 }
64 119
65 if self.__project.isOpen(): 120 if self.__project.isOpen():
66 self.__projectOpened() 121 self.__projectOpened()
67 else: 122 else:
68 self.__projectClosed() 123 self.__projectClosed()
69 124
70 self.__project.projectOpened.connect(self.__projectOpened) 125 self.__project.projectOpened.connect(self.__projectOpened)
71 self.__project.projectClosed.connect(self.__projectClosed) 126 self.__project.projectClosed.connect(self.__projectClosed)
127 self.__project.vcsCommitted.connect(self.__committed)
72 self.__project.vcsStatusMonitorInfo.connect(self.__setInfoText) 128 self.__project.vcsStatusMonitorInfo.connect(self.__setInfoText)
73 self.__project.vcsStatusMonitorData.connect(self.__processStatusData) 129 self.__project.vcsStatusMonitorAllData.connect(
130 self.__processStatusData)
74 131
75 @pyqtSlot() 132 @pyqtSlot()
76 def __projectOpened(self): 133 def __projectOpened(self):
77 """ 134 """
78 Private slot to handle the opening of a project. 135 Private slot to handle the opening of a project.
105 """ 162 """
106 Private slot to reload the status list. 163 Private slot to reload the status list.
107 """ 164 """
108 self.__project.checkVCSStatus() 165 self.__project.checkVCSStatus()
109 166
110 @pyqtSlot(list) 167 @pyqtSlot(dict)
111 def __processStatusData(self, data): 168 def __processStatusData(self, data):
112 """ 169 """
113 Private slot to process the status data emitted by the project. 170 Private slot to process the status data emitted by the project.
114 171
115 Each entry of the status data consists of a status flag and and the 172 Each entry of the status data consists of a status flag and and the
120 <li>"M" path has local changes</li> 177 <li>"M" path has local changes</li>
121 <li>"O" path was removed</li> 178 <li>"O" path was removed</li>
122 <li>"R" path was deleted and then re-added</li> 179 <li>"R" path was deleted and then re-added</li>
123 <li>"U" path needs an update</li> 180 <li>"U" path needs an update</li>
124 <li>"Z" path contains a conflict</li> 181 <li>"Z" path contains a conflict</li>
182 <li>"?" path is not tracked</li>
183 <li>"!" path is missing</li>
125 <li>" " path is back at normal</li> 184 <li>" " path is back at normal</li>
126 </ul> 185 </ul>
127 186
128 @param data list of VCS status data 187 @param data dictionary containing the status data
129 @type list of str 188 @type dict
130 """ 189 """
131 self.__statusList.clear() 190 self.__statusList.clear()
132 191
133 for entry in data: 192 for name, status in data.items():
134 QListWidgetItem(entry, self.__statusList) 193 if status:
194 itm = QListWidgetItem(name, self.__statusList)
195 with contextlib.suppress(KeyError):
196 itm.setToolTip(self.__statusTexts[status])
197 itm.setIcon(UI.PixmapCache.getIcon(
198 self.__statusIcons[status]))
199 itm.setData(self.StatusDataRole, status)
200 if status in "AMOR":
201 itm.setFlags(
202 itm.flags() | Qt.ItemFlag.ItemIsUserCheckable)
203 itm.setCheckState(Qt.CheckState.Checked)
204 else:
205 itm.setFlags(
206 itm.flags() & ~Qt.ItemFlag.ItemIsUserCheckable)
207
135 self.__statusList.sortItems(Qt.SortOrder.AscendingOrder) 208 self.__statusList.sortItems(Qt.SortOrder.AscendingOrder)
209
210 @pyqtSlot()
211 def __toggleCheckMark(self):
212 """
213 Private slot to toggle the check marks.
214 """
215 for row in range(self.__statusList.count()):
216 itm = self.__statusList.item(row)
217 if (
218 itm.flags() & Qt.ItemFlag.ItemIsUserCheckable ==
219 Qt.ItemFlag.ItemIsUserCheckable
220 ):
221 if itm.checkState() == Qt.CheckState.Unchecked:
222 itm.setCheckState(Qt.CheckState.Checked)
223 else:
224 itm.setCheckState(Qt.CheckState.Unchecked)
225
226 @pyqtSlot()
227 def __commit(self):
228 """
229 Private slot to handle the commit button.
230 """
231 projectPath = self.__project.getProjectPath()
232 names = []
233
234 for row in range(self.__statusList.count()):
235 itm = self.__statusList.item(row)
236 if itm.checkState() == Qt.CheckState.Checked:
237 names.append(os.path.join(projectPath, itm.text()))
238
239 if not names:
240 EricMessageBox.information(
241 self,
242 self.tr("Commit"),
243 self.tr("""There are no entries selected to be"""
244 """ committed."""))
245 return
246
247 if Preferences.getVCS("AutoSaveFiles"):
248 vm = ericApp().getObject("ViewManager")
249 for name in names:
250 vm.saveEditor(name)
251 vcs = self.__project.getVcs()
252 vcs and vcs.vcsCommit(names, '')
253
254 @pyqtSlot()
255 def __committed(self):
256 """
257 Private slot called after the commit has been completed.
258 """
259 self.__reload()
260
261 @pyqtSlot()
262 def __addUntracked(self):
263 """
264 Private slot to add the selected untracked entries.
265 """
266 projectPath = self.__project.getProjectPath()
267
268 names = [
269 os.path.join(projectPath, itm.text())
270 for itm in self.__statusList.selectedItems()
271 if itm.data(self.StatusDataRole) == "?"
272 ]
273
274 if not names:
275 EricMessageBox.information(
276 self,
277 self.tr("Add"),
278 self.tr("""There are no unversioned entries"""
279 """ available/selected."""))
280 return
281
282 vcs = self.__project.getVcs()
283 vcs and vcs.vcsAdd(names)
284 self.__reload()

eric ide

mercurial