qobserver: add support for optional args in init()
[ugit.git] / ugit / controllers / util.py
blob558718b200bdd545c94cb19dcfb7cd5a5584ff07
1 #!/usr/bin/env python
2 import os
3 import time
4 from PyQt4.QtGui import QDialog
5 from PyQt4.QtGui import QFont
7 from ugit import utils
8 from ugit import qtutils
9 from ugit.model import Model
10 from ugit.views import BranchView
11 from ugit.views import CommitView
12 from ugit.views import OptionsView
13 from ugit.views import LogView
14 from ugit.qobserver import QObserver
16 def set_diff_font(model, widget):
17 if model.has_param('global_ugit_fontdiff'):
18 font = model.get_param('global_ugit_fontdiff')
19 if not font: return
20 qf = QFont()
21 qf.fromString(font)
22 widget.setFont(qf)
24 def choose_branch(title, parent, branches):
25 dlg = BranchView(parent,branches)
26 dlg.setWindowTitle(dlg.tr(title))
27 return dlg.get_selected()
29 #+-------------------------------------------------------------
30 def select_commits(model, parent, title, revs, summaries):
31 '''Use the CommitView to select commits from a list.'''
32 model = model.clone()
33 model.set_revisions(revs)
34 model.set_summaries(summaries)
35 view = CommitView(parent, title)
36 ctl = SelectCommitsController(model, view)
37 return ctl.select_commits()
39 class SelectCommitsController(QObserver):
40 def init(self, model, view):
41 set_diff_font( model, view.commit_text )
42 self.connect( view.commit_list, 'itemSelectionChanged()',
43 self.commit_sha1_selected )
45 def select_commits(self):
46 summaries = self.model.get_summaries()
47 if not summaries:
48 msg = self.tr('No commits exist in this branch.')
49 qtutils.show_output(msg)
50 return []
51 qtutils.set_items(self.view.commit_list, summaries)
52 self.view.show()
53 if self.view.exec_() != QDialog.Accepted:
54 return []
55 revs = self.model.get_revisions()
56 list_widget = self.view.commit_list
57 return qtutils.get_selection_list(list_widget, revs)
59 def commit_sha1_selected(self):
60 row, selected = qtutils.get_selected_row(self.view.commit_list)
61 if not selected:
62 self.view.commit_text.setText('')
63 self.view.revision.setText('')
64 return
66 # Get the sha1 and put it in the revision line
67 sha1 = self.model.get_revision_sha1(row)
68 self.view.revision.setText(sha1)
69 self.view.revision.selectAll()
71 # Lookup the sha1's commit
72 commit_diff = self.model.get_commit_diff(sha1)
73 self.view.commit_text.setText(commit_diff)
75 # Copy the sha1 into the clipboard
76 qtutils.set_clipboard(sha1)
79 #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
80 #+ The Options GUI Controller
81 def update_options(model, parent):
82 view = OptionsView(parent)
83 ctl = OptionsController(model,view)
84 view.show()
85 return view.exec_() == QDialog.Accepted
87 class OptionsController(QObserver):
88 '''ASSUMPTIONS:
89 This controller assumes that the view's widgets are named
90 the same as the model parameters.'''
92 def init(self,model,view):
93 # used for telling about interactive font changes
94 self.original_model = model
95 model = model.clone()
96 self.add_observables(
97 'local_user_email',
98 'local_user_name',
99 'local_merge_summary',
100 'local_merge_diffstat',
101 'local_merge_verbosity',
102 'local_gui_diffcontext',
103 'global_user_email',
104 'global_user_name',
105 'global_merge_summary',
106 'global_merge_diffstat',
107 'global_merge_verbosity',
108 'global_gui_editor',
109 'global_gui_diffeditor',
110 'global_gui_diffcontext',
111 'global_gui_historybrowser',
112 'global_ugit_fontdiff_size',
113 'global_ugit_fontdiff',
114 'global_ugit_fontui_size',
115 'global_ugit_fontui',
116 'global_ugit_savewindowsettings',
117 'global_ugit_saveatexit',
119 self.add_actions(global_ugit_fontdiff_size = self.update_size)
120 self.add_actions(global_ugit_fontui_size = self.update_size)
121 self.add_actions(global_ugit_fontdiff = self.tell_parent_model)
122 self.add_actions(global_ugit_fontui = self.tell_parent_model)
123 self.add_callbacks(save_button = self.save_settings)
124 self.connect(self.view, 'rejected()', self.restore_settings)
126 self.refresh_view()
127 self.backup_model = self.model.clone()
129 def refresh_view(self):
130 font = self.model.get_param('global_ugit_fontui')
131 if font:
132 size = int(font.split(',')[1])
133 self.view.global_ugit_fontui_size.setValue(size)
134 self.model.set_global_ugit_fontui_size(size)
135 fontui = QFont()
136 fontui.fromString(font)
137 self.view.global_ugit_fontui.setCurrentFont(fontui)
139 font = self.model.get_global_ugit_fontdiff()
140 if font:
141 size = int(font.split(',')[1])
142 self.view.global_ugit_fontdiff_size.setValue(size)
143 self.model.set_global_ugit_fontdiff_size(size)
144 fontdiff = QFont()
145 fontdiff.fromString(font)
146 self.view.global_ugit_fontdiff.setCurrentFont(fontdiff)
148 self.view.local_groupbox.setTitle(
149 unicode(self.tr('%s Repository'))
150 % self.model.get_project())
151 QObserver.refresh_view(self)
153 # save button
154 def save_settings(self):
155 params_to_save = []
156 params = self.model.get_config_params()
157 for param in params:
158 value = self.model.get_param(param)
159 backup = self.backup_model.get_param(param)
160 if value != backup:
161 params_to_save.append(param)
162 for param in params_to_save:
163 self.model.save_config_param(param)
165 self.original_model.copy_params(self.model, params_to_save)
166 self.view.done(QDialog.Accepted)
168 # cancel button -> undo changes
169 def restore_settings(self):
170 params = self.backup_model.get_config_params()
171 self.model.copy_params(self.backup_model, params)
172 self.tell_parent_model()
174 def tell_parent_model(self,*rest):
175 params= (
176 'global_ugit_fontdiff',
177 'global_ugit_fontui',
178 'global_ugit_fontdiff_size',
179 'global_ugit_fontui_size',
180 'global_ugit_savewindowsettings',
181 'global_ugit_saveatexit',
183 for param in params:
184 self.original_model.set_param(
185 param, self.model.get_param(param))
187 def update_size(self, *rest):
188 combo = self.view.global_ugit_fontui
189 param = str(combo.objectName())
190 default = str(combo.currentFont().toString())
191 self.model.apply_font_size(param, default)
193 combo = self.view.global_ugit_fontdiff
194 param = str(combo.objectName())
195 default = str(combo.currentFont().toString())
196 self.model.apply_font_size(param, default)
198 self.tell_parent_model()
200 #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
201 #+ The Log GUI Controller
202 def logger():
203 model = Model( search_text = '' )
204 view = LogView(None)
205 ctl = LogController(model,view)
206 return view
208 class LogController(QObserver):
209 def init(self, model, view):
210 self.add_observables('search_text')
211 self.add_actions(search_text = self.insta_search)
212 self.add_callbacks(
213 clear_button = self.clear,
214 next_button = self.next,
215 prev_button = self.prev,
217 self.connect(self.view.output_text,
218 'cursorPositionChanged()',
219 self.cursor_position_changed)
220 self.search_offset = 0
222 def insta_search(self,*rest):
223 self.search_offset = 0
224 txt = self.model.get_search_text().lower()
225 if len(txt.strip()):
226 self.next()
227 else:
228 cursor = self.view.output_text.textCursor()
229 cursor.clearSelection()
230 self.view.output_text.setTextCursor(cursor)
232 def clear(self):
233 self.view.output_text.clear()
234 self.search_offset = 0
236 def next(self):
237 text = self.model.get_search_text().lower().strip()
238 if not text: return
239 output = str(self.view.output_text.toPlainText())
240 if self.search_offset + len(text) > len(output):
241 answer = qtutils.question(
242 self.view,
243 unicode(self.tr("%s not found")) % text,
244 unicode(self.tr(
245 "Could not find '%s'.\n"
246 "Search from the beginning?"
247 )) % text,
248 default=False)
250 if answer:
251 self.search_offset = 0
252 else:
253 return
255 find_in = output[self.search_offset:].lower()
256 try:
257 index = find_in.index(text)
258 except:
259 self.search_offset = 0
260 answer = qtutils.question(
261 self.view,
262 unicode(self.tr("%s not found")) % text,
263 unicode(self.tr(
264 "Could not find '%s'.\n"
265 "Search from the beginning?"
266 )) % text,
267 default=False)
268 if answer:
269 self.next()
270 return
271 cursor = self.view.output_text.textCursor()
272 offset = self.search_offset + index
273 new_offset = offset + len(text)
275 cursor.setPosition(offset)
276 cursor.setPosition(new_offset, cursor.KeepAnchor)
278 self.view.output_text.setTextCursor(cursor)
279 self.search_offset = new_offset
281 def prev(self):
282 text = self.model.get_search_text().lower().strip()
283 if not text: return
284 output = str(self.view.output_text.toPlainText())
285 if self.search_offset == 0:
286 self.search_offset = len(output)
288 find_in = output[:self.search_offset].lower()
289 try:
290 offset = find_in.rindex(text)
291 except:
292 self.search_offset = 0
293 if qtutils.question(
294 self.view,
295 unicode(self.tr("%s not found")) % text,
296 unicode(self.tr("Could not find '%s'.\n"
297 "Search from the end?"
298 )) % text):
299 self.prev()
300 return
301 cursor = self.view.output_text.textCursor()
302 new_offset = offset + len(text)
304 cursor.setPosition(offset)
305 cursor.setPosition(new_offset, cursor.KeepAnchor)
307 self.view.output_text.setTextCursor(cursor)
308 self.search_offset = offset
310 def cursor_position_changed(self):
311 cursor = self.view.output_text.textCursor()
312 self.search_offset = cursor.selectionStart()