4 from qtpy
import QtCore
6 from qtpy
import QtWidgets
7 from qtpy
.QtCore
import Qt
8 from qtpy
.QtCore
import Signal
10 from ..models
import prefs
12 from .. import gitcmds
14 from .. import qtutils
17 from .text
import HintedLineEdit
21 def __init__(self
, regex
):
22 self
.regex
= re
.compile(regex
) # regex to scrub
24 def validate(self
, string
, idx
):
25 """Scrub and validate the user-supplied input"""
26 state
= QtGui
.QValidator
.Acceptable
27 if self
.regex
.search(string
):
28 string
= self
.regex
.sub('', string
) # scrub matching bits
29 idx
= min(idx
- 1, len(string
))
30 return (state
, string
, idx
)
33 class RemoteValidator(QtGui
.QValidator
):
34 """Prevent invalid remote names"""
36 def __init__(self
, parent
=None):
37 super().__init
__(parent
)
38 self
._validate
= ValidateRegex(r
'[ \t\\/]')
40 def validate(self
, string
, idx
):
41 return self
._validate
.validate(string
, idx
)
44 class BranchValidator(QtGui
.QValidator
):
45 """Prevent invalid branch names"""
47 def __init__(self
, git
, parent
=None):
48 super().__init
__(parent
)
50 self
._validate
= ValidateRegex(r
'[ \t\\]') # forward-slash is okay
52 def validate(self
, string
, idx
):
53 """Scrub and validate the user-supplied input"""
54 state
, string
, idx
= self
._validate
.validate(string
, idx
)
55 if string
: # Allow empty strings
56 status
, _
, _
= self
._git
.check_ref_format(string
, branch
=True)
58 # The intermediate string, when deleting characters, might
59 # end in a name that is invalid to Git, but we must allow it
60 # otherwise we won't be able to delete it using backspace.
61 if string
.endswith('/') or string
.endswith('.'):
62 state
= self
.Intermediate
65 return (state
, string
, idx
)
68 def _is_case_sensitive(text
):
69 return bool([char
for char
in text
if char
.isupper()])
72 class CompletionLineEdit(HintedLineEdit
):
73 """A lineedit with advanced completion abilities"""
82 # Activation keys will cause a selected completion item to be chosen
83 ACTIVATION_KEYS
= (Qt
.Key_Return
, Qt
.Key_Enter
)
85 # Navigation keys trigger signals that widgets can use for customization
87 Qt
.Key_Return
: 'enter',
88 Qt
.Key_Enter
: 'enter',
94 self
, context
, model_factory
, hint
='', show_all_completions
=False, parent
=None
96 HintedLineEdit
.__init
__(self
, context
, hint
, parent
=parent
)
97 # Tracks when the completion popup was active during key events
99 self
.context
= context
100 # The most recently selected completion item
101 self
._selection
= None
102 self
._show
_all
_completions
= show_all_completions
104 # Create a completion model
105 completion_model
= model_factory(context
, self
)
106 completer
= Completer(completion_model
, self
)
107 completer
.setWidget(self
)
108 self
._completer
= completer
109 self
._completion
_model
= completion_model
111 # The delegate highlights matching completion text in the popup widget
112 self
._delegate
= HighlightDelegate(self
)
113 completer
.popup().setItemDelegate(self
._delegate
)
115 self
.textChanged
.connect(self
._text
_changed
)
116 self
._completer
.activated
.connect(self
.choose_completion
)
117 self
._completion
_model
.updated
.connect(
118 self
._completions
_updated
, type=Qt
.QueuedConnection
120 self
.destroyed
.connect(self
.dispose
)
125 def dispose(self
, *args
):
126 self
._completer
.dispose()
128 def completion_selection(self
):
129 """Return the last completion's selection"""
130 return self
._selection
133 """Trigger the completion popup to appear and offer completions"""
134 self
._completer
.complete()
137 """Refresh the completion model"""
138 return self
._completer
.model().update()
141 """Return the completer's popup"""
142 return self
._completer
.popup()
144 def _text_changed(self
, full_text
):
145 match_text
= self
._last
_word
()
146 self
._do
_text
_changed
(full_text
, match_text
)
147 self
.complete_last_word()
149 def _do_text_changed(self
, full_text
, match_text
):
150 case_sensitive
= _is_case_sensitive(match_text
)
152 self
._completer
.setCaseSensitivity(Qt
.CaseSensitive
)
154 self
._completer
.setCaseSensitivity(Qt
.CaseInsensitive
)
155 self
._delegate
.set_highlight_text(match_text
, case_sensitive
)
156 self
._completer
.set_match_text(full_text
, match_text
, case_sensitive
)
158 def update_matches(self
):
159 text
= self
._last
_word
()
160 case_sensitive
= _is_case_sensitive(text
)
161 self
._completer
.setCompletionPrefix(text
)
162 self
._completer
.model().update_matches(case_sensitive
)
164 def choose_completion(self
, completion
):
166 This is the event handler for the QCompleter.activated(QString) signal,
167 it is called when the user selects an item in the completer popup.
170 self
._do
_text
_changed
('', '')
172 words
= self
._words
()
173 if words
and not self
._ends
_with
_whitespace
():
176 words
.append(completion
)
177 text
= core
.list2cmdline(words
)
180 self
._do
_text
_changed
(text
, '')
184 return utils
.shell_split(self
.value())
186 def _ends_with_whitespace(self
):
188 return value
!= value
.rstrip()
190 def _last_word(self
):
191 if self
._ends
_with
_whitespace
():
193 words
= self
._words
()
200 def complete_last_word(self
):
201 self
.update_matches()
204 def close_popup(self
):
205 """Close the completion popup"""
208 def _completions_updated(self
):
209 """Select the first completion item when completions are updated"""
211 if self
._completion
_model
.rowCount() == 0:
214 if not popup
.isVisible():
215 if not self
.hasFocus() or not self
._show
_all
_completions
:
217 self
.select_first_completion()
219 def select_first_completion(self
):
220 """Select the first item in the completion model"""
221 idx
= self
._completion
_model
.index(0, 0)
223 QtCore
.QItemSelectionModel
.Rows | QtCore
.QItemSelectionModel
.SelectCurrent
225 self
.popup().selectionModel().setCurrentIndex(idx
, mode
)
227 def selected_completion(self
):
228 """Return the selected completion item"""
230 if not popup
.isVisible():
232 model
= popup
.selectionModel()
233 indexes
= model
.selectedIndexes()
237 item
= self
._completion
_model
.itemFromIndex(idx
)
242 def select_completion(self
):
243 """Choose the selected completion option from the completion popup"""
245 visible
= self
.popup().isVisible()
247 selection
= self
.selected_completion()
249 self
.choose_completion(selection
)
253 def show_popup(self
):
254 """Display the completion popup"""
257 y_val
= self
.y() + self
.height()
258 point
= QtCore
.QPoint(x_val
, y_val
)
259 mapped
= self
.parent().mapToGlobal(point
)
261 popup
.move(mapped
.x(), mapped
.y())
265 def event(self
, event
):
266 """Override QWidget::event() for tab completion"""
267 event_type
= event
.type()
270 event_type
== QtCore
.QEvent
.KeyPress
271 and event
.key() == Qt
.Key_Tab
272 and self
.select_completion()
276 # Make sure the popup goes away during teardown
277 if event_type
== QtCore
.QEvent
.Close
:
279 elif event_type
== QtCore
.QEvent
.Hide
:
282 return super().event(event
)
284 def keyPressEvent(self
, event
):
285 """Process completion and navigation events"""
286 super().keyPressEvent(event
)
289 visible
= popup
.isVisible()
291 # Hide the popup when the field becomes empty.
292 is_empty
= not self
.value()
293 if is_empty
and event
.modifiers() != Qt
.ControlModifier
:
298 # Activation keys select the completion when pressed and emit the
299 # activated signal. Navigation keys have lower priority, and only
300 # emit when it wasn't already handled as an activation event.
302 if key
in self
.ACTIVATION_KEYS
and visible
:
303 if self
.select_completion():
304 self
.activated
.emit()
307 navigation
= self
.NAVIGATION_KEYS
.get(key
, None)
309 signal
= getattr(self
, navigation
)
313 # Show the popup when Ctrl-Space is pressed.
316 and key
== Qt
.Key_Space
317 and event
.modifiers() == Qt
.ControlModifier
322 class GatherCompletionsThread(QtCore
.QThread
):
323 items_gathered
= Signal(object)
325 def __init__(self
, model
):
326 QtCore
.QThread
.__init
__(self
)
328 self
.case_sensitive
= False
333 utils
.catch_runtime_error(self
.wait
)
339 # Loop when the matched text changes between the start and end time.
340 # This happens when gather_matches() takes too long and the
341 # model's match_text changes in-between.
342 while self
.running
and text
!= self
.model
.match_text
:
343 text
= self
.model
.match_text
344 items
= self
.model
.gather_matches(self
.case_sensitive
)
346 if self
.running
and text
is not None:
347 self
.items_gathered
.emit(items
)
350 class HighlightDelegate(QtWidgets
.QStyledItemDelegate
):
351 """A delegate used for auto-completion to give formatted completion"""
353 def __init__(self
, parent
):
354 QtWidgets
.QStyledItemDelegate
.__init
__(self
, parent
)
356 self
.highlight_text
= ''
357 self
.case_sensitive
= False
359 self
.doc
= QtGui
.QTextDocument()
360 # older PyQt4 does not have setDocumentMargin
361 if hasattr(self
.doc
, 'setDocumentMargin'):
362 self
.doc
.setDocumentMargin(0)
364 def set_highlight_text(self
, text
, case_sensitive
):
365 """Sets the text that will be made bold when displayed"""
366 self
.highlight_text
= text
367 self
.case_sensitive
= case_sensitive
369 def paint(self
, painter
, option
, index
):
370 """Overloaded Qt method for custom painting of a model index"""
371 if not self
.highlight_text
:
372 QtWidgets
.QStyledItemDelegate
.paint(self
, painter
, option
, index
)
375 if self
.case_sensitive
:
377 self
.highlight_text
, '<strong>%s</strong>' % self
.highlight_text
381 r
'(.*)(%s)(.*)' % re
.escape(self
.highlight_text
), text
, re
.IGNORECASE
384 start
= match
.group(1) or ''
385 middle
= match
.group(2) or ''
386 end
= match
.group(3) or ''
387 html
= start
+ ('<strong>%s</strong>' % middle
) + end
390 self
.doc
.setHtml(html
)
392 # Painting item without text, Text Document will paint the text
393 params
= QtWidgets
.QStyleOptionViewItem(option
)
394 self
.initStyleOption(params
, index
)
397 style
= QtWidgets
.QApplication
.style()
398 style
.drawControl(QtWidgets
.QStyle
.CE_ItemViewItem
, params
, painter
)
399 ctx
= QtGui
.QAbstractTextDocumentLayout
.PaintContext()
401 # Highlighting text if item is selected
402 if params
.state
& QtWidgets
.QStyle
.State_Selected
:
403 color
= params
.palette
.color(
404 QtGui
.QPalette
.Active
, QtGui
.QPalette
.HighlightedText
406 ctx
.palette
.setColor(QtGui
.QPalette
.Text
, color
)
408 # translate the painter to where the text is drawn
409 item_text
= QtWidgets
.QStyle
.SE_ItemViewItemText
410 rect
= style
.subElementRect(item_text
, params
, self
.widget
)
413 start
= rect
.topLeft() + QtCore
.QPoint(defs
.margin
, 0)
414 painter
.translate(start
)
416 # tell the text document to draw the html for us
417 self
.doc
.documentLayout().draw(painter
, ctx
)
421 def ref_sort_key(ref
):
422 """Sort key function that causes shorter refs to sort first, but
423 alphabetizes refs of equal length (in order to make local branches sort
424 before remote ones)."""
428 class CompletionModel(QtGui
.QStandardItemModel
):
430 items_gathered
= Signal(object)
431 model_updated
= Signal()
433 def __init__(self
, context
, parent
):
434 QtGui
.QStandardItemModel
.__init
__(self
, parent
)
435 self
.context
= context
438 self
.case_sensitive
= False
440 self
.update_thread
= GatherCompletionsThread(self
)
441 self
.update_thread
.items_gathered
.connect(
442 self
.apply_matches
, type=Qt
.QueuedConnection
446 case_sensitive
= self
.update_thread
.case_sensitive
447 self
.update_matches(case_sensitive
)
449 def set_match_text(self
, full_text
, match_text
, case_sensitive
):
450 self
.full_text
= full_text
451 self
.match_text
= match_text
452 self
.update_matches(case_sensitive
)
454 def update_matches(self
, case_sensitive
):
455 self
.case_sensitive
= case_sensitive
456 self
.update_thread
.case_sensitive
= case_sensitive
457 if not self
.update_thread
.isRunning():
458 self
.update_thread
.start()
460 def gather_matches(self
, case_sensitive
):
461 return ((), (), set())
463 def apply_matches(self
, match_tuple
):
464 """Build widgets for all of the matching items"""
466 # Results from background tasks may arrive after the widget
467 # has been destroyed.
468 utils
.catch_runtime_error(self
.set_items
, [])
470 matched_refs
, matched_paths
, dirs
= match_tuple
471 QStandardItem
= QtGui
.QStandardItem
473 dir_icon
= icons
.directory()
474 git_icon
= icons
.cola()
477 for ref
in matched_refs
:
478 item
= QStandardItem()
480 item
.setIcon(git_icon
)
483 from_filename
= icons
.from_filename
484 for match
in matched_paths
:
485 item
= QStandardItem()
488 item
.setIcon(dir_icon
)
490 item
.setIcon(from_filename(match
))
493 # Results from background tasks can arrive after the widget has been destroyed.
494 utils
.catch_runtime_error(self
.set_items
, items
)
496 def set_items(self
, items
):
497 """Clear the widget and add items to the model"""
499 self
.invisibleRootItem().appendRows(items
)
503 self
.update_thread
.dispose()
506 def _identity(value
):
514 def filter_matches(match_text
, candidates
, case_sensitive
, sort_key
=None):
515 """Filter candidates and return the matches"""
517 case_transform
= _identity
519 case_transform
= _lower
522 match_text
= case_transform(match_text
)
523 matches
= [r
for r
in candidates
if match_text
in case_transform(r
)]
525 matches
= list(candidates
)
531 matches
.sort(key
=sort_key
)
534 matches
.sort(key
=_lower
)
536 matches
.sort(key
=lambda x
: sort_key(_lower(x
)))
540 def filter_path_matches(match_text
, file_list
, case_sensitive
):
541 """Return matching completions from a list of candidate files"""
542 files
= set(file_list
)
543 files_and_dirs
= utils
.add_parents(files
)
544 dirs
= files_and_dirs
.difference(files
)
546 paths
= filter_matches(match_text
, files_and_dirs
, case_sensitive
)
550 class Completer(QtWidgets
.QCompleter
):
551 def __init__(self
, model
, parent
):
552 QtWidgets
.QCompleter
.__init
__(self
, parent
)
554 self
.setCompletionMode(QtWidgets
.QCompleter
.UnfilteredPopupCompletion
)
555 self
.setCaseSensitivity(Qt
.CaseInsensitive
)
556 self
.setFilterMode(QtCore
.Qt
.MatchContains
)
558 model
.model_updated
.connect(self
.update
, type=Qt
.QueuedConnection
)
565 self
._model
.dispose()
567 def set_match_text(self
, full_text
, match_text
, case_sensitive
):
568 self
._model
.set_match_text(full_text
, match_text
, case_sensitive
)
571 class GitCompletionModel(CompletionModel
):
572 def __init__(self
, context
, parent
):
573 CompletionModel
.__init
__(self
, context
, parent
)
574 self
.context
= context
575 context
.model
.updated
.connect(self
.model_updated
, type=Qt
.QueuedConnection
)
577 def gather_matches(self
, case_sensitive
):
578 refs
= filter_matches(
579 self
.match_text
, self
.matches(), case_sensitive
, sort_key
=ref_sort_key
581 return (refs
, (), set())
587 class GitRefCompletionModel(GitCompletionModel
):
588 """Completer for branches and tags"""
590 def __init__(self
, context
, parent
):
591 GitCompletionModel
.__init
__(self
, context
, parent
)
592 context
.model
.refs_updated
.connect(self
.model_updated
, type=Qt
.QueuedConnection
)
595 model
= self
.context
.model
596 return model
.local_branches
+ model
.remote_branches
+ model
.tags
599 def find_potential_branches(model
):
600 remotes
= model
.remotes
601 remote_branches
= model
.remote_branches
604 allnames
= set(model
.local_branches
)
607 for remote_branch
in remote_branches
:
608 branch
= gitcmds
.strip_remote(remotes
, remote_branch
)
609 if branch
in allnames
or branch
== remote_branch
:
610 ambiguous
.add(branch
)
612 potential
.append(branch
)
615 potential_branches
= [p
for p
in potential
if p
not in ambiguous
]
616 return potential_branches
619 class GitCreateBranchCompletionModel(GitCompletionModel
):
620 """Completer for naming new branches"""
623 model
= self
.context
.model
624 potential_branches
= find_potential_branches(model
)
625 return model
.local_branches
+ potential_branches
+ model
.tags
628 class GitCheckoutBranchCompletionModel(GitCompletionModel
):
629 """Completer for git checkout <branch>"""
632 model
= self
.context
.model
633 potential_branches
= find_potential_branches(model
)
637 + model
.remote_branches
642 class GitBranchCompletionModel(GitCompletionModel
):
643 """Completer for local branches"""
645 def __init__(self
, context
, parent
):
646 GitCompletionModel
.__init
__(self
, context
, parent
)
649 model
= self
.context
.model
650 return model
.local_branches
653 class GitRemoteBranchCompletionModel(GitCompletionModel
):
654 """Completer for remote branches"""
656 def __init__(self
, context
, parent
):
657 GitCompletionModel
.__init
__(self
, context
, parent
)
660 model
= self
.context
.model
661 return model
.remote_branches
664 class GitPathCompletionModel(GitCompletionModel
):
665 """Base class for path completion"""
667 def __init__(self
, context
, parent
):
668 GitCompletionModel
.__init
__(self
, context
, parent
)
670 def candidate_paths(self
):
673 def gather_matches(self
, case_sensitive
):
674 paths
, dirs
= filter_path_matches(
675 self
.match_text
, self
.candidate_paths(), case_sensitive
677 return ((), paths
, dirs
)
680 class GitStatusFilterCompletionModel(GitPathCompletionModel
):
681 """Completer for modified files and folders for status filtering"""
683 def __init__(self
, context
, parent
):
684 GitPathCompletionModel
.__init
__(self
, context
, parent
)
686 def candidate_paths(self
):
687 model
= self
.context
.model
688 return model
.staged
+ model
.unmerged
+ model
.modified
+ model
.untracked
691 class GitTrackedCompletionModel(GitPathCompletionModel
):
692 """Completer for tracked files and folders"""
694 def __init__(self
, context
, parent
):
695 GitPathCompletionModel
.__init
__(self
, context
, parent
)
696 self
.model_updated
.connect(self
.gather_paths
, type=Qt
.QueuedConnection
)
699 def gather_paths(self
):
700 context
= self
.context
701 self
._paths
= gitcmds
.tracked_files(context
)
703 def gather_matches(self
, case_sensitive
):
708 paths
, dirs
= filter_path_matches(self
.match_text
, self
._paths
, case_sensitive
)
709 return (refs
, paths
, dirs
)
712 class GitLogCompletionModel(GitRefCompletionModel
):
713 """Completer for arguments suitable for git-log like commands"""
715 def __init__(self
, context
, parent
):
716 GitRefCompletionModel
.__init
__(self
, context
, parent
)
718 self
._model
= context
.model
719 self
._runtask
= qtutils
.RunTask(parent
=self
)
720 self
._time
= 0.0 # ensure that the first event runs a task.
721 self
.model_updated
.connect(
722 self
._start
_gathering
_paths
, type=Qt
.QueuedConnection
726 """Return candidate values for completion"""
727 matches
= super().matches()
732 '--after=two.days.ago',
734 '--before=two.days.ago',
751 '--regexp-ignore-case',
762 def _start_gathering_paths(self
):
763 """Gather paths when the model changes"""
764 # Debounce updates that land within 1 second of each other.
765 if time
.time() - self
._time
> 1.0:
766 self
._runtask
.start(qtutils
.SimpleTask(self
.gather_paths
))
767 self
._time
= time
.time()
769 def gather_paths(self
):
770 """Gather paths and store them in the model"""
771 self
._time
= time
.time()
772 if self
._model
.cfg
.get(prefs
.AUTOCOMPLETE_PATHS
, True):
773 self
._paths
= gitcmds
.tracked_files(self
.context
)
776 self
._time
= time
.time()
778 def gather_matches(self
, case_sensitive
):
779 """Filter paths and refs to find matching entries"""
782 refs
= filter_matches(
783 self
.match_text
, self
.matches(), case_sensitive
, sort_key
=ref_sort_key
785 paths
, dirs
= filter_path_matches(self
.match_text
, self
._paths
, case_sensitive
)
787 self
.match_text
== '--'
788 or self
.full_text
.startswith('-- ')
789 or ' -- ' in self
.full_text
794 paths
.insert(0, '--')
796 return (refs
, paths
, dirs
)
799 def bind_lineedit(model
, hint
='', show_all_completions
=False):
800 """Create a line edit bound against a specific model"""
802 class BoundLineEdit(CompletionLineEdit
):
803 def __init__(self
, context
, hint
=hint
, parent
=None):
804 CompletionLineEdit
.__init
__(
809 show_all_completions
=show_all_completions
,
812 self
.context
= context
818 GitLogLineEdit
= bind_lineedit(GitLogCompletionModel
, hint
='<ref>')
819 GitRefLineEdit
= bind_lineedit(GitRefCompletionModel
, hint
='<ref>')
820 GitCheckoutBranchLineEdit
= bind_lineedit(
821 GitCheckoutBranchCompletionModel
,
823 show_all_completions
=True,
825 GitCreateBranchLineEdit
= bind_lineedit(GitCreateBranchCompletionModel
, hint
='<branch>')
826 GitBranchLineEdit
= bind_lineedit(GitBranchCompletionModel
, hint
='<branch>')
827 GitRemoteBranchLineEdit
= bind_lineedit(
828 GitRemoteBranchCompletionModel
, hint
='<remote-branch>'
830 GitStatusFilterLineEdit
= bind_lineedit(GitStatusFilterCompletionModel
, hint
='<path>')
831 GitTrackedLineEdit
= bind_lineedit(GitTrackedCompletionModel
, hint
='<path>')
834 class GitDialog(QtWidgets
.QDialog
):
835 # The "lineedit" argument is provided by the derived class constructor.
836 def __init__(self
, lineedit
, context
, title
, text
, parent
, icon
=None):
837 QtWidgets
.QDialog
.__init
__(self
, parent
)
838 self
.context
= context
839 self
.setWindowTitle(title
)
840 self
.setWindowModality(Qt
.WindowModal
)
841 self
.setMinimumWidth(333)
843 self
.label
= QtWidgets
.QLabel()
844 self
.label
.setText(title
)
845 self
.lineedit
= lineedit(context
)
846 self
.ok_button
= qtutils
.ok_button(text
, icon
=icon
, enabled
=False)
847 self
.close_button
= qtutils
.close_button()
849 self
.button_layout
= qtutils
.hbox(
857 self
.main_layout
= qtutils
.vbox(
858 defs
.margin
, defs
.spacing
, self
.label
, self
.lineedit
, self
.button_layout
860 self
.setLayout(self
.main_layout
)
862 self
.lineedit
.textChanged
.connect(self
.text_changed
)
863 self
.lineedit
.enter
.connect(self
.accept
)
864 qtutils
.connect_button(self
.ok_button
, self
.accept
)
865 qtutils
.connect_button(self
.close_button
, self
.reject
)
867 self
.setFocusProxy(self
.lineedit
)
868 self
.lineedit
.setFocus()
871 return self
.lineedit
.text()
873 def text_changed(self
, _txt
):
874 self
.ok_button
.setEnabled(bool(self
.text()))
876 def set_text(self
, ref
):
877 self
.lineedit
.setText(ref
)
880 def get(cls
, context
, title
, text
, parent
, default
=None, icon
=None):
881 dlg
= cls(context
, title
, text
, parent
, icon
=icon
)
883 dlg
.set_text(default
)
886 QtCore
.QTimer().singleShot(250, dlg
.lineedit
.show_popup
)
888 if dlg
.exec_() == cls
.Accepted
:
893 class GitRefDialog(GitDialog
):
894 def __init__(self
, context
, title
, text
, parent
, icon
=None):
896 self
, GitRefLineEdit
, context
, title
, text
, parent
, icon
=icon
900 class GitCheckoutBranchDialog(GitDialog
):
901 def __init__(self
, context
, title
, text
, parent
, icon
=None):
903 self
, GitCheckoutBranchLineEdit
, context
, title
, text
, parent
, icon
=icon
907 class GitBranchDialog(GitDialog
):
908 def __init__(self
, context
, title
, text
, parent
, icon
=None):
910 self
, GitBranchLineEdit
, context
, title
, text
, parent
, icon
=icon
914 class GitRemoteBranchDialog(GitDialog
):
915 def __init__(self
, context
, title
, text
, parent
, icon
=None):
917 self
, GitRemoteBranchLineEdit
, context
, title
, text
, parent
, icon
=icon