eric6/Plugins/VcsPlugins/vcsSubversion/SvnStatusDialog.py

changeset 6942
2602857055c5
parent 6645
ad476851d7e0
child 7192
a22eee00b052
equal deleted inserted replaced
6941:f99d60d6b59b 6942:2602857055c5
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2003 - 2019 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a dialog to show the output of the svn status command
8 process.
9 """
10
11 from __future__ import unicode_literals
12 try:
13 str = unicode
14 except NameError:
15 pass
16
17 import os
18
19 from PyQt5.QtCore import QTimer, QProcess, QRegExp, Qt, pyqtSlot
20 from PyQt5.QtWidgets import QWidget, QHeaderView, QLineEdit, QApplication, \
21 QMenu, QDialogButtonBox, QTreeWidgetItem
22
23 from E5Gui.E5Application import e5App
24 from E5Gui import E5MessageBox
25
26 from .Ui_SvnStatusDialog import Ui_SvnStatusDialog
27
28 import Preferences
29 from Globals import strToQByteArray
30
31
32 class SvnStatusDialog(QWidget, Ui_SvnStatusDialog):
33 """
34 Class implementing a dialog to show the output of the svn status command
35 process.
36 """
37 def __init__(self, vcs, parent=None):
38 """
39 Constructor
40
41 @param vcs reference to the vcs object
42 @param parent parent widget (QWidget)
43 """
44 super(SvnStatusDialog, self).__init__(parent)
45 self.setupUi(self)
46
47 self.__toBeCommittedColumn = 0
48 self.__changelistColumn = 1
49 self.__statusColumn = 2
50 self.__propStatusColumn = 3
51 self.__lockedColumn = 4
52 self.__historyColumn = 5
53 self.__switchedColumn = 6
54 self.__lockinfoColumn = 7
55 self.__upToDateColumn = 8
56 self.__pathColumn = 12
57 self.__lastColumn = self.statusList.columnCount()
58
59 self.refreshButton = \
60 self.buttonBox.addButton(self.tr("Refresh"),
61 QDialogButtonBox.ActionRole)
62 self.refreshButton.setToolTip(
63 self.tr("Press to refresh the status display"))
64 self.refreshButton.setEnabled(False)
65 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False)
66 self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True)
67
68 self.diff = None
69 self.vcs = vcs
70 self.vcs.committed.connect(self.__committed)
71
72 self.process = QProcess()
73 self.process.finished.connect(self.__procFinished)
74 self.process.readyReadStandardOutput.connect(self.__readStdout)
75 self.process.readyReadStandardError.connect(self.__readStderr)
76
77 self.statusList.headerItem().setText(self.__lastColumn, "")
78 self.statusList.header().setSortIndicator(self.__pathColumn,
79 Qt.AscendingOrder)
80 if self.vcs.version < (1, 5, 0):
81 self.statusList.header().hideSection(self.__changelistColumn)
82
83 self.menuactions = []
84 self.menu = QMenu()
85 self.menuactions.append(self.menu.addAction(
86 self.tr("Commit changes to repository..."), self.__commit))
87 self.menuactions.append(self.menu.addAction(
88 self.tr("Select all for commit"), self.__commitSelectAll))
89 self.menuactions.append(self.menu.addAction(
90 self.tr("Deselect all from commit"), self.__commitDeselectAll))
91 self.menu.addSeparator()
92 self.menuactions.append(self.menu.addAction(
93 self.tr("Add to repository"), self.__add))
94 self.menuactions.append(self.menu.addAction(
95 self.tr("Show differences"), self.__diff))
96 self.menuactions.append(self.menu.addAction(
97 self.tr("Show differences side-by-side"), self.__sbsDiff))
98 self.menuactions.append(self.menu.addAction(
99 self.tr("Revert changes"), self.__revert))
100 self.menuactions.append(self.menu.addAction(
101 self.tr("Restore missing"), self.__restoreMissing))
102 if self.vcs.version >= (1, 5, 0):
103 self.menu.addSeparator()
104 self.menuactions.append(self.menu.addAction(
105 self.tr("Add to Changelist"), self.__addToChangelist))
106 self.menuactions.append(self.menu.addAction(
107 self.tr("Remove from Changelist"),
108 self.__removeFromChangelist))
109 if self.vcs.version >= (1, 2, 0):
110 self.menu.addSeparator()
111 self.menuactions.append(self.menu.addAction(
112 self.tr("Lock"), self.__lock))
113 self.menuactions.append(self.menu.addAction(
114 self.tr("Unlock"), self.__unlock))
115 self.menuactions.append(self.menu.addAction(
116 self.tr("Break lock"),
117 self.__breakLock))
118 self.menuactions.append(self.menu.addAction(
119 self.tr("Steal lock"),
120 self.__stealLock))
121 self.menu.addSeparator()
122 self.menuactions.append(self.menu.addAction(
123 self.tr("Adjust column sizes"),
124 self.__resizeColumns))
125 for act in self.menuactions:
126 act.setEnabled(False)
127
128 self.statusList.setContextMenuPolicy(Qt.CustomContextMenu)
129 self.statusList.customContextMenuRequested.connect(
130 self.__showContextMenu)
131
132 self.modifiedIndicators = [
133 self.tr('added'),
134 self.tr('deleted'),
135 self.tr('modified'),
136 ]
137
138 self.missingIndicators = [
139 self.tr('missing'),
140 ]
141
142 self.unversionedIndicators = [
143 self.tr('unversioned'),
144 ]
145
146 self.lockedIndicators = [
147 self.tr('locked'),
148 ]
149
150 self.stealBreakLockIndicators = [
151 self.tr('other lock'),
152 self.tr('stolen lock'),
153 self.tr('broken lock'),
154 ]
155
156 self.unlockedIndicators = [
157 self.tr('not locked'),
158 ]
159
160 self.status = {
161 ' ': self.tr('normal'),
162 'A': self.tr('added'),
163 'C': self.tr('conflict'),
164 'D': self.tr('deleted'),
165 'I': self.tr('ignored'),
166 'M': self.tr('modified'),
167 'R': self.tr('replaced'),
168 'X': self.tr('external'),
169 '?': self.tr('unversioned'),
170 '!': self.tr('missing'),
171 '~': self.tr('type error'),
172 }
173 self.propStatus = {
174 ' ': self.tr('normal'),
175 'M': self.tr('modified'),
176 'C': self.tr('conflict'),
177 }
178 self.locked = {
179 ' ': self.tr('no'),
180 'L': self.tr('yes'),
181 }
182 self.history = {
183 ' ': self.tr('no'),
184 '+': self.tr('yes'),
185 }
186 self.switched = {
187 ' ': self.tr('no'),
188 'S': self.tr('yes'),
189 'X': self.tr('external')
190 }
191 self.lockinfo = {
192 ' ': self.tr('not locked'),
193 'K': self.tr('locked'),
194 'O': self.tr('other lock'),
195 'T': self.tr('stolen lock'),
196 'B': self.tr('broken lock'),
197 }
198 self.uptodate = {
199 ' ': self.tr('yes'),
200 '*': self.tr('no'),
201 }
202
203 self.rx_status = QRegExp(
204 '(.{8,9})\\s+([0-9-]+)\\s+([0-9?]+)\\s+(\\S+)\\s+(.+)\\s*')
205 # flags (8 or 9 anything), revision, changed rev, author, path
206 self.rx_status2 = \
207 QRegExp('(.{8,9})\\s+(.+)\\s*')
208 # flags (8 or 9 anything), path
209 self.rx_changelist = \
210 QRegExp('--- \\S+ .([\\w\\s]+).:\\s+')
211 # three dashes, Changelist (translated), quote,
212 # changelist name, quote, :
213
214 self.__nonverbose = True
215
216 def __resort(self):
217 """
218 Private method to resort the tree.
219 """
220 self.statusList.sortItems(
221 self.statusList.sortColumn(),
222 self.statusList.header().sortIndicatorOrder())
223
224 def __resizeColumns(self):
225 """
226 Private method to resize the list columns.
227 """
228 self.statusList.header().resizeSections(QHeaderView.ResizeToContents)
229 self.statusList.header().setStretchLastSection(True)
230
231 def __generateItem(self, status, propStatus, locked, history, switched,
232 lockinfo, uptodate, revision, change, author, path):
233 """
234 Private method to generate a status item in the status list.
235
236 @param status status indicator (string)
237 @param propStatus property status indicator (string)
238 @param locked locked indicator (string)
239 @param history history indicator (string)
240 @param switched switched indicator (string)
241 @param lockinfo lock indicator (string)
242 @param uptodate up to date indicator (string)
243 @param revision revision string (string)
244 @param change revision of last change (string)
245 @param author author of the last change (string)
246 @param path path of the file or directory (string)
247 """
248 if self.__nonverbose and \
249 status == " " and \
250 propStatus == " " and \
251 locked == " " and \
252 history == " " and \
253 switched == " " and \
254 lockinfo == " " and \
255 uptodate == " " and \
256 self.currentChangelist == "":
257 return
258
259 if revision == "":
260 rev = ""
261 else:
262 try:
263 rev = int(revision)
264 except ValueError:
265 rev = revision
266 if change == "":
267 chg = ""
268 else:
269 try:
270 chg = int(change)
271 except ValueError:
272 chg = change
273 statusText = self.status[status]
274
275 itm = QTreeWidgetItem(self.statusList)
276 itm.setData(0, Qt.DisplayRole, "")
277 itm.setData(1, Qt.DisplayRole, self.currentChangelist)
278 itm.setData(2, Qt.DisplayRole, statusText)
279 itm.setData(3, Qt.DisplayRole, self.propStatus[propStatus])
280 itm.setData(4, Qt.DisplayRole, self.locked[locked])
281 itm.setData(5, Qt.DisplayRole, self.history[history])
282 itm.setData(6, Qt.DisplayRole, self.switched[switched])
283 itm.setData(7, Qt.DisplayRole, self.lockinfo[lockinfo])
284 itm.setData(8, Qt.DisplayRole, self.uptodate[uptodate])
285 itm.setData(9, Qt.DisplayRole, rev)
286 itm.setData(10, Qt.DisplayRole, chg)
287 itm.setData(11, Qt.DisplayRole, author)
288 itm.setData(12, Qt.DisplayRole, path)
289
290 itm.setTextAlignment(1, Qt.AlignLeft)
291 itm.setTextAlignment(2, Qt.AlignHCenter)
292 itm.setTextAlignment(3, Qt.AlignHCenter)
293 itm.setTextAlignment(4, Qt.AlignHCenter)
294 itm.setTextAlignment(5, Qt.AlignHCenter)
295 itm.setTextAlignment(6, Qt.AlignHCenter)
296 itm.setTextAlignment(7, Qt.AlignHCenter)
297 itm.setTextAlignment(8, Qt.AlignHCenter)
298 itm.setTextAlignment(9, Qt.AlignRight)
299 itm.setTextAlignment(10, Qt.AlignRight)
300 itm.setTextAlignment(11, Qt.AlignLeft)
301 itm.setTextAlignment(12, Qt.AlignLeft)
302
303 if status in "ADM" or propStatus in "M":
304 itm.setFlags(itm.flags() | Qt.ItemIsUserCheckable)
305 itm.setCheckState(self.__toBeCommittedColumn, Qt.Checked)
306 else:
307 itm.setFlags(itm.flags() & ~Qt.ItemIsUserCheckable)
308
309 self.hidePropertyStatusColumn = self.hidePropertyStatusColumn and \
310 propStatus == " "
311 self.hideLockColumns = self.hideLockColumns and \
312 locked == " " and lockinfo == " "
313 self.hideUpToDateColumn = self.hideUpToDateColumn and uptodate == " "
314 self.hideHistoryColumn = self.hideHistoryColumn and history == " "
315 self.hideSwitchedColumn = self.hideSwitchedColumn and switched == " "
316
317 if statusText not in self.__statusFilters:
318 self.__statusFilters.append(statusText)
319
320 def closeEvent(self, e):
321 """
322 Protected slot implementing a close event handler.
323
324 @param e close event (QCloseEvent)
325 """
326 if self.process is not None and \
327 self.process.state() != QProcess.NotRunning:
328 self.process.terminate()
329 QTimer.singleShot(2000, self.process.kill)
330 self.process.waitForFinished(3000)
331
332 e.accept()
333
334 def start(self, fn):
335 """
336 Public slot to start the svn status command.
337
338 @param fn filename(s)/directoryname(s) to show the status of
339 (string or list of strings)
340 """
341 self.errorGroup.hide()
342 self.intercept = False
343 self.args = fn
344
345 for act in self.menuactions:
346 act.setEnabled(False)
347
348 self.addButton.setEnabled(False)
349 self.commitButton.setEnabled(False)
350 self.diffButton.setEnabled(False)
351 self.sbsDiffButton.setEnabled(False)
352 self.revertButton.setEnabled(False)
353 self.restoreButton.setEnabled(False)
354
355 self.statusFilterCombo.clear()
356 self.__statusFilters = []
357 self.statusList.clear()
358
359 self.currentChangelist = ""
360 self.changelistFound = False
361
362 self.hidePropertyStatusColumn = True
363 self.hideLockColumns = True
364 self.hideUpToDateColumn = True
365 self.hideHistoryColumn = True
366 self.hideSwitchedColumn = True
367
368 self.process.kill()
369
370 args = []
371 args.append('status')
372 self.vcs.addArguments(args, self.vcs.options['global'])
373 self.vcs.addArguments(args, self.vcs.options['status'])
374 if '--verbose' not in self.vcs.options['global'] and \
375 '--verbose' not in self.vcs.options['status']:
376 args.append('--verbose')
377 self.__nonverbose = True
378 else:
379 self.__nonverbose = False
380 if '--show-updates' in self.vcs.options['status'] or \
381 '-u' in self.vcs.options['status']:
382 self.activateWindow()
383 self.raise_()
384 if isinstance(fn, list):
385 self.dname, fnames = self.vcs.splitPathList(fn)
386 self.vcs.addArguments(args, fnames)
387 else:
388 self.dname, fname = self.vcs.splitPath(fn)
389 args.append(fname)
390
391 self.process.setWorkingDirectory(self.dname)
392
393 self.setWindowTitle(self.tr('Subversion Status'))
394
395 self.process.start('svn', args)
396 procStarted = self.process.waitForStarted(5000)
397 if not procStarted:
398 self.inputGroup.setEnabled(False)
399 self.inputGroup.hide()
400 E5MessageBox.critical(
401 self,
402 self.tr('Process Generation Error'),
403 self.tr(
404 'The process {0} could not be started. '
405 'Ensure, that it is in the search path.'
406 ).format('svn'))
407 else:
408 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False)
409 self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(True)
410 self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True)
411
412 self.inputGroup.setEnabled(True)
413 self.inputGroup.show()
414 self.refreshButton.setEnabled(False)
415
416 def __finish(self):
417 """
418 Private slot called when the process finished or the user pressed
419 the button.
420 """
421 if self.process is not None and \
422 self.process.state() != QProcess.NotRunning:
423 self.process.terminate()
424 QTimer.singleShot(2000, self.process.kill)
425 self.process.waitForFinished(3000)
426
427 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True)
428 self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False)
429 self.buttonBox.button(QDialogButtonBox.Close).setDefault(True)
430 self.buttonBox.button(QDialogButtonBox.Close).setFocus(
431 Qt.OtherFocusReason)
432
433 self.inputGroup.setEnabled(False)
434 self.inputGroup.hide()
435 self.refreshButton.setEnabled(True)
436
437 self.__statusFilters.sort()
438 self.__statusFilters.insert(0, "<{0}>".format(self.tr("all")))
439 self.statusFilterCombo.addItems(self.__statusFilters)
440
441 for act in self.menuactions:
442 act.setEnabled(True)
443
444 self.__resort()
445 self.__resizeColumns()
446
447 self.statusList.setColumnHidden(self.__changelistColumn,
448 not self.changelistFound)
449 self.statusList.setColumnHidden(self.__propStatusColumn,
450 self.hidePropertyStatusColumn)
451 self.statusList.setColumnHidden(self.__lockedColumn,
452 self.hideLockColumns)
453 self.statusList.setColumnHidden(self.__lockinfoColumn,
454 self.hideLockColumns)
455 self.statusList.setColumnHidden(self.__upToDateColumn,
456 self.hideUpToDateColumn)
457 self.statusList.setColumnHidden(self.__historyColumn,
458 self.hideHistoryColumn)
459 self.statusList.setColumnHidden(self.__switchedColumn,
460 self.hideSwitchedColumn)
461
462 self.__updateButtons()
463 self.__updateCommitButton()
464
465 def on_buttonBox_clicked(self, button):
466 """
467 Private slot called by a button of the button box clicked.
468
469 @param button button that was clicked (QAbstractButton)
470 """
471 if button == self.buttonBox.button(QDialogButtonBox.Close):
472 self.close()
473 elif button == self.buttonBox.button(QDialogButtonBox.Cancel):
474 self.__finish()
475 elif button == self.refreshButton:
476 self.on_refreshButton_clicked()
477
478 def __procFinished(self, exitCode, exitStatus):
479 """
480 Private slot connected to the finished signal.
481
482 @param exitCode exit code of the process (integer)
483 @param exitStatus exit status of the process (QProcess.ExitStatus)
484 """
485 self.__finish()
486
487 def __readStdout(self):
488 """
489 Private slot to handle the readyReadStandardOutput signal.
490
491 It reads the output of the process, formats it and inserts it into
492 the contents pane.
493 """
494 if self.process is not None:
495 self.process.setReadChannel(QProcess.StandardOutput)
496
497 while self.process.canReadLine():
498 s = str(self.process.readLine(),
499 Preferences.getSystem("IOEncoding"),
500 'replace')
501 if self.rx_status.exactMatch(s):
502 flags = self.rx_status.cap(1)
503 rev = self.rx_status.cap(2)
504 change = self.rx_status.cap(3)
505 author = self.rx_status.cap(4)
506 path = self.rx_status.cap(5).strip()
507
508 self.__generateItem(flags[0], flags[1], flags[2], flags[3],
509 flags[4], flags[5], flags[-1], rev,
510 change, author, path)
511 elif self.rx_status2.exactMatch(s):
512 flags = self.rx_status2.cap(1)
513 path = self.rx_status2.cap(2).strip()
514
515 if flags[-1] in self.uptodate:
516 self.__generateItem(flags[0], flags[1], flags[2],
517 flags[3], flags[4], flags[5],
518 flags[-1], "", "", "", path)
519 elif self.rx_changelist.exactMatch(s):
520 self.currentChangelist = self.rx_changelist.cap(1)
521 self.changelistFound = True
522
523 def __readStderr(self):
524 """
525 Private slot to handle the readyReadStandardError signal.
526
527 It reads the error output of the process and inserts it into the
528 error pane.
529 """
530 if self.process is not None:
531 self.errorGroup.show()
532 s = str(self.process.readAllStandardError(),
533 Preferences.getSystem("IOEncoding"),
534 'replace')
535 self.errors.insertPlainText(s)
536 self.errors.ensureCursorVisible()
537
538 def on_passwordCheckBox_toggled(self, isOn):
539 """
540 Private slot to handle the password checkbox toggled.
541
542 @param isOn flag indicating the status of the check box (boolean)
543 """
544 if isOn:
545 self.input.setEchoMode(QLineEdit.Password)
546 else:
547 self.input.setEchoMode(QLineEdit.Normal)
548
549 @pyqtSlot()
550 def on_sendButton_clicked(self):
551 """
552 Private slot to send the input to the subversion process.
553 """
554 inputTxt = self.input.text()
555 inputTxt += os.linesep
556
557 if self.passwordCheckBox.isChecked():
558 self.errors.insertPlainText(os.linesep)
559 self.errors.ensureCursorVisible()
560 else:
561 self.errors.insertPlainText(inputTxt)
562 self.errors.ensureCursorVisible()
563
564 self.process.write(strToQByteArray(inputTxt))
565
566 self.passwordCheckBox.setChecked(False)
567 self.input.clear()
568
569 def on_input_returnPressed(self):
570 """
571 Private slot to handle the press of the return key in the input field.
572 """
573 self.intercept = True
574 self.on_sendButton_clicked()
575
576 def keyPressEvent(self, evt):
577 """
578 Protected slot to handle a key press event.
579
580 @param evt the key press event (QKeyEvent)
581 """
582 if self.intercept:
583 self.intercept = False
584 evt.accept()
585 return
586 super(SvnStatusDialog, self).keyPressEvent(evt)
587
588 @pyqtSlot()
589 def on_refreshButton_clicked(self):
590 """
591 Private slot to refresh the status display.
592 """
593 self.start(self.args)
594
595 def __updateButtons(self):
596 """
597 Private method to update the VCS buttons status.
598 """
599 modified = len(self.__getModifiedItems())
600 unversioned = len(self.__getUnversionedItems())
601 missing = len(self.__getMissingItems())
602
603 self.addButton.setEnabled(unversioned)
604 self.diffButton.setEnabled(modified)
605 self.sbsDiffButton.setEnabled(modified == 1)
606 self.revertButton.setEnabled(modified)
607 self.restoreButton.setEnabled(missing)
608
609 def __updateCommitButton(self):
610 """
611 Private method to update the Commit button status.
612 """
613 commitable = len(self.__getCommitableItems())
614 self.commitButton.setEnabled(commitable)
615
616 @pyqtSlot(str)
617 def on_statusFilterCombo_activated(self, txt):
618 """
619 Private slot to react to the selection of a status filter.
620
621 @param txt selected status filter (string)
622 """
623 if txt == "<{0}>".format(self.tr("all")):
624 for topIndex in range(self.statusList.topLevelItemCount()):
625 topItem = self.statusList.topLevelItem(topIndex)
626 topItem.setHidden(False)
627 else:
628 for topIndex in range(self.statusList.topLevelItemCount()):
629 topItem = self.statusList.topLevelItem(topIndex)
630 topItem.setHidden(topItem.text(self.__statusColumn) != txt)
631
632 @pyqtSlot(QTreeWidgetItem, int)
633 def on_statusList_itemChanged(self, item, column):
634 """
635 Private slot to act upon item changes.
636
637 @param item reference to the changed item (QTreeWidgetItem)
638 @param column index of column that changed (integer)
639 """
640 if column == self.__toBeCommittedColumn:
641 self.__updateCommitButton()
642
643 @pyqtSlot()
644 def on_statusList_itemSelectionChanged(self):
645 """
646 Private slot to act upon changes of selected items.
647 """
648 self.__updateButtons()
649
650 @pyqtSlot()
651 def on_commitButton_clicked(self):
652 """
653 Private slot to handle the press of the Commit button.
654 """
655 self.__commit()
656
657 @pyqtSlot()
658 def on_addButton_clicked(self):
659 """
660 Private slot to handle the press of the Add button.
661 """
662 self.__add()
663
664 @pyqtSlot()
665 def on_diffButton_clicked(self):
666 """
667 Private slot to handle the press of the Differences button.
668 """
669 self.__diff()
670
671 @pyqtSlot()
672 def on_sbsDiffButton_clicked(self):
673 """
674 Private slot to handle the press of the Side-by-Side Diff button.
675 """
676 self.__sbsDiff()
677
678 @pyqtSlot()
679 def on_revertButton_clicked(self):
680 """
681 Private slot to handle the press of the Revert button.
682 """
683 self.__revert()
684
685 @pyqtSlot()
686 def on_restoreButton_clicked(self):
687 """
688 Private slot to handle the press of the Restore button.
689 """
690 self.__restoreMissing()
691
692 ###########################################################################
693 ## Context menu handling methods
694 ###########################################################################
695
696 def __showContextMenu(self, coord):
697 """
698 Private slot to show the context menu of the status list.
699
700 @param coord the position of the mouse pointer (QPoint)
701 """
702 self.menu.popup(self.statusList.mapToGlobal(coord))
703
704 def __commit(self):
705 """
706 Private slot to handle the Commit context menu entry.
707 """
708 names = [os.path.join(self.dname, itm.text(self.__pathColumn))
709 for itm in self.__getCommitableItems()]
710 if not names:
711 E5MessageBox.information(
712 self,
713 self.tr("Commit"),
714 self.tr("""There are no entries selected to be"""
715 """ committed."""))
716 return
717
718 if Preferences.getVCS("AutoSaveFiles"):
719 vm = e5App().getObject("ViewManager")
720 for name in names:
721 vm.saveEditor(name)
722 self.vcs.vcsCommit(names, '')
723
724 def __committed(self):
725 """
726 Private slot called after the commit has finished.
727 """
728 if self.isVisible():
729 self.on_refreshButton_clicked()
730 self.vcs.checkVCSStatus()
731
732 def __commitSelectAll(self):
733 """
734 Private slot to select all entries for commit.
735 """
736 self.__commitSelect(True)
737
738 def __commitDeselectAll(self):
739 """
740 Private slot to deselect all entries from commit.
741 """
742 self.__commitSelect(False)
743
744 def __add(self):
745 """
746 Private slot to handle the Add context menu entry.
747 """
748 names = [os.path.join(self.dname, itm.text(self.__pathColumn))
749 for itm in self.__getUnversionedItems()]
750 if not names:
751 E5MessageBox.information(
752 self,
753 self.tr("Add"),
754 self.tr("""There are no unversioned entries"""
755 """ available/selected."""))
756 return
757
758 self.vcs.vcsAdd(names)
759 self.on_refreshButton_clicked()
760
761 project = e5App().getObject("Project")
762 for name in names:
763 project.getModel().updateVCSStatus(name)
764 self.vcs.checkVCSStatus()
765
766 def __revert(self):
767 """
768 Private slot to handle the Revert context menu entry.
769 """
770 names = [os.path.join(self.dname, itm.text(self.__pathColumn))
771 for itm in self.__getModifiedItems()]
772 if not names:
773 E5MessageBox.information(
774 self,
775 self.tr("Revert"),
776 self.tr("""There are no uncommitted changes"""
777 """ available/selected."""))
778 return
779
780 self.vcs.vcsRevert(names)
781 self.raise_()
782 self.activateWindow()
783 self.on_refreshButton_clicked()
784
785 project = e5App().getObject("Project")
786 for name in names:
787 project.getModel().updateVCSStatus(name)
788 self.vcs.checkVCSStatus()
789
790 def __restoreMissing(self):
791 """
792 Private slot to handle the Restore Missing context menu entry.
793 """
794 names = [os.path.join(self.dname, itm.text(self.__pathColumn))
795 for itm in self.__getMissingItems()]
796 if not names:
797 E5MessageBox.information(
798 self,
799 self.tr("Revert"),
800 self.tr("""There are no missing entries"""
801 """ available/selected."""))
802 return
803
804 self.vcs.vcsRevert(names)
805 self.on_refreshButton_clicked()
806 self.vcs.checkVCSStatus()
807
808 def __diff(self):
809 """
810 Private slot to handle the Diff context menu entry.
811 """
812 names = [os.path.join(self.dname, itm.text(self.__pathColumn))
813 for itm in self.__getModifiedItems()]
814 if not names:
815 E5MessageBox.information(
816 self,
817 self.tr("Differences"),
818 self.tr("""There are no uncommitted changes"""
819 """ available/selected."""))
820 return
821
822 if self.diff is None:
823 from .SvnDiffDialog import SvnDiffDialog
824 self.diff = SvnDiffDialog(self.vcs)
825 self.diff.show()
826 QApplication.processEvents()
827 self.diff.start(names, refreshable=True)
828
829 def __sbsDiff(self):
830 """
831 Private slot to handle the Side-by-Side Diff context menu entry.
832 """
833 names = [os.path.join(self.dname, itm.text(self.__pathColumn))
834 for itm in self.__getModifiedItems()]
835 if not names:
836 E5MessageBox.information(
837 self,
838 self.tr("Side-by-Side Diff"),
839 self.tr("""There are no uncommitted changes"""
840 """ available/selected."""))
841 return
842 elif len(names) > 1:
843 E5MessageBox.information(
844 self,
845 self.tr("Side-by-Side Diff"),
846 self.tr("""Only one file with uncommitted changes"""
847 """ must be selected."""))
848 return
849
850 self.vcs.svnSbsDiff(names[0])
851
852 def __lock(self):
853 """
854 Private slot to handle the Lock context menu entry.
855 """
856 names = [os.path.join(self.dname, itm.text(self.__pathColumn))
857 for itm in self.__getLockActionItems(self.unlockedIndicators)]
858 if not names:
859 E5MessageBox.information(
860 self,
861 self.tr("Lock"),
862 self.tr("""There are no unlocked files"""
863 """ available/selected."""))
864 return
865
866 self.vcs.svnLock(names, parent=self)
867 self.on_refreshButton_clicked()
868
869 def __unlock(self):
870 """
871 Private slot to handle the Unlock context menu entry.
872 """
873 names = [os.path.join(self.dname, itm.text(self.__pathColumn))
874 for itm in self.__getLockActionItems(self.lockedIndicators)]
875 if not names:
876 E5MessageBox.information(
877 self,
878 self.tr("Unlock"),
879 self.tr("""There are no locked files"""
880 """ available/selected."""))
881 return
882
883 self.vcs.svnUnlock(names, parent=self)
884 self.on_refreshButton_clicked()
885
886 def __breakLock(self):
887 """
888 Private slot to handle the Break Lock context menu entry.
889 """
890 names = [os.path.join(self.dname, itm.text(self.__pathColumn))
891 for itm in self.__getLockActionItems(
892 self.stealBreakLockIndicators)]
893 if not names:
894 E5MessageBox.information(
895 self,
896 self.tr("Break Lock"),
897 self.tr("""There are no locked files"""
898 """ available/selected."""))
899 return
900
901 self.vcs.svnUnlock(names, parent=self, breakIt=True)
902 self.on_refreshButton_clicked()
903
904 def __stealLock(self):
905 """
906 Private slot to handle the Break Lock context menu entry.
907 """
908 names = [os.path.join(self.dname, itm.text(self.__pathColumn))
909 for itm in self.__getLockActionItems(
910 self.stealBreakLockIndicators)]
911 if not names:
912 E5MessageBox.information(
913 self,
914 self.tr("Steal Lock"),
915 self.tr("""There are no locked files"""
916 """ available/selected."""))
917 return
918
919 self.vcs.svnLock(names, parent=self, stealIt=True)
920 self.on_refreshButton_clicked()
921
922 def __addToChangelist(self):
923 """
924 Private slot to add entries to a changelist.
925 """
926 names = [os.path.join(self.dname, itm.text(self.__pathColumn))
927 for itm in self.__getNonChangelistItems()]
928 if not names:
929 E5MessageBox.information(
930 self,
931 self.tr("Remove from Changelist"),
932 self.tr(
933 """There are no files available/selected not """
934 """belonging to a changelist."""
935 )
936 )
937 return
938 self.vcs.svnAddToChangelist(names)
939 self.on_refreshButton_clicked()
940
941 def __removeFromChangelist(self):
942 """
943 Private slot to remove entries from their changelists.
944 """
945 names = [os.path.join(self.dname, itm.text(self.__pathColumn))
946 for itm in self.__getChangelistItems()]
947 if not names:
948 E5MessageBox.information(
949 self,
950 self.tr("Remove from Changelist"),
951 self.tr(
952 """There are no files available/selected belonging"""
953 """ to a changelist."""
954 )
955 )
956 return
957 self.vcs.svnRemoveFromChangelist(names)
958 self.on_refreshButton_clicked()
959
960 def __getCommitableItems(self):
961 """
962 Private method to retrieve all entries the user wants to commit.
963
964 @return list of all items, the user has checked
965 """
966 commitableItems = []
967 for index in range(self.statusList.topLevelItemCount()):
968 itm = self.statusList.topLevelItem(index)
969 if itm.checkState(self.__toBeCommittedColumn) == Qt.Checked:
970 commitableItems.append(itm)
971 return commitableItems
972
973 def __getModifiedItems(self):
974 """
975 Private method to retrieve all entries, that have a modified status.
976
977 @return list of all items with a modified status
978 """
979 modifiedItems = []
980 for itm in self.statusList.selectedItems():
981 if itm.text(self.__statusColumn) in self.modifiedIndicators or \
982 itm.text(self.__propStatusColumn) in self.modifiedIndicators:
983 modifiedItems.append(itm)
984 return modifiedItems
985
986 def __getUnversionedItems(self):
987 """
988 Private method to retrieve all entries, that have an unversioned
989 status.
990
991 @return list of all items with an unversioned status
992 """
993 unversionedItems = []
994 for itm in self.statusList.selectedItems():
995 if itm.text(self.__statusColumn) in self.unversionedIndicators:
996 unversionedItems.append(itm)
997 return unversionedItems
998
999 def __getMissingItems(self):
1000 """
1001 Private method to retrieve all entries, that have a missing status.
1002
1003 @return list of all items with a missing status
1004 """
1005 missingItems = []
1006 for itm in self.statusList.selectedItems():
1007 if itm.text(self.__statusColumn) in self.missingIndicators:
1008 missingItems.append(itm)
1009 return missingItems
1010
1011 def __getLockActionItems(self, indicators):
1012 """
1013 Private method to retrieve all emtries, that have a locked status.
1014
1015 @param indicators list of indicators to check against (list of strings)
1016 @return list of all items with a locked status
1017 """
1018 lockitems = []
1019 for itm in self.statusList.selectedItems():
1020 if itm.text(self.__lockinfoColumn) in indicators:
1021 lockitems.append(itm)
1022 return lockitems
1023
1024 def __getChangelistItems(self):
1025 """
1026 Private method to retrieve all entries, that are members of
1027 a changelist.
1028
1029 @return list of all items belonging to a changelist
1030 """
1031 clitems = []
1032 for itm in self.statusList.selectedItems():
1033 if itm.text(self.__changelistColumn) != "":
1034 clitems.append(itm)
1035 return clitems
1036
1037 def __getNonChangelistItems(self):
1038 """
1039 Private method to retrieve all entries, that are not members of
1040 a changelist.
1041
1042 @return list of all items not belonging to a changelist
1043 """
1044 clitems = []
1045 for itm in self.statusList.selectedItems():
1046 if itm.text(self.__changelistColumn) == "":
1047 clitems.append(itm)
1048 return clitems
1049
1050 def __commitSelect(self, selected):
1051 """
1052 Private slot to select or deselect all entries.
1053
1054 @param selected commit selection state to be set (boolean)
1055 """
1056 for index in range(self.statusList.topLevelItemCount()):
1057 itm = self.statusList.topLevelItem(index)
1058 if itm.flags() & Qt.ItemIsUserCheckable:
1059 if selected:
1060 itm.setCheckState(self.__toBeCommittedColumn, Qt.Checked)
1061 else:
1062 itm.setCheckState(self.__toBeCommittedColumn, Qt.Unchecked)

eric ide

mercurial