resources: remove unnecessary os.path.dirname import
[git-cola.git] / cola / widgets / merge.py
blob098fa6fcab5b91c466842d1a5609f650c9fe43de
1 from qtpy import QtWidgets
2 from qtpy.QtCore import Qt
4 from ..i18n import N_
5 from ..interaction import Interaction
6 from ..qtutils import get
7 from .. import cmds
8 from .. import icons
9 from .. import qtutils
10 from . import completion
11 from . import standard
12 from . import defs
15 def local_merge(context):
16 """Provides a dialog for merging branches"""
17 view = Merge(context, qtutils.active_window())
18 view.show()
19 view.raise_()
20 return view
23 class Merge(standard.Dialog):
24 """Provides a dialog for merging branches."""
26 def __init__(self, context, parent=None, ref=None):
27 standard.Dialog.__init__(self, parent=parent)
28 self.context = context
29 self.cfg = cfg = context.cfg
30 self.model = context.model
31 if parent is not None:
32 self.setWindowModality(Qt.WindowModal)
34 # Widgets
35 self.title_label = QtWidgets.QLabel()
36 self.revision_label = QtWidgets.QLabel()
37 self.revision_label.setText(N_('Revision to Merge'))
39 self.revision = completion.GitRefLineEdit(context)
40 self.revision.setToolTip(N_('Revision to Merge'))
41 if ref:
42 self.revision.set_value(ref)
44 self.radio_local = qtutils.radio(text=N_('Local Branch'), checked=True)
45 self.radio_remote = qtutils.radio(text=N_('Tracking Branch'))
46 self.radio_tag = qtutils.radio(text=N_('Tag'))
48 self.revisions = QtWidgets.QListWidget()
49 self.revisions.setAlternatingRowColors(True)
51 self.button_viz = qtutils.create_button(
52 text=N_('Visualize'), icon=icons.visualize()
55 tooltip = N_('Squash the merged commits into a single commit')
56 self.checkbox_squash = qtutils.checkbox(text=N_('Squash'), tooltip=tooltip)
58 tooltip = N_(
59 'Always create a merge commit when enabled, '
60 'even when the merge is a fast-forward update'
62 self.checkbox_noff = qtutils.checkbox(
63 text=N_('No fast forward'), tooltip=tooltip, checked=False
65 self.checkbox_noff_state = False
67 tooltip = N_(
68 'Commit the merge if there are no conflicts. '
69 'Uncheck to leave the merge uncommitted'
71 self.checkbox_commit = qtutils.checkbox(
72 text=N_('Commit'), tooltip=tooltip, checked=True
74 self.checkbox_commit_state = True
76 text = N_('Create Signed Commit')
77 checked = cfg.get('cola.signcommits', False)
78 tooltip = N_('GPG-sign the merge commit')
79 self.checkbox_sign = qtutils.checkbox(
80 text=text, checked=checked, tooltip=tooltip
82 self.button_close = qtutils.close_button()
84 icon = icons.merge()
85 self.button_merge = qtutils.create_button(
86 text=N_('Merge'), icon=icon, default=True
89 # Layouts
90 self.revlayt = qtutils.hbox(
91 defs.no_margin,
92 defs.spacing,
93 self.revision_label,
94 self.revision,
95 qtutils.STRETCH,
96 self.title_label,
99 self.radiolayt = qtutils.hbox(
100 defs.no_margin,
101 defs.spacing,
102 self.radio_local,
103 self.radio_remote,
104 self.radio_tag,
107 self.buttonlayt = qtutils.hbox(
108 defs.no_margin,
109 defs.button_spacing,
110 self.button_viz,
111 self.checkbox_squash,
112 self.checkbox_noff,
113 self.checkbox_commit,
114 self.checkbox_sign,
115 qtutils.STRETCH,
116 self.button_close,
117 self.button_merge,
120 self.mainlayt = qtutils.vbox(
121 defs.margin,
122 defs.spacing,
123 self.radiolayt,
124 self.revisions,
125 self.revlayt,
126 self.buttonlayt,
128 self.setLayout(self.mainlayt)
130 # Signal/slot connections
131 self.revision.textChanged.connect(self.update_title)
132 self.revision.enter.connect(self.merge_revision)
133 self.revisions.itemSelectionChanged.connect(self.revision_selected)
135 qtutils.connect_released(self.radio_local, self.update_revisions)
136 qtutils.connect_released(self.radio_remote, self.update_revisions)
137 qtutils.connect_released(self.radio_tag, self.update_revisions)
138 qtutils.connect_button(self.button_merge, self.merge_revision)
139 qtutils.connect_button(self.checkbox_squash, self.toggle_squash)
140 qtutils.connect_button(self.button_viz, self.viz_revision)
141 qtutils.connect_button(self.button_close, self.reject)
143 # Observer messages
144 self.model.updated.connect(self.update_all)
145 self.update_all()
147 self.init_size(parent=parent)
148 self.revision.setFocus()
150 def update_all(self):
151 """Set the branch name for the window title and label."""
152 self.update_title()
153 self.update_revisions()
155 def update_title(self, _txt=None):
156 branch = self.model.currentbranch
157 revision = self.revision.text()
158 if revision:
159 txt = N_('Merge "%(revision)s" into "%(branch)s"') % {
160 'revision': revision,
161 'branch': branch,
163 else:
164 txt = N_('Merge into "%s"') % branch
165 self.button_merge.setEnabled(bool(revision))
166 self.title_label.setText(txt)
167 self.setWindowTitle(txt)
169 def toggle_squash(self):
170 """Toggles the commit checkbox based on the squash checkbox."""
171 if get(self.checkbox_squash):
172 self.checkbox_commit_state = self.checkbox_commit.checkState()
173 self.checkbox_commit.setCheckState(Qt.Unchecked)
174 self.checkbox_commit.setDisabled(True)
175 self.checkbox_noff_state = self.checkbox_noff.checkState()
176 self.checkbox_noff.setCheckState(Qt.Unchecked)
177 self.checkbox_noff.setDisabled(True)
178 else:
179 self.checkbox_noff.setDisabled(False)
180 oldstateff = self.checkbox_noff_state
181 self.checkbox_noff.setCheckState(oldstateff)
182 self.checkbox_commit.setDisabled(False)
183 oldstate = self.checkbox_commit_state
184 self.checkbox_commit.setCheckState(oldstate)
186 def update_revisions(self):
187 """Update the revision list whenever a radio button is clicked"""
188 self.revisions.clear()
189 self.revisions.addItems(self.current_revisions())
191 def revision_selected(self):
192 """Update the revision field when a list item is selected"""
193 revlist = self.current_revisions()
194 widget = self.revisions
195 revision = qtutils.selected_item(widget, revlist)
196 if revision is not None:
197 self.revision.setText(revision)
199 def current_revisions(self):
200 """Retrieve candidate items to merge"""
201 if get(self.radio_local):
202 return self.model.local_branches
203 if get(self.radio_remote):
204 return self.model.remote_branches
205 if get(self.radio_tag):
206 return self.model.tags
207 return []
209 def viz_revision(self):
210 """Launch a gitk-like viewer on the selection revision"""
211 revision = self.revision.text()
212 if not revision:
213 Interaction.information(
214 N_('No Revision Specified'), N_('You must specify a revision to view.')
216 return
217 cmds.do(cmds.VisualizeRevision, self.context, revision)
219 def merge_revision(self):
220 """Merge the selected revision/branch"""
221 revision = self.revision.text()
222 if not revision:
223 Interaction.information(
224 N_('No Revision Specified'), N_('You must specify a revision to merge.')
226 return
228 noff = get(self.checkbox_noff)
229 no_commit = not get(self.checkbox_commit)
230 squash = get(self.checkbox_squash)
231 sign = get(self.checkbox_sign)
232 context = self.context
233 cmds.do(cmds.Merge, context, revision, no_commit, squash, noff, sign)
234 self.accept()
236 def export_state(self):
237 """Export persistent settings"""
238 state = super().export_state()
239 state['no-ff'] = get(self.checkbox_noff)
240 state['sign'] = get(self.checkbox_sign)
241 state['commit'] = get(self.checkbox_commit)
242 return state
244 def apply_state(self, state):
245 """Apply persistent settings"""
246 result = super().apply_state(state)
247 self.checkbox_noff.setChecked(state.get('no-ff', False))
248 self.checkbox_sign.setChecked(state.get('sign', False))
249 self.checkbox_commit.setChecked(state.get('commit', True))
250 return result