class PackageViewWidget(OALabTreeView): """ Widget for Package Manager """ def __init__(self, parent=None): super(PackageViewWidget, self).__init__(parent=parent) # package tree view self.pkg_model = PkgModel(package_manager) self.setModel(self.pkg_model) self.clicked.connect(self.on_package_manager_focus_change) 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 = package_manager[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 applet = get_applet(identifier='HelpWidget') if applet: applet.setText(txt) def reinit_treeview(self): """ Reinitialise package and category views """ self.pkg_model.reset()
class PackageViewWidget(OALabTreeView): """ Widget for Package Manager """ def __init__(self, parent=None): super(PackageViewWidget, self).__init__(parent=parent) # package tree view self.pkg_model = PkgModel(package_manager) self.setModel(self.pkg_model) self.clicked.connect(self.on_package_manager_focus_change) 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 = package_manager[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 applet = get_applet(identifier='HelpWidget') if applet: applet.setText(txt) def reinit_treeview(self): """ Reinitialise package and category views """ self.pkg_model.reset()
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) 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 def get_provenance(self): """ :return: boolean which is set to True if we want to register provenance. Else, False. """ return self._prov 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) 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() def debug(self): v = self.packageTreeView print "items", v.expanded_items print "model", v.model() print "map", v.model().index_map 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() 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 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) 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) 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 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) 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") def help(self): """ Display help """ self.web() def web(self): """ Open OpenAlea website """ qt.QtGui.QDesktopServices.openUrl(qt.QtCore.QUrl(metainfo.url)) 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) 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() 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() 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() 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 def current_view(self): """ Return the active widget """ return self.tabWorkspace.currentWidget() 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) 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
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) 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 def get_provenance(self): """ :return: boolean which is set to True if we want to register provenance. Else, False. """ return self._prov 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) 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() def debug(self): v = self.packageTreeView print "items", v.expanded_items print "model", v.model() print "map", v.model().index_map 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() 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 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) 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) 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 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) 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" ) def help(self): """ Display help """ self.web() def web(self): """ Open OpenAlea website """ qt.QtGui.QDesktopServices.openUrl(qt.QtCore.QUrl(metainfo.url)) 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) 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() 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() 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() 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 def current_view(self): """ Return the active widget """ return self.tabWorkspace.currentWidget() 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) 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