Source code for openalea.oalab.project.manager
# -*- python -*-
#
# OpenAlea.OALab: Multi-Paradigm GUI
#
# Copyright 2013 INRIA - CIRAD - INRA
#
# File author(s): Julien Coste <julien.coste@inria.fr>
#
# File contributor(s):
#
# Distributed under the Cecill-C License.
# See accompanying file LICENSE.txt or copy at
# http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.html
#
# OpenAlea WebSite : http://openalea.gforge.inria.fr
#
###############################################################################
__revision__ = "$Id: "
from openalea.vpltk.qt import QtGui, QtCore
from openalea.core.path import path
from openalea.core import settings
from openalea.core import logger
from openalea.vpltk.project.manager import ProjectManager
from openalea.oalab.project.creator import CreateProjectWidget
[docs]class ProjectManagerWidget(QtGui.QWidget):
"""
Object which permit to manage projects.
:Warning: this QWidget is not used like a widget but like the interface between GUI (buttons "newProj", "newScript",...)
and objects (project, control, ...)
:TODO: Refactor it
"""
def __init__(self, session, controller, parent=None):
super(ProjectManagerWidget, self).__init__(parent)
self._actions = []
self.paradigms_actions = []
self.session = session
self.controller = controller
self.setAccessibleName("Project Manager")
self.projectManager = ProjectManager()
for proj in self.projectManager.projects:
self.session._project = proj
self.actionEditFile = QtGui.QAction(QtGui.QIcon(":/images/resources/edit.png"), "Edit file", self)
self.actionImportFile = QtGui.QAction(QtGui.QIcon(":/images/resources/import.png"), "Import", self)
self.actionNewProj = QtGui.QAction(QtGui.QIcon(":/images/resources/new.png"), "New", self)
self.actionNewProj.setShortcut(
QtGui.QApplication.translate("MainWindow", "Ctrl+N", None, QtGui.QApplication.UnicodeUTF8))
self.actionOpenProj = QtGui.QAction(QtGui.QIcon(":/images/resources/open.png"), "Open", self)
self.actionOpenProj.setShortcut(
QtGui.QApplication.translate("MainWindow", "Ctrl+O", None, QtGui.QApplication.UnicodeUTF8))
self.actionSaveProj = QtGui.QAction(QtGui.QIcon(":/images/resources/save.png"), "Save", self)
self.actionSaveProjAs = QtGui.QAction(QtGui.QIcon(":/images/resources/save.png"), "Save As", self)
# self.actionSaveProj.setShortcut(QtGui.QApplication.translate("MainWindow", "Ctrl+S", None, QtGui.QApplication.UnicodeUTF8))
self.actionCloseProj = QtGui.QAction(QtGui.QIcon(":/images/resources/closeButton.png"), "Close All", self)
self.connect(self.actionNewProj, QtCore.SIGNAL('triggered(bool)'), self.new)
self.connect(self.actionOpenProj, QtCore.SIGNAL('triggered(bool)'), self.open)
self.connect(self.actionSaveProjAs, QtCore.SIGNAL('triggered(bool)'), self.saveAs)
self.connect(self.actionSaveProj, QtCore.SIGNAL('triggered(bool)'), self.saveCurrent)
self.connect(self.actionCloseProj, QtCore.SIGNAL('triggered(bool)'), self.closeCurrent)
self.connect(self.actionImportFile, QtCore.SIGNAL('triggered(bool)'), self.importFile)
self.connect(self.actionEditFile, QtCore.SIGNAL('triggered(bool)'), self.editFile)
self._actions = [["Project", "Manage Project", self.actionNewProj, 1],
["Project", "Manage Project", self.actionOpenProj, 0],
["Project", "Manage Project", self.actionSaveProj, 0],
["Project", "Manage Project", self.actionSaveProjAs, 1],
["Project", "Manage Project", self.actionCloseProj, 1],
# ["Model", "New Model", self.actionEditFile, 0],
["Model", "New Model", self.actionImportFile, 0]]
self.extensions = ""
self.connectParadigmContainer()
self.defaultProj()
[docs] def connectParadigmContainer(self):
# Connect actions from applet_container.paradigms to menu (newPython, newLpy,...)
for applet in self.controller.applet_container.paradigms.values():
action = QtGui.QAction(QtGui.QIcon(applet.icon), applet.default_name, self)
action.triggered.connect(self.newModel)
self._actions.append(["Model", "New Model", action, 0],)
self.paradigms_actions.append(action)
self.extensions = self.extensions + applet.pattern + " "
[docs] def defaultProj(self):
proj = self.projectManager.load_default()
self.session._project = proj
self.session._is_proj = True
if not self.session.project.src:
txt = '''# -*- coding: utf-8 -*-
"""
OpenAlea Lab editor
This temporary script is saved in temporary project in
%s
You can rename/move this project thanks to the button "Save As" in menu.
"""''' % str(self.session.project.path / self.session.project.name)
self.session.project.add(category="src", name=".temp.py", value=txt)
self._project_changed()
self._load_control()
[docs] def open(self, name=False, project_path=None):
"""
If name==false, display a widget to choose project to open.
Then open project.
"""
self.closeCurrent()
# self.controller.applet_container.closeAll()
"""
if name is False:
name = showOpenProjectDialog()
if name:
proj_path = path(name).abspath()
proj_name = proj_path.basename()
proj_path = proj_path.dirname()
if project_path:
proj_path = path(project_path)
logger.debug("Open Project named " + proj_name)
if self.session.project is not None:
if self.session.current_is_project():
logger.debug("Close Project named " + self.session.project.name)
self.projectManager.close(self.session.project.name)
logger.debug("Project named " + self.session.project.name + " closed.")
proj = self.projectManager.load(proj_name, proj_path)
logger.debug("Project " + str(proj) + " loaded")
if proj == -1:
logger.warning("Project was not loaded...")
return -1
else:
return self.openProject(proj)"""
[docs] def openProject(self, project):
"""
Open a project in application from project
:param project: project from vpltk
"""
project.start()
logger.debug("Project " + str(project) + " opened")
project.scene = self.session.scene
self.session._project = project
self.session._is_proj = True
self._project_changed()
self._load_control()
logger.debug("Project opened: " + str(self.session._project))
return self.session._project
[docs] def editFile(self, filename=None, extension=None):
"""
Permit to edit a file which is outside project.
And add link to file in project.
"""
if extension is None:
extension = self.extensions
if self.session.current_is_project():
project = self.session.project
if not filename:
if extension:
filename = showOpenFileDialog(extension)
else:
filename = showOpenFileDialog()
if filename:
filename = path(filename).abspath()
f = open(filename, "r")
txt = f.read()
f.close()
tab_name = str(path(filename).splitpath()[-1])
ext = str(path(filename).splitext()[-1])
ext = ext.split(".")[-1]
logger.debug("Try to import file named " + tab_name + " . With applet_type " + ext)
try:
self.controller.applet_container.newTab(applet_type=ext, tab_name=tab_name, script=txt)
project.add("src", filename, txt)
self.controller._update_locals()
self._tree_view_change()
logger.debug("Import file named " + tab_name)
except:
print "File extension " + ext + " not recognised"
logger.warning("Can't import file named %s in current project. Unknow extension." % filename)
else:
print "You are not working inside project. Please create or load one first."
[docs] def importFile(self, filename=None, extension=None):
"""
Import a file and add it to the project.
:param filename: name of file to add in project
:param extension:
"""
if extension is None:
extension = self.extensions
if self.session.current_is_project():
project = self.session.project
if not filename:
filename = showOpenFileDialog(extension)
if filename:
filename = path(filename)
f = open(filename, "r")
txt = f.read()
f.close()
name = filename.splitpath()[1]
project.add("src", name, txt)
self.controller._update_locals()
self._project_changed()
logger.debug("Import file named " + name)
else:
print "You are not working inside project. Please create or load one first."
[docs] def new(self):
"""
Create an default empty project with a default name.
Open a window to define metadata of the project.
"""
self.project_creator = CreateProjectWidget()
self.project_creator.show()
self.connect(self.project_creator, QtCore.SIGNAL('ProjectOpened(PyQt_PyObject)'), self.openProject)
[docs] def newModel(self, applet_type=None, tab_name=None, script=""):
"""
Create a new model of type 'applet_type
:param applet_type: type of applet to add. Can be Workflow, LSystem, Python, R
"""
if self.session.current_is_project():
if not applet_type:
button = self.sender()
applet_type = button.text() # can be Workflow, LSystem, Python, R
# TODO: this approach is not reliable. If a developer change action name, it breaks the system
# a better approach should be to define a "newModel" method in IApplet and call it directly
# for instance in __init__ : action.triggered.connect(applet.newModel)
Applet = self.controller.applet_container.paradigms[applet_type]
if not tab_name:
tab_name = Applet.default_file_name
self.controller.applet_container.newTab(applet_type=applet_type, tab_name=tab_name, script=script)
text = self.controller.applet_container.applets[-1].widget().get_text()
self.session.project.add("src", tab_name, text)
self.controller._update_locals()
self._project_changed()
else:
print "You are not working inside project. Please create or load one first."
[docs] def removeModel(self, model_name):
"""
:param model_name: Name of the model to remove in the current project
"""
if self.session.current_is_project():
self.session.project.remove("src", model_name)
self._project_changed()
else:
print "You are not working inside project. Please create or load one first."
[docs] def openModel(self, fname=None, extension="*.*"):
""""
Open a (script-type) file named "fname".
If "fname"==None, display a dialog with filter "extension".
:param fname: filename to open. Default = None
:param extension: extension of file to open. Default = "*.*"
"""
if self.session.current_is_project():
self.importFile(filename=fname, extension=extension)
self._project_changed()
else:
print "You are not working inside project. Please create or load one first."
[docs] def renameCurrent(self, new_name=None):
"""
Rename current project.
"""
if self.session.current_is_project():
name = self.session.project.name
if not new_name:
new_name = showNewProjectDialog(default_name=path(name) / "..",
text='Select new name to save project')
self.session.project.rename(category="project", old_name=name, new_name=new_name)
self._project_changed()
else:
print(
"You are not working inside project, so you can't use 'rename project'. Please create or load one first.")
[docs] def saveAs(self):
"""
Save current project but permit to rename and move it..
"""
if self.session.current_is_project():
name = showNewProjectDialog(default_name=None, text="Select name to save project")
if name:
self.session.project.rename(category="project", old_name=self.session.project.name, new_name=name)
self._tree_view_change()
self.saveCurrent()
else:
print "You are not working inside project. Please create or load one first."
[docs] def saveCurrent(self):
"""
Save current project.
"""
if self.session.current_is_project():
container = self.controller.applet_container
for i in range(container.count()):
container.setCurrentIndex(i)
name = container.tabText(i)
container.widget(i).save(name)
self._update_control()
self.session.project.save()
self._project_changed()
else:
print "You are not working inside project. Please create or load one first."
[docs] def closeCurrent(self):
"""
Close current project.
"""
if self.session.current_is_project():
logger.debug("Close Project named %s" % self.session.project.name)
self.projectManager.close(self.session.project.name)
self.session._project = None
self.session._is_proj = False
self._clear_control()
self.controller.applet_container.closeAll()
self._project_changed()
else:
print "You are not working inside project. Please create or load one first."
def _project_changed(self):
"""
Update what is needed when the current project is changed
"""
logger.debug("Project changed")
self.controller._update_locals()
self._scene_change()
self._control_change() # do nothing
self._script_change()
self._tree_view_change()
def _load_control(self):
"""
Get control from project and put them into widgets
"""
if self.controller.applets.has_key('ControlPanel'):
logger.debug("Load Controls")
self.controller.applets['ControlPanel'].load()
def _update_control(self):
"""
Get control from widget and put them into project
"""
if self.controller.applets.has_key('ControlPanel'):
logger.debug("Update Controls")
self.controller.applets['ControlPanel'].update()
def _clear_control(self):
if self.controller.applets.has_key('ControlPanel'):
logger.debug("Clear Controls")
self.controller.applets['ControlPanel'].clear()
def _control_change(self):
pass
def _tree_view_change(self):
logger.debug("Tree View changed")
self.controller.applets['Project'].update()
def _script_change(self):
logger.debug("Script changed")
if self.session.current_is_project():
project = self.session.project
self.controller.applet_container.reset()
for script in project.src:
language = str(script).split('.')[-1]
self.controller.applet_container.openTab(language, script, project.src[script])
def _scene_change(self):
logger.debug("Scene changed")
if self.session.current_is_project():
self.session.scene.reset()
project = self.session.project
for w in project.scene:
self.session.scene.add(name=w, obj=project.scene[w])
[docs]def showNewProjectDialog(default_name=None, text=None, parent=None):
my_path = path(settings.get_project_dir())
if default_name:
my_path = my_path / default_name
if not text:
text = 'Select name to create project'
fname = QtGui.QFileDialog.getSaveFileName(parent, text,
my_path)
return fname
[docs]def showOpenProjectDialog(parent=None):
my_path = path(settings.get_project_dir())
fname = QtGui.QFileDialog.getExistingDirectory(parent, 'Select Project Directory',
my_path)
return fname
[docs]def showOpenFileDialog(extension=None, where=None, parent=None):
if extension is None:
extension = self.extensions
if where is not None:
my_path = path(str(where)).abspath().splitpath()[0]
else:
my_path = path(settings.get_project_dir())
logger.debug("Search to open file with extension " + extension + " from " + my_path)
fname = QtGui.QFileDialog.getOpenFileName(parent, 'Select File to open',
my_path, "All (*);;Scripts Files (%s)" % extension)
return fname