VCS/ProjectHelper.py

changeset 0
de9c2efb9d02
child 12
1d8dd9706f46
equal deleted inserted replaced
-1:000000000000 0:de9c2efb9d02
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2005 - 2009 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing the base class of the VCS project helper.
8 """
9
10 import os
11 import sys
12 import shutil
13 import copy
14
15 from PyQt4.QtCore import *
16 from PyQt4.QtGui import *
17
18 from E4Gui.E4Application import e4App
19
20 import VCS
21 from CommandOptionsDialog import vcsCommandOptionsDialog
22 from RepositoryInfoDialog import VcsRepositoryInfoDialog
23
24 from E4Gui.E4Action import E4Action
25
26 import Utilities
27 import Preferences
28
29 class VcsProjectHelper(QObject):
30 """
31 Class implementing the base class of the VCS project helper.
32 """
33 def __init__(self, vcsObject, projectObject, parent = None, name = None):
34 """
35 Constructor
36
37 @param vcsObject reference to the vcs object
38 @param projectObject reference to the project object
39 @param parent parent widget (QWidget)
40 @param name name of this object (string)
41 """
42 QObject.__init__(self, parent)
43 if name:
44 self.setObjectName(name)
45
46 self.vcs = vcsObject
47 self.project = projectObject
48
49 self.actions = []
50
51 self.initActions()
52
53 def setObjects(self, vcsObject, projectObject):
54 """
55 Public method to set references to the vcs and project objects.
56
57 @param vcsObject reference to the vcs object
58 @param projectObject reference to the project object
59 """
60 self.vcs = vcsObject
61 self.project = projectObject
62
63 def initActions(self):
64 """
65 Public method to generate the action objects.
66 """
67 self.vcsNewAct = E4Action(self.trUtf8('New from repository'),
68 self.trUtf8('&New from repository...'), 0, 0, self, 'vcs_new')
69 self.vcsNewAct.setStatusTip(self.trUtf8(
70 'Create a new project from the VCS repository'
71 ))
72 self.vcsNewAct.setWhatsThis(self.trUtf8(
73 """<b>New from repository</b>"""
74 """<p>This creates a new local project from the VCS repository.</p>"""
75 ))
76 self.connect(self.vcsNewAct, SIGNAL('triggered()'), self._vcsCheckout)
77 self.actions.append(self.vcsNewAct)
78
79 self.vcsExportAct = E4Action(self.trUtf8('Export from repository'),
80 self.trUtf8('&Export from repository...'), 0, 0, self, 'vcs_export')
81 self.vcsExportAct.setStatusTip(self.trUtf8(
82 'Export a project from the repository'
83 ))
84 self.vcsExportAct.setWhatsThis(self.trUtf8(
85 """<b>Export from repository</b>"""
86 """<p>This exports a project from the repository.</p>"""
87 ))
88 self.connect(self.vcsExportAct, SIGNAL('triggered()'), self._vcsExport)
89 self.actions.append(self.vcsExportAct)
90
91 self.vcsAddAct = E4Action(self.trUtf8('Add to repository'),
92 self.trUtf8('&Add to repository...'), 0, 0, self, 'vcs_add')
93 self.vcsAddAct.setStatusTip(self.trUtf8(
94 'Add the local project to the VCS repository'
95 ))
96 self.vcsAddAct.setWhatsThis(self.trUtf8(
97 """<b>Add to repository</b>"""
98 """<p>This adds (imports) the local project to the VCS repository.</p>"""
99 ))
100 self.connect(self.vcsAddAct, SIGNAL('triggered()'), self._vcsImport)
101 self.actions.append(self.vcsAddAct)
102
103 def initMenu(self, menu):
104 """
105 Public method to generate the VCS menu.
106
107 @param menu reference to the menu to be populated (QMenu)
108 """
109 menu.clear()
110
111 menu.addAction(self.vcsNewAct)
112 menu.addAction(self.vcsExportAct)
113 menu.addSeparator()
114 menu.addAction(self.vcsAddAct)
115 menu.addSeparator()
116
117 def showMenu(self):
118 """
119 Public slot called before the vcs menu is shown.
120 """
121 self.vcsAddAct.setEnabled(self.project.isOpen())
122
123 def _vcsCheckout(self, export = False):
124 """
125 Protected slot used to create a local project from the repository.
126
127 @param export flag indicating whether an export or a checkout
128 should be performed
129 """
130 if not self.project.checkDirty():
131 return
132
133 vcsSystemsDict = e4App().getObject("PluginManager")\
134 .getPluginDisplayStrings("version_control")
135 vcsSystemsDisplay = []
136 keys = sorted(vcsSystemsDict.keys())
137 for key in keys:
138 vcsSystemsDisplay.append(vcsSystemsDict[key])
139 vcsSelected, ok = QInputDialog.getItem(\
140 None,
141 self.trUtf8("New Project"),
142 self.trUtf8("Select version control system for the project"),
143 vcsSystemsDisplay,
144 0, False)
145 if not ok:
146 return
147 for vcsSystem, vcsSystemDisplay in vcsSystemsDict.items():
148 if vcsSystemDisplay == vcsSelected:
149 break
150
151 self.project.pdata["VCS"] = [vcsSystem]
152 self.project.vcs = self.project.initVCS(vcsSystem)
153 if self.project.vcs is not None:
154 vcsdlg = self.project.vcs.vcsNewProjectOptionsDialog()
155 if vcsdlg.exec_() == QDialog.Accepted:
156 self.project.closeProject()
157 projectdir, vcsDataDict = vcsdlg.getData()
158 self.project.pdata["VCS"] = [vcsSystem]
159 self.project.vcs = self.project.initVCS(vcsSystem)
160 # edit VCS command options
161 vcores = QMessageBox.question(None,
162 self.trUtf8("New Project"),
163 self.trUtf8("""Would you like to edit the VCS command options?"""),
164 QMessageBox.StandardButtons(\
165 QMessageBox.No | \
166 QMessageBox.Yes),
167 QMessageBox.No)
168 if vcores == QMessageBox.Yes:
169 codlg = vcsCommandOptionsDialog(self.project.vcs)
170 if codlg.exec_() == QDialog.Accepted:
171 self.project.vcs.vcsSetOptions(codlg.getOptions())
172
173 # create the project directory if it doesn't exist already
174 if not os.path.isdir(projectdir):
175 try:
176 os.makedirs(projectdir)
177 except EnvironmentError:
178 QMessageBox.critical(None,
179 self.trUtf8("Create project directory"),
180 self.trUtf8("<p>The project directory <b>{0}</b> could not"
181 " be created.</p>").format(projectdir))
182 self.project.pdata["VCS"] = ['None']
183 self.project.vcs = self.project.initVCS()
184 return
185
186 # create the project from the VCS
187 self.project.vcs.vcsSetDataFromDict(vcsDataDict)
188 if export:
189 ok = self.project.vcs.vcsExport(vcsDataDict, projectdir)
190 else:
191 ok = self.project.vcs.vcsCheckout(vcsDataDict, projectdir, False)
192 if ok:
193 projectdir = os.path.normpath(projectdir)
194 filters = ["*.e4p", "*.e4pz", "*.e3p", "*.e3pz"]
195 d = QDir(projectdir)
196 plist = d.entryInfoList(filters)
197 if len(plist):
198 if len(plist) == 1:
199 self.project.openProject(plist[0].absoluteFilePath())
200 self.project.emit(SIGNAL('newProject'))
201 else:
202 pfilenamelist = d.entryList(filters)
203 pfilename, ok = QInputDialog.getItem(
204 None,
205 self.trUtf8("New project from repository"),
206 self.trUtf8("Select a project file to open."),
207 pfilenamelist, 0, False)
208 if ok:
209 self.project.openProject(\
210 QFileInfo(d, pfilename).absoluteFilePath())
211 self.project.emit(SIGNAL('newProject'))
212 if export:
213 self.project.pdata["VCS"] = ['None']
214 self.project.vcs = self.project.initVCS()
215 self.project.setDirty(True)
216 self.project.saveProject()
217 else:
218 res = QMessageBox.question(None,
219 self.trUtf8("New project from repository"),
220 self.trUtf8("The project retrieved from the repository"
221 " does not contain an eric project file"
222 " (*.e4p *.e4pz *.e3p *.e3pz)."
223 " Create it?"),
224 QMessageBox.StandardButtons(\
225 QMessageBox.No | \
226 QMessageBox.Yes),
227 QMessageBox.Yes)
228 if res == QMessageBox.Yes:
229 self.project.ppath = projectdir
230 self.project.opened = True
231
232 from Project.PropertiesDialog import PropertiesDialog
233 dlg = PropertiesDialog(self.project, False)
234 if dlg.exec_() == QDialog.Accepted:
235 dlg.storeData()
236 self.project.initFileTypes()
237 self.project.setDirty(True)
238 try:
239 ms = os.path.join(self.project.ppath,
240 self.project.pdata["MAINSCRIPT"][0])
241 if os.path.exists(ms):
242 self.project.appendFile(ms)
243 except IndexError:
244 ms = ""
245 self.project.newProjectAddFiles(ms)
246 self.project.saveProject()
247 self.project.openProject(self.project.pfile)
248 if not export:
249 res = QMessageBox.question(None,
250 self.trUtf8("New project from repository"),
251 self.trUtf8("Shall the project file be added to"
252 " the repository?"),
253 QMessageBox.StandardButtons(\
254 QMessageBox.No | \
255 QMessageBox.Yes),
256 QMessageBox.Yes)
257 if res == QMessageBox.Yes:
258 self.project.vcs.vcsAdd(self.project.pfile)
259 else:
260 QMessageBox.critical(None,
261 self.trUtf8("New project from repository"),
262 self.trUtf8("""The project could not be retrieved from"""
263 """ the repository."""))
264 self.project.pdata["VCS"] = ['None']
265 self.project.vcs = self.project.initVCS()
266 else:
267 self.project.pdata["VCS"] = ['None']
268 self.project.vcs = self.project.initVCS()
269
270 def _vcsExport(self):
271 """
272 Protected slot used to export a project from the repository.
273 """
274 self._vcsCheckout(True)
275
276 def _vcsImport(self):
277 """
278 Protected slot used to import the local project into the repository.
279
280 <b>NOTE</b>:
281 This does not necessarily make the local project a vcs controlled
282 project. You may have to checkout the project from the repository in
283 order to accomplish that.
284 """
285 def revertChanges():
286 """
287 Local function to revert the changes made to the project object.
288 """
289 self.project.pdata["VCS"] = pdata_vcs[:]
290 self.project.pdata["VCSOPTIONS"] = copy.deepcopy(pdata_vcsoptions)
291 self.project.pdata["VCSOTHERDATA"] = copy.deepcopy(pdata_vcsother)
292 self.project.vcs = vcs
293 self.project.vcsProjectHelper = vcsHelper
294 self.project.vcsBasicHelper = vcs is None
295 self.initMenu(self.project.vcsMenu)
296 self.project.setDirty(True)
297 self.project.saveProject()
298
299 pdata_vcs = self.project.pdata["VCS"][:]
300 pdata_vcsoptions = copy.deepcopy(self.project.pdata["VCSOPTIONS"])
301 pdata_vcsother = copy.deepcopy(self.project.pdata["VCSOTHERDATA"])
302 vcs = self.project.vcs
303 vcsHelper = self.project.vcsProjectHelper
304 vcsSystemsDict = e4App().getObject("PluginManager")\
305 .getPluginDisplayStrings("version_control")
306 vcsSystemsDisplay = []
307 keys = vcsSystemsDict.keys()
308 keys.sort()
309 for key in keys:
310 vcsSystemsDisplay.append(vcsSystemsDict[key])
311 vcsSelected, ok = QInputDialog.getItem(\
312 None,
313 self.trUtf8("Import Project"),
314 self.trUtf8("Select version control system for the project"),
315 vcsSystemsDisplay,
316 0, False)
317 if not ok:
318 return
319 for vcsSystem, vcsSystemDisplay in vcsSystemsDict.items():
320 if vcsSystemDisplay == vcsSelected:
321 break
322
323 self.project.pdata["VCS"] = [vcsSystem]
324 self.project.vcs = self.project.initVCS(vcsSystem)
325 if self.project.vcs is not None:
326 vcsdlg = self.project.vcs.vcsOptionsDialog(self.project, self.project.name, 1)
327 if vcsdlg.exec_() == QDialog.Accepted:
328 vcsDataDict = vcsdlg.getData()
329 # edit VCS command options
330 vcores = QMessageBox.question(None,
331 self.trUtf8("Import Project"),
332 self.trUtf8("""Would you like to edit the VCS command options?"""),
333 QMessageBox.StandardButtons(\
334 QMessageBox.No | \
335 QMessageBox.Yes),
336 QMessageBox.No)
337 if vcores == QMessageBox.Yes:
338 codlg = vcsCommandOptionsDialog(self.project.vcs)
339 if codlg.exec_() == QDialog.Accepted:
340 self.project.vcs.vcsSetOptions(codlg.getOptions())
341 self.project.setDirty(True)
342 self.project.vcs.vcsSetDataFromDict(vcsDataDict)
343 self.project.saveProject()
344 isVcsControlled = \
345 self.project.vcs.vcsImport(vcsDataDict, self.project.ppath)[1]
346 if isVcsControlled:
347 # reopen the project
348 self.project.openProject(self.project.pfile)
349 else:
350 # revert the changes to the local project
351 # because the project dir is not a VCS directory
352 revertChanges()
353 else:
354 # revert the changes because user cancelled
355 revertChanges()
356
357 def _vcsUpdate(self):
358 """
359 Protected slot used to update the local project from the repository.
360 """
361 shouldReopen = self.vcs.vcsUpdate(self.project.ppath)
362 if shouldReopen:
363 res = QMessageBox.information(None,
364 self.trUtf8("Update"),
365 self.trUtf8("""The project should be reread. Do this now?"""),
366 QMessageBox.StandardButtons(\
367 QMessageBox.No | \
368 QMessageBox.Yes),
369 QMessageBox.Yes)
370 if res == QMessageBox.Yes:
371 self.project.reopenProject()
372
373 def _vcsCommit(self):
374 """
375 Protected slot used to commit changes to the local project to the repository.
376 """
377 if Preferences.getVCS("AutoSaveProject"):
378 self.project.saveProject()
379 if Preferences.getVCS("AutoSaveFiles"):
380 self.project.saveAllScripts()
381 self.vcs.vcsCommit(self.project.ppath, '')
382
383 def _vcsRemove(self):
384 """
385 Protected slot used to remove the local project from the repository.
386
387 Depending on the parameters set in the vcs object the project
388 may be removed from the local disk as well.
389 """
390 res = QMessageBox.warning(None,
391 self.trUtf8("Remove project from repository"),
392 self.trUtf8("Dou you really want to remove this project from"
393 " the repository (and disk)?"),
394 QMessageBox.StandardButtons(\
395 QMessageBox.No | \
396 QMessageBox.Yes),
397 QMessageBox.No)
398 if res == QMessageBox.Yes:
399 self.vcs.vcsRemove(self.project.ppath, True)
400 self._vcsCommit()
401 if not os.path.exists(self.project.pfile):
402 ppath = self.project.ppath
403 self.setDirty(False)
404 self.project.closeProject()
405 shutil.rmtree(ppath, True)
406
407 def _vcsCommandOptions(self):
408 """
409 Protected slot to edit the VCS command options.
410 """
411 codlg = vcsCommandOptionsDialog(self.vcs)
412 if codlg.exec_() == QDialog.Accepted:
413 self.vcs.vcsSetOptions(codlg.getOptions())
414 self.project.setDirty(True)
415
416 def _vcsLog(self):
417 """
418 Protected slot used to show the log of the local project.
419 """
420 self.vcs.vcsLog(self.project.ppath)
421
422 def _vcsDiff(self):
423 """
424 Protected slot used to show the difference of the local project to the repository.
425 """
426 self.vcs.vcsDiff(self.project.ppath)
427
428 def _vcsStatus(self):
429 """
430 Protected slot used to show the status of the local project.
431 """
432 self.vcs.vcsStatus(self.project.ppath)
433
434 def _vcsTag(self):
435 """
436 Protected slot used to tag the local project in the repository.
437 """
438 self.vcs.vcsTag(self.project.ppath)
439
440 def _vcsRevert(self):
441 """
442 Protected slot used to revert changes made to the local project.
443 """
444 self.vcs.vcsRevert(self.project.ppath)
445
446 def _vcsSwitch(self):
447 """
448 Protected slot used to switch the local project to another tag/branch.
449 """
450 self.vcs.vcsSwitch(self.project.ppath)
451
452 def _vcsMerge(self):
453 """
454 Protected slot used to merge changes of a tag/revision into the local project.
455 """
456 self.vcs.vcsMerge(self.project.ppath)
457
458 def _vcsCleanup(self):
459 """
460 Protected slot used to cleanup the local project.
461 """
462 self.vcs.vcsCleanup(self.project.ppath)
463
464 def _vcsCommand(self):
465 """
466 Protected slot used to execute an arbitrary vcs command.
467 """
468 self.vcs.vcsCommandLine(self.project.ppath)
469
470 def _vcsInfoDisplay(self):
471 """
472 Protected slot called to show some vcs information.
473 """
474 info = self.vcs.vcsRepositoryInfos(self.project.ppath)
475 dlg = VcsRepositoryInfoDialog(None, info)
476 dlg.exec_()

eric ide

mercurial