29 |
39 |
30 class StatusWidget(QWidget): |
40 class StatusWidget(QWidget): |
31 """ |
41 """ |
32 Class implementing a VCS Status widget for the sidebar/toolbox. |
42 Class implementing a VCS Status widget for the sidebar/toolbox. |
33 """ |
43 """ |
|
44 |
34 StatusDataRole = Qt.ItemDataRole.UserRole + 1 |
45 StatusDataRole = Qt.ItemDataRole.UserRole + 1 |
35 |
46 |
36 def __init__(self, project, viewmanager, parent=None): |
47 def __init__(self, project, viewmanager, parent=None): |
37 """ |
48 """ |
38 Constructor |
49 Constructor |
39 |
50 |
40 @param project reference to the project object |
51 @param project reference to the project object |
41 @type Project |
52 @type Project |
42 @param viewmanager reference to the viewmanager object |
53 @param viewmanager reference to the viewmanager object |
43 @type ViewManager |
54 @type ViewManager |
44 @param parent reference to the parent widget (defaults to None) |
55 @param parent reference to the parent widget (defaults to None) |
45 @type QWidget (optional) |
56 @type QWidget (optional) |
46 """ |
57 """ |
47 super().__init__(parent) |
58 super().__init__(parent) |
48 self.setObjectName("VcsStatusWidget") |
59 self.setObjectName("VcsStatusWidget") |
49 |
60 |
50 self.__project = project |
61 self.__project = project |
51 self.__vm = viewmanager |
62 self.__vm = viewmanager |
52 |
63 |
53 self.__layout = QVBoxLayout() |
64 self.__layout = QVBoxLayout() |
54 self.__layout.setObjectName("MainLayout") |
65 self.__layout.setObjectName("MainLayout") |
55 self.__layout.setContentsMargins(0, 3, 0, 0) |
66 self.__layout.setContentsMargins(0, 3, 0, 0) |
56 self.__topLayout = QHBoxLayout() |
67 self.__topLayout = QHBoxLayout() |
57 self.__topLayout.setObjectName("topLayout") |
68 self.__topLayout.setObjectName("topLayout") |
58 |
69 |
59 # Create the top area |
70 # Create the top area |
60 self.__infoLabel = QLabel(self) |
71 self.__infoLabel = QLabel(self) |
61 self.__infoLabel.setSizePolicy( |
72 self.__infoLabel.setSizePolicy( |
62 QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Preferred) |
73 QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Preferred |
|
74 ) |
63 self.__topLayout.addWidget(self.__infoLabel) |
75 self.__topLayout.addWidget(self.__infoLabel) |
64 |
76 |
65 self.__commitToggleButton = QToolButton(self) |
77 self.__commitToggleButton = QToolButton(self) |
66 self.__commitToggleButton.setIcon(UI.PixmapCache.getIcon("check")) |
78 self.__commitToggleButton.setIcon(UI.PixmapCache.getIcon("check")) |
67 self.__commitToggleButton.setToolTip( |
79 self.__commitToggleButton.setToolTip( |
68 self.tr("Press to toggle the commit markers")) |
80 self.tr("Press to toggle the commit markers") |
|
81 ) |
69 self.__commitToggleButton.clicked.connect(self.__toggleCheckMark) |
82 self.__commitToggleButton.clicked.connect(self.__toggleCheckMark) |
70 self.__topLayout.addWidget(self.__commitToggleButton) |
83 self.__topLayout.addWidget(self.__commitToggleButton) |
71 |
84 |
72 self.__commitButton = QToolButton(self) |
85 self.__commitButton = QToolButton(self) |
73 self.__commitButton.setIcon(UI.PixmapCache.getIcon("vcsCommit")) |
86 self.__commitButton.setIcon(UI.PixmapCache.getIcon("vcsCommit")) |
74 self.__commitButton.setToolTip( |
87 self.__commitButton.setToolTip( |
75 self.tr("Press to commit the marked entries with options")) |
88 self.tr("Press to commit the marked entries with options") |
|
89 ) |
76 self.__commitButton.clicked.connect(self.__commit) |
90 self.__commitButton.clicked.connect(self.__commit) |
77 self.__topLayout.addWidget(self.__commitButton) |
91 self.__topLayout.addWidget(self.__commitButton) |
78 |
92 |
79 self.__addButton = QToolButton(self) |
93 self.__addButton = QToolButton(self) |
80 self.__addButton.setIcon(UI.PixmapCache.getIcon("vcsAdd")) |
94 self.__addButton.setIcon(UI.PixmapCache.getIcon("vcsAdd")) |
81 self.__addButton.setToolTip( |
95 self.__addButton.setToolTip( |
82 self.tr("Press to add the selected, untracked entries")) |
96 self.tr("Press to add the selected, untracked entries") |
|
97 ) |
83 self.__addButton.clicked.connect(self.__addUntracked) |
98 self.__addButton.clicked.connect(self.__addUntracked) |
84 self.__topLayout.addWidget(self.__addButton) |
99 self.__topLayout.addWidget(self.__addButton) |
85 |
100 |
86 self.__reloadButton = QToolButton(self) |
101 self.__reloadButton = QToolButton(self) |
87 self.__reloadButton.setIcon(UI.PixmapCache.getIcon("reload")) |
102 self.__reloadButton.setIcon(UI.PixmapCache.getIcon("reload")) |
88 self.__reloadButton.setToolTip( |
103 self.__reloadButton.setToolTip(self.tr("Press to reload the status list")) |
89 self.tr("Press to reload the status list")) |
|
90 self.__reloadButton.clicked.connect(self.__reload) |
104 self.__reloadButton.clicked.connect(self.__reload) |
91 self.__topLayout.addWidget(self.__reloadButton) |
105 self.__topLayout.addWidget(self.__reloadButton) |
92 |
106 |
93 self.__actionsButton = QToolButton(self) |
107 self.__actionsButton = QToolButton(self) |
94 self.__actionsButton.setIcon( |
108 self.__actionsButton.setIcon(UI.PixmapCache.getIcon("actionsToolButton")) |
95 UI.PixmapCache.getIcon("actionsToolButton")) |
109 self.__actionsButton.setToolTip(self.tr("Select action from menu")) |
96 self.__actionsButton.setToolTip( |
110 self.__actionsButton.setPopupMode(QToolButton.ToolButtonPopupMode.InstantPopup) |
97 self.tr("Select action from menu")) |
|
98 self.__actionsButton.setPopupMode( |
|
99 QToolButton.ToolButtonPopupMode.InstantPopup) |
|
100 self.__topLayout.addWidget(self.__actionsButton) |
111 self.__topLayout.addWidget(self.__actionsButton) |
101 |
112 |
102 self.__layout.addLayout(self.__topLayout) |
113 self.__layout.addLayout(self.__topLayout) |
103 ################################################################### |
114 ################################################################### |
104 |
115 |
105 # Create the middle part |
116 # Create the middle part |
106 self.__statusList = QListWidget(self) |
117 self.__statusList = QListWidget(self) |
107 self.__statusList.setAlternatingRowColors(True) |
118 self.__statusList.setAlternatingRowColors(True) |
108 self.__statusList.setSortingEnabled(True) |
119 self.__statusList.setSortingEnabled(True) |
109 self.__statusList.setViewMode(QListView.ViewMode.ListMode) |
120 self.__statusList.setViewMode(QListView.ViewMode.ListMode) |
110 self.__statusList.setTextElideMode(Qt.TextElideMode.ElideLeft) |
121 self.__statusList.setTextElideMode(Qt.TextElideMode.ElideLeft) |
111 self.__statusList.setSelectionMode( |
122 self.__statusList.setSelectionMode( |
112 QAbstractItemView.SelectionMode.ExtendedSelection) |
123 QAbstractItemView.SelectionMode.ExtendedSelection |
113 self.__statusList.itemSelectionChanged.connect( |
124 ) |
114 self.__updateEnabledStates) |
125 self.__statusList.itemSelectionChanged.connect(self.__updateEnabledStates) |
115 self.__statusList.itemDoubleClicked.connect(self.__itemDoubleClicked) |
126 self.__statusList.itemDoubleClicked.connect(self.__itemDoubleClicked) |
116 self.__statusList.itemChanged.connect(self.__updateEnabledStates) |
127 self.__statusList.itemChanged.connect(self.__updateEnabledStates) |
117 self.__layout.addWidget(self.__statusList) |
128 self.__layout.addWidget(self.__statusList) |
118 ################################################################### |
129 ################################################################### |
119 |
130 |
120 # create the Quick Commit area |
131 # create the Quick Commit area |
121 self.__quickCommitGroup = QGroupBox(self.tr("Quick Commit"), self) |
132 self.__quickCommitGroup = QGroupBox(self.tr("Quick Commit"), self) |
122 self.__quickCommitLayout = QVBoxLayout() |
133 self.__quickCommitLayout = QVBoxLayout() |
123 self.__quickCommitEdit = EricSpellCheckedTextEdit(self) |
134 self.__quickCommitEdit = EricSpellCheckedTextEdit(self) |
124 self.__quickCommitEdit.setSizePolicy( |
135 self.__quickCommitEdit.setSizePolicy( |
125 QSizePolicy.Policy.Expanding, |
136 QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Preferred |
126 QSizePolicy.Policy.Preferred) |
137 ) |
127 self.__quickCommitEdit.setMaximumHeight(100) |
138 self.__quickCommitEdit.setMaximumHeight(100) |
128 self.__quickCommitEdit.setTabChangesFocus(True) |
139 self.__quickCommitEdit.setTabChangesFocus(True) |
129 self.__quickCommitEdit.installEventFilter(self) |
140 self.__quickCommitEdit.installEventFilter(self) |
130 self.__quickCommitEdit.textChanged.connect( |
141 self.__quickCommitEdit.textChanged.connect(self.__quickCommitEditTextChanged) |
131 self.__quickCommitEditTextChanged) |
|
132 self.__quickCommitLayout.addWidget(self.__quickCommitEdit) |
142 self.__quickCommitLayout.addWidget(self.__quickCommitEdit) |
133 |
143 |
134 self.__quickCommitLayout2 = QHBoxLayout() |
144 self.__quickCommitLayout2 = QHBoxLayout() |
135 self.__quickCommitLayout2.addStretch() |
145 self.__quickCommitLayout2.addStretch() |
136 |
146 |
137 self.__quickCommitHistoryButton = QToolButton(self) |
147 self.__quickCommitHistoryButton = QToolButton(self) |
138 self.__quickCommitHistoryButton.setIcon( |
148 self.__quickCommitHistoryButton.setIcon(UI.PixmapCache.getIcon("history")) |
139 UI.PixmapCache.getIcon("history")) |
|
140 self.__quickCommitHistoryButton.setToolTip( |
149 self.__quickCommitHistoryButton.setToolTip( |
141 self.tr("Select commit message from previous commits")) |
150 self.tr("Select commit message from previous commits") |
142 self.__quickCommitHistoryButton.clicked.connect( |
151 ) |
143 self.__selectQuickCommitMessage) |
152 self.__quickCommitHistoryButton.clicked.connect(self.__selectQuickCommitMessage) |
144 self.__quickCommitLayout2.addWidget(self.__quickCommitHistoryButton) |
153 self.__quickCommitLayout2.addWidget(self.__quickCommitHistoryButton) |
145 |
154 |
146 self.__quickCommitHistoryClearButton = QToolButton(self) |
155 self.__quickCommitHistoryClearButton = QToolButton(self) |
147 self.__quickCommitHistoryClearButton.setIcon( |
156 self.__quickCommitHistoryClearButton.setIcon( |
148 UI.PixmapCache.getIcon("historyClear")) |
157 UI.PixmapCache.getIcon("historyClear") |
|
158 ) |
149 self.__quickCommitHistoryClearButton.setToolTip( |
159 self.__quickCommitHistoryClearButton.setToolTip( |
150 self.tr("Clear the list of saved commit messages")) |
160 self.tr("Clear the list of saved commit messages") |
151 self.__quickCommitHistoryClearButton.clicked.connect( |
161 ) |
152 self.__clearCommitMessages) |
162 self.__quickCommitHistoryClearButton.clicked.connect(self.__clearCommitMessages) |
153 self.__quickCommitLayout2.addWidget( |
163 self.__quickCommitLayout2.addWidget(self.__quickCommitHistoryClearButton) |
154 self.__quickCommitHistoryClearButton) |
164 |
155 |
|
156 self.__quickCommitButton = QToolButton(self) |
165 self.__quickCommitButton = QToolButton(self) |
157 self.__quickCommitButton.setIcon( |
166 self.__quickCommitButton.setIcon(UI.PixmapCache.getIcon("vcsCommit")) |
158 UI.PixmapCache.getIcon("vcsCommit")) |
|
159 self.__quickCommitButton.setToolTip( |
167 self.__quickCommitButton.setToolTip( |
160 self.tr("Press to commit the marked entries")) |
168 self.tr("Press to commit the marked entries") |
|
169 ) |
161 self.__quickCommitButton.clicked.connect(self.__quickCommit) |
170 self.__quickCommitButton.clicked.connect(self.__quickCommit) |
162 self.__quickCommitLayout2.addWidget(self.__quickCommitButton) |
171 self.__quickCommitLayout2.addWidget(self.__quickCommitButton) |
163 |
172 |
164 self.__quickCommitLayout.addLayout(self.__quickCommitLayout2) |
173 self.__quickCommitLayout.addLayout(self.__quickCommitLayout2) |
165 self.__quickCommitGroup.setLayout(self.__quickCommitLayout) |
174 self.__quickCommitGroup.setLayout(self.__quickCommitLayout) |
166 self.__layout.addWidget(self.__quickCommitGroup) |
175 self.__layout.addWidget(self.__quickCommitGroup) |
167 ################################################################### |
176 ################################################################### |
168 |
177 |
169 self.setLayout(self.__layout) |
178 self.setLayout(self.__layout) |
170 |
179 |
171 self.__statusIcons = { |
180 self.__statusIcons = { |
172 "A": "vcs-added", # added |
181 "A": "vcs-added", # added |
173 "M": "vcs-modified", # modified |
182 "M": "vcs-modified", # modified |
174 "O": "vcs-removed", # removed |
183 "O": "vcs-removed", # removed |
175 "R": "vcs-renamed", # renamed |
184 "R": "vcs-renamed", # renamed |
176 "U": "vcs-update-required", # update needed |
185 "U": "vcs-update-required", # update needed |
177 "Z": "vcs-conflicting", # conflict |
186 "Z": "vcs-conflicting", # conflict |
178 "?": "vcs-untracked", # not tracked |
187 "?": "vcs-untracked", # not tracked |
179 "!": "vcs-missing", # missing |
188 "!": "vcs-missing", # missing |
180 } |
189 } |
181 self.__statusTexts = { |
190 self.__statusTexts = { |
182 "A": self.tr("added"), |
191 "A": self.tr("added"), |
183 "M": self.tr("modified"), |
192 "M": self.tr("modified"), |
184 "O": self.tr("removed"), |
193 "O": self.tr("removed"), |
186 "U": self.tr("needs update"), |
195 "U": self.tr("needs update"), |
187 "Z": self.tr("conflict"), |
196 "Z": self.tr("conflict"), |
188 "?": self.tr("not tracked"), |
197 "?": self.tr("not tracked"), |
189 "!": self.tr("missing"), |
198 "!": self.tr("missing"), |
190 } |
199 } |
191 |
200 |
192 self.__initActionsMenu() |
201 self.__initActionsMenu() |
193 |
202 |
194 self.__reset() |
203 self.__reset() |
195 |
204 |
196 if self.__project.isOpen(): |
205 if self.__project.isOpen(): |
197 self.__projectOpened() |
206 self.__projectOpened() |
198 else: |
207 else: |
199 self.__projectClosed() |
208 self.__projectClosed() |
200 |
209 |
201 self.__addedItemsText = [] |
210 self.__addedItemsText = [] |
202 |
211 |
203 self.__project.projectOpened.connect(self.__projectOpened) |
212 self.__project.projectOpened.connect(self.__projectOpened) |
204 self.__project.projectClosed.connect(self.__projectClosed) |
213 self.__project.projectClosed.connect(self.__projectClosed) |
205 self.__project.projectPropertiesChanged.connect( |
214 self.__project.projectPropertiesChanged.connect(self.__setProjectSpellCheckData) |
206 self.__setProjectSpellCheckData) |
|
207 self.__project.vcsCommitted.connect(self.__committed) |
215 self.__project.vcsCommitted.connect(self.__committed) |
208 self.__project.vcsStatusMonitorInfo.connect(self.__setInfoText) |
216 self.__project.vcsStatusMonitorInfo.connect(self.__setInfoText) |
209 self.__project.vcsStatusMonitorAllData.connect( |
217 self.__project.vcsStatusMonitorAllData.connect(self.__processStatusData) |
210 self.__processStatusData) |
218 |
211 |
|
212 def __initActionsMenu(self): |
219 def __initActionsMenu(self): |
213 """ |
220 """ |
214 Private method to initialize the actions menu. |
221 Private method to initialize the actions menu. |
215 """ |
222 """ |
216 self.__actionsMenu = QMenu() |
223 self.__actionsMenu = QMenu() |
217 self.__actionsMenu.setToolTipsVisible(True) |
224 self.__actionsMenu.setToolTipsVisible(True) |
218 self.__actionsMenu.aboutToShow.connect(self.__showActionsMenu) |
225 self.__actionsMenu.aboutToShow.connect(self.__showActionsMenu) |
219 |
226 |
220 self.__commitAct = self.__actionsMenu.addAction( |
227 self.__commitAct = self.__actionsMenu.addAction( |
221 UI.PixmapCache.getIcon("vcsCommit"), |
228 UI.PixmapCache.getIcon("vcsCommit"), self.tr("Commit"), self.__commit |
222 self.tr("Commit"), self.__commit) |
229 ) |
223 self.__commitAct.setToolTip(self.tr( |
230 self.__commitAct.setToolTip(self.tr("Commit the marked entries with options")) |
224 "Commit the marked entries with options")) |
|
225 self.__commitSelectAct = self.__actionsMenu.addAction( |
231 self.__commitSelectAct = self.__actionsMenu.addAction( |
226 self.tr("Select all for commit"), self.__commitSelectAll) |
232 self.tr("Select all for commit"), self.__commitSelectAll |
|
233 ) |
227 self.__commitDeselectAct = self.__actionsMenu.addAction( |
234 self.__commitDeselectAct = self.__actionsMenu.addAction( |
228 self.tr("Unselect all from commit"), self.__commitDeselectAll) |
235 self.tr("Unselect all from commit"), self.__commitDeselectAll |
229 |
236 ) |
|
237 |
230 self.__actionsMenu.addSeparator() |
238 self.__actionsMenu.addSeparator() |
231 |
239 |
232 self.__addAct = self.__actionsMenu.addAction( |
240 self.__addAct = self.__actionsMenu.addAction( |
233 UI.PixmapCache.getIcon("vcsAdd"), |
241 UI.PixmapCache.getIcon("vcsAdd"), self.tr("Add"), self.__addUntracked |
234 self.tr("Add"), self.__addUntracked) |
242 ) |
235 self.__addAct.setToolTip(self.tr( |
243 self.__addAct.setToolTip(self.tr("Add the selected, untracked entries")) |
236 "Add the selected, untracked entries")) |
|
237 self.__addAllAct = self.__actionsMenu.addAction( |
244 self.__addAllAct = self.__actionsMenu.addAction( |
238 self.tr("Add All"), self.__addAllUntracked) |
245 self.tr("Add All"), self.__addAllUntracked |
239 self.__addAllAct.setToolTip(self.tr( |
246 ) |
240 "Add all untracked entries")) |
247 self.__addAllAct.setToolTip(self.tr("Add all untracked entries")) |
241 |
248 |
242 self.__actionsMenu.addSeparator() |
249 self.__actionsMenu.addSeparator() |
243 |
250 |
244 self.__diffAct = self.__actionsMenu.addAction( |
251 self.__diffAct = self.__actionsMenu.addAction( |
245 UI.PixmapCache.getIcon("vcsDiff"), |
252 UI.PixmapCache.getIcon("vcsDiff"), self.tr("Differences"), self.__diff |
246 self.tr("Differences"), self.__diff) |
253 ) |
247 self.__diffAct.setToolTip(self.tr( |
254 self.__diffAct.setToolTip( |
248 "Shows the differences of the selected entry in a" |
255 self.tr( |
249 " separate dialog")) |
256 "Shows the differences of the selected entry in a" " separate dialog" |
|
257 ) |
|
258 ) |
250 self.__sbsDiffAct = self.__actionsMenu.addAction( |
259 self.__sbsDiffAct = self.__actionsMenu.addAction( |
251 UI.PixmapCache.getIcon("vcsSbsDiff"), |
260 UI.PixmapCache.getIcon("vcsSbsDiff"), |
252 self.tr("Differences Side-By-Side"), self.__sbsDiff) |
261 self.tr("Differences Side-By-Side"), |
253 self.__sbsDiffAct.setToolTip(self.tr( |
262 self.__sbsDiff, |
254 "Shows the differences of the selected entry side-by-side in" |
263 ) |
255 " a separate dialog")) |
264 self.__sbsDiffAct.setToolTip( |
|
265 self.tr( |
|
266 "Shows the differences of the selected entry side-by-side in" |
|
267 " a separate dialog" |
|
268 ) |
|
269 ) |
256 self.__diffAllAct = self.__actionsMenu.addAction( |
270 self.__diffAllAct = self.__actionsMenu.addAction( |
257 self.tr("All Differences"), self.__diffAll) |
271 self.tr("All Differences"), self.__diffAll |
258 self.__diffAllAct.setToolTip(self.tr( |
272 ) |
259 "Shows the differences of all entries in a separate dialog")) |
273 self.__diffAllAct.setToolTip( |
260 |
274 self.tr("Shows the differences of all entries in a separate dialog") |
|
275 ) |
|
276 |
261 self.__actionsMenu.addSeparator() |
277 self.__actionsMenu.addSeparator() |
262 |
278 |
263 self.__revertAct = self.__actionsMenu.addAction( |
279 self.__revertAct = self.__actionsMenu.addAction( |
264 UI.PixmapCache.getIcon("vcsRevert"), |
280 UI.PixmapCache.getIcon("vcsRevert"), self.tr("Revert"), self.__revert |
265 self.tr("Revert"), self.__revert) |
281 ) |
266 self.__revertAct.setToolTip(self.tr( |
282 self.__revertAct.setToolTip( |
267 "Reverts the changes of the selected files")) |
283 self.tr("Reverts the changes of the selected files") |
268 |
284 ) |
|
285 |
269 self.__actionsMenu.addSeparator() |
286 self.__actionsMenu.addSeparator() |
270 |
287 |
271 self.__forgetAct = self.__actionsMenu.addAction( |
288 self.__forgetAct = self.__actionsMenu.addAction( |
272 self.tr("Forget Missing"), self.__forgetMissing) |
289 self.tr("Forget Missing"), self.__forgetMissing |
273 self.__forgetAct.setToolTip(self.tr( |
290 ) |
274 "Forgets about the selected missing files")) |
291 self.__forgetAct.setToolTip(self.tr("Forgets about the selected missing files")) |
275 self.__restoreAct = self.__actionsMenu.addAction( |
292 self.__restoreAct = self.__actionsMenu.addAction( |
276 self.tr("Restore Missing"), self.__restoreMissing) |
293 self.tr("Restore Missing"), self.__restoreMissing |
277 self.__restoreAct.setToolTip(self.tr( |
294 ) |
278 "Restores the selected missing files")) |
295 self.__restoreAct.setToolTip(self.tr("Restores the selected missing files")) |
279 self.__actionsMenu.addSeparator() |
296 self.__actionsMenu.addSeparator() |
280 |
297 |
281 self.__editAct = self.__actionsMenu.addAction( |
298 self.__editAct = self.__actionsMenu.addAction( |
282 UI.PixmapCache.getIcon("open"), |
299 UI.PixmapCache.getIcon("open"), |
283 self.tr("Edit Conflict"), self.__editConflict) |
300 self.tr("Edit Conflict"), |
284 self.__editAct.setToolTip(self.tr( |
301 self.__editConflict, |
285 "Edit the selected conflicting file")) |
302 ) |
|
303 self.__editAct.setToolTip(self.tr("Edit the selected conflicting file")) |
286 self.__resolvedAct = self.__actionsMenu.addAction( |
304 self.__resolvedAct = self.__actionsMenu.addAction( |
287 UI.PixmapCache.getIcon("vcsResolved"), |
305 UI.PixmapCache.getIcon("vcsResolved"), |
288 self.tr("Conflict Resolved"), self.__conflictResolved) |
306 self.tr("Conflict Resolved"), |
289 self.__resolvedAct.setToolTip(self.tr( |
307 self.__conflictResolved, |
290 "Mark the selected conflicting file as resolved")) |
308 ) |
291 |
309 self.__resolvedAct.setToolTip( |
|
310 self.tr("Mark the selected conflicting file as resolved") |
|
311 ) |
|
312 |
292 self.__actionsButton.setMenu(self.__actionsMenu) |
313 self.__actionsButton.setMenu(self.__actionsMenu) |
293 |
314 |
294 @pyqtSlot() |
315 @pyqtSlot() |
295 def __projectOpened(self): |
316 def __projectOpened(self): |
296 """ |
317 """ |
297 Private slot to handle the opening of a project. |
318 Private slot to handle the opening of a project. |
298 """ |
319 """ |
299 self.__reloadButton.setEnabled(True) |
320 self.__reloadButton.setEnabled(True) |
300 self.__setProjectSpellCheckData() |
321 self.__setProjectSpellCheckData() |
301 |
322 |
302 @pyqtSlot() |
323 @pyqtSlot() |
303 def __setProjectSpellCheckData(self): |
324 def __setProjectSpellCheckData(self): |
304 """ |
325 """ |
305 Private slot to set the spell check properties of the |
326 Private slot to set the spell check properties of the |
306 quick commit area. |
327 quick commit area. |
307 """ |
328 """ |
308 pwl, pel = self.__project.getProjectDictionaries() |
329 pwl, pel = self.__project.getProjectDictionaries() |
309 language = self.__project.getProjectSpellLanguage() |
330 language = self.__project.getProjectSpellLanguage() |
310 self.__quickCommitEdit.setLanguageWithPWL( |
331 self.__quickCommitEdit.setLanguageWithPWL(language, pwl or None, pel or None) |
311 language, pwl or None, pel or None) |
332 |
312 |
|
313 @pyqtSlot() |
333 @pyqtSlot() |
314 def __projectClosed(self): |
334 def __projectClosed(self): |
315 """ |
335 """ |
316 Private slot to handle the closing of a project. |
336 Private slot to handle the closing of a project. |
317 """ |
337 """ |
318 self.__infoLabel.setText(self.tr("No project open.")) |
338 self.__infoLabel.setText(self.tr("No project open.")) |
319 |
339 |
320 self.__reloadButton.setEnabled(False) |
340 self.__reloadButton.setEnabled(False) |
321 |
341 |
322 self.__reset() |
342 self.__reset() |
323 |
343 |
324 @pyqtSlot(str) |
344 @pyqtSlot(str) |
325 def __setInfoText(self, info): |
345 def __setInfoText(self, info): |
326 """ |
346 """ |
327 Private slot to set the info label text. |
347 Private slot to set the info label text. |
328 |
348 |
329 @param info text to be shown |
349 @param info text to be shown |
330 @type str |
350 @type str |
331 """ |
351 """ |
332 self.__infoLabel.setText(info) |
352 self.__infoLabel.setText(info) |
333 |
353 |
334 @pyqtSlot() |
354 @pyqtSlot() |
335 def __reload(self): |
355 def __reload(self): |
336 """ |
356 """ |
337 Private slot to reload the status list. |
357 Private slot to reload the status list. |
338 """ |
358 """ |
339 self.__project.checkVCSStatus() |
359 self.__project.checkVCSStatus() |
340 |
360 |
341 def __reset(self): |
361 def __reset(self): |
342 """ |
362 """ |
343 Private method to reset the widget to default. |
363 Private method to reset the widget to default. |
344 """ |
364 """ |
345 self.__statusList.clear() |
365 self.__statusList.clear() |
346 |
366 |
347 self.__commitToggleButton.setEnabled(False) |
367 self.__commitToggleButton.setEnabled(False) |
348 self.__commitButton.setEnabled(False) |
368 self.__commitButton.setEnabled(False) |
349 self.__addButton.setEnabled(False) |
369 self.__addButton.setEnabled(False) |
350 |
370 |
351 self.__quickCommitEdit.clear() |
371 self.__quickCommitEdit.clear() |
352 self.__quickCommitGroup.setEnabled(False) |
372 self.__quickCommitGroup.setEnabled(False) |
353 |
373 |
354 def __updateEnabledStates(self): |
374 def __updateEnabledStates(self): |
355 """ |
375 """ |
356 Private method to set the enabled states depending on the list state. |
376 Private method to set the enabled states depending on the list state. |
357 """ |
377 """ |
358 modified = len(self.__getModifiedItems()) |
378 modified = len(self.__getModifiedItems()) |
359 unversioned = len(self.__getSelectedUnversionedItems()) |
379 unversioned = len(self.__getSelectedUnversionedItems()) |
360 commitable = len(self.__getCommitableItems()) |
380 commitable = len(self.__getCommitableItems()) |
361 |
381 |
362 self.__commitToggleButton.setEnabled(modified) |
382 self.__commitToggleButton.setEnabled(modified) |
363 self.__commitButton.setEnabled(commitable) |
383 self.__commitButton.setEnabled(commitable) |
364 self.__addButton.setEnabled(unversioned) |
384 self.__addButton.setEnabled(unversioned) |
365 |
385 |
366 self.__quickCommitGroup.setEnabled(commitable) |
386 self.__quickCommitGroup.setEnabled(commitable) |
367 |
387 |
368 @pyqtSlot(dict) |
388 @pyqtSlot(dict) |
369 def __processStatusData(self, data): |
389 def __processStatusData(self, data): |
370 """ |
390 """ |
371 Private slot to process the status data emitted by the project. |
391 Private slot to process the status data emitted by the project. |
372 |
392 |
373 Each entry of the status data consists of a status flag and and the |
393 Each entry of the status data consists of a status flag and and the |
374 path relative to the project directory starting with the third column. |
394 path relative to the project directory starting with the third column. |
375 The known status flags are: |
395 The known status flags are: |
376 <ul> |
396 <ul> |
377 <li>"A" path was added but not yet committed</li> |
397 <li>"A" path was added but not yet committed</li> |
382 <li>"Z" path contains a conflict</li> |
402 <li>"Z" path contains a conflict</li> |
383 <li>"?" path is not tracked</li> |
403 <li>"?" path is not tracked</li> |
384 <li>"!" path is missing</li> |
404 <li>"!" path is missing</li> |
385 <li>" " path is back at normal</li> |
405 <li>" " path is back at normal</li> |
386 </ul> |
406 </ul> |
387 |
407 |
388 @param data dictionary containing the status data |
408 @param data dictionary containing the status data |
389 @type dict |
409 @type dict |
390 """ |
410 """ |
391 # step 1: remember all currently checked entries |
411 # step 1: remember all currently checked entries |
392 checkedEntries = [itm.text() for itm in self.__getCommitableItems()] |
412 checkedEntries = [itm.text() for itm in self.__getCommitableItems()] |
393 selectedEntries = [itm.text() |
413 selectedEntries = [itm.text() for itm in self.__statusList.selectedItems()] |
394 for itm in self.__statusList.selectedItems()] |
414 knownEntries = [ |
395 knownEntries = [self.__statusList.item(row).text() |
415 self.__statusList.item(row).text() |
396 for row in range(self.__statusList.count())] |
416 for row in range(self.__statusList.count()) |
397 |
417 ] |
|
418 |
398 # step 2: clear the list and re-populate it with new data |
419 # step 2: clear the list and re-populate it with new data |
399 self.__statusList.clear() |
420 self.__statusList.clear() |
400 |
421 |
401 block = self.__statusList.blockSignals(True) |
422 block = self.__statusList.blockSignals(True) |
402 for name, status in data.items(): |
423 for name, status in data.items(): |
403 if status: |
424 if status: |
404 itm = QListWidgetItem(name, self.__statusList) |
425 itm = QListWidgetItem(name, self.__statusList) |
405 with contextlib.suppress(KeyError): |
426 with contextlib.suppress(KeyError): |
406 itm.setToolTip(self.__statusTexts[status]) |
427 itm.setToolTip(self.__statusTexts[status]) |
407 itm.setIcon(UI.PixmapCache.getIcon( |
428 itm.setIcon(UI.PixmapCache.getIcon(self.__statusIcons[status])) |
408 self.__statusIcons[status])) |
|
409 itm.setData(self.StatusDataRole, status) |
429 itm.setData(self.StatusDataRole, status) |
410 if status in "AMOR": |
430 if status in "AMOR": |
411 itm.setFlags( |
431 itm.setFlags(itm.flags() | Qt.ItemFlag.ItemIsUserCheckable) |
412 itm.flags() | Qt.ItemFlag.ItemIsUserCheckable) |
|
413 if ( |
432 if ( |
414 name in checkedEntries or |
433 name in checkedEntries |
415 name not in knownEntries or |
434 or name not in knownEntries |
416 name in self.__addedItemsText |
435 or name in self.__addedItemsText |
417 ): |
436 ): |
418 itm.setCheckState(Qt.CheckState.Checked) |
437 itm.setCheckState(Qt.CheckState.Checked) |
419 else: |
438 else: |
420 itm.setCheckState(Qt.CheckState.Unchecked) |
439 itm.setCheckState(Qt.CheckState.Unchecked) |
421 else: |
440 else: |
422 itm.setFlags( |
441 itm.setFlags(itm.flags() & ~Qt.ItemFlag.ItemIsUserCheckable) |
423 itm.flags() & ~Qt.ItemFlag.ItemIsUserCheckable) |
|
424 itm.setSelected(name in selectedEntries) |
442 itm.setSelected(name in selectedEntries) |
425 |
443 |
426 self.__statusList.sortItems(Qt.SortOrder.AscendingOrder) |
444 self.__statusList.sortItems(Qt.SortOrder.AscendingOrder) |
427 self.__statusList.blockSignals(block) |
445 self.__statusList.blockSignals(block) |
428 |
446 |
429 self.__updateEnabledStates() |
447 self.__updateEnabledStates() |
430 |
448 |
431 @pyqtSlot() |
449 @pyqtSlot() |
432 def __toggleCheckMark(self): |
450 def __toggleCheckMark(self): |
433 """ |
451 """ |
434 Private slot to toggle the check marks. |
452 Private slot to toggle the check marks. |
435 """ |
453 """ |
436 itemList = ( |
454 itemList = ( |
437 self.__statusList.selectedItems() |
455 self.__statusList.selectedItems() |
438 if len(self.__statusList.selectedItems()) else |
456 if len(self.__statusList.selectedItems()) |
439 [self.__statusList.item(row) |
457 else [ |
440 for row in range(self.__statusList.count())] |
458 self.__statusList.item(row) for row in range(self.__statusList.count()) |
|
459 ] |
441 ) |
460 ) |
442 for itm in itemList: |
461 for itm in itemList: |
443 if ( |
462 if ( |
444 itm.flags() & Qt.ItemFlag.ItemIsUserCheckable == |
463 itm.flags() & Qt.ItemFlag.ItemIsUserCheckable |
445 Qt.ItemFlag.ItemIsUserCheckable |
464 == Qt.ItemFlag.ItemIsUserCheckable |
446 ): |
465 ): |
447 if itm.checkState() == Qt.CheckState.Unchecked: |
466 if itm.checkState() == Qt.CheckState.Unchecked: |
448 itm.setCheckState(Qt.CheckState.Checked) |
467 itm.setCheckState(Qt.CheckState.Checked) |
449 else: |
468 else: |
450 itm.setCheckState(Qt.CheckState.Unchecked) |
469 itm.setCheckState(Qt.CheckState.Unchecked) |
451 |
470 |
452 def __setCheckMark(self, checked): |
471 def __setCheckMark(self, checked): |
453 """ |
472 """ |
454 Private method to set or unset all check marks. |
473 Private method to set or unset all check marks. |
455 |
474 |
456 @param checked check mark state to be set |
475 @param checked check mark state to be set |
457 @type bool |
476 @type bool |
458 """ |
477 """ |
459 for row in range(self.__statusList.count()): |
478 for row in range(self.__statusList.count()): |
460 itm = self.__statusList.item(row) |
479 itm = self.__statusList.item(row) |
461 if ( |
480 if ( |
462 itm.flags() & Qt.ItemFlag.ItemIsUserCheckable == |
481 itm.flags() & Qt.ItemFlag.ItemIsUserCheckable |
463 Qt.ItemFlag.ItemIsUserCheckable |
482 == Qt.ItemFlag.ItemIsUserCheckable |
464 ): |
483 ): |
465 if checked: |
484 if checked: |
466 itm.setCheckState(Qt.CheckState.Checked) |
485 itm.setCheckState(Qt.CheckState.Checked) |
467 else: |
486 else: |
468 itm.setCheckState(Qt.CheckState.Unchecked) |
487 itm.setCheckState(Qt.CheckState.Unchecked) |
469 |
488 |
470 @pyqtSlot() |
489 @pyqtSlot() |
471 def __commit(self): |
490 def __commit(self): |
472 """ |
491 """ |
473 Private slot to handle the commit button. |
492 Private slot to handle the commit button. |
474 """ |
493 """ |
475 projectPath = self.__project.getProjectPath() |
494 projectPath = self.__project.getProjectPath() |
476 names = [] |
495 names = [] |
477 |
496 |
478 for row in range(self.__statusList.count()): |
497 for row in range(self.__statusList.count()): |
479 itm = self.__statusList.item(row) |
498 itm = self.__statusList.item(row) |
480 if itm.checkState() == Qt.CheckState.Checked: |
499 if itm.checkState() == Qt.CheckState.Checked: |
481 names.append(os.path.join(projectPath, itm.text())) |
500 names.append(os.path.join(projectPath, itm.text())) |
482 |
501 |
483 if not names: |
502 if not names: |
484 EricMessageBox.information( |
503 EricMessageBox.information( |
485 self, |
504 self, |
486 self.tr("Commit"), |
505 self.tr("Commit"), |
487 self.tr("""There are no entries selected to be""" |
506 self.tr("""There are no entries selected to be""" """ committed."""), |
488 """ committed.""")) |
507 ) |
489 return |
508 return |
490 |
509 |
491 if Preferences.getVCS("AutoSaveFiles"): |
510 if Preferences.getVCS("AutoSaveFiles"): |
492 vm = ericApp().getObject("ViewManager") |
511 vm = ericApp().getObject("ViewManager") |
493 for name in names: |
512 for name in names: |
494 vm.saveEditor(name) |
513 vm.saveEditor(name) |
495 vcs = self.__project.getVcs() |
514 vcs = self.__project.getVcs() |
496 vcs and vcs.vcsCommit(names, '') |
515 vcs and vcs.vcsCommit(names, "") |
497 |
516 |
498 @pyqtSlot() |
517 @pyqtSlot() |
499 def __committed(self): |
518 def __committed(self): |
500 """ |
519 """ |
501 Private slot called after the commit has been completed. |
520 Private slot called after the commit has been completed. |
502 """ |
521 """ |
503 self.__reload() |
522 self.__reload() |
504 |
523 |
505 @pyqtSlot() |
524 @pyqtSlot() |
506 def __commitSelectAll(self): |
525 def __commitSelectAll(self): |
507 """ |
526 """ |
508 Private slot to select all entries for commit. |
527 Private slot to select all entries for commit. |
509 """ |
528 """ |
510 self.__setCheckMark(True) |
529 self.__setCheckMark(True) |
511 |
530 |
512 @pyqtSlot() |
531 @pyqtSlot() |
513 def __commitDeselectAll(self): |
532 def __commitDeselectAll(self): |
514 """ |
533 """ |
515 Private slot to deselect all entries from commit. |
534 Private slot to deselect all entries from commit. |
516 """ |
535 """ |
517 self.__setCheckMark(False) |
536 self.__setCheckMark(False) |
518 |
537 |
519 @pyqtSlot() |
538 @pyqtSlot() |
520 def __addUntracked(self, allItems=False): |
539 def __addUntracked(self, allItems=False): |
521 """ |
540 """ |
522 Private slot to add the selected untracked entries. |
541 Private slot to add the selected untracked entries. |
523 |
542 |
524 @param allItems flag indicating to show the differences of all files |
543 @param allItems flag indicating to show the differences of all files |
525 (defaults to False) |
544 (defaults to False) |
526 @type bool (optional) |
545 @type bool (optional) |
527 """ |
546 """ |
528 projectPath = self.__project.getProjectPath() |
547 projectPath = self.__project.getProjectPath() |
529 |
548 |
530 names = [ |
549 names = ( |
531 os.path.join(projectPath, itm.text()) |
550 [ |
532 for itm in self.__getUnversionedItems() |
551 os.path.join(projectPath, itm.text()) |
533 ] if allItems else [ |
552 for itm in self.__getUnversionedItems() |
534 os.path.join(projectPath, itm.text()) |
553 ] |
535 for itm in self.__getSelectedUnversionedItems() |
554 if allItems |
536 ] |
555 else [ |
537 |
556 os.path.join(projectPath, itm.text()) |
|
557 for itm in self.__getSelectedUnversionedItems() |
|
558 ] |
|
559 ) |
|
560 |
538 if not names: |
561 if not names: |
539 EricMessageBox.information( |
562 EricMessageBox.information( |
540 self, |
563 self, |
541 self.tr("Add"), |
564 self.tr("Add"), |
542 self.tr("""There are no unversioned entries""" |
565 self.tr( |
543 """ available/selected.""")) |
566 """There are no unversioned entries""" """ available/selected.""" |
|
567 ), |
|
568 ) |
544 return |
569 return |
545 |
570 |
546 self.__addedItemsText = [ |
571 self.__addedItemsText = ( |
547 itm.text() for itm in self.__getUnversionedItems() |
572 [itm.text() for itm in self.__getUnversionedItems()] |
548 ] if allItems else [ |
573 if allItems |
549 itm.text() for itm in self.__getSelectedUnversionedItems() |
574 else [itm.text() for itm in self.__getSelectedUnversionedItems()] |
550 ] |
575 ) |
551 |
576 |
552 vcs = self.__project.getVcs() |
577 vcs = self.__project.getVcs() |
553 vcs and vcs.vcsAdd(names) |
578 vcs and vcs.vcsAdd(names) |
554 self.__reload() |
579 self.__reload() |
555 |
580 |
556 @pyqtSlot(QListWidgetItem) |
581 @pyqtSlot(QListWidgetItem) |
557 def __itemDoubleClicked(self, itm): |
582 def __itemDoubleClicked(self, itm): |
558 """ |
583 """ |
559 Private slot to handle double clicking an item. |
584 Private slot to handle double clicking an item. |
560 |
585 |
561 @param itm reference to the double clicked item |
586 @param itm reference to the double clicked item |
562 @type QListWidgetItem |
587 @type QListWidgetItem |
563 """ |
588 """ |
564 projectPath = self.__project.getProjectPath() |
589 projectPath = self.__project.getProjectPath() |
565 |
590 |
566 if itm.data(self.StatusDataRole) in "MZ": |
591 if itm.data(self.StatusDataRole) in "MZ": |
567 # modified and conflicting items |
592 # modified and conflicting items |
568 name = os.path.join(projectPath, itm.text()) |
593 name = os.path.join(projectPath, itm.text()) |
569 vcs = self.__project.getVcs() |
594 vcs = self.__project.getVcs() |
570 vcs and vcs.vcsDiff(name) |
595 vcs and vcs.vcsDiff(name) |
571 |
596 |
572 ########################################################################### |
597 ########################################################################### |
573 ## Menu handling methods |
598 ## Menu handling methods |
574 ########################################################################### |
599 ########################################################################### |
575 |
600 |
576 def __showActionsMenu(self): |
601 def __showActionsMenu(self): |
577 """ |
602 """ |
578 Private slot to prepare the actions button menu before it is shown. |
603 Private slot to prepare the actions button menu before it is shown. |
579 """ |
604 """ |
580 modified = len(self.__getSelectedModifiedItems()) |
605 modified = len(self.__getSelectedModifiedItems()) |
597 self.__commitAct.setEnabled(commitable) |
622 self.__commitAct.setEnabled(commitable) |
598 self.__commitSelectAct.setEnabled(commitableUnselected) |
623 self.__commitSelectAct.setEnabled(commitableUnselected) |
599 self.__commitDeselectAct.setEnabled(commitable) |
624 self.__commitDeselectAct.setEnabled(commitable) |
600 self.__editAct.setEnabled(conflicting == 1) |
625 self.__editAct.setEnabled(conflicting == 1) |
601 self.__resolvedAct.setEnabled(conflicting) |
626 self.__resolvedAct.setEnabled(conflicting) |
602 |
627 |
603 def __getCommitableItems(self): |
628 def __getCommitableItems(self): |
604 """ |
629 """ |
605 Private method to retrieve all entries the user wants to commit. |
630 Private method to retrieve all entries the user wants to commit. |
606 |
631 |
607 @return list of all items, the user has checked |
632 @return list of all items, the user has checked |
608 @rtype list of QListWidgetItem |
633 @rtype list of QListWidgetItem |
609 """ |
634 """ |
610 commitableItems = [] |
635 commitableItems = [] |
611 for row in range(self.__statusList.count()): |
636 for row in range(self.__statusList.count()): |
612 itm = self.__statusList.item(row) |
637 itm = self.__statusList.item(row) |
613 if ( |
638 if itm.checkState() == Qt.CheckState.Checked: |
614 itm.checkState() == Qt.CheckState.Checked |
|
615 ): |
|
616 commitableItems.append(itm) |
639 commitableItems.append(itm) |
617 return commitableItems |
640 return commitableItems |
618 |
641 |
619 def __getCommitableUnselectedItems(self): |
642 def __getCommitableUnselectedItems(self): |
620 """ |
643 """ |
621 Private method to retrieve all entries the user may commit but hasn't |
644 Private method to retrieve all entries the user may commit but hasn't |
622 selected. |
645 selected. |
623 |
646 |
624 @return list of all items, the user has checked |
647 @return list of all items, the user has checked |
625 @rtype list of QListWidgetItem |
648 @rtype list of QListWidgetItem |
626 """ |
649 """ |
627 items = [] |
650 items = [] |
628 for row in range(self.__statusList.count()): |
651 for row in range(self.__statusList.count()): |
629 itm = self.__statusList.item(row) |
652 itm = self.__statusList.item(row) |
630 if ( |
653 if ( |
631 (itm.flags() & Qt.ItemFlag.ItemIsUserCheckable == |
654 itm.flags() & Qt.ItemFlag.ItemIsUserCheckable |
632 Qt.ItemFlag.ItemIsUserCheckable) and |
655 == Qt.ItemFlag.ItemIsUserCheckable |
633 itm.checkState() == Qt.CheckState.Unchecked |
656 ) and itm.checkState() == Qt.CheckState.Unchecked: |
634 ): |
|
635 items.append(itm) |
657 items.append(itm) |
636 return items |
658 return items |
637 |
659 |
638 def __getModifiedItems(self): |
660 def __getModifiedItems(self): |
639 """ |
661 """ |
640 Private method to retrieve all entries, that have a modified status. |
662 Private method to retrieve all entries, that have a modified status. |
641 |
663 |
642 @return list of all items with a modified status |
664 @return list of all items with a modified status |
643 @rtype list of QListWidgetItem |
665 @rtype list of QListWidgetItem |
644 """ |
666 """ |
645 items = [] |
667 items = [] |
646 for row in range(self.__statusList.count()): |
668 for row in range(self.__statusList.count()): |
647 itm = self.__statusList.item(row) |
669 itm = self.__statusList.item(row) |
648 if itm.data(self.StatusDataRole) in "AMOR": |
670 if itm.data(self.StatusDataRole) in "AMOR": |
649 items.append(itm) |
671 items.append(itm) |
650 return items |
672 return items |
651 |
673 |
652 def __getSelectedModifiedItems(self): |
674 def __getSelectedModifiedItems(self): |
653 """ |
675 """ |
654 Private method to retrieve all selected entries, that have a modified |
676 Private method to retrieve all selected entries, that have a modified |
655 status. |
677 status. |
656 |
678 |
657 @return list of all selected entries with a modified status |
679 @return list of all selected entries with a modified status |
658 @rtype list of QListWidgetItem |
680 @rtype list of QListWidgetItem |
659 """ |
681 """ |
660 return [itm for itm in self.__statusList.selectedItems() |
682 return [ |
661 if itm.data(self.StatusDataRole) in "AMOR"] |
683 itm |
662 |
684 for itm in self.__statusList.selectedItems() |
|
685 if itm.data(self.StatusDataRole) in "AMOR" |
|
686 ] |
|
687 |
663 def __getUnversionedItems(self): |
688 def __getUnversionedItems(self): |
664 """ |
689 """ |
665 Private method to retrieve all entries, that have an unversioned |
690 Private method to retrieve all entries, that have an unversioned |
666 status. |
691 status. |
667 |
692 |
668 @return list of all items with an unversioned status |
693 @return list of all items with an unversioned status |
669 @rtype list of QListWidgetItem |
694 @rtype list of QListWidgetItem |
670 """ |
695 """ |
671 items = [] |
696 items = [] |
672 for row in range(self.__statusList.count()): |
697 for row in range(self.__statusList.count()): |
673 itm = self.__statusList.item(row) |
698 itm = self.__statusList.item(row) |
674 if itm.data(self.StatusDataRole) == "?": |
699 if itm.data(self.StatusDataRole) == "?": |
675 items.append(itm) |
700 items.append(itm) |
676 return items |
701 return items |
677 |
702 |
678 def __getSelectedUnversionedItems(self): |
703 def __getSelectedUnversionedItems(self): |
679 """ |
704 """ |
680 Private method to retrieve all selected entries, that have an |
705 Private method to retrieve all selected entries, that have an |
681 unversioned status. |
706 unversioned status. |
682 |
707 |
683 @return list of all items with an unversioned status |
708 @return list of all items with an unversioned status |
684 @rtype list of QListWidgetItem |
709 @rtype list of QListWidgetItem |
685 """ |
710 """ |
686 return [itm for itm in self.__statusList.selectedItems() |
711 return [ |
687 if itm.data(self.StatusDataRole) == "?"] |
712 itm |
688 |
713 for itm in self.__statusList.selectedItems() |
|
714 if itm.data(self.StatusDataRole) == "?" |
|
715 ] |
|
716 |
689 def __getMissingItems(self): |
717 def __getMissingItems(self): |
690 """ |
718 """ |
691 Private method to retrieve all entries, that have a missing status. |
719 Private method to retrieve all entries, that have a missing status. |
692 |
720 |
693 @return list of all items with a missing status |
721 @return list of all items with a missing status |
694 @rtype list of QListWidgetItem |
722 @rtype list of QListWidgetItem |
695 """ |
723 """ |
696 return [itm for itm in self.__statusList.selectedItems() |
724 return [ |
697 if itm.data(self.StatusDataRole) == "!"] |
725 itm |
698 |
726 for itm in self.__statusList.selectedItems() |
|
727 if itm.data(self.StatusDataRole) == "!" |
|
728 ] |
|
729 |
699 def __getSelectedConflictingItems(self): |
730 def __getSelectedConflictingItems(self): |
700 """ |
731 """ |
701 Private method to retrieve all selected entries, that have a conflict |
732 Private method to retrieve all selected entries, that have a conflict |
702 status. |
733 status. |
703 |
734 |
704 @return list of all selected entries with a conflict status |
735 @return list of all selected entries with a conflict status |
705 @rtype list of QListWidgetItem |
736 @rtype list of QListWidgetItem |
706 """ |
737 """ |
707 return [itm for itm in self.__statusList.selectedItems() |
738 return [ |
708 if itm.data(self.StatusDataRole) == "Z"] |
739 itm |
709 |
740 for itm in self.__statusList.selectedItems() |
|
741 if itm.data(self.StatusDataRole) == "Z" |
|
742 ] |
|
743 |
710 @pyqtSlot() |
744 @pyqtSlot() |
711 def __addAllUntracked(self): |
745 def __addAllUntracked(self): |
712 """ |
746 """ |
713 Private slot to handle the Add All action menu entry. |
747 Private slot to handle the Add All action menu entry. |
714 """ |
748 """ |
715 self.__addUntracked(allItems=True) |
749 self.__addUntracked(allItems=True) |
716 |
750 |
717 @pyqtSlot() |
751 @pyqtSlot() |
718 def __diff(self, allItems=False): |
752 def __diff(self, allItems=False): |
719 """ |
753 """ |
720 Private slot to handle the Differences action menu entry. |
754 Private slot to handle the Differences action menu entry. |
721 |
755 |
722 @param allItems flag indicating to show the differences of all files |
756 @param allItems flag indicating to show the differences of all files |
723 (defaults to False) |
757 (defaults to False) |
724 @type bool (optional) |
758 @type bool (optional) |
725 """ |
759 """ |
726 projectPath = self.__project.getProjectPath() |
760 projectPath = self.__project.getProjectPath() |
727 |
761 |
|
762 names = ( |
|
763 [os.path.join(projectPath, itm.text()) for itm in self.__getModifiedItems()] |
|
764 if allItems |
|
765 else [ |
|
766 os.path.join(projectPath, itm.text()) |
|
767 for itm in self.__getSelectedModifiedItems() |
|
768 ] |
|
769 ) |
|
770 if not names: |
|
771 EricMessageBox.information( |
|
772 self, |
|
773 self.tr("Differences"), |
|
774 self.tr( |
|
775 """There are no uncommitted changes""" """ available/selected.""" |
|
776 ), |
|
777 ) |
|
778 return |
|
779 |
|
780 vcs = self.__project.getVcs() |
|
781 vcs and vcs.vcsDiff(names) |
|
782 |
|
783 @pyqtSlot() |
|
784 def __diffAll(self): |
|
785 """ |
|
786 Private slot to handle the All Differences action menu entry. |
|
787 """ |
|
788 self.__diff(allItems=True) |
|
789 |
|
790 @pyqtSlot() |
|
791 def __sbsDiff(self): |
|
792 """ |
|
793 Private slot to handle the Side-By-Side Differences action menu entry. |
|
794 """ |
|
795 projectPath = self.__project.getProjectPath() |
|
796 |
728 names = [ |
797 names = [ |
729 os.path.join(projectPath, itm.text()) |
|
730 for itm in self.__getModifiedItems() |
|
731 ] if allItems else [ |
|
732 os.path.join(projectPath, itm.text()) |
798 os.path.join(projectPath, itm.text()) |
733 for itm in self.__getSelectedModifiedItems() |
799 for itm in self.__getSelectedModifiedItems() |
734 ] |
800 ] |
735 if not names: |
801 if not names: |
736 EricMessageBox.information( |
802 EricMessageBox.information( |
737 self, |
803 self, |
738 self.tr("Differences"), |
|
739 self.tr("""There are no uncommitted changes""" |
|
740 """ available/selected.""")) |
|
741 return |
|
742 |
|
743 vcs = self.__project.getVcs() |
|
744 vcs and vcs.vcsDiff(names) |
|
745 |
|
746 @pyqtSlot() |
|
747 def __diffAll(self): |
|
748 """ |
|
749 Private slot to handle the All Differences action menu entry. |
|
750 """ |
|
751 self.__diff(allItems=True) |
|
752 |
|
753 @pyqtSlot() |
|
754 def __sbsDiff(self): |
|
755 """ |
|
756 Private slot to handle the Side-By-Side Differences action menu entry. |
|
757 """ |
|
758 projectPath = self.__project.getProjectPath() |
|
759 |
|
760 names = [os.path.join(projectPath, itm.text()) |
|
761 for itm in self.__getSelectedModifiedItems()] |
|
762 if not names: |
|
763 EricMessageBox.information( |
|
764 self, |
|
765 self.tr("Differences Side-By-Side"), |
804 self.tr("Differences Side-By-Side"), |
766 self.tr("""There are no uncommitted changes""" |
805 self.tr( |
767 """ available/selected.""")) |
806 """There are no uncommitted changes""" """ available/selected.""" |
|
807 ), |
|
808 ) |
768 return |
809 return |
769 elif len(names) > 1: |
810 elif len(names) > 1: |
770 EricMessageBox.information( |
811 EricMessageBox.information( |
771 self, |
812 self, |
772 self.tr("Differences Side-By-Side"), |
813 self.tr("Differences Side-By-Side"), |
773 self.tr("""Only one file with uncommitted changes""" |
814 self.tr( |
774 """ must be selected.""")) |
815 """Only one file with uncommitted changes""" |
|
816 """ must be selected.""" |
|
817 ), |
|
818 ) |
775 return |
819 return |
776 |
820 |
777 vcs = self.__project.getVcs() |
821 vcs = self.__project.getVcs() |
778 vcs and vcs.vcsSbsDiff(names[0]) |
822 vcs and vcs.vcsSbsDiff(names[0]) |
779 |
823 |
780 @pyqtSlot() |
824 @pyqtSlot() |
781 def __revert(self): |
825 def __revert(self): |
782 """ |
826 """ |
783 Private slot to handle the Revert action menu entry. |
827 Private slot to handle the Revert action menu entry. |
784 """ |
828 """ |
785 projectPath = self.__project.getProjectPath() |
829 projectPath = self.__project.getProjectPath() |
786 |
830 |
787 names = [os.path.join(projectPath, itm.text()) |
831 names = [ |
788 for itm in self.__getSelectedModifiedItems()] |
832 os.path.join(projectPath, itm.text()) |
|
833 for itm in self.__getSelectedModifiedItems() |
|
834 ] |
789 if not names: |
835 if not names: |
790 EricMessageBox.information( |
836 EricMessageBox.information( |
791 self, |
837 self, |
792 self.tr("Revert"), |
838 self.tr("Revert"), |
793 self.tr("""There are no uncommitted changes""" |
839 self.tr( |
794 """ available/selected.""")) |
840 """There are no uncommitted changes""" """ available/selected.""" |
|
841 ), |
|
842 ) |
795 return |
843 return |
796 |
844 |
797 vcs = self.__project.getVcs() |
845 vcs = self.__project.getVcs() |
798 vcs and vcs.vcsRevert(names) |
846 vcs and vcs.vcsRevert(names) |
799 self.__reload() |
847 self.__reload() |
800 |
848 |
801 @pyqtSlot() |
849 @pyqtSlot() |
802 def __forgetMissing(self): |
850 def __forgetMissing(self): |
803 """ |
851 """ |
804 Private slot to handle the Forget action menu entry. |
852 Private slot to handle the Forget action menu entry. |
805 """ |
853 """ |
806 projectPath = self.__project.getProjectPath() |
854 projectPath = self.__project.getProjectPath() |
807 |
855 |
808 names = [os.path.join(projectPath, itm.text()) |
856 names = [ |
809 for itm in self.__getMissingItems()] |
857 os.path.join(projectPath, itm.text()) for itm in self.__getMissingItems() |
|
858 ] |
810 if not names: |
859 if not names: |
811 EricMessageBox.information( |
860 EricMessageBox.information( |
812 self, |
861 self, |
813 self.tr("Forget Missing"), |
862 self.tr("Forget Missing"), |
814 self.tr("""There are no missing entries""" |
863 self.tr("""There are no missing entries""" """ available/selected."""), |
815 """ available/selected.""")) |
864 ) |
816 return |
865 return |
817 |
866 |
818 vcs = self.__project.getVcs() |
867 vcs = self.__project.getVcs() |
819 vcs and vcs.vcsForget(names) |
868 vcs and vcs.vcsForget(names) |
820 self.__reload() |
869 self.__reload() |
821 |
870 |
822 @pyqtSlot() |
871 @pyqtSlot() |
823 def __restoreMissing(self): |
872 def __restoreMissing(self): |
824 """ |
873 """ |
825 Private slot to handle the Restore Missing context menu entry. |
874 Private slot to handle the Restore Missing context menu entry. |
826 """ |
875 """ |
827 projectPath = self.__project.getProjectPath() |
876 projectPath = self.__project.getProjectPath() |
828 |
877 |
829 names = [os.path.join(projectPath, itm.text()) |
878 names = [ |
830 for itm in self.__getMissingItems()] |
879 os.path.join(projectPath, itm.text()) for itm in self.__getMissingItems() |
|
880 ] |
831 if not names: |
881 if not names: |
832 EricMessageBox.information( |
882 EricMessageBox.information( |
833 self, |
883 self, |
834 self.tr("Restore Missing"), |
884 self.tr("Restore Missing"), |
835 self.tr("""There are no missing entries""" |
885 self.tr("""There are no missing entries""" """ available/selected."""), |
836 """ available/selected.""")) |
886 ) |
837 return |
887 return |
838 |
888 |
839 vcs = self.__project.getVcs() |
889 vcs = self.__project.getVcs() |
840 vcs and vcs.vcsRevert(names) |
890 vcs and vcs.vcsRevert(names) |
841 self.__reload() |
891 self.__reload() |
842 |
892 |
843 @pyqtSlot() |
893 @pyqtSlot() |
844 def __editConflict(self): |
894 def __editConflict(self): |
845 """ |
895 """ |
846 Private slot to handle the Edit Conflict action menu entry. |
896 Private slot to handle the Edit Conflict action menu entry. |
847 """ |
897 """ |
848 projectPath = self.__project.getProjectPath() |
898 projectPath = self.__project.getProjectPath() |
849 |
899 |
850 itm = self.__getSelectedConflictingItems()[0] |
900 itm = self.__getSelectedConflictingItems()[0] |
851 filename = os.path.join(projectPath, itm.text()) |
901 filename = os.path.join(projectPath, itm.text()) |
852 if Utilities.MimeTypes.isTextFile(filename): |
902 if Utilities.MimeTypes.isTextFile(filename): |
853 self.__vm.getEditor(filename) |
903 self.__vm.getEditor(filename) |
854 |
904 |
855 @pyqtSlot() |
905 @pyqtSlot() |
856 def __conflictResolved(self): |
906 def __conflictResolved(self): |
857 """ |
907 """ |
858 Private slot to handle the Conflict Resolved action menu entry. |
908 Private slot to handle the Conflict Resolved action menu entry. |
859 """ |
909 """ |
860 projectPath = self.__project.getProjectPath() |
910 projectPath = self.__project.getProjectPath() |
861 |
911 |
862 names = [os.path.join(projectPath, itm.text()) |
912 names = [ |
863 for itm in self.__getSelectedConflictingItems()] |
913 os.path.join(projectPath, itm.text()) |
|
914 for itm in self.__getSelectedConflictingItems() |
|
915 ] |
864 if not names: |
916 if not names: |
865 EricMessageBox.information( |
917 EricMessageBox.information( |
866 self, |
918 self, |
867 self.tr("Conflict Resolved"), |
919 self.tr("Conflict Resolved"), |
868 self.tr("""There are no conflicting entries""" |
920 self.tr( |
869 """ available/selected.""")) |
921 """There are no conflicting entries""" """ available/selected.""" |
|
922 ), |
|
923 ) |
870 return |
924 return |
871 |
925 |
872 vcs = self.__project.getVcs() |
926 vcs = self.__project.getVcs() |
873 vcs and vcs.vcsResolved(names) |
927 vcs and vcs.vcsResolved(names) |
874 self.__reload() |
928 self.__reload() |
875 |
929 |
876 ####################################################################### |
930 ####################################################################### |
877 ## Quick Commit handling methods |
931 ## Quick Commit handling methods |
878 ####################################################################### |
932 ####################################################################### |
879 |
933 |
880 @pyqtSlot() |
934 @pyqtSlot() |
881 def __selectQuickCommitMessage(self): |
935 def __selectQuickCommitMessage(self): |
882 """ |
936 """ |
883 Private slot to select a commit message from the list of |
937 Private slot to select a commit message from the list of |
884 saved messages. |
938 saved messages. |
890 commitMessages, |
944 commitMessages, |
891 selectionMode=QAbstractItemView.SelectionMode.SingleSelection, |
945 selectionMode=QAbstractItemView.SelectionMode.SingleSelection, |
892 title=self.tr("Quick Commit"), |
946 title=self.tr("Quick Commit"), |
893 message=self.tr("Select your commit message:"), |
947 message=self.tr("Select your commit message:"), |
894 doubleClickOk=True, |
948 doubleClickOk=True, |
895 parent=self |
949 parent=self, |
896 ) |
950 ) |
897 if dlg.exec() == QDialog.DialogCode.Accepted: |
951 if dlg.exec() == QDialog.DialogCode.Accepted: |
898 selection = dlg.getSelection() |
952 selection = dlg.getSelection() |
899 if selection: |
953 if selection: |
900 self.__quickCommitEdit.setPlainText(selection[0]) |
954 self.__quickCommitEdit.setPlainText(selection[0]) |
901 |
955 |
902 @pyqtSlot() |
956 @pyqtSlot() |
903 def __clearCommitMessages(self): |
957 def __clearCommitMessages(self): |
904 """ |
958 """ |
905 Private slot to clear the list of saved commit messages. |
959 Private slot to clear the list of saved commit messages. |
906 """ |
960 """ |
907 vcs = self.__project.getVcs() |
961 vcs = self.__project.getVcs() |
908 vcs and vcs.vcsClearCommitMessages() |
962 vcs and vcs.vcsClearCommitMessages() |
909 |
963 |
910 @pyqtSlot() |
964 @pyqtSlot() |
911 def __quickCommit(self): |
965 def __quickCommit(self): |
912 """ |
966 """ |
913 Private slot to commit all marked entries with the entered |
967 Private slot to commit all marked entries with the entered |
914 commit message. |
968 commit message. |
915 """ |
969 """ |
916 projectPath = self.__project.getProjectPath() |
970 projectPath = self.__project.getProjectPath() |
917 names = [] |
971 names = [] |
918 |
972 |
919 for row in range(self.__statusList.count()): |
973 for row in range(self.__statusList.count()): |
920 itm = self.__statusList.item(row) |
974 itm = self.__statusList.item(row) |
921 if itm.checkState() == Qt.CheckState.Checked: |
975 if itm.checkState() == Qt.CheckState.Checked: |
922 names.append(os.path.join(projectPath, itm.text())) |
976 names.append(os.path.join(projectPath, itm.text())) |
923 |
977 |
924 if not names: |
978 if not names: |
925 EricMessageBox.information( |
979 EricMessageBox.information( |
926 self, |
980 self, |
927 self.tr("Commit"), |
981 self.tr("Commit"), |
928 self.tr("""There are no entries selected to be""" |
982 self.tr("""There are no entries selected to be""" """ committed."""), |
929 """ committed.""")) |
983 ) |
930 return |
984 return |
931 |
985 |
932 if Preferences.getVCS("AutoSaveFiles"): |
986 if Preferences.getVCS("AutoSaveFiles"): |
933 vm = ericApp().getObject("ViewManager") |
987 vm = ericApp().getObject("ViewManager") |
934 for name in names: |
988 for name in names: |
935 vm.saveEditor(name) |
989 vm.saveEditor(name) |
936 |
990 |
937 commitMessage = self.__quickCommitEdit.toPlainText() |
991 commitMessage = self.__quickCommitEdit.toPlainText() |
938 vcs = self.__project.getVcs() |
992 vcs = self.__project.getVcs() |
939 if vcs: |
993 if vcs: |
940 vcs.vcsCommit(names, commitMessage, noDialog=True) |
994 vcs.vcsCommit(names, commitMessage, noDialog=True) |
941 vcs.vcsAddCommitMessage(commitMessage) |
995 vcs.vcsAddCommitMessage(commitMessage) |
942 self.__quickCommitEdit.clear() |
996 self.__quickCommitEdit.clear() |
943 |
997 |
944 @pyqtSlot() |
998 @pyqtSlot() |
945 def __quickCommitEditTextChanged(self): |
999 def __quickCommitEditTextChanged(self): |
946 """ |
1000 """ |
947 Private slot to react upon changes of the quick commit text. |
1001 Private slot to react upon changes of the quick commit text. |
948 """ |
1002 """ |
949 self.__quickCommitButton.setEnabled(bool( |
1003 self.__quickCommitButton.setEnabled(bool(self.__quickCommitEdit.toPlainText())) |
950 self.__quickCommitEdit.toPlainText())) |
1004 |
951 |
|
952 def eventFilter(self, obj, evt): |
1005 def eventFilter(self, obj, evt): |
953 """ |
1006 """ |
954 Public method to process some events for the Commit edit. |
1007 Public method to process some events for the Commit edit. |
955 |
1008 |
956 @param obj reference to the object the event was meant for |
1009 @param obj reference to the object the event was meant for |
957 @type QObject |
1010 @type QObject |
958 @param evt reference to the event object |
1011 @param evt reference to the event object |
959 @type QEvent |
1012 @type QEvent |
960 @return flag to indicate that the event was handled |
1013 @return flag to indicate that the event was handled |
961 @rtype bool |
1014 @rtype bool |
962 """ |
1015 """ |
963 if ( |
1016 if ( |
964 obj is self.__quickCommitEdit and |
1017 obj is self.__quickCommitEdit |
965 evt.type() == QEvent.Type.KeyPress and |
1018 and evt.type() == QEvent.Type.KeyPress |
966 evt.key() in (Qt.Key.Key_Return, Qt.Key.Key_Enter) and |
1019 and evt.key() in (Qt.Key.Key_Return, Qt.Key.Key_Enter) |
967 evt.modifiers() == Qt.KeyboardModifier.ControlModifier |
1020 and evt.modifiers() == Qt.KeyboardModifier.ControlModifier |
968 ): |
1021 ): |
969 # Ctrl-Enter or Ctrl-Return => commit |
1022 # Ctrl-Enter or Ctrl-Return => commit |
970 self.__quickCommitButton.animateClick() |
1023 self.__quickCommitButton.animateClick() |
971 return True |
1024 return True |
972 else: |
1025 else: |