# -*- python -*-
#
# OpenAlea.Visualea: OpenAlea graphical user interface
#
# Copyright 2006-2009 INRIA - CIRAD - INRA
#
# File author(s): Samuel Dufour-Kowalski <samuel.dufour@sophia.inria.fr>
# Christophe Pradal <christophe.prada@cirad.fr>
#
# Distributed under the CeCILL v2 License.
# See accompanying file LICENSE.txt or copy at
# http://www.cecill.info/licences/Licence_CeCILL_V2-en.html
#
# OpenAlea WebSite : http://openalea.gforge.inria.fr
#
################################################################################
"""QT4 Main window"""
__license__ = "CeCILL v2"
__revision__ = " $Id$ "
from openalea.vpltk.qt import qt
from openalea.vpltk.qt.designer import generate_pyfile_from_uifile, get_data
src = get_data("openalea.visualea.mainwindow", "resources") / 'mainwindow.ui'
dest = get_data("openalea.visualea.mainwindow", "ui_mainwindow.py")
generate_pyfile_from_uifile(__name__, src=src, dest=dest)
import ui_mainwindow
try:
from openalea.oalab.shell import get_shell_class
from openalea.core.service.ipython import interpreter as get_interpreter
except ImportError:
from openalea.vpltk.shell.shell import get_shell_class, get_interpreter_class
from openalea.core.algo.dataflow_evaluation import AbstractEvaluation
from openalea.core import cli, logger
from openalea.core.pkgmanager import PackageManager
from openalea.core.settings import Settings, NoSectionError, NoOptionError
from openalea.core.node import NodeFactory
from openalea.core.compositenode import CompositeNodeFactory
from openalea.visualea.node_treeview import NodeFactoryView, NodeFactoryTreeView, PkgModel, CategoryModel
from openalea.visualea.node_treeview import DataPoolListView, DataPoolModel
from openalea.visualea.node_treeview import SearchListView, SearchModel
from openalea.visualea.node_widget import SignalSlotListener
import metainfo
from openalea.visualea import helpwidget
from openalea import misc
from os.path import join as pj
from openalea.visualea.dialogs import NewGraph, NewPackage
from openalea.visualea.dialogs import PreferencesDialog, NewData
from openalea.visualea import dataflowview
from openalea.visualea.logger import LoggerView
from graph_operator import GraphOperator
from graph_operator.vertex import VertexOperators
import traceback
PROVENANCE = False
[docs]class MainWindow(qt.QtGui.QMainWindow,
ui_mainwindow.Ui_MainWindow,
SignalSlotListener):
def __init__(self, session, parent=None):
"""
@param session : user session
@param parent : parent window
"""
qt.QtGui.QMainWindow.__init__(self, parent)
SignalSlotListener.__init__(self)
ui_mainwindow.Ui_MainWindow.__init__(self)
self.setupUi(self)
self.setAcceptDrops(True)
self.setAttribute(qt.QtCore.Qt.WA_QuitOnClose)
self.tabWorkspace.removeTab(0)
self.tabWorkspace.setTabsClosable(True)
self.ws_cpt = 0
if hasattr(AbstractEvaluation, "__provenance__"):
self._prov = AbstractEvaluation.__provenance__
else:
self._prov = False
#last opened nodes
self._last_opened = []
#lower tab pane : python shell, logger...
self.lowerpane = qt.QtGui.QTabWidget()
self.splitter.addWidget(self.lowerpane)
# python interpreter
try:
interpreter = get_interpreter()
except NameError:
InterpreterClass = get_interpreter_class()
interpreter = InterpreterClass()
# interpreter init defered after session init
shellclass = get_shell_class()
self.interpreterWidget = shellclass(interpreter,
cli.get_welcome_msg())
GraphOperator.globalInterpreter = interpreter
self.lowerpane.addTab(self.interpreterWidget, "Python Shell")
if logger.QT_LOGGING_MODEL_AVAILABLE:
# openalea logger
model = logger.LoggerOffice().get_handler("qt")
view = LoggerView(parent=self.lowerpane, model=model)
self.lowerpane.addTab(view, "Logging")
# search list view
self.search_model = SearchModel()
self.searchListView = \
SearchListView(self, self.searchview)
self.searchListView.setModel(self.search_model)
self.vboxlayout3.addWidget(self.searchListView)
self.searchListView.clicked.connect(self.on_package_manager_focus_change)
# help widget
self.helpWidget = helpwidget.HelpWidget()
css = pj(misc.__path__[0], "..", "..", "..",
"share", "_static", "openalea.css")
self.helpWidget.set_stylesheet_file(css)
self.poolTabWidget.addTab(self.helpWidget, "Help")
# Widgets
self.connect(self.tabWorkspace, qt.QtCore.SIGNAL("contextMenuEvent(QContextMenuEvent)"),
self.contextMenuEvent)
self.tabWorkspace.currentChanged.connect(self.ws_changed)
self.search_lineEdit.editingFinished.connect(self.search_node)
self.tabWorkspace.tabCloseRequested.connect(self.close_tab_workspace)
# Help Menu
self.action_About.triggered.connect(self.about)
self.actionOpenAlea_Web.triggered.connect(self.web)
self.action_Help.triggered.connect(self.help)
# File Menu
self.action_New_Session.triggered.connect(self.new_session)
self.action_Open_Session.triggered.connect(self.open_session)
self.action_Save_Session.triggered.connect(self.save_session)
self.actionSave_as.triggered.connect(self.save_as)
self.action_Quit.triggered.connect(self.quit)
self.action_Image.triggered.connect(self.export_image)
self.action_Svg.triggered.connect(self.export_image_svg)
# Package Manager Menu
self.action_Auto_Search.triggered.connect(self.reload_all)
self.action_Add_File.triggered.connect(self.add_pkgdir)
self.actionFind_Node.triggered.connect(self.find_node)
self.action_New_Network.triggered.connect(self.new_graph)
self.actionNew_Python_Node.triggered.connect(self.new_python_node)
self.actionNew_Package.triggered.connect(self.new_package)
self.action_Data_File.triggered.connect(self.new_data)
# DataPool Menu
self.actionClear_Data_Pool.triggered.connect(self.clear_data_pool)
# Python Menu
self.action_Execute_script.triggered.connect(
self.exec_python_script)
self.actionOpen_Console.triggered.connect(
self.open_python_console)
self.actionClea_r_Console.triggered.connect(
self.clear_python_console)
# WorkspaceMenu
self.__operatorAction = dict([(self.action_Run, "graph_run"),
(self.actionInvalidate, "graph_invalidate"),
(self.actionReset, "graph_reset"),
(self.actionConfigure_I_O, "graph_configure_io"),
(self.actionGroup_Selection, "graph_group_selection"),
(self.action_Copy, "graph_copy"),
(self.action_Paste, "graph_paste"),
(self.action_Cut, "graph_cut"),
(self.action_Delete_2, "graph_remove_selection"),
(self.action_Close_current_workspace, "graph_close"),
(self.action_Export_to_Factory, "graph_export_to_factory"),
(self.actionReload_from_Model, "graph_reload_from_factory"),
(self.actionExport_to_Application, "graph_export_application"),
(self.actionPreview_Application, "graph_preview_application"),
(self.actionAlignHorizontally, "graph_align_selection_horizontal"),
(self.actionAlignLeft, "graph_align_selection_left"),
(self.actionAlignRight, "graph_align_selection_right"),
(self.actionAlignMean, "graph_align_selection_mean"),
(self.actionDistributeHorizontally, "graph_distribute_selection_horizontally"),
(self.actionDistributeVertically, "graph_distribute_selection_vertically"),
(self.actionSetCustomColor, "graph_set_selection_color"),
(self.actionUseCustomColor, "graph_use_user_color")])
self._last_open_action_group = qt.QtGui.QActionGroup(self)
self.connect(self._last_open_action_group,
qt.QtCore.SIGNAL("triggered(QAction*)"),
self.reopen_last)
self.action_New_Empty_Workspace.triggered.connect(self.new_workspace)
self.menu_Workspace.aboutToShow.connect(self.__wsMenuShow)
self.menu_Workspace.aboutToShow.connect(self.__wsMenuHide)
for ac, fname in self.__operatorAction.iteritems():
f = self.__make_operator_action_connector(ac, fname)
ac.triggered.connect(f)
self.actionTo_script.triggered.connect(self.to_python_script)
# Window Mneu
self.actionPreferences.triggered.connect(self.open_preferences)
self.actionDisplay_Package_Manager.toggled.connect(self.display_leftpanel)
self.actionDisplay_Workspaces.toggled.connect(self.display_rightpanel)
#load personnal GUI settings
self.read_settings()
#############
# Provenance
#############
if PROVENANCE:
self.menu_provenance = qt.QtGui.QMenu(self.menubar)
self.menu_provenance.setObjectName("menu_provenance")
self.menu_provenance.setTitle(qt.QtGui.QApplication.translate("MainWindow", "&Provenance", None, qt.QtGui.QApplication.UnicodeUTF8))
self.action_activ_prov = qt.QtGui.QAction(self)
self.action_activ_prov.setCheckable(True)
prov = self.get_provenance()
self.action_activ_prov.setChecked(prov)
self.action_activ_prov.setObjectName("action_activ_prov")
self.action_activ_prov.setText(qt.QtGui.QApplication.translate("MainWindow", "Connect/Disconnect Provenance", None, qt.QtGui.QApplication.UnicodeUTF8))
self.action_show_prov = qt.QtGui.QAction(self)
self.action_show_prov.setCheckable(False)
self.action_show_prov.setObjectName("action_show_prov")
self.action_show_prov.setText(qt.QtGui.QApplication.translate("MainWindow", "Show Provenance", None, qt.QtGui.QApplication.UnicodeUTF8))
self.menu_provenance.addAction(self.action_activ_prov)
self.menu_provenance.addAction(self.action_show_prov)
self.menubar.addAction(self.menu_provenance.menuAction())
self.action_activ_prov.toggled.connect(self.set_provenance)
self.action_show_prov.triggered.connect(self.show_provenance)
[docs] def set_provenance(self, provenance):
"""
Set/Unset the registry of provenance
:param provenance: boolean which is set to True if we want to register provenance. Else, False.
"""
if hasattr(AbstractEvaluation, "__provenance__"):
self._prov = provenance
AbstractEvaluation.__provenance__ = self._prov
[docs] def get_provenance(self):
"""
:return: boolean which is set to True if we want to register provenance. Else, False.
"""
return self._prov
[docs] def show_provenance(self):
"""
Display the provenance
"""
from openalea.visualea.provenance import ModalDialog, ProvenanceSelectorWidget, search_trace
prov_widget = ProvenanceSelectorWidget(self)
dialog = ModalDialog(prov_widget)
dialog.show()
dialog.raise_()
if dialog.exec_():
cn = prov_widget.c_n.text()
pkg = prov_widget.pkg.text()
wk = prov_widget.workspace.text()
search_trace(cn, pkg, wk, parent=self)
[docs] def on_session_started(self, session):
self.initialise(session)
self.session = session
# -- configure the interpreter --
cli.init_interpreter(self.interpreterWidget.interpreter,
session,
{"tabs": self.tabWorkspace})
# -- now, many package manager related views --
self.pkgmanager = session.pkgmanager
self.actionShow_log.triggered.connect(self.pkgmanager.log.print_log)
# package tree view
self.pkg_model = PkgModel(self.pkgmanager)
self.packageTreeView = \
NodeFactoryTreeView(self, self.packageview)
self.packageTreeView.setModel(self.pkg_model)
self.vboxlayout1.addWidget(self.packageTreeView)
self.packageTreeView.clicked.connect(self.on_package_manager_focus_change)
# category tree view
self.cat_model = CategoryModel(self.pkgmanager)
self.categoryTreeView = \
NodeFactoryTreeView(self, self.categoryview)
self.categoryTreeView.setModel(self.cat_model)
self.vboxlayout2.addWidget(self.categoryTreeView)
self.categoryTreeView.clicked.connect(self.on_package_manager_focus_change)
# data pool list view
self.datapool_model = DataPoolModel(session.datapool)
self.datapoolListView = \
DataPoolListView(self, session.datapool, self.pooltab)
self.datapoolListView.setModel(self.datapool_model)
self.vboxlayout4.addWidget(self.datapoolListView)
self.session.simulate_workspace_addition()
[docs] def debug(self):
v = self.packageTreeView
print "items", v.expanded_items
print "model", v.model()
print "map", v.model().index_map
[docs] def write_settings(self):
"""Save application settings.
"""
settings = Settings()
#main window
settings.set("MainWindow", "size", "(%d,%d)" % (self.width(), self.height()))
settings.set("MainWindow", "pos", "(%d,%d)" % (self.x(), self.y()))
sizes = "[%s]" % ",".join("%d" % val for val in self.splitter_2.sizes())
settings.set("MainWindow", "splitter_2", sizes)
sizes = "[%s]" % ",".join("%d" % val for val in self.splitter_3.sizes())
settings.set("MainWindow", "splitter_3", sizes)
#tree view
settings.set("TreeView", "open", "[]")
#workspace
last_open = "[%s]" % ",".join("'%s'" % item for item in self._last_opened)
settings.set("WorkSpace", "last", last_open)
#provenance
prov = self.get_provenance()
settings.set("Provenance", "enable", str(prov))
settings.write()
[docs] def read_settings(self):
"""Read application settings.
"""
settings = Settings()
#main window
try:
size = eval(settings.get("MainWindow", "size"))
self.resize(qt.QtCore.QSize(*size))
except NoSectionError:
pass
except NoOptionError:
pass
try:
pos = eval(settings.get("MainWindow", "pos"))
self.move(qt.QtCore.QPoint(*pos))
except NoSectionError:
pass
except NoOptionError:
pass
try:
sizes = eval(settings.get("MainWindow", "splitter_2"))
self.splitter_2.setSizes(sizes)
except NoSectionError:
pass
except NoOptionError:
pass
try:
sizes = eval(settings.get("MainWindow", "splitter_3"))
self.splitter_3.setSizes(sizes)
except NoSectionError:
pass
except NoOptionError:
pass
#workspace
try:
last_open = eval(settings.get("WorkSpace", "last"))
last_open.reverse()
for item in last_open:
gr = item.split(".")
pkgid = ".".join(gr[:-1])
name = gr[-1]
self.add_last_open(pkgid, name)
except NoSectionError:
pass
except NoOptionError:
pass
try:
prov = eval(settings.get("Provenance", "enable"))
self.set_provenance(bool(prov))
except NoSectionError:
pass
except NoOptionError:
pass
[docs] def redo_last_open_menu(self):
"""Create entries for last opened nodes.
"""
self.menuLast_open.clear()
for action in self._last_open_action_group.actions():
self._last_open_action_group.removeAction(action)
for i, node_descr in enumerate(self._last_opened):
action = self.menuLast_open.addAction(node_descr)
action.setShortcut("Ctrl+%d" % (i + 1))
self._last_open_action_group.addAction(action)
self.menuLast_open.setEnabled(len(self._last_opened) > 0)
[docs] def reopen_last(self, action):
"""Reopen a last open node.
"""
gr = str(action.text()).split(".")
pkgid = ".".join(gr[:-1])
name = gr[-1]
manager = PackageManager()
factory = manager[pkgid][name]
self.open_compositenode(factory)
[docs] def add_last_open(self, pkgid, factory_name):
"""Register a new lest opened node.
"""
key = ".".join([pkgid, factory_name])
try:
self._last_opened.remove(key)
except ValueError:
pass
self._last_opened.insert(0, key)
if len(self._last_opened) > 4:
del self._last_opened[-1]
self.redo_last_open_menu()
def __wsMenuShow(self, abool=False):
graphview = self.tabWorkspace.currentWidget()
if not isinstance(graphview, dataflowview.DataflowView):
return
items = graphview.scene().get_selected_items(dataflowview.vertex.GraphicalVertex)
self.actionUseCustomColor.setChecked(False)
for i in items:
if i.vertex().get_ad_hoc_dict().get_metadata("useUserColor"):
self.actionUseCustomColor.setChecked(True)
break
def __make_operator_action_connector(self, action, name):
def connector(aBool=None):
graphview = self.tabWorkspace.currentWidget()
if not isinstance(graphview, dataflowview.DataflowView):
return
# daniel was here: now the menu is built using the graph operator.
operator = GraphOperator(graph=graphview.scene().get_graph(),
graphScene=graphview.scene(),
clipboard=self.session.clipboard,
siblings=self.session.workspaces)
operator.register_listener(self)
operator(fName=name)()
return connector
def __wsMenuHide(self):
pass
[docs] def open_compositenode(self, factory):
""" open a composite node editor """
node = factory.instantiate()
self.session.add_workspace(node, notify=False)
self.open_widget_tab(node, factory=factory)
self.add_last_open(factory.__pkg_id__, factory.name)
[docs] def about(self):
""" Display About Dialog """
mess = qt.QtGui.QMessageBox.about(self, "About Visualea",
"Version %s\n\n" % (metainfo.get_version()) +
"VisuAlea is part of the OpenAlea framework.\n" +
metainfo.get_copyright() +
"This Software is distributed under the Cecill-V2 License.\n\n" +
"Visit " + metainfo.url + "\n\n"
)
[docs] def help(self):
""" Display help """
self.web()
[docs] def web(self):
""" Open OpenAlea website """
qt.QtGui.QDesktopServices.openUrl(qt.QtCore.QUrl(metainfo.url))
[docs] def quit(self):
""" Quit Application """
if(qt.QtGui.QMessageBox.question(self, "Quit?", "Are you sure you want to quit?",
qt.QtGui.QMessageBox.Ok | qt.QtGui.QMessageBox.Cancel) ==
qt.QtGui.QMessageBox.Ok):
qt.QtGui.QApplication.exit(0)
[docs] def notify(self, sender, event):
""" Notification from observed """
if event and isinstance(sender, GraphOperator):
index = -1
for i in range(self.tabWorkspace.count()):
wid = self.tabWorkspace.widget(i)
if isinstance(wid, dataflowview.DataflowView) and wid.scene() == event[1]:
index = i
if index <= -1:
return
if(event[0] == "graphoperator_graphsaved"):
self.reinit_treeview()
caption = "Workspace %i - %s" % (index, event[2].name)
self.tabWorkspace.setTabText(index, caption)
elif(event[0] == "graphoperator_graphclosed"):
self.close_tab_workspace(index)
elif(event[0] == "graphoperator_graphreloaded"):
self.session.workspaces[index] = event[2]
if(type(sender) == type(self.session)):
if(event and event[0] == "workspace_added"):
graph = event[1]
self.open_widget_tab(graph, graph.factory)
else:
self.update_tabwidget()
self.reinit_treeview()
[docs] def closeEvent(self, event):
""" Close All subwindows """
#Save personnal settings
self.write_settings()
#close windows
for i in range(self.tabWorkspace.count()):
w = self.tabWorkspace.widget(i)
w.close()
event.accept()
[docs] def reinit_treeview(self):
""" Reinitialise package and category views """
self.cat_model.reset()
self.pkg_model.reset()
self.datapool_model.reset()
self.search_model.reset()
[docs] def close_tab_workspace(self, cindex):
""" Close workspace indexed by cindex cindex is Node"""
w = self.tabWorkspace.widget(cindex)
self.tabWorkspace.removeTab(cindex)
self.session.close_workspace(cindex, False)
g = w.scene().get_graph()
g.close()
#finally we close the dataflowview.
w.close()
del w
[docs] def current_view(self):
""" Return the active widget """
return self.tabWorkspace.currentWidget()
[docs] def update_tabwidget(self):
""" open tab widget """
# open tab widgets
for (i, node) in enumerate(self.session.workspaces):
if(i < self.tabWorkspace.count()):
widget = self.tabWorkspace.widget(i)
if(node != widget.scene().get_graph()):
self.close_tab_workspace(i)
self.open_widget_tab(node, factory=node.factory, pos=i)
# close last tabs
removelist = range(len(self.session.workspaces), self.tabWorkspace.count())
removelist.reverse()
for i in removelist:
self.close_tab_workspace(i)
[docs] def open_widget_tab(self, graph, factory, caption=None, pos=-1):
"""
Open a widget in a tab giving an instance and its widget
caption is append to the tab title
"""
gwidget = None
try:
# Since dataflowview.GraphicalGraph.__adapterType__ is dataflowview.adapter.GraphAdapter
# graph will automatically be wrapped by that class and gwidget will exclusevily
# talk to the adapter instead of the original graph. This thing is twisted but works well.
gwidget = dataflowview.GraphicalGraph.create_view(graph, parent=self)
gwidget.set_clipboard(self.session.clipboard)
gwidget.set_siblings(self.session.workspaces)
gwidget.scene().focusedItemChanged.connect(self.on_scene_focus_change)
self.session.add_graph_view(gwidget)
except Exception, e:
print "open_widget_tab", e
traceback.print_exc()
return
if(not caption):
i = self.session.workspaces.index(graph)
caption = "Workspace %i - %s" % (i, graph.get_caption())
index = self.tabWorkspace.insertTab(pos, gwidget, caption)
self.tabWorkspace.setCurrentIndex(index)
#there is a bug in QGraphicsScene+QTabWidget that makes
#secondary tabs inactive, so we force them to be active
#by sending new views the QEvent.WindowActivate event.
#The bug is present until Qt4.6.2 at least. Bugreport:
#http://bugreports.qt.nokia.com/browse/QTBUG-11148
qt.QtCore.QCoreApplication.instance().notify(gwidget, qt.QtCore.QEvent(qt.QtCore.QEvent.WindowActivate))
if gwidget is not None:
gwidget.show_entire_scene()
return index
[docs] def add_pkgdir(self):
dirname = qt.QtGui.QFileDialog.getExistingDirectory(self, "Select Package/Directory")
if(dirname):
self.pkgmanager.load_directory(str(dirname))
self.reinit_treeview()
[docs] def reload_all(self):
# Reload package manager
self.pkgmanager.reload()
self.reinit_treeview()
# Reload workspace
print "WARNING TODO RELOAD EACH TAB"
#for index in range(len(self.index_nodewidget)):
# self.reload_from_factory(index)
[docs] def ws_changed(self, index):
""" Current workspace has changed """
self.session.cworkspace = index
[docs] def contextMenuEvent(self, event):
""" Context menu event : Display the menu"""
pos = self.tabWorkspace.mapFromGlobal(event.globalPos())
tabBar = self.tabWorkspace.tabBar()
count = tabBar.count()
index = -1
for i in range(count):
if(tabBar.tabRect(i).contains(pos)):
index = i
break
# if no bar was hit, return
if (index < 0):
return
# set hit bar to front
self.tabWorkspace.setCurrentIndex(index)
def close_current_ws():
self.close_tab_workspace(index)
menu = qt.QtGui.QMenu(self)
action = menu.addAction("Close")
self.connect(action, qt.QtCore.SIGNAL("triggered()"), close_current_ws)
# action = menu.addAction("Run")
# self.connect(action, qt.QtCore.SIGNAL("triggered()"), self.run)
# action = menu.addAction("Export to Model")
# self.connect(action, qt.QtCore.SIGNAL("triggered()"), self.export_to_factory)
menu.move(event.globalPos())
menu.show()
[docs] def new_workspace(self):
""" Create an empty workspace """
self.session.add_workspace()
[docs] def new_graph(self):
""" Create a new graph """
dialog = NewGraph("New Composite Node", self.pkgmanager, self)
ret = dialog.exec_()
if(ret > 0):
newfactory = dialog.create_cnfactory(self.pkgmanager)
self.reinit_treeview()
self.open_compositenode(newfactory)
[docs] def new_python_node(self):
""" Create a new node """
dialog = NewGraph("New Python Node", self.pkgmanager, self)
ret = dialog.exec_()
if(ret > 0):
dialog.create_nodefactory(self.pkgmanager)
self.reinit_treeview()
[docs] def new_data(self):
""" Import file """
dialog = NewData("Import data file", self.pkgmanager, self)
ret = dialog.exec_()
if(ret > 0):
dialog.create_datafactory(self.pkgmanager)
self.reinit_treeview()
[docs] def new_package(self):
""" Create a new user package """
dialog = NewPackage(self.pkgmanager.keys(), parent=self)
ret = dialog.exec_()
if(ret > 0):
(name, metainfo, path) = dialog.get_data()
self.pkgmanager.create_user_package(name, metainfo, path)
self.reinit_treeview()
[docs] def exec_python_script(self):
""" Choose a python source and execute it """
filename = qt.QtGui.QFileDialog.getOpenFileName(
self, "Python Script", "Python script (*.py)")
filename = str(filename)
if(not filename):
return
# Try if IPython
try:
file = open(filename, 'r')
src = ""
for f in file:
src += f
self.interpreterWidget.get_interpreter().runcode(src, hidden=False)
file.close()
except:
file = open(filename, 'r')
sources = ''
compiled = None
import code
for line in file:
sources += line
compiled = code.compile_command(sources, filename)
if(compiled):
self.interpreterWidget.get_interpreter().runcode(compiled)
sources = ''
file.close()
sources = ''
[docs] def open_python_console(self):
""" Set focus on the python shell """
try:
self.interpreterWidget.setFocus(qt.QtCore.Qt.ShortcutFocusReason)
except:
pass
[docs] def clear_python_console(self):
""" Clear python shell """
self.interpreterWidget.clear()
[docs] def new_session(self):
self.session.clear()
[docs] def open_session(self):
filename = qt.QtGui.QFileDialog.getOpenFileName(
self, "OpenAlea Session", qt.QtCore.QDir.homePath(), "Session file (*.oas)")
filename = str(filename)
if(not filename):
return
self.session.load(filename)
[docs] def save_session(self):
""" Save menu entry """
if(not self.session.session_filename):
self.save_as()
else:
self.session.save(self.session.session_filename)
[docs] def save_as(self):
""" Save as menu entry """
filename = qt.QtGui.QFileDialog.getSaveFileName(
self, "OpenAlea Session", qt.QtCore.QDir.homePath(), "Session file (*.oas)")
filename = str(filename)
if(not filename):
return
self.session.save(filename)
[docs] def clear_data_pool(self):
""" Clear the data pool """
self.session.datapool.clear()
[docs] def search_node(self):
""" Activated when search line edit is validated """
text = str(unicode(self.search_lineEdit.text()).encode('latin1'))
results = self.pkgmanager.search_node(text)
self.search_model.set_results(results)
[docs] def find_node(self):
""" Find node Command """
i = self.tabPackager.indexOf(self.searchview)
self.tabPackager.setCurrentIndex(i)
self.search_lineEdit.setFocus()
[docs] def open_preferences(self):
""" Open Preference dialog """
dialog = PreferencesDialog(self)
dialog.show()
ret = dialog.exec_()
# ! does not return anythin and do not use ret ?
# Drag and drop support
[docs] def dragEnterEvent(self, event):
"""todo"""
if event.mimeData().hasUrls():
event.accept()
else:
event.ignore()
[docs] def dropEvent(self, event):
"""todo"""
urls = event.mimeData().urls()
try:
file = urls[0]
filename = str(file.path())
self.session.load(filename)
event.accept()
except Exception, e:
print e
event.ignore()
############################
# Handling the Help widget #
############################
[docs] def on_scene_focus_change(self, scene, item):
assert isinstance(item, dataflowview.vertex.GraphicalVertex)
self.helpWidget.set_rst(item.vertex().get_tip())
[docs] def on_package_manager_focus_change(self, item):
pkg_id, factory_id, mimetype = NodeFactoryView.get_item_info(item)
if len(pkg_id) and len(factory_id) and mimetype in [NodeFactory.mimetype,
CompositeNodeFactory.mimetype]:
factory = self.pkgmanager[pkg_id][factory_id]
factoryDoc = factory.get_documentation()
txt = factory.get_tip(asRst=True) + "\n\n"
if factoryDoc is not None:
txt += "**Docstring:**\n" + factoryDoc
self.helpWidget.set_rst(txt)
# Window support
[docs] def display_leftpanel(self, toggled):
self.splitter_2.setVisible(toggled)
[docs] def display_rightpanel(self, toggled):
self.splitter.setVisible(toggled)
[docs] def to_python_script(self):
"""Translate the active workspace into a python script"""
widget = self.tabWorkspace.currentWidget()
if widget is None:
return
composite_node = widget.scene().get_graph()
if composite_node is not None:
print "BEGIN script"
print composite_node.to_script(), "END script"
[docs] def export_image(self):
""" Export current workspace to an image """
filename = qt.QtGui.QFileDialog.getSaveFileName(
self, "Export image", qt.QtCore.QDir.homePath(), "PNG Image (*.png)")
filename = str(filename)
if not filename:
return
elif '.' not in filename:
filename += '.png'
# Get current workspace
view = self.tabWorkspace.currentWidget()
# Retreive the user layout
rect = view.scene().sceneRect()
matrix = view.matrix()
rect = matrix.mapRect(rect)
pixmap = qt.QtGui.QPixmap(rect.width(), rect.height())
pixmap.fill()
painter = qt.QtGui.QPainter(pixmap)
painter.setRenderHint(qt.QtGui.QPainter.Antialiasing)
view.update()
view.scene().render(painter)
painter.end()
pixmap.save(filename)
[docs] def export_image_svg(self):
""" Export current workspace to an image """
filename = qt.QtGui.QFileDialog.getSaveFileName(
self, "Export svg image", qt.QtCore.QDir.homePath(), "SVG Image (*.svg)")
filename = str(filename)
if not filename:
return
elif '.' not in filename:
filename += '.png'
# Get current workspace
view = self.tabWorkspace.currentWidget()
# Retreive the user layout
rect = view.scene().sceneRect()
matrix = view.matrix()
rect = matrix.mapRect(rect)
svg_gen = qt.QtSvg.QSvgGenerator()
svg_gen.setFileName(filename)
svg_gen.setSize(rect.toRect().size())
painter = qt.QtGui.QPainter(svg_gen)
painter.setRenderHint(qt.QtGui.QPainter.Antialiasing)
view.scene().render(painter, )
painter.end()