1 from PyQt4
import QtGui
2 from PyQt4
.QtCore
import Qt
3 from PyQt4
.QtCore
import SIGNAL
5 from cola
import gitcmds
7 from cola
import qtutils
9 from cola
.widgets
import defs
10 from cola
.widgets
import standard
11 from cola
.main
.model
import MainModel
14 def create_new_branch(revision
=''):
15 """Launches a dialog for creating a new branch"""
18 view
= CreateBranchDialog(model
, qtutils
.active_window())
20 view
.set_revision(revision
)
25 class CreateBranchDialog(standard
.Dialog
):
26 """A dialog for creating branches."""
28 def __init__(self
, model
, parent
=None):
29 super(CreateBranchDialog
, self
).__init
__(parent
=parent
)
30 self
.setAttribute(Qt
.WA_MacMetalStyle
)
33 self
.setWindowTitle(self
.tr('Create Branch'))
35 self
.branch_name_label
= QtGui
.QLabel()
36 self
.branch_name_label
.setText(self
.tr('Branch Name'))
38 self
.local_branch
= QtGui
.QLineEdit()
40 self
.rev_label
= QtGui
.QLabel()
41 self
.rev_label
.setText(self
.tr('Revision Expression:'))
43 self
.revision
= QtGui
.QLineEdit()
45 self
.local_radio
= QtGui
.QRadioButton()
46 self
.local_radio
.setText(self
.tr('Local Branch'))
47 self
.local_radio
.setChecked(True)
49 self
.remote_radio
= QtGui
.QRadioButton()
50 self
.remote_radio
.setText(self
.tr('Tracking Branch'))
52 self
.tag_radio
= QtGui
.QRadioButton()
53 self
.tag_radio
.setText(self
.tr('Tag'))
55 self
.branch_list
= QtGui
.QListWidget()
57 self
.update_existing_label
= QtGui
.QLabel()
58 self
.update_existing_label
.setText(self
.tr('Update Existing Branch:'))
60 self
.no_update_radio
= QtGui
.QRadioButton()
61 self
.no_update_radio
.setText(self
.tr('No'))
63 self
.ffwd_only_radio
= QtGui
.QRadioButton()
64 self
.ffwd_only_radio
.setText(self
.tr('Fast Forward Only'))
65 self
.ffwd_only_radio
.setChecked(True)
67 self
.reset_radio
= QtGui
.QRadioButton()
68 self
.reset_radio
.setText(self
.tr('Reset'))
70 self
.options_bottom_layout
= QtGui
.QHBoxLayout()
71 self
.options_checkbox_layout
= QtGui
.QVBoxLayout()
73 self
.fetch_checkbox
= QtGui
.QCheckBox()
74 self
.fetch_checkbox
.setText(self
.tr('Fetch Tracking Branch'))
75 self
.fetch_checkbox
.setChecked(True)
76 self
.options_checkbox_layout
.addWidget(self
.fetch_checkbox
)
78 self
.checkout_checkbox
= QtGui
.QCheckBox()
79 self
.checkout_checkbox
.setText(self
.tr('Checkout After Creation'))
80 self
.checkout_checkbox
.setChecked(True)
81 self
.options_checkbox_layout
.addWidget(self
.checkout_checkbox
)
83 self
.options_bottom_layout
.addLayout(self
.options_checkbox_layout
)
84 self
.options_bottom_layout
.addStretch()
86 self
.create_button
= qt
.create_button(text
='Create Branch',
87 icon
=qtutils
.git_icon())
88 self
.create_button
.setDefault(True)
90 self
.cancel_button
= qt
.create_button(text
='Cancel')
92 self
.branch_name_layout
= QtGui
.QHBoxLayout()
93 self
.branch_name_layout
.addWidget(self
.branch_name_label
)
94 self
.branch_name_layout
.addWidget(self
.local_branch
)
96 self
.rev_start_radiobtn_layout
= QtGui
.QHBoxLayout()
97 self
.rev_start_radiobtn_layout
.addWidget(self
.local_radio
)
98 self
.rev_start_radiobtn_layout
.addWidget(self
.remote_radio
)
99 self
.rev_start_radiobtn_layout
.addWidget(self
.tag_radio
)
100 self
.rev_start_radiobtn_layout
.addStretch()
102 self
.rev_start_textinput_layout
= QtGui
.QHBoxLayout()
103 self
.rev_start_textinput_layout
.setMargin(0)
104 self
.rev_start_textinput_layout
.setSpacing(defs
.spacing
)
105 self
.rev_start_textinput_layout
.addWidget(self
.rev_label
)
106 self
.rev_start_textinput_layout
.addWidget(self
.revision
)
108 self
.rev_start_group
= QtGui
.QGroupBox()
109 self
.rev_start_group
.setTitle(self
.tr('Starting Revision'))
111 self
.rev_start_layout
= QtGui
.QVBoxLayout(self
.rev_start_group
)
112 self
.rev_start_layout
.setMargin(defs
.margin
)
113 self
.rev_start_layout
.setSpacing(defs
.spacing
)
114 self
.rev_start_layout
.addLayout(self
.rev_start_radiobtn_layout
)
115 self
.rev_start_layout
.addWidget(self
.branch_list
)
116 self
.rev_start_layout
.addLayout(self
.rev_start_textinput_layout
)
118 self
.options_radio_layout
= QtGui
.QHBoxLayout()
119 self
.options_radio_layout
.addWidget(self
.update_existing_label
)
120 self
.options_radio_layout
.addWidget(self
.no_update_radio
)
121 self
.options_radio_layout
.addWidget(self
.ffwd_only_radio
)
122 self
.options_radio_layout
.addWidget(self
.reset_radio
)
124 self
.option_group
= QtGui
.QGroupBox()
125 self
.option_group
.setTitle(self
.tr('Options'))
127 self
.options_grp_layout
= QtGui
.QVBoxLayout(self
.option_group
)
128 self
.options_grp_layout
.setMargin(defs
.margin
)
129 self
.options_grp_layout
.setSpacing(defs
.spacing
)
130 self
.options_grp_layout
.addLayout(self
.options_radio_layout
)
131 self
.options_grp_layout
.addLayout(self
.options_bottom_layout
)
133 self
.buttons_layout
= QtGui
.QHBoxLayout()
134 self
.buttons_layout
.setMargin(defs
.margin
)
135 self
.buttons_layout
.setSpacing(defs
.spacing
)
136 self
.buttons_layout
.addWidget(self
.create_button
)
137 self
.buttons_layout
.addWidget(self
.cancel_button
)
139 self
.options_section_layout
= QtGui
.QHBoxLayout()
140 self
.options_section_layout
.setMargin(defs
.margin
)
141 self
.options_section_layout
.setSpacing(defs
.spacing
)
142 self
.options_section_layout
.addWidget(self
.option_group
)
143 self
.options_section_layout
.addLayout(self
.buttons_layout
)
145 self
.main_layout
= QtGui
.QVBoxLayout()
146 self
.main_layout
.setMargin(defs
.margin
)
147 self
.main_layout
.setSpacing(defs
.spacing
)
148 self
.main_layout
.addLayout(self
.branch_name_layout
)
149 self
.main_layout
.addWidget(self
.rev_start_group
)
150 self
.main_layout
.addLayout(self
.options_section_layout
)
151 self
.setLayout(self
.main_layout
)
153 qtutils
.connect_button(self
.cancel_button
, self
.reject
)
154 qtutils
.connect_button(self
.create_button
, self
.create_branch
)
155 qtutils
.connect_button(self
.local_radio
, self
.display_model
)
156 qtutils
.connect_button(self
.remote_radio
, self
.display_model
)
157 qtutils
.connect_button(self
.tag_radio
, self
.display_model
)
159 self
.connect(self
.branch_list
, SIGNAL('itemSelectionChanged()'),
160 self
.branch_item_changed
)
163 self
.resize(self
.parent().width(), self
.parent().height())
165 self
.resize(555, 333)
169 def set_revision(self
, revision
):
170 self
.revision
.setText(revision
)
172 def create_branch(self
):
173 """Creates a branch; called by the "Create Branch" button"""
175 revision
= unicode(self
.revision
.text())
176 branch
= unicode(self
.local_branch
.text())
177 existing_branches
= self
.model
.local_branches
179 if not branch
or not revision
:
180 qtutils
.critical('Missing Data',
181 'Please provide both a branch '
182 'name and revision expression.')
186 if branch
in existing_branches
:
187 if self
.no_update_radio
.isChecked():
188 msg
= self
.tr("Branch '%s' already exists.")
189 msg
= unicode(msg
) % branch
190 qtutils
.critical('Branch Exists', msg
)
192 # Whether we should prompt the user for lost commits
193 commits
= gitcmds
.rev_list_range(revision
, branch
)
194 check_branch
= bool(commits
)
197 msg
= self
.tr("Resetting '%s' to '%s' will "
198 "lose the following commits:")
199 lines
= [ unicode(msg
) % (branch
, revision
) ]
201 for idx
, commit
in enumerate(commits
):
202 subject
= commit
[1][0:min(len(commit
[1]),16)]
203 if len(subject
) < len(commit
[1]):
205 lines
.append('\t' + commit
[0][:8]
208 skip
= len(commits
) - 5
209 lines
.append('\t(%d skipped)' % skip
)
213 unicode(self
.tr('Recovering lost commits may not be easy.')),
216 if not qtutils
.confirm('Reset Branch?',
218 'Reset "%s" to "%s"?' % (branch
, revision
),
221 icon
=qtutils
.icon('undo.svg')):
225 track
= self
.remote_radio
.isChecked()
226 fetch
= self
.fetch_checkbox
.isChecked()
227 ffwd
= self
.ffwd_only_radio
.isChecked()
228 reset
= self
.reset_radio
.isChecked()
229 chkout
= self
.checkout_checkbox
.isChecked()
231 status
, output
= self
.model
.create_branch(branch
, revision
, track
=track
)
232 qtutils
.log(status
, output
)
233 if status
== 0 and chkout
:
234 status
, output
= self
.model
.git
.checkout(branch
,
237 qtutils
.log(status
, output
)
240 def branch_item_changed(self
, *rest
):
241 """This callback is called when the branch selection changes"""
243 # When the branch selection changes then we should update
244 # the "Revision Expression" accordingly.
245 qlist
= self
.branch_list
246 (row
, selected
) = qtutils
.selected_row(qlist
)
250 sources
= self
.branch_sources()
253 # Update the model with the selection
254 self
.revision
.setText(rev
)
256 # Only set the branch name field if we're
257 # branching from a remote branch.
258 if not self
.remote_radio
.isChecked():
260 branch
= utils
.basename(rev
)
264 # Signal that we've clicked on a remote branch
265 self
.local_branch
.setText(branch
)
267 def display_model(self
):
268 """Sets the branch list to the available branches
270 branches
= self
.branch_sources()
271 qtutils
.set_items(self
.branch_list
, branches
)
273 def branch_sources(self
):
274 """Get the list of items for populating the branch root list.
276 if self
.local_radio
.isChecked():
277 return self
.model
.local_branches
278 elif self
.remote_radio
.isChecked():
279 return self
.model
.remote_branches
280 elif self
.tag_radio
.isChecked():
281 return self
.model
.tags