def __init__(self, parent=None): super(DataflowWindow, self).__init__(parent) # misc initializations self.factory = plugins.PluginFactory() self.dataflow = plugins.DataflowGraph() self.scene = DataflowScene(self.factory, self.dataflow) self.scene.setSceneRect(0, 0, 500, 500) # result from dataflow self.results = {} self.timer = QTimer() self.connect(self.timer, SIGNAL('timeout()'), self.updateStatusBar) self.connect(self.timer, SIGNAL('timeout()'), self.updateFlowStatus) # setup menus fileMenu = self.menuBar().addMenu('File') fileMenu.addAction('New', self.openNew) fileMenu.addAction('Load', self.openFile) fileMenu.addAction('Save', self.saveFile) actionsMenu = ActionsMenu(self.dataflow, self.menuBar()) self.menuBar().addMenu(actionsMenu) # flag to select the correct statusbar message self.some_processing_done = False self.statusBar().showMessage('Ready') # setup dataflow page dataflowTab = QWidget() self.view = DataflowView() self.view.setScene(self.scene) self.toolbox = PluginToolbox(factory) self.populatePluginToolbox() dataflow_tab_layout = QGridLayout() dataflow_tab_layout.addWidget(self.toolbox, 0, 0) dataflow_tab_layout.addWidget(self.view, 0, 1) dataflowTab.setLayout(dataflow_tab_layout) # setup report tab reportTab = QWidget() outputsLabel = QLabel('Data provided by plugins') self.outputList = QListWidget() self.result_preview = QTextEdit() self.result_preview.setReadOnly(True) self.html_edit = QTextEdit() self.preview_button = QPushButton('Preview report') report_tab_layout = QGridLayout() report_tab_layout.addWidget(outputsLabel, 0, 0) report_tab_layout.addWidget(self.outputList, 1, 0) report_tab_layout.addWidget(self.result_preview, 1, 1) report_tab_layout.addWidget(self.html_edit, 1, 2) report_tab_layout.addWidget(self.preview_button, 2, 2) reportTab.setLayout(report_tab_layout) self.connect(self.preview_button, SIGNAL('clicked()'), self.show_report) self.connect(self.outputList, SIGNAL('currentItemChanged(QListWidgetItem *, QListWidgetItem *)'), self.tmp_show_data) # setup tab widget tabWidget = QTabWidget() tabWidget.addTab(dataflowTab, 'Dataflow') tabWidget.addTab(reportTab, 'Output') self.setCentralWidget(tabWidget) self.timer.start(100)
class DataflowWindow(QMainWindow): def __init__(self, parent=None): super(DataflowWindow, self).__init__(parent) # misc initializations self.factory = plugins.PluginFactory() self.dataflow = plugins.DataflowGraph() self.scene = DataflowScene(self.factory, self.dataflow) self.scene.setSceneRect(0, 0, 500, 500) # result from dataflow self.results = {} self.timer = QTimer() self.connect(self.timer, SIGNAL('timeout()'), self.updateStatusBar) self.connect(self.timer, SIGNAL('timeout()'), self.updateFlowStatus) # setup menus fileMenu = self.menuBar().addMenu('File') fileMenu.addAction('New', self.openNew) fileMenu.addAction('Load', self.openFile) fileMenu.addAction('Save', self.saveFile) actionsMenu = ActionsMenu(self.dataflow, self.menuBar()) self.menuBar().addMenu(actionsMenu) # flag to select the correct statusbar message self.some_processing_done = False self.statusBar().showMessage('Ready') # setup dataflow page dataflowTab = QWidget() self.view = DataflowView() self.view.setScene(self.scene) self.toolbox = PluginToolbox(factory) self.populatePluginToolbox() dataflow_tab_layout = QGridLayout() dataflow_tab_layout.addWidget(self.toolbox, 0, 0) dataflow_tab_layout.addWidget(self.view, 0, 1) dataflowTab.setLayout(dataflow_tab_layout) # setup report tab reportTab = QWidget() outputsLabel = QLabel('Data provided by plugins') self.outputList = QListWidget() self.result_preview = QTextEdit() self.result_preview.setReadOnly(True) self.html_edit = QTextEdit() self.preview_button = QPushButton('Preview report') report_tab_layout = QGridLayout() report_tab_layout.addWidget(outputsLabel, 0, 0) report_tab_layout.addWidget(self.outputList, 1, 0) report_tab_layout.addWidget(self.result_preview, 1, 1) report_tab_layout.addWidget(self.html_edit, 1, 2) report_tab_layout.addWidget(self.preview_button, 2, 2) reportTab.setLayout(report_tab_layout) self.connect(self.preview_button, SIGNAL('clicked()'), self.show_report) self.connect(self.outputList, SIGNAL('currentItemChanged(QListWidgetItem *, QListWidgetItem *)'), self.tmp_show_data) # setup tab widget tabWidget = QTabWidget() tabWidget.addTab(dataflowTab, 'Dataflow') tabWidget.addTab(reportTab, 'Output') self.setCentralWidget(tabWidget) self.timer.start(100) def populatePluginToolbox(self): plugins = self.factory.list_plugins() # add plugins to tabs for name in plugins: tab_idx = self.toolbox.addTab(name) for plugin_name in plugins[name]: w = QListWidgetItem(plugin_name) # FIXME w.setData(100, QVariant('.'.join([name, plugin_name]))) self.toolbox.widget(tab_idx).addItem(w) def openNew(self): self.dataflow.clear() self.scene.reload_dataflow() self.results = {} self.outputList.clear() self.result_preview.clear() def openFile(self): fn = QFileDialog.getOpenFileName(self, "Open File", os.getcwd()) text = None try: with open(fn, 'rb') as fo: text = fo.read() except EnvironmentError: # FIXME pass if text is not None: if self.dataflow.load_XML(text): # all OK self.scene.reload_dataflow() else: # FIXME: notify pass # read report structure root = ElementTree.XML(text) report_elem = root.find('report') print report_elem.find('text') report_text = report_elem.find('text').text report_text = report_text if report_text is not None else '' self.html_edit.setPlainText(report_text) def saveFile(self): fn = QFileDialog.getSaveFileName(self, "Save File", os.getcwd()) # dump dataflow as XML XML_string = self.dataflow.to_XML() if XML_string is not None: try: root = ElementTree.XML(XML_string) report_element = ElementTree.SubElement(root, 'report') ElementTree.SubElement(report_element, 'text').text = str(self.html_edit.toPlainText()) XML_string = ElementTree.tostring(root, encoding='UTF-8') with open(fn, 'wb') as fo: fo.write(XML_string) except (EnvironmentError, ExpatError) as e: # FIXME: handle better print e def updateStatusBar(self): if self.dataflow.is_running(): self.statusBar().showMessage('Processing dataflow') self.some_processing_done = True elif self.some_processing_done == True: self.statusBar().showMessage('Processing done') def updateFlowStatus(self): if self.dataflow.results_ready() == True: self.results = self.dataflow.get_results() for plugin_id in self.results: text = 'Output from plugin with id: %d' % plugin_id self.outputList.addItem(text) def show_report(self): class ReportDialog(QDialog): def __init__(self, text, parent=None): super(ReportDialog, self).__init__(parent) text_edit = QTextEdit() text_edit.setReadOnly(True) text_edit.setHtml(result) okButton = QPushButton('Close') self.connect(okButton, SIGNAL('clicked()'), partial(self.done, 0)) # layout layout = QVBoxLayout() layout.addWidget(text_edit) button_layout = QHBoxLayout() button_layout.addStretch() button_layout.addWidget(okButton) layout.addLayout(button_layout) self.setLayout(layout) def preprocess(HTML): HTML = ''.join(['<html><body>', str(HTML), '</html></body>']) expr = re.compile(r'\$\{(\S*)\}') replacement_info = [] for match in re.finditer(expr, HTML): result_id = match.group(1) # FIXME: allow result_id strings result = self.results[int(result_id)] element = result.as_HTML_element() replacement_info.append((match.start(), match.end(), element)) new_HTML = '' new_start = 0 for start, end, replacement_text in replacement_info: new_HTML += HTML[new_start:start] + replacement_text new_start = end new_HTML += HTML[new_start:] return new_HTML try: result = preprocess(self.html_edit.document().toPlainText()) dialog = ReportDialog(result) dialog.exec_() except ValueError: # html was invalid QMessageBox.warning(None, 'Invalid HTML', 'Report contains errors and cannot be displayed.', QMessageBox.Ok) except KeyError: # plugin id was invalid QMessageBox.warning(None, 'Invalid result referenced', 'Invalid result referenced.', QMessageBox.Ok) def tmp_show_data(self): item = self.outputList.currentItem() if item is not None: i = int(str(item.text()).split(':')[1].strip()) data = self.results[i].as_HTML_element() self.result_preview.setHtml(data)