]>
Commit | Line | Data |
---|---|---|
6f1a3f9c RD |
1 | #---------------------------------------------------------------------------- |
2 | # Name: SVNService.py | |
3 | # Purpose: Subversion Service for pydocview | |
4 | # | |
5 | # Author: Morgan Hua | |
6 | # | |
7 | # Created: 5/13/05 | |
8 | # CVS-ID: $Id$ | |
9 | # Copyright: (c) 2005 ActiveGrid, Inc. | |
10 | # License: wxWindows License | |
11 | #---------------------------------------------------------------------------- | |
12 | ||
13 | import wx | |
26ee3a06 | 14 | import os |
6f1a3f9c RD |
15 | import os.path |
16 | import ProjectEditor | |
17 | import MessageService | |
18 | ||
19 | import sys # for errors | |
20 | import traceback # for errors | |
21 | ||
22 | try: | |
23 | import pysvn # python-subversion integration | |
24 | SVN_INSTALLED = True | |
25 | except ImportError: | |
26 | SVN_INSTALLED = False | |
27 | ||
28 | _ = wx.GetTranslation | |
29 | ||
30 | ||
31 | #---------------------------------------------------------------------------- | |
32 | # Constants | |
33 | #---------------------------------------------------------------------------- | |
34 | SVN_CONFIG_DIR = "SVNConfigDir" | |
26ee3a06 | 35 | SVN_REPOSITORY_URL = "SVNRepositoryURLs" |
6f1a3f9c RD |
36 | |
37 | SPACE = 10 | |
38 | HALF_SPACE = 5 | |
39 | ||
40 | ||
41 | #---------------------------------------------------------------------------- | |
42 | # Classes | |
43 | #---------------------------------------------------------------------------- | |
44 | ||
45 | class SVNService(wx.lib.pydocview.DocService): | |
26ee3a06 | 46 | SVN_UPDATE_ALL_ID = wx.NewId() |
6f1a3f9c RD |
47 | SVN_UPDATE_ID = wx.NewId() |
48 | SVN_CHECKIN_ID = wx.NewId() | |
26ee3a06 | 49 | SVN_CHECKIN_ALL_ID = wx.NewId() |
6f1a3f9c RD |
50 | SVN_CHECKOUT_ID = wx.NewId() |
51 | SVN_REVERT_ID = wx.NewId() | |
52 | SVN_ADD_ID = wx.NewId() | |
53 | SVN_DELETE_ID = wx.NewId() | |
26ee3a06 | 54 | SVN_COMMAND_LIST = [SVN_UPDATE_ALL_ID, SVN_CHECKIN_ALL_ID, SVN_UPDATE_ID, SVN_CHECKIN_ID, SVN_CHECKOUT_ID, SVN_REVERT_ID, SVN_ADD_ID, SVN_DELETE_ID] |
6f1a3f9c RD |
55 | |
56 | ||
57 | def __init__(self): | |
58 | self._defaultURL = "svn://" | |
59 | ||
60 | global SVN_INSTALLED | |
61 | if SVN_INSTALLED: | |
62 | config = wx.ConfigBase_Get() | |
26ee3a06 | 63 | |
6f1a3f9c | 64 | configDir = config.Read(SVN_CONFIG_DIR, "") |
6f1a3f9c RD |
65 | self._client = pysvn.Client(configDir) |
66 | try: | |
67 | self._defaultURL = self._client.info('.').url | |
68 | except: | |
69 | pass | |
26ee3a06 | 70 | |
6f1a3f9c RD |
71 | self._client.callback_cancel = self.IfCancel |
72 | self._client.callback_notify = self.UpdateStatus | |
73 | self._client.callback_get_log_message = self.GetLogMessage | |
74 | self._client.callback_get_login = self.GetLogin | |
75 | self._client.callback_ssl_server_trust_prompt = self.GetSSLServerTrust | |
76 | self._client.callback_ssl_client_cert_password_prompt = self.SSLClientPassword | |
77 | self._client.callback_ssl_client_cert_prompt = self.SSLClientCert | |
78 | self._client.callback_ssl_server_prompt = self.SSLServerPrompt | |
79 | ||
80 | #---------------------------------------------------------------------------- | |
81 | # pysvn.Client() Callback Methods | |
82 | #---------------------------------------------------------------------------- | |
83 | ||
84 | def IfCancel(self): | |
85 | """ return True if user wants to cancel current command """ | |
86 | return False | |
87 | ||
88 | ||
89 | def UpdateStatus(self, eventDict): | |
90 | messageService = wx.GetApp().GetService(MessageService.MessageService) | |
91 | messageService.ShowWindow() | |
92 | ||
93 | view = messageService.GetView() | |
94 | view.AddLines(_("%s %s\n") % (eventDict['action'], eventDict['path'])) | |
95 | ||
96 | ||
97 | def GetLogMessage(self): | |
98 | dlg = wx.TextEntryDialog(wx.GetApp().GetTopWindow(), | |
99 | _("Comment"), | |
100 | _("SVN Log Message")) | |
101 | ||
02b800ce | 102 | dlg.CenterOnParent() |
6f1a3f9c RD |
103 | if dlg.ShowModal() == wx.ID_OK: |
104 | retcode = True | |
105 | message = dlg.GetValue() | |
106 | else: | |
107 | retcode = False | |
108 | message = _("Cancel Action") | |
109 | ||
110 | dlg.Destroy() | |
111 | ||
112 | return retcode, message | |
113 | ||
114 | ||
115 | def GetLogin(self, realm, username, maySave): | |
116 | dlg = wx.Dialog(wx.GetApp().GetTopWindow(), -1, _("SVN Login")) | |
117 | ||
118 | sizer = wx.FlexGridSizer(cols = 2, hgap = 5, vgap = 5) | |
119 | sizer.Add(wx.StaticText(dlg, -1, _("Username:")), 0, wx.ALIGN_CENTER_VERTICAL) | |
120 | usernameTxt = wx.TextCtrl(dlg, -1, username, size = (200, -1)) | |
121 | sizer.Add(usernameTxt, 0, wx.ALIGN_CENTER_VERTICAL) | |
122 | sizer.Add(wx.StaticText(dlg, -1, _("Password:")), 0, wx.ALIGN_CENTER_VERTICAL) | |
123 | passwordTxt = wx.TextCtrl(dlg, -1, size=(200, -1), style=wx.TE_PASSWORD) | |
124 | sizer.Add(passwordTxt, 0, wx.ALIGN_CENTER_VERTICAL) | |
125 | ||
126 | savePasswordCheckbox = wx.CheckBox(dlg, -1, _("Remember Username and Password")) | |
127 | if not maySave: | |
128 | savePasswordCheckbox.Enable(False) | |
129 | ||
130 | buttonSizer = wx.BoxSizer(wx.HORIZONTAL) | |
131 | okBtn = wx.Button(dlg, wx.ID_OK) | |
132 | okBtn.SetDefault() | |
133 | buttonSizer.Add(okBtn, 0, wx.RIGHT, HALF_SPACE) | |
134 | buttonSizer.Add(wx.Button(dlg, wx.ID_CANCEL), 0) | |
135 | ||
136 | contentSizer = wx.BoxSizer(wx.VERTICAL) | |
137 | contentSizer.Add(sizer, 0, wx.LEFT|wx.TOP|wx.RIGHT, SPACE) | |
138 | contentSizer.Add(savePasswordCheckbox, 0, wx.TOP|wx.LEFT|wx.BOTTOM, SPACE) | |
139 | contentSizer.Add(buttonSizer, 0, wx.ALL|wx.ALIGN_RIGHT, SPACE) | |
140 | ||
141 | dlg.SetSizer(contentSizer) | |
142 | dlg.Fit() | |
143 | dlg.Layout() | |
144 | ||
02b800ce | 145 | dlg.CenterOnParent() |
6f1a3f9c RD |
146 | if dlg.ShowModal() == wx.ID_OK: |
147 | retcode = True | |
148 | username = usernameTxt.GetValue().strip() | |
149 | password = passwordTxt.GetValue() | |
02b800ce | 150 | save = savePasswordCheckbox.IsChecked() |
6f1a3f9c RD |
151 | else: |
152 | retcode = False | |
153 | username = None | |
154 | password = None | |
155 | save = False | |
156 | ||
157 | dlg.Destroy() | |
158 | return retcode, username, password, save | |
159 | ||
160 | ||
161 | def SSLServerPrompt(self): | |
162 | """ Not implemented, as per pysvn documentation """ | |
163 | return | |
164 | ||
165 | ||
166 | def GetSSLServerTrust(self, trustDict): | |
167 | dlg = wx.Dialog(wx.GetApp().GetTopWindow(), -1, _("SSL Server Certificate")) | |
168 | ||
169 | sizer = wx.FlexGridSizer(cols = 2, hgap = 5, vgap = 5) | |
170 | for k in ['hostname', 'valid_from', 'valid_to', 'issuer_dname', 'realm']: | |
171 | if trustDict.has_key(k): | |
172 | sizer.Add(wx.StaticText(dlg, -1, "%s:" % k), 0, wx.ALIGN_CENTER_VERTICAL) | |
173 | sizer.Add(wx.StaticText(dlg, -1, "%s" % trustDict[k]), 0, wx.ALIGN_CENTER_VERTICAL) | |
174 | ||
175 | box = wx.StaticBoxSizer(wx.StaticBox(dlg, -1, _("Certificate Info")), wx.VERTICAL) | |
176 | box.Add(sizer, 0, wx.EXPAND) | |
177 | ||
178 | certRadio = wx.RadioBox(dlg, -1, _("Certificate"), choices=[_("Accept Always"), _("Accept Once"), _("Reject")], majorDimension=1, style=wx.RA_SPECIFY_COLS) | |
179 | ||
180 | buttonSizer = wx.BoxSizer(wx.HORIZONTAL) | |
181 | okBtn = wx.Button(dlg, wx.ID_OK) | |
182 | okBtn.SetDefault() | |
183 | buttonSizer.Add(okBtn, 0, wx.RIGHT, HALF_SPACE) | |
184 | buttonSizer.Add(wx.Button(dlg, wx.ID_CANCEL), 0) | |
185 | ||
186 | contentSizer = wx.BoxSizer(wx.VERTICAL) | |
187 | contentSizer.Add(box, 0, wx.TOP|wx.LEFT|wx.RIGHT|wx.EXPAND, SPACE) | |
188 | contentSizer.Add(certRadio, 0, wx.TOP|wx.LEFT|wx.RIGHT|wx.BOTTOM|wx.EXPAND, SPACE) | |
189 | contentSizer.Add(buttonSizer, 0, wx.ALL|wx.ALIGN_RIGHT, SPACE) | |
190 | ||
191 | dlg.SetSizer(contentSizer) | |
192 | dlg.Fit() | |
193 | dlg.Layout() | |
194 | ||
195 | # default values for reject | |
196 | retcode = False | |
197 | acceptedFailures = 0 | |
198 | save = False | |
199 | ||
02b800ce | 200 | dlg.CenterOnParent() |
6f1a3f9c RD |
201 | if dlg.ShowModal() == wx.ID_OK: |
202 | cert = certRadio.GetStringSelection() | |
203 | if cert == _("Accept Always"): | |
204 | retcode = True | |
205 | acceptedFailures = trustDict.get('failures') | |
206 | save = True | |
207 | elif cert == _("Accept Once"): | |
208 | retcode = True | |
209 | acceptedFailures = trustDict.get('failures') | |
210 | save = False | |
211 | ||
02b800ce | 212 | dlg.Destroy() |
6f1a3f9c RD |
213 | return retcode, acceptedFailures, save |
214 | ||
215 | ||
216 | def SSLClientPassword(self, realm, maySave): | |
217 | dlg = wx.Dialog(wx.GetApp().GetTopWindow(), -1, _("SSL Client Certificate Login")) | |
218 | ||
219 | sizer = wx.FlexGridSizer(cols = 2, hgap = 5, vgap = 5) | |
220 | sizer.Add(wx.StaticText(dlg, -1, _("Realm:")), 0, wx.ALIGN_CENTER_VERTICAL) | |
221 | sizer.Add(wx.StaticText(dlg, -1, realm), 0, wx.ALIGN_CENTER_VERTICAL) | |
222 | sizer.Add(wx.StaticText(dlg, -1, _("Password:")), 0, wx.ALIGN_CENTER_VERTICAL) | |
223 | passwordTxt = wx.TextCtrl(dlg, -1, size=(200, -1), style=wx.TE_PASSWORD) | |
224 | sizer.Add(passwordTxt, 0, wx.ALIGN_CENTER_VERTICAL) | |
225 | ||
226 | savePasswordCheckbox = wx.CheckBox(dlg, -1, _("Remember Password")) | |
227 | if not maySave: | |
228 | savePasswordCheckbox.Enable(False) | |
229 | ||
230 | buttonSizer = wx.BoxSizer(wx.HORIZONTAL) | |
231 | okBtn = wx.Button(dlg, wx.ID_OK) | |
232 | okBtn.SetDefault() | |
233 | buttonSizer.Add(okBtn, 0, wx.RIGHT, HALF_SPACE) | |
234 | buttonSizer.Add(wx.Button(dlg, wx.ID_CANCEL), 0) | |
235 | ||
236 | contentSizer = wx.BoxSizer(wx.VERTICAL) | |
237 | contentSizer.Add(sizer, 0, wx.LEFT|wx.TOP|wx.RIGHT, SPACE) | |
238 | contentSizer.Add(savePasswordCheckbox, 0, wx.TOP|wx.LEFT|wx.BOTTOM, SPACE) | |
239 | contentSizer.Add(buttonSizer, 0, wx.ALL|wx.ALIGN_RIGHT, SPACE) | |
240 | ||
241 | dlg.SetSizer(contentSizer) | |
242 | dlg.Fit() | |
243 | dlg.Layout() | |
244 | ||
02b800ce | 245 | dlg.CenterOnParent() |
6f1a3f9c RD |
246 | if dlg.ShowModal() == wx.ID_OK: |
247 | retcode = True | |
248 | password = passwordTxt.GetValue() | |
02b800ce | 249 | save = savePasswordCheckbox.IsChecked() |
6f1a3f9c RD |
250 | else: |
251 | retcode = False | |
252 | password = None | |
253 | save = False | |
254 | ||
255 | dlg.Destroy() | |
256 | return retcode, password, save | |
257 | ||
258 | ||
259 | def SSLClientCert(self): | |
260 | dlg = wx.FileDialog(wx.GetApp().GetTopWindow(), | |
02b800ce RD |
261 | message="Choose certificate", |
262 | style=wx.OPEN|wx.FILE_MUST_EXIST|wx.CHANGE_DIR | |
6f1a3f9c RD |
263 | ) |
264 | ||
02b800ce | 265 | # dlg.CenterOnParent() # wxBug: caused crash with wx.FileDialog |
6f1a3f9c RD |
266 | if dlg.ShowModal() == wx.ID_OK: |
267 | retcode = True | |
268 | certfile = dlg.GetPath() | |
269 | else: | |
270 | retcode = False | |
271 | certfile = None | |
272 | ||
273 | dlg.Destroy() | |
274 | return retcode, certfile | |
275 | ||
276 | ||
277 | ||
278 | #---------------------------------------------------------------------------- | |
279 | # Service Methods | |
280 | #---------------------------------------------------------------------------- | |
281 | ||
282 | def InstallControls(self, frame, menuBar = None, toolBar = None, statusBar = None, document = None): | |
283 | menu = menuBar.GetMenu(menuBar.FindMenu(_("Project"))) | |
284 | ||
285 | menu.AppendSeparator() | |
286 | ||
26ee3a06 RD |
287 | wx.EVT_MENU(frame, SVNService.SVN_UPDATE_ALL_ID, self.ProcessEvent) |
288 | wx.EVT_UPDATE_UI(frame, SVNService.SVN_UPDATE_ALL_ID, self.ProcessUpdateUIEvent) | |
289 | menu.Append(SVNService.SVN_UPDATE_ALL_ID, _("SVN Update All in Project"), _("Update all files in a project from Subversion")) | |
290 | wx.EVT_MENU(frame, SVNService.SVN_CHECKIN_ALL_ID, self.ProcessEvent) | |
291 | wx.EVT_UPDATE_UI(frame, SVNService.SVN_CHECKIN_ALL_ID, self.ProcessUpdateUIEvent) | |
292 | menu.Append(SVNService.SVN_CHECKIN_ALL_ID, _("SVN Commit All in Project..."), _("Commit all files changes in a project to Subversion")) | |
6f1a3f9c RD |
293 | wx.EVT_MENU(frame, SVNService.SVN_UPDATE_ID, self.ProcessEvent) |
294 | wx.EVT_UPDATE_UI(frame, SVNService.SVN_UPDATE_ID, self.ProcessUpdateUIEvent) | |
295 | menu.Append(SVNService.SVN_UPDATE_ID, _("SVN Update"), _("Update file from Subversion")) | |
296 | wx.EVT_MENU(frame, SVNService.SVN_CHECKIN_ID, self.ProcessEvent) | |
297 | wx.EVT_UPDATE_UI(frame, SVNService.SVN_CHECKIN_ID, self.ProcessUpdateUIEvent) | |
298 | menu.Append(SVNService.SVN_CHECKIN_ID, _("SVN Commit..."), _("Commit file changes to Subversion")) | |
299 | wx.EVT_MENU(frame, SVNService.SVN_CHECKOUT_ID, self.ProcessEvent) | |
300 | wx.EVT_UPDATE_UI(frame, SVNService.SVN_CHECKOUT_ID, self.ProcessUpdateUIEvent) | |
301 | menu.Append(SVNService.SVN_CHECKOUT_ID, _("SVN Checkout..."), _("Checkout file from Subversion")) | |
302 | wx.EVT_MENU(frame, SVNService.SVN_REVERT_ID, self.ProcessEvent) | |
303 | wx.EVT_UPDATE_UI(frame, SVNService.SVN_REVERT_ID, self.ProcessUpdateUIEvent) | |
304 | menu.Append(SVNService.SVN_REVERT_ID, _("SVN Revert"), _("Revert file from Subversion")) | |
305 | ||
306 | menu.AppendSeparator() | |
307 | ||
308 | wx.EVT_MENU(frame, SVNService.SVN_ADD_ID, self.ProcessEvent) | |
309 | wx.EVT_UPDATE_UI(frame, SVNService.SVN_ADD_ID, self.ProcessUpdateUIEvent) | |
310 | menu.Append(SVNService.SVN_ADD_ID, _("SVN Add"), _("Add file to Subversion")) | |
311 | wx.EVT_MENU(frame, SVNService.SVN_DELETE_ID, self.ProcessEvent) | |
312 | wx.EVT_UPDATE_UI(frame, SVNService.SVN_DELETE_ID, self.ProcessUpdateUIEvent) | |
313 | menu.Append(SVNService.SVN_DELETE_ID, _("SVN Delete"), _("Delete file from Subversion")) | |
314 | ||
315 | ||
316 | def ProcessEvent(self, event): | |
317 | ||
318 | id = event.GetId() | |
319 | ||
320 | if not SVN_INSTALLED: | |
321 | if id in SVNService.SVN_COMMAND_LIST: | |
322 | wx.MessageBox(_("pysvn not found. Please install pysvn"), _("Python Subversion")) | |
323 | return True | |
324 | return False | |
325 | ||
326 | ||
327 | if id == SVNService.SVN_UPDATE_ID: | |
6f1a3f9c | 328 | wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT)) |
26ee3a06 | 329 | |
02b800ce RD |
330 | filenames = self.GetCurrentDocuments() |
331 | if filenames: | |
332 | filenames = filenames[:] | |
333 | filenames.sort(self.BasenameCaseInsensitiveCompare) | |
334 | else: | |
335 | folderPath = self.GetCurrentFolder() | |
336 | if folderPath: | |
337 | filenames = [folderPath] | |
6f1a3f9c RD |
338 | |
339 | messageService = wx.GetApp().GetService(MessageService.MessageService) | |
340 | messageService.ShowWindow() | |
341 | ||
342 | view = messageService.GetView() | |
343 | view.ClearLines() | |
344 | view.AddLines(_("SVN Update:\n")) | |
345 | ||
346 | for filename in filenames: | |
347 | view.AddLines("%s\n" % filename) | |
348 | try: | |
349 | status = self._client.update(filename) | |
350 | ||
351 | if status.number > 0: | |
352 | view.AddLines(_("Updated to revision %s\n") % status.number) | |
353 | ||
354 | openDocs = wx.GetApp().GetDocumentManager().GetDocuments() | |
355 | for doc in openDocs: | |
356 | if doc.GetFilename() == filename: | |
357 | yesNoMsg = wx.MessageDialog(wx.GetApp().GetTopWindow(), | |
358 | _("Updated file '%s' is currently open. Close it?") % os.path.basename(filename), | |
359 | _("Close File"), | |
360 | wx.YES_NO|wx.ICON_QUESTION) | |
02b800ce RD |
361 | yesNoMsg.CenterOnParent() |
362 | status = yesNoMsg.ShowModal() | |
363 | yesNoMsg.Destroy() | |
364 | if status == wx.ID_YES: | |
6f1a3f9c RD |
365 | doc.DeleteAllViews() |
366 | break | |
367 | else: | |
368 | view.AddLines(_("Update failed.\n")) | |
369 | ||
370 | except pysvn.ClientError, e: | |
371 | view.AddLines("%s\n" % str(e)) | |
372 | wx.MessageBox(str(e), _("SVN Update"), wx.OK | wx.ICON_EXCLAMATION) | |
373 | except: | |
374 | extype, ex, tb = sys.exc_info() | |
375 | view.AddLines("Update failed: (%s) %s\n" % (extype, str(ex))) | |
376 | for line in traceback.format_tb(tb): | |
377 | view.AddLines(line) | |
378 | ||
379 | wx.MessageBox(_("Update failed."), _("SVN Update"), wx.OK | wx.ICON_EXCLAMATION) | |
380 | ||
381 | wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) | |
382 | ||
383 | return True | |
26ee3a06 RD |
384 | |
385 | elif id == SVNService.SVN_UPDATE_ALL_ID: | |
386 | wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT)) | |
387 | ||
388 | messageService = wx.GetApp().GetService(MessageService.MessageService) | |
389 | messageService.ShowWindow() | |
390 | ||
391 | view = messageService.GetView() | |
392 | view.ClearLines() | |
393 | view.AddLines(_("SVN Update:\n")) | |
394 | ||
02b800ce RD |
395 | project = self.GetCurrentProject() |
396 | if project: | |
26ee3a06 RD |
397 | openDocs = wx.GetApp().GetDocumentManager().GetDocuments() |
398 | for doc in openDocs: | |
399 | if doc.GetFilename() == project: | |
400 | filenames = doc.GetFiles()[:] # make a copy and sort it. | |
401 | filenames.sort(self.BasenameCaseInsensitiveCompare) | |
402 | ||
403 | for filename in filenames: | |
404 | view.AddLines("%s\n" % filename) | |
405 | try: | |
406 | status = self._client.update(filename) | |
407 | ||
408 | if status.number > 0: | |
409 | view.AddLines(_("Updated to revision %s\n") % status.number) | |
410 | ||
411 | openDocs = wx.GetApp().GetDocumentManager().GetDocuments() | |
412 | for doc in openDocs: | |
413 | if doc.GetFilename() == filename: | |
414 | yesNoMsg = wx.MessageDialog(wx.GetApp().GetTopWindow(), | |
415 | _("Updated file '%s' is currently open. Close it?") % os.path.basename(filename), | |
416 | _("Close File"), | |
417 | wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION) | |
02b800ce | 418 | yesNoMsg.CenterOnParent() |
26ee3a06 | 419 | status = yesNoMsg.ShowModal() |
02b800ce | 420 | yesNoMsg.Destroy() |
26ee3a06 RD |
421 | if status == wx.ID_YES: |
422 | doc.DeleteAllViews() | |
423 | elif status == wx.ID_NO: | |
424 | pass | |
425 | else: # elif status == wx.CANCEL: | |
426 | wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) | |
427 | return True | |
428 | break | |
429 | else: | |
430 | view.AddLines(_("Update failed.\n")) | |
431 | ||
432 | except pysvn.ClientError, e: | |
433 | view.AddLines("%s\n" % str(e)) | |
434 | wx.MessageBox(str(e), _("SVN Update"), wx.OK | wx.ICON_EXCLAMATION) | |
435 | except: | |
436 | extype, ex, tb = sys.exc_info() | |
437 | view.AddLines("Update failed: (%s) %s\n" % (extype, str(ex))) | |
438 | for line in traceback.format_tb(tb): | |
439 | view.AddLines(line) | |
440 | ||
441 | wx.MessageBox(_("Update failed."), _("SVN Update"), wx.OK | wx.ICON_EXCLAMATION) | |
442 | ||
443 | wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) | |
444 | return True | |
445 | ||
446 | elif id == SVNService.SVN_CHECKIN_ALL_ID: | |
447 | filenames = [] | |
02b800ce RD |
448 | project = self.GetCurrentProject() |
449 | if project: | |
26ee3a06 RD |
450 | openDocs = wx.GetApp().GetDocumentManager().GetDocuments() |
451 | for doc in openDocs: | |
452 | if doc.GetFilename() == project: | |
453 | for filename in doc.GetFiles(): | |
454 | if filename not in filenames: | |
455 | filenames.append(filename) | |
456 | filenames.sort(self.BasenameCaseInsensitiveCompare) | |
457 | ||
458 | # ask user if dirty files should be saved first | |
459 | openDocs = wx.GetApp().GetDocumentManager().GetDocuments() | |
460 | for filename in filenames: | |
461 | for doc in openDocs: | |
462 | if doc.GetFilename() == filename and doc.IsModified(): | |
463 | yesNoMsg = wx.MessageDialog(wx.GetApp().GetTopWindow(), | |
464 | _("'%s' has unsaved modifications. Save it before commit?") % os.path.basename(filename), | |
465 | _("SVN Commit"), | |
466 | wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION) | |
02b800ce | 467 | yesNoMsg.CenterOnParent() |
26ee3a06 | 468 | status = yesNoMsg.ShowModal() |
02b800ce | 469 | yesNoMsg.Destroy() |
26ee3a06 RD |
470 | if status == wx.ID_YES: |
471 | doc.Save() | |
472 | elif status == wx.ID_NO: | |
473 | pass | |
474 | else: # elif status == wx.CANCEL: | |
475 | return True | |
476 | break | |
477 | ||
478 | shortFilenames = [] | |
479 | for i, filename in enumerate(filenames): | |
480 | shortFilename = os.path.basename(filename) | |
481 | shortFilenames.append(shortFilename) | |
482 | ||
483 | dlg = wx.Dialog(wx.GetApp().GetTopWindow(), -1, _("SVN Commit")) | |
484 | ||
485 | sizer = wx.BoxSizer(wx.VERTICAL) | |
486 | sizer.Add(wx.StaticText(dlg, -1, _("Comment:")), 0, wx.ALIGN_CENTER_VERTICAL) | |
487 | commentText = wx.TextCtrl(dlg, -1, size=(250,-1), style=wx.TE_MULTILINE) | |
488 | sizer.Add(commentText, 1, wx.EXPAND|wx.TOP, HALF_SPACE) | |
489 | ||
490 | sizer.Add(wx.StaticText(dlg, -1, _("Files:")), 0, wx.ALIGN_CENTER_VERTICAL|wx.TOP, SPACE) | |
491 | fileList = wx.CheckListBox(dlg, -1, choices = shortFilenames) | |
492 | for i in range(fileList.GetCount()): | |
493 | fileList.Check(i, True) | |
494 | sizer.Add(fileList, 0, wx.EXPAND|wx.TOP, HALF_SPACE) | |
495 | ||
02b800ce | 496 | buttonSizer = wx.StdDialogButtonSizer() |
26ee3a06 RD |
497 | okBtn = wx.Button(dlg, wx.ID_OK) |
498 | okBtn.SetDefault() | |
02b800ce RD |
499 | buttonSizer.AddButton(okBtn) |
500 | buttonSizer.AddButton(wx.Button(dlg, wx.ID_CANCEL)) | |
501 | buttonSizer.Realize() | |
26ee3a06 RD |
502 | |
503 | contentSizer = wx.BoxSizer(wx.VERTICAL) | |
504 | contentSizer.Add(sizer, 0, wx.ALL, SPACE) | |
505 | contentSizer.Add(buttonSizer, 0, wx.ALL|wx.ALIGN_RIGHT, SPACE) | |
506 | ||
507 | dlg.SetSizer(contentSizer) | |
508 | dlg.Fit() | |
509 | dlg.Layout() | |
510 | ||
02b800ce | 511 | dlg.CenterOnParent() |
26ee3a06 RD |
512 | if dlg.ShowModal() == wx.ID_OK: |
513 | wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT)) | |
514 | ||
515 | messageService = wx.GetApp().GetService(MessageService.MessageService) | |
516 | messageService.ShowWindow() | |
517 | ||
518 | view = messageService.GetView() | |
519 | view.ClearLines() | |
520 | view.AddLines(_("SVN Commit:\n")) | |
521 | ||
522 | try: | |
523 | selFilenames = [] | |
524 | for i in range(fileList.GetCount()): | |
525 | if fileList.IsChecked(i): | |
526 | selFilenames.append(filenames[i]) | |
527 | view.AddLines("%s\n" % filenames[i]) | |
528 | ||
529 | if len(selFilenames): | |
530 | comment = commentText.GetValue() | |
531 | status = self._client.checkin(selFilenames, comment) | |
532 | ||
533 | if status is None: | |
534 | view.AddLines(_("Nothing to commit.\n")) | |
535 | elif status.number > 0: | |
536 | view.AddLines(_("Committed as revision %s.\n") % status.number) | |
537 | else: | |
538 | view.AddLines(_("Commit failed.\n")) | |
539 | ||
540 | except pysvn.ClientError, e: | |
541 | view.AddLines("%s\n" % str(e)) | |
542 | wx.MessageBox(str(e), _("SVN Commit"), wx.OK | wx.ICON_EXCLAMATION) | |
543 | except: | |
544 | extype, ex, tb = sys.exc_info() | |
545 | view.AddLines("Commit failed: (%s) %s\n" % (extype, str(ex))) | |
546 | for line in traceback.format_tb(tb): | |
547 | view.AddLines(line) | |
548 | wx.MessageBox(_("Commit failed."), _("SVN Commit"), wx.OK | wx.ICON_EXCLAMATION) | |
549 | ||
550 | wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) | |
551 | dlg.Destroy() | |
552 | return True | |
553 | ||
6f1a3f9c RD |
554 | |
555 | elif id == SVNService.SVN_CHECKIN_ID: | |
26ee3a06 RD |
556 | filenames = self.GetCurrentDocuments()[:] |
557 | filenames.sort(self.BasenameCaseInsensitiveCompare) | |
6f1a3f9c RD |
558 | |
559 | # ask user if dirty files should be saved first | |
560 | openDocs = wx.GetApp().GetDocumentManager().GetDocuments() | |
561 | for filename in filenames: | |
562 | for doc in openDocs: | |
563 | if doc.GetFilename() == filename and doc.IsModified(): | |
564 | yesNoMsg = wx.MessageDialog(wx.GetApp().GetTopWindow(), | |
565 | _("'%s' has unsaved modifications. Save it before commit?") % os.path.basename(filename), | |
566 | _("SVN Commit"), | |
567 | wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION) | |
02b800ce | 568 | yesNoMsg.CenterOnParent() |
6f1a3f9c | 569 | status = yesNoMsg.ShowModal() |
02b800ce | 570 | yesNoMsg.Destroy() |
6f1a3f9c RD |
571 | if status == wx.ID_YES: |
572 | doc.Save() | |
573 | elif status == wx.ID_NO: | |
574 | pass | |
575 | else: # elif status == wx.CANCEL: | |
576 | return True | |
577 | break | |
578 | ||
579 | shortFilenames = [] | |
580 | for i, filename in enumerate(filenames): | |
581 | shortFilename = os.path.basename(filename) | |
582 | shortFilenames.append(shortFilename) | |
583 | ||
584 | dlg = wx.Dialog(wx.GetApp().GetTopWindow(), -1, _("SVN Commit")) | |
585 | ||
586 | sizer = wx.BoxSizer(wx.VERTICAL) | |
587 | sizer.Add(wx.StaticText(dlg, -1, _("Comment:")), 0, wx.ALIGN_CENTER_VERTICAL) | |
588 | commentText = wx.TextCtrl(dlg, -1, size=(250,-1), style=wx.TE_MULTILINE) | |
589 | sizer.Add(commentText, 1, wx.EXPAND|wx.TOP, HALF_SPACE) | |
590 | ||
591 | sizer.Add(wx.StaticText(dlg, -1, _("Files:")), 0, wx.ALIGN_CENTER_VERTICAL|wx.TOP, SPACE) | |
592 | fileList = wx.CheckListBox(dlg, -1, choices = shortFilenames) | |
593 | for i in range(fileList.GetCount()): | |
594 | fileList.Check(i, True) | |
595 | sizer.Add(fileList, 0, wx.EXPAND|wx.TOP, HALF_SPACE) | |
596 | ||
02b800ce | 597 | buttonSizer = wx.StdDialogButtonSizer() |
6f1a3f9c RD |
598 | okBtn = wx.Button(dlg, wx.ID_OK) |
599 | okBtn.SetDefault() | |
02b800ce RD |
600 | buttonSizer.AddButton(okBtn) |
601 | buttonSizer.AddButton(wx.Button(dlg, wx.ID_CANCEL)) | |
602 | buttonSizer.Realize() | |
603 | ||
6f1a3f9c RD |
604 | contentSizer = wx.BoxSizer(wx.VERTICAL) |
605 | contentSizer.Add(sizer, 0, wx.ALL, SPACE) | |
606 | contentSizer.Add(buttonSizer, 0, wx.ALL|wx.ALIGN_RIGHT, SPACE) | |
607 | ||
608 | dlg.SetSizer(contentSizer) | |
609 | dlg.Fit() | |
610 | dlg.Layout() | |
611 | ||
02b800ce | 612 | dlg.CenterOnParent() |
6f1a3f9c RD |
613 | if dlg.ShowModal() == wx.ID_OK: |
614 | wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT)) | |
615 | ||
616 | messageService = wx.GetApp().GetService(MessageService.MessageService) | |
617 | messageService.ShowWindow() | |
618 | ||
619 | view = messageService.GetView() | |
620 | view.ClearLines() | |
621 | view.AddLines(_("SVN Commit:\n")) | |
622 | ||
623 | try: | |
624 | selFilenames = [] | |
625 | for i in range(fileList.GetCount()): | |
626 | if fileList.IsChecked(i): | |
627 | selFilenames.append(filenames[i]) | |
628 | view.AddLines("%s\n" % filenames[i]) | |
629 | ||
630 | if len(selFilenames): | |
631 | comment = commentText.GetValue() | |
632 | status = self._client.checkin(selFilenames, comment) | |
633 | ||
634 | if status is None: | |
635 | view.AddLines(_("Nothing to commit.\n")) | |
636 | elif status.number > 0: | |
637 | view.AddLines(_("Committed as revision %s.\n") % status.number) | |
638 | else: | |
639 | view.AddLines(_("Commit failed.\n")) | |
640 | ||
641 | except pysvn.ClientError, e: | |
642 | view.AddLines("%s\n" % str(e)) | |
643 | wx.MessageBox(str(e), _("SVN Commit"), wx.OK | wx.ICON_EXCLAMATION) | |
644 | except: | |
645 | extype, ex, tb = sys.exc_info() | |
646 | view.AddLines("Commit failed: (%s) %s\n" % (extype, str(ex))) | |
647 | for line in traceback.format_tb(tb): | |
648 | view.AddLines(line) | |
649 | wx.MessageBox(_("Commit failed."), _("SVN Commit"), wx.OK | wx.ICON_EXCLAMATION) | |
650 | ||
651 | wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) | |
652 | dlg.Destroy() | |
653 | return True | |
654 | ||
655 | elif id == SVNService.SVN_CHECKOUT_ID: | |
656 | config = wx.ConfigBase_Get() | |
657 | svnUrl = config.Read(SVN_REPOSITORY_URL, self._defaultURL) | |
658 | ||
659 | dlg = wx.Dialog(wx.GetApp().GetTopWindow(), -1, _("SVN Checkout")) | |
660 | ||
661 | gridSizer = wx.FlexGridSizer(cols = 2, hgap = 5, vgap = 5) | |
662 | gridSizer.Add(wx.StaticText(dlg, -1, _("Repository URL:")), 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT|wx.TOP, HALF_SPACE) | |
26ee3a06 RD |
663 | svnUrlList = ReadSvnUrlList() |
664 | svnURLCombobox = wx.ComboBox(dlg, -1, size=(200, -1), choices=svnUrlList, style=wx.CB_DROPDOWN) | |
665 | if len(svnUrlList): | |
666 | svnURLCombobox.SetToolTipString(svnUrlList[0]) | |
667 | svnURLCombobox.SetStringSelection(svnUrlList[0]) | |
668 | else: | |
669 | svnURLCombobox.SetToolTipString(_("Set Repository URL")) | |
670 | gridSizer.Add(svnURLCombobox, 0) | |
6f1a3f9c RD |
671 | |
672 | gridSizer.Add(wx.StaticText(dlg, -1, _("Checkout to dir:")), 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT|wx.TOP, HALF_SPACE) | |
673 | localPath = wx.TextCtrl(dlg, -1, size = (200, -1)) | |
674 | localPath.SetToolTipString(_("Path in local file system where files will be located.")) | |
675 | findDirButton = wx.Button(dlg, -1, _("Browse...")) | |
676 | ||
677 | def OnBrowseButton(event): | |
678 | dirDlg = wx.DirDialog(wx.GetApp().GetTopWindow(), _("Choose a directory:"), style=wx.DD_DEFAULT_STYLE) | |
679 | dir = localPath.GetValue() | |
680 | if len(dir): | |
681 | dirDlg.SetPath(dir) | |
02b800ce | 682 | dirDlg.CenterOnParent() |
6f1a3f9c RD |
683 | if dirDlg.ShowModal() == wx.ID_OK: |
684 | localPath.SetValue(dirDlg.GetPath()) | |
685 | localPath.SetToolTipString(localPath.GetValue()) | |
686 | localPath.SetInsertionPointEnd() | |
6f1a3f9c RD |
687 | dirDlg.Destroy() |
688 | wx.EVT_BUTTON(findDirButton, -1, OnBrowseButton) | |
689 | ||
690 | sizer = wx.BoxSizer(wx.HORIZONTAL) | |
691 | sizer.Add(localPath, 1, wx.EXPAND) | |
692 | sizer.Add(findDirButton, 0, wx.LEFT, HALF_SPACE) | |
693 | gridSizer.Add(sizer, 0) | |
694 | ||
02b800ce | 695 | buttonSizer = wx.StdDialogButtonSizer() |
6f1a3f9c RD |
696 | okBtn = wx.Button(dlg, wx.ID_OK) |
697 | okBtn.SetDefault() | |
02b800ce RD |
698 | buttonSizer.AddButton(okBtn) |
699 | buttonSizer.AddButton(wx.Button(dlg, wx.ID_CANCEL)) | |
700 | buttonSizer.Realize() | |
6f1a3f9c RD |
701 | |
702 | contentSizer = wx.BoxSizer(wx.VERTICAL) | |
703 | contentSizer.Add(gridSizer, 0, wx.ALL, SPACE) | |
704 | contentSizer.Add(buttonSizer, 0, wx.ALL|wx.ALIGN_RIGHT, SPACE) | |
705 | ||
706 | dlg.SetSizer(contentSizer) | |
707 | dlg.Fit() | |
708 | dlg.Layout() | |
709 | ||
02b800ce | 710 | dlg.CenterOnParent() |
6f1a3f9c RD |
711 | if dlg.ShowModal() == wx.ID_OK: |
712 | wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT)) | |
26ee3a06 RD |
713 | |
714 | WriteSvnUrlList(svnURLCombobox) | |
6f1a3f9c RD |
715 | |
716 | messageService = wx.GetApp().GetService(MessageService.MessageService) | |
717 | messageService.ShowWindow() | |
718 | ||
719 | view = messageService.GetView() | |
720 | view.ClearLines() | |
721 | view.AddLines(_("SVN Checkout:\n")) | |
722 | ||
26ee3a06 | 723 | svnUrl = svnURLCombobox.GetValue() |
6f1a3f9c RD |
724 | toLocation = localPath.GetValue() |
725 | try: | |
726 | self._client.checkout(svnUrl, toLocation) | |
727 | view.AddLines(_("Checkout completed.\n")) | |
728 | except pysvn.ClientError, e: | |
729 | view.AddLines(_("Checkout failed. %s\n") % str(e)) | |
730 | wx.MessageBox(_("Checkout failed. %s") % str(e), _("SVN Checkout"), wx.OK | wx.ICON_EXCLAMATION) | |
731 | except: | |
732 | extype, ex, tb = sys.exc_info() | |
733 | view.AddLines("Checkout failed: (%s) %s\n" % (extype, str(ex))) | |
734 | for line in traceback.format_tb(tb): | |
735 | view.AddLines(line) | |
736 | wx.MessageBox(_("Checkout failed."), _("SVN Checkout"), wx.OK | wx.ICON_EXCLAMATION) | |
737 | ||
738 | wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) | |
739 | dlg.Destroy() | |
740 | return True | |
741 | ||
742 | elif id == SVNService.SVN_REVERT_ID: | |
743 | wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT)) | |
744 | ||
745 | filenames = self.GetCurrentDocuments() | |
746 | ||
747 | messageService = wx.GetApp().GetService(MessageService.MessageService) | |
748 | messageService.ShowWindow() | |
749 | ||
750 | view = messageService.GetView() | |
751 | view.ClearLines() | |
752 | view.AddLines(_("SVN Revert:\n")) | |
753 | for filename in filenames: | |
754 | view.AddLines("%s\n" % filename) | |
755 | ||
756 | try: | |
757 | self._client.revert(filenames) | |
758 | view.AddLines(_("Revert completed.\n")) | |
759 | ||
760 | openDocs = wx.GetApp().GetDocumentManager().GetDocuments() | |
761 | for doc in openDocs[:]: # need to make a copy of the list otherwise ordinality changes as we close the files | |
762 | if doc.GetFilename() in filenames: | |
763 | yesNoMsg = wx.MessageDialog(wx.GetApp().GetTopWindow(), | |
764 | _("Reverted file '%s' is currently open. Close it?") % os.path.basename(doc.GetFilename()), | |
765 | _("Close File"), | |
766 | wx.YES_NO|wx.ICON_QUESTION) | |
02b800ce RD |
767 | yesNoMsg.CenterOnParent() |
768 | status = yesNoMsg.ShowModal() | |
769 | yesNoMsg.Destroy() | |
770 | if status == wx.ID_YES: | |
6f1a3f9c RD |
771 | doc.DeleteAllViews() |
772 | ||
773 | except pysvn.ClientError, e: | |
774 | view.AddLines("%s\n" % str(e)) | |
775 | wx.MessageBox(str(e), _("SVN Revert"), wx.OK | wx.ICON_EXCLAMATION) | |
776 | except: | |
777 | extype, ex, tb = sys.exc_info() | |
778 | view.AddLines("Revert failed: (%s) %s\n" % (extype, str(ex))) | |
779 | for line in traceback.format_tb(tb): | |
780 | view.AddLines(line) | |
781 | wx.MessageBox(_("Revert failed."), _("SVN Revert"), wx.OK | wx.ICON_EXCLAMATION) | |
782 | ||
783 | wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) | |
784 | return True | |
785 | ||
786 | elif id == SVNService.SVN_ADD_ID: | |
787 | wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT)) | |
788 | ||
789 | filenames = self.GetCurrentDocuments() | |
790 | ||
791 | messageService = wx.GetApp().GetService(MessageService.MessageService) | |
792 | messageService.ShowWindow() | |
793 | ||
794 | view = messageService.GetView() | |
795 | view.ClearLines() | |
796 | view.AddLines(_("SVN Add:\n")) | |
797 | for filename in filenames: | |
798 | view.AddLines("%s\n" % filename) | |
799 | ||
800 | try: | |
801 | self._client.add(filenames) | |
802 | view.AddLines(_("Add completed.\n")) | |
803 | except pysvn.ClientError, e: | |
804 | view.AddLines("%s\n" % str(e)) | |
805 | wx.MessageBox(str(e), _("SVN Add"), wx.OK | wx.ICON_EXCLAMATION) | |
806 | except: | |
807 | extype, ex, tb = sys.exc_info() | |
808 | view.AddLines("Add failed: (%s) %s\n" % (extype, str(ex))) | |
809 | for line in traceback.format_tb(tb): | |
810 | view.AddLines(line) | |
811 | wx.MessageBox(_("Add failed."), _("SVN Add"), wx.OK | wx.ICON_EXCLAMATION) | |
812 | ||
813 | wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) | |
814 | return True | |
815 | ||
816 | elif id == SVNService.SVN_DELETE_ID: | |
817 | wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT)) | |
818 | ||
819 | filenames = self.GetCurrentDocuments() | |
820 | ||
821 | messageService = wx.GetApp().GetService(MessageService.MessageService) | |
822 | messageService.ShowWindow() | |
823 | ||
824 | view = messageService.GetView() | |
825 | view.ClearLines() | |
826 | view.AddLines(_("SVN Delete:\n")) | |
827 | for filename in filenames: | |
828 | view.AddLines("%s\n" % filename) | |
829 | ||
830 | try: | |
831 | self._client.remove(filenames) | |
832 | view.AddLines(_("Delete completed.\n")) | |
833 | except pysvn.ClientError, e: | |
834 | view.AddLines("%s\n" % str(e)) | |
835 | wx.MessageBox(str(e), _("SVN Delete"), wx.OK | wx.ICON_EXCLAMATION) | |
836 | except: | |
837 | extype, ex, tb = sys.exc_info() | |
838 | view.AddLines("Delete failed: (%s) %s\n" % (extype, str(ex))) | |
839 | for line in traceback.format_tb(tb): | |
840 | view.AddLines(line) | |
841 | wx.MessageBox(_("Delete failed."), _("SVN Delete"), wx.OK | wx.ICON_EXCLAMATION) | |
842 | ||
843 | wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) | |
844 | return True | |
845 | ||
846 | return False | |
847 | ||
848 | ||
849 | def ProcessUpdateUIEvent(self, event): | |
850 | id = event.GetId() | |
851 | ||
02b800ce | 852 | if id in [SVNService.SVN_CHECKIN_ID, |
6f1a3f9c RD |
853 | SVNService.SVN_REVERT_ID, |
854 | SVNService.SVN_ADD_ID, | |
855 | SVNService.SVN_DELETE_ID]: | |
856 | if self.GetCurrentDocuments(): | |
857 | event.Enable(True) | |
858 | else: | |
859 | event.Enable(False) | |
860 | return True | |
861 | ||
02b800ce RD |
862 | elif id == SVNService.SVN_UPDATE_ID: |
863 | if self.GetCurrentDocuments() or self.GetCurrentFolder(): | |
864 | event.Enable(True) | |
865 | else: | |
866 | event.Enable(False) | |
867 | return True | |
868 | ||
6f1a3f9c RD |
869 | elif id == SVNService.SVN_CHECKOUT_ID: |
870 | event.Enable(True) | |
871 | return True | |
872 | ||
26ee3a06 RD |
873 | elif (id == SVNService.SVN_UPDATE_ALL_ID |
874 | or id == SVNService.SVN_CHECKIN_ALL_ID): | |
02b800ce | 875 | if self.GetCurrentProject(): |
26ee3a06 RD |
876 | event.Enable(True) |
877 | else: | |
878 | event.Enable(False) | |
879 | return True | |
880 | ||
6f1a3f9c RD |
881 | return False |
882 | ||
883 | ||
02b800ce | 884 | def GetCurrentProject(self): |
26ee3a06 RD |
885 | projectService = wx.GetApp().GetService(ProjectEditor.ProjectService) |
886 | if projectService: | |
887 | projView = projectService.GetView() | |
02b800ce | 888 | return projView.GetSelectedProject() |
26ee3a06 RD |
889 | return None |
890 | ||
891 | ||
6f1a3f9c | 892 | def GetCurrentDocuments(self): |
6f1a3f9c RD |
893 | projectService = wx.GetApp().GetService(ProjectEditor.ProjectService) |
894 | if projectService: | |
895 | projView = projectService.GetView() | |
896 | ||
02b800ce | 897 | if projView.FilesHasFocus(): |
6f1a3f9c RD |
898 | filenames = projView.GetSelectedFiles() |
899 | if len(filenames): | |
900 | return filenames | |
901 | else: | |
902 | return None | |
903 | ||
904 | doc = wx.GetApp().GetTopWindow().GetDocumentManager().GetCurrentDocument() | |
905 | if doc: | |
906 | filenames = [doc.GetFilename()] | |
907 | else: | |
908 | filenames = None | |
909 | ||
910 | return filenames | |
911 | ||
912 | ||
02b800ce RD |
913 | def GetCurrentFolder(self): |
914 | projectService = wx.GetApp().GetService(ProjectEditor.ProjectService) | |
915 | if projectService: | |
916 | projView = projectService.GetView() | |
917 | ||
918 | if projView.FilesHasFocus(): | |
919 | folderPath = projView.GetSelectedPhysicalFolder() | |
920 | if folderPath: | |
921 | return folderPath | |
922 | ||
923 | return None | |
924 | ||
925 | ||
26ee3a06 RD |
926 | def BasenameCaseInsensitiveCompare(self, s1, s2): |
927 | s1L = os.path.basename(s1).lower() | |
928 | s2L = os.path.basename(s2).lower() | |
929 | if s1L == s2L: | |
930 | return 0 | |
931 | elif s1L < s2L: | |
932 | return -1 | |
933 | else: | |
934 | return 1 | |
935 | ||
936 | ||
6f1a3f9c RD |
937 | class SVNOptionsPanel(wx.Panel): |
938 | ||
939 | ||
940 | def __init__(self, parent, id): | |
941 | wx.Panel.__init__(self, parent, id) | |
942 | ||
943 | config = wx.ConfigBase_Get() | |
6f1a3f9c RD |
944 | configDir = config.Read(SVN_CONFIG_DIR, "") |
945 | ||
946 | borderSizer = wx.BoxSizer(wx.VERTICAL) | |
947 | sizer = wx.FlexGridSizer(cols = 2, hgap = 5, vgap = 5) | |
02b800ce | 948 | sizer.AddGrowableCol(1, 1) |
6f1a3f9c RD |
949 | |
950 | sizer.Add(wx.StaticText(self, -1, _("SVN Config Dir:")), 0, wx.ALIGN_CENTER_VERTICAL) | |
951 | ||
952 | self._svnConfigDir = wx.TextCtrl(self, -1, configDir, size = (200, -1)) | |
953 | if configDir == "": | |
954 | self._svnConfigDir.SetToolTipString(_("Path Subversion configuration directory.")) | |
955 | else: | |
956 | self._svnConfigDir.SetToolTipString(configDir) | |
957 | ||
958 | findDirButton = wx.Button(self, -1, _("Browse...")) | |
959 | ||
960 | def OnBrowseButton(event): | |
961 | dirDlg = wx.DirDialog(self, _("Choose a directory:"), style=wx.DD_DEFAULT_STYLE) | |
962 | dir = self._svnConfigDir.GetValue() | |
963 | if len(dir): | |
964 | dirDlg.SetPath(dir) | |
02b800ce | 965 | dirDlg.CenterOnParent() |
6f1a3f9c RD |
966 | if dirDlg.ShowModal() == wx.ID_OK: |
967 | self._svnConfigDir.SetValue(dirDlg.GetPath()) | |
968 | self._svnConfigDir.SetToolTipString(self._svnConfigDir.GetValue()) | |
969 | self._svnConfigDir.SetInsertionPointEnd() | |
6f1a3f9c RD |
970 | dirDlg.Destroy() |
971 | wx.EVT_BUTTON(findDirButton, -1, OnBrowseButton) | |
972 | ||
973 | hsizer = wx.BoxSizer(wx.HORIZONTAL) | |
974 | hsizer.Add(self._svnConfigDir, 1, wx.EXPAND) | |
975 | hsizer.Add(findDirButton, 0, wx.LEFT, HALF_SPACE) | |
02b800ce | 976 | sizer.Add(hsizer, 0, wx.EXPAND) |
6f1a3f9c | 977 | |
26ee3a06 RD |
978 | |
979 | svnUrlList = ReadSvnUrlList() | |
6f1a3f9c | 980 | sizer.Add(wx.StaticText(self, -1, _("SVN URL:")), 0, wx.ALIGN_CENTER_VERTICAL) |
26ee3a06 RD |
981 | self._svnURLCombobox = wx.ComboBox(self, -1, size=(200, -1), choices=svnUrlList, style=wx.CB_DROPDOWN) |
982 | if len(svnUrlList): | |
983 | self._svnURLCombobox.SetToolTipString(svnUrlList[0]) | |
984 | self._svnURLCombobox.SetStringSelection(svnUrlList[0]) | |
985 | else: | |
986 | self._svnURLCombobox.SetToolTipString(_("Set Repository URL")) | |
02b800ce | 987 | sizer.Add(self._svnURLCombobox, 0, wx.EXPAND) |
26ee3a06 RD |
988 | |
989 | ||
990 | sizer.Add(wx.StaticText(self, -1, _("SVN_SSH:")), 0, wx.ALIGN_CENTER_VERTICAL) | |
991 | svnSSH = os.getenv("SVN_SSH") | |
992 | if not svnSSH or svnSSH == "": | |
993 | self._svnSSH = wx.TextCtrl(self, -1, size = (200, -1)) | |
994 | else: | |
995 | self._svnSSH = wx.TextCtrl(self, -1, svnSSH, size = (200, -1)) | |
996 | self._svnSSH.SetToolTipString(_("Override SVN_SSH environment variable temporarily.")) | |
997 | ||
998 | findSSHButton = wx.Button(self, -1, _("Browse...")) | |
999 | ||
1000 | def OnBrowseFileButton(event): | |
1001 | dirDlg = wx.FileDialog(self, _("Choose a file:"), style=wx.OPEN|wx.CHANGE_DIR) | |
02b800ce | 1002 | # dirDlg.CenterOnParent() # wxBug: caused crash with wx.FileDialog |
26ee3a06 RD |
1003 | if dirDlg.ShowModal() == wx.ID_OK: |
1004 | self._svnSSH.SetValue(dirDlg.GetPath()) | |
1005 | self._svnSSH.SetToolTipString(self._svnSSH.GetValue()) | |
1006 | self._svnSSH.SetInsertionPointEnd() | |
1007 | dirDlg.Destroy() | |
1008 | wx.EVT_BUTTON(findSSHButton, -1, OnBrowseFileButton) | |
1009 | ||
1010 | hsizer = wx.BoxSizer(wx.HORIZONTAL) | |
1011 | hsizer.Add(self._svnSSH, 1, wx.EXPAND) | |
1012 | hsizer.Add(findSSHButton, 0, wx.LEFT, HALF_SPACE) | |
02b800ce | 1013 | sizer.Add(hsizer, 0, wx.EXPAND) |
26ee3a06 | 1014 | |
6f1a3f9c | 1015 | |
02b800ce | 1016 | borderSizer.Add(sizer, 0, wx.ALL|wx.EXPAND, SPACE) |
6f1a3f9c RD |
1017 | self.SetSizer(borderSizer) |
1018 | self.Layout() | |
1019 | parent.AddPage(self, _("SVN")) | |
1020 | ||
1021 | ||
02b800ce RD |
1022 | def GetIcon(self): |
1023 | return wx.NullIcon | |
1024 | ||
1025 | ||
6f1a3f9c RD |
1026 | def OnOK(self, optionsDialog): |
1027 | config = wx.ConfigBase_Get() | |
26ee3a06 | 1028 | |
6f1a3f9c | 1029 | config.Write(SVN_CONFIG_DIR, self._svnConfigDir.GetValue()) |
26ee3a06 RD |
1030 | |
1031 | WriteSvnUrlList(self._svnURLCombobox) | |
1032 | ||
1033 | os.environ["SVN_SSH"] = self._svnSSH.GetValue() | |
1034 | ||
1035 | ||
1036 | def ReadSvnUrlList(): | |
1037 | """ Read in list of SNV repository URLs. First in list is the last one path used. """ | |
1038 | config = wx.ConfigBase_Get() | |
1039 | urlStringList = config.Read(SVN_REPOSITORY_URL) | |
1040 | if len(urlStringList): | |
1041 | urlList = eval(urlStringList) | |
1042 | else: | |
1043 | urlList = [] | |
1044 | if len(urlList) == 0: | |
1045 | svnService = wx.GetApp().GetService(SVNService) | |
1046 | if svnService and hasattr(svnService, "_defaultURL"): | |
1047 | urlList.append(svnService._defaultURL) | |
1048 | return urlList | |
1049 | ||
1050 | ||
1051 | def WriteSvnUrlList(comboBox): | |
1052 | """ Save out list of SVN repository URLs from combobox. Put on top the current selection. Only save out first 10 from the list """ | |
1053 | urlList = [] | |
1054 | ||
1055 | url = comboBox.GetValue() | |
1056 | if len(url): | |
1057 | urlList.append(url) | |
1058 | ||
1059 | for i in range(min(comboBox.GetCount(), 10)): | |
1060 | url = comboBox.GetString(i) | |
1061 | if url not in urlList: | |
1062 | urlList.append(url) | |
1063 | ||
1064 | config = wx.ConfigBase_Get() | |
1065 | config.Write(SVN_REPOSITORY_URL, urlList.__repr__()) | |
1066 | ||
6f1a3f9c | 1067 |