widgets: do not set window modality without a parent
[git-cola.git] / cola / widgets / merge.py
blobddc31c345c604702726e734b42e9f2a9425bcab2
1 from PyQt4 import QtGui
2 from PyQt4.QtCore import Qt
3 from PyQt4.QtCore import SIGNAL
5 from cola import cmds
6 from cola import gitcmds
7 from cola import qtutils
8 from cola.i18n import N_
9 from cola.models import main
10 from cola.widgets import completion
11 from cola.widgets import defs
14 def local_merge():
15 """Provides a dialog for merging branches"""
16 model = main.model()
17 view = MergeView(model, qtutils.active_window())
18 view.show()
19 view.raise_()
20 return view
23 def abort_merge():
24 """Prompts before aborting a merge in progress
25 """
26 title = N_('Abort Merge...')
27 txt = N_('Aborting the current merge will cause '
28 '*ALL* uncommitted changes to be lost.\n'
29 'Recovering uncommitted changes is not possible.')
30 info_txt = N_('Aborting the current merge?')
31 ok_txt = N_('Abort Merge')
32 if qtutils.confirm(title, txt, info_txt, ok_txt,
33 default=False, icon=qtutils.icon('undo.svg')):
34 gitcmds.abort_merge()
37 class MergeView(QtGui.QDialog):
38 """Provides a dialog for merging branches."""
40 def __init__(self, model, parent=None):
41 QtGui.QDialog.__init__(self, parent)
42 self.model = model
43 if parent is not None:
44 self.setWindowModality(Qt.WindowModal)
45 self.resize(700, 400)
47 # Widgets
48 self.title_label = QtGui.QLabel()
49 self.revision_label = QtGui.QLabel()
50 self.revision_label.setText(N_('Revision To Merge'))
52 self.revision = completion.GitRefLineEdit()
54 self.radio_local = QtGui.QRadioButton()
55 self.radio_local.setText(N_('Local Branch'))
56 self.radio_local.setChecked(True)
57 self.radio_remote = QtGui.QRadioButton()
58 self.radio_remote.setText(N_('Tracking Branch'))
59 self.radio_tag = QtGui.QRadioButton()
60 self.radio_tag.setText(N_('Tag'))
62 self.revisions = QtGui.QListWidget()
63 self.revisions.setAlternatingRowColors(True)
65 self.button_viz = QtGui.QPushButton(self)
66 self.button_viz.setText(N_('Visualize'))
68 self.checkbox_squash = QtGui.QCheckBox(self)
69 self.checkbox_squash.setText(N_('Squash'))
71 self.checkbox_commit = QtGui.QCheckBox(self)
72 self.checkbox_commit.setText(N_('Commit'))
73 self.checkbox_commit.setChecked(True)
74 self.checkbox_commit_state = True
76 self.button_cancel = QtGui.QPushButton(self)
77 self.button_cancel.setText(N_('Cancel'))
79 self.button_merge = QtGui.QPushButton(self)
80 self.button_merge.setText(N_('Merge'))
82 # Layouts
83 self.revlayt = QtGui.QHBoxLayout()
84 self.revlayt.addWidget(self.revision_label)
85 self.revlayt.addWidget(self.revision)
86 self.revlayt.addStretch()
87 self.revlayt.addWidget(self.title_label)
89 self.radiolayt = QtGui.QHBoxLayout()
90 self.radiolayt.addWidget(self.radio_local)
91 self.radiolayt.addWidget(self.radio_remote)
92 self.radiolayt.addWidget(self.radio_tag)
94 self.buttonlayt = QtGui.QHBoxLayout()
95 self.buttonlayt.setSpacing(defs.button_spacing)
96 self.buttonlayt.addWidget(self.button_viz)
97 self.buttonlayt.addStretch()
98 self.buttonlayt.addWidget(self.checkbox_squash)
99 self.buttonlayt.addWidget(self.checkbox_commit)
100 self.buttonlayt.addWidget(self.button_cancel)
101 self.buttonlayt.addWidget(self.button_merge)
103 self.mainlayt = QtGui.QVBoxLayout()
104 self.mainlayt.setMargin(defs.margin)
105 self.mainlayt.setSpacing(defs.spacing)
106 self.mainlayt.addLayout(self.radiolayt)
107 self.mainlayt.addWidget(self.revisions)
108 self.mainlayt.addLayout(self.revlayt)
109 self.mainlayt.addLayout(self.buttonlayt)
110 self.setLayout(self.mainlayt)
112 self.revision.setFocus()
114 # Signal/slot connections
115 self.connect(self.revision, SIGNAL('textChanged(QString)'),
116 self.update_title)
118 self.connect(self.revisions, SIGNAL('itemSelectionChanged()'),
119 self.revision_selected)
121 qtutils.connect_button(self.button_cancel, self.reject)
122 qtutils.connect_button(self.checkbox_squash, self.toggle_squash)
123 qtutils.connect_button(self.radio_local, self.update_revisions)
124 qtutils.connect_button(self.radio_remote, self.update_revisions)
125 qtutils.connect_button(self.radio_tag, self.update_revisions)
126 qtutils.connect_button(self.button_merge, self.merge_revision)
127 qtutils.connect_button(self.button_viz, self.viz_revision)
129 # Observer messages
130 model.add_observer(model.message_updated, self.update_all)
131 self.update_all()
133 def update_all(self):
134 """Set the branch name for the window title and label."""
135 self.update_title()
136 self.update_revisions()
138 def update_title(self, dummy_txt=None):
139 branch = self.model.currentbranch
140 revision = unicode(self.revision.text())
141 if revision:
142 txt = (N_('Merge "%(revision)s" into "%(branch)s"') %
143 dict(revision=revision, branch=branch))
144 else:
145 txt = N_('Merge into "%s"') % branch
146 self.title_label.setText(txt)
147 self.setWindowTitle(txt)
149 def toggle_squash(self):
150 """Toggles the commit checkbox based on the squash checkbox."""
151 if self.checkbox_squash.isChecked():
152 self.checkbox_commit_state =\
153 self.checkbox_commit.checkState()
154 self.checkbox_commit.setCheckState(Qt.Unchecked)
155 self.checkbox_commit.setDisabled(True)
156 else:
157 self.checkbox_commit.setDisabled(False)
158 oldstate = self.checkbox_commit_state
159 self.checkbox_commit.setCheckState(oldstate)
161 def update_revisions(self):
162 """Update the revision list whenever a radio button is clicked"""
163 self.revisions.clear()
164 self.revisions.addItems(self.current_revisions())
166 def revision_selected(self):
167 """Update the revision field when a list item is selected"""
168 revlist = self.current_revisions()
169 widget = self.revisions
170 row, selected = qtutils.selected_row(widget)
171 if selected and row < len(revlist):
172 revision = revlist[row]
173 self.revision.setText(revision)
175 def current_revisions(self):
176 """Retrieve candidate items to merge"""
177 if self.radio_local.isChecked():
178 return self.model.local_branches
179 elif self.radio_remote.isChecked():
180 return self.model.remote_branches
181 elif self.radio_tag.isChecked():
182 return self.model.tags
183 return []
185 def viz_revision(self):
186 """Launch a gitk-like viewer on the selection revision"""
187 revision = unicode(self.revision.text())
188 if not revision:
189 qtutils.information(N_('No Revision Specified'),
190 N_('You must specify a revision to view.'))
191 return
192 cmds.do(cmds.VisualizeRevision, revision)
194 def merge_revision(self):
195 """Merge the selected revision/branch"""
196 revision = unicode(self.revision.text())
197 if not revision:
198 qtutils.information(N_('No Revision Specified'),
199 N_('You must specify a revision to merge.'))
200 return
202 do_commit = self.checkbox_commit.isChecked()
203 squash = self.checkbox_squash.isChecked()
204 cmds.do(cmds.Merge, revision, not(do_commit), squash)
205 self.accept()