doc: fix release notes typo
[git-cola.git] / cola / widgets / stash.py
blob1ab05b7907ecd3d43eb701b3bdc8f134b7af9cc5
1 """Provides the StashView dialog."""
3 from PyQt4 import QtCore
4 from PyQt4 import QtGui
5 from PyQt4.QtCore import SIGNAL
7 from cola import cmds
8 from cola import qtutils
9 from cola import utils
10 from cola.i18n import N_
11 from cola.models.stash import StashModel
12 from cola.models.stash import ApplyStash
13 from cola.models.stash import SaveStash
14 from cola.models.stash import DropStash
15 from cola.widgets import defs
16 from cola.widgets.diff import DiffTextEdit
17 from cola.widgets.standard import Dialog
20 def stash():
21 """Launches a stash dialog using the provided model + view
22 """
23 model = StashModel()
24 view = StashView(model, qtutils.active_window())
25 view.show()
26 view.raise_()
27 return view
30 class StashView(Dialog):
31 def __init__(self, model, parent=None):
32 Dialog.__init__(self, parent=parent)
33 self.setAttribute(QtCore.Qt.WA_MacMetalStyle)
34 self.model = model
35 self.stashes = []
36 self.revids = []
37 self.names = []
39 self.setWindowModality(QtCore.Qt.WindowModal)
40 self.setWindowTitle(N_('Stash'))
41 if parent:
42 self.resize(parent.width(), 420)
43 else:
44 self.resize(700, 420)
46 self.stash_list = QtGui.QListWidget(self)
47 self.stash_text = DiffTextEdit(self)
49 self.button_apply =\
50 self.toolbutton(N_('Apply'),
51 N_('Apply the selected stash'),
52 qtutils.apply_icon())
53 self.button_save =\
54 self.toolbutton(N_('Save'),
55 N_('Save modified state to new stash'),
56 qtutils.save_icon())
57 self.button_drop = \
58 self.toolbutton(N_('Drop'),
59 N_('Drop the selected stash'),
60 qtutils.discard_icon())
61 self.button_close = \
62 self.pushbutton(N_('Close'),
63 N_('Close'), qtutils.close_icon())
65 self.keep_index = QtGui.QCheckBox(self)
66 self.keep_index.setText(N_('Keep Index'))
67 self.keep_index.setChecked(True)
69 # Arrange layouts
70 self.main_layt = QtGui.QVBoxLayout()
71 self.main_layt.setMargin(defs.margin)
72 self.main_layt.setSpacing(defs.spacing)
74 self.btn_layt = QtGui.QHBoxLayout()
75 self.btn_layt.setMargin(0)
76 self.btn_layt.setSpacing(defs.spacing)
78 self.splitter = QtGui.QSplitter()
79 self.splitter.setHandleWidth(defs.handle_width)
80 self.splitter.setOrientation(QtCore.Qt.Horizontal)
81 self.splitter.setChildrenCollapsible(True)
82 self.splitter.setStretchFactor(0, 1)
83 self.splitter.setStretchFactor(1, 1)
84 self.splitter.insertWidget(0, self.stash_list)
85 self.splitter.insertWidget(1, self.stash_text)
87 self.btn_layt.addWidget(self.button_save)
88 self.btn_layt.addWidget(self.button_apply)
89 self.btn_layt.addWidget(self.button_drop)
90 self.btn_layt.addWidget(self.keep_index)
91 self.btn_layt.addStretch()
92 self.btn_layt.addWidget(self.button_close)
94 self.main_layt.addWidget(self.splitter)
95 self.main_layt.addLayout(self.btn_layt)
96 self.setLayout(self.main_layt)
98 self.splitter.setSizes([self.width()/3, self.width()*2/3])
100 self.update_from_model()
101 self.update_actions()
103 self.setTabOrder(self.button_save, self.button_apply)
104 self.setTabOrder(self.button_apply, self.button_drop)
105 self.setTabOrder(self.button_drop, self.keep_index)
106 self.setTabOrder(self.keep_index, self.button_close)
108 self.connect(self.stash_list, SIGNAL('itemSelectionChanged()'),
109 self.item_selected)
111 qtutils.connect_button(self.button_apply, self.stash_apply)
112 qtutils.connect_button(self.button_save, self.stash_save)
113 qtutils.connect_button(self.button_drop, self.stash_drop)
114 qtutils.connect_button(self.button_close, self.close)
116 def close(self):
117 self.accept()
118 cmds.do(cmds.Rescan)
120 def toolbutton(self, text, tooltip, icon):
121 return qtutils.create_toolbutton(text=text, tooltip=tooltip, icon=icon)
123 def pushbutton(self, text, tooltip, icon):
124 btn = QtGui.QPushButton(self)
125 btn.setText(text)
126 btn.setToolTip(tooltip)
127 btn.setIcon(icon)
128 return btn
130 def selected_stash(self):
131 """Returns the stash name of the currently selected stash
133 list_widget = self.stash_list
134 stash_list = self.revids
135 return qtutils.selected_item(list_widget, stash_list)
137 def selected_name(self):
138 list_widget = self.stash_list
139 stash_list = self.names
140 return qtutils.selected_item(list_widget, stash_list)
142 def item_selected(self):
143 """Shows the current stash in the main view."""
144 self.update_actions()
145 selection = self.selected_stash()
146 if not selection:
147 return
148 diff_text = self.model.stash_diff(selection)
149 self.stash_text.setPlainText(diff_text)
151 def update_actions(self):
152 has_changes = self.model.has_stashable_changes()
153 has_stash = bool(self.selected_stash())
154 self.button_save.setEnabled(has_changes)
155 self.button_apply.setEnabled(has_stash)
156 self.button_drop.setEnabled(has_stash)
158 def update_from_model(self):
159 """Initiates git queries on the model and updates the view
161 stashes, revids, names = self.model.stash_info()
162 self.stashes = stashes
163 self.revids = revids
164 self.names = names
166 self.stash_list.clear()
167 self.stash_list.addItems(self.stashes)
169 def stash_apply(self):
170 """Applies the currently selected stash
172 selection = self.selected_stash()
173 if not selection:
174 return
175 index = self.keep_index.isChecked()
176 cmds.do(ApplyStash, selection, index)
177 self.accept()
178 cmds.do(cmds.Rescan)
180 def stash_save(self):
181 """Saves the worktree in a stash
183 This prompts the user for a stash name and creates
184 a git stash named accordingly.
187 stash_name, ok = qtutils.prompt(N_('Save Stash'),
188 N_('Enter a name for the stash'))
189 if not ok or not stash_name:
190 return
191 # Sanitize the stash name
192 stash_name = utils.sanitize(stash_name)
193 if stash_name in self.names:
194 qtutils.critical(N_('Error: Stash exists'),
195 N_('A stash named "%s" already exists') % stash_name)
196 return
198 keep_index = self.keep_index.isChecked()
199 cmds.do(SaveStash, stash_name, keep_index)
200 self.accept()
201 cmds.do(cmds.Rescan)
203 def stash_drop(self):
204 """Drops the currently selected stash
206 selection = self.selected_stash()
207 name = self.selected_name()
208 if not selection:
209 return
210 if not qtutils.confirm(N_('Drop Stash?'),
211 N_('Recovering a dropped stash is not possible.'),
212 N_('Drop the "%s" stash?') % name,
213 N_('Drop Stash'),
214 default=True,
215 icon=qtutils.discard_icon()):
216 return
217 cmds.do(DropStash, selection)
218 self.update_from_model()
219 self.stash_text.setPlainText('')