def _setup_ui_(self): self.table_model = ReportItemModel(0, len(Column.__members__)) self.table = ReportTable(self.controlArea) self.table.setModel(self.table_model) self.table.setShowGrid(False) self.table.setSelectionBehavior(QTableView.SelectRows) self.table.setSelectionMode(QTableView.SingleSelection) self.table.setWordWrap(False) self.table.setMouseTracking(True) self.table.verticalHeader().setResizeMode(QHeaderView.Fixed) self.table.verticalHeader().setDefaultSectionSize(20) self.table.verticalHeader().setVisible(False) self.table.horizontalHeader().setVisible(False) self.table.setFixedWidth(250) self.table.setColumnWidth(Column.item, 200) self.table.setColumnWidth(Column.remove, 23) self.table.setColumnWidth(Column.scheme, 25) self.table.clicked.connect(self._table_clicked) self.table.selectionModel().selectionChanged.connect( self._table_selection_changed) self.controlArea.layout().addWidget(self.table) self.last_scheme = None self.scheme_button = gui.button(self.controlArea, self, "Back to Last Scheme", callback=self._show_last_scheme) box = gui.hBox(self.controlArea) box.setContentsMargins(-6, 0, -6, 0) self.save_button = gui.button(box, self, "Save", callback=self.save_report) self.print_button = gui.button(box, self, "Print", callback=self._print_report) self.report_view = WebView(self.mainArea, bridge=self)
def _setup_ui_(self): self.table_model = ReportItemModel(0, len(Column.__members__)) self.table = ReportTable(self.controlArea) self.table.setModel(self.table_model) self.table.setShowGrid(False) self.table.setSelectionBehavior(QTableView.SelectRows) self.table.setSelectionMode(QTableView.SingleSelection) self.table.setWordWrap(False) self.table.setMouseTracking(True) self.table.verticalHeader().setResizeMode(QHeaderView.Fixed) self.table.verticalHeader().setDefaultSectionSize(20) self.table.verticalHeader().setVisible(False) self.table.horizontalHeader().setVisible(False) self.table.setFixedWidth(250) self.table.setColumnWidth(Column.item, 200) self.table.setColumnWidth(Column.remove, 23) self.table.setColumnWidth(Column.scheme, 25) self.table.clicked.connect(self._table_clicked) self.table.selectionModel().selectionChanged.connect( self._table_selection_changed) self.controlArea.layout().addWidget(self.table) self.last_scheme = None self.scheme_button = gui.button( self.controlArea, self, "Back to Last Scheme", callback=self._show_last_scheme ) box = gui.hBox(self.controlArea) box.setContentsMargins(-6, 0, -6, 0) self.save_button = gui.button( box, self, "Save", callback=self.save_report ) self.print_button = gui.button( box, self, "Print", callback=self._print_report ) self.report_view = WebView(self.mainArea, bridge=self)
class OWReport(OWWidget): name = "Report" save_dir = Setting("") open_dir = Setting("") def __init__(self): super().__init__() self._setup_ui_() self.report_changed = False index_file = pkg_resources.resource_filename(__name__, "index.html") self.report_html_template = open(index_file, "r").read() def _setup_ui_(self): self.table_model = ReportItemModel(0, len(Column.__members__)) self.table = ReportTable(self.controlArea) self.table.setModel(self.table_model) self.table.setShowGrid(False) self.table.setSelectionBehavior(QTableView.SelectRows) self.table.setSelectionMode(QTableView.SingleSelection) self.table.setWordWrap(False) self.table.setMouseTracking(True) self.table.verticalHeader().setResizeMode(QHeaderView.Fixed) self.table.verticalHeader().setDefaultSectionSize(20) self.table.verticalHeader().setVisible(False) self.table.horizontalHeader().setVisible(False) self.table.setFixedWidth(250) self.table.setColumnWidth(Column.item, 200) self.table.setColumnWidth(Column.remove, 23) self.table.setColumnWidth(Column.scheme, 25) self.table.clicked.connect(self._table_clicked) self.table.selectionModel().selectionChanged.connect( self._table_selection_changed) self.controlArea.layout().addWidget(self.table) self.last_scheme = None self.scheme_button = gui.button(self.controlArea, self, "Back to Last Scheme", callback=self._show_last_scheme) box = gui.hBox(self.controlArea) box.setContentsMargins(-6, 0, -6, 0) self.save_button = gui.button(box, self, "Save", callback=self.save_report) self.print_button = gui.button(box, self, "Print", callback=self._print_report) self.report_view = WebView(self.mainArea, bridge=self) @deprecated("Widgets should not be pickled") def __getstate__(self): rep_dict = self.__dict__.copy() for key in ('_OWWidget__env', 'controlArea', 'mainArea', 'report_view', 'table', 'table_model'): del rep_dict[key] items_len = self.table_model.rowCount() return rep_dict, [self.table_model.item(i) for i in range(items_len)] @deprecated("Widgets should not be pickled") def __setstate__(self, state): rep_dict, items = state self.__dict__.update(rep_dict) self._setup_ui_() for i in range(len(items)): item = items[i] self.table_model.add_item( ReportItem(item.name, item.html, item.scheme, item.module, item.icon_name, item.comment)) def _table_clicked(self, index): if index.column() == Column.remove: self._remove_item(index.row()) indexes = self.table.selectionModel().selectedIndexes() if indexes: item = self.table_model.item(indexes[0].row()) self._scroll_to_item(item) self._change_selected_item(item) if index.column() == Column.scheme: self._show_scheme(index.row()) def _table_selection_changed(self, new_selection, _): if new_selection.indexes(): item = self.table_model.item(new_selection.indexes()[0].row()) self._scroll_to_item(item) self._change_selected_item(item) def _remove_item(self, row): self.table_model.removeRow(row) self.report_changed = True self._build_html() def clear(self): self.table_model.clear() self.report_changed = True self._build_html() def _add_item(self, widget): name = widget.get_widget_name_extension() name = "{} - {}".format(widget.name, name) if name else widget.name item = ReportItem(name, widget.report_html, self._get_scheme(), widget.__module__, widget.icon) self.table_model.add_item(item) self.report_changed = True return item def _build_html(self): html = self.report_html_template html += "<body>" for i in range(self.table_model.rowCount()): item = self.table_model.item(i) html += "<div id='{}' class='normal' " \ "onClick='pybridge._select_item(this.id)'>{}<div " \ "class='textwrapper'><textarea required='required' " \ "placeholder='Write a comment...'" \ "onInput='pybridge._add_comment(this.parentNode." \ "parentNode.id, this.value)'>{}</textarea></div>" \ "</div>".format(item.id, item.html, item.comment) html += "</body></html>" self.report_view.setHtml(html) def _scroll_to_item(self, item): self.report_view.evalJS("document.getElementById('{}')." "scrollIntoView();".format(item.id)) def _change_selected_item(self, item): self.report_view.evalJS( "var sel_el = document.getElementsByClassName('selected')[0]; " "if (sel_el.id != {}) " " sel_el.className = 'normal';".format(item.id)) self.report_view.evalJS("document.getElementById('{}')." "className = 'selected';".format(item.id)) self.report_changed = True @pyqtSlot(str) def _select_item(self, item_id): item = self.table_model.get_item_by_id(item_id) self.table.selectRow(self.table_model.indexFromItem(item).row()) self._change_selected_item(item) @pyqtSlot(str, str) def _add_comment(self, item_id, value): item = self.table_model.get_item_by_id(item_id) item.comment = value self.report_changed = True def make_report(self, widget): item = self._add_item(widget) self._build_html() self._scroll_to_item(item) self.table.selectRow(self.table_model.rowCount() - 1) def _get_scheme(self): canvas = self.get_canvas_instance() return canvas.get_scheme_xml() if canvas else None def _show_scheme(self, row): scheme = self.table_model.item(row).scheme canvas = self.get_canvas_instance() if canvas: document = canvas.current_document() if document.isModifiedStrict(): self.last_scheme = canvas.get_scheme_xml() canvas.load_scheme_xml(scheme) def _show_last_scheme(self): if self.last_scheme: canvas = self.get_canvas_instance() if canvas: canvas.load_scheme_xml(self.last_scheme) def save_report(self): """Save report""" filename = QFileDialog.getSaveFileName( self, "Save Report", self.save_dir, "HTML (*.html);;PDF (*.pdf);;Report (*.report)") if not filename: return QDialog.Rejected self.save_dir = os.path.dirname(filename) self.saveSettings() _, extension = os.path.splitext(filename) if extension == ".pdf": printer = QPrinter() printer.setPageSize(QPrinter.A4) printer.setOutputFormat(QPrinter.PdfFormat) printer.setOutputFileName(filename) self.report_view.print_(printer) elif extension == ".report": self.save(filename) else: frame = self.report_view.page().currentFrame() with open(filename, "w", encoding="utf-8") as f: f.write(frame.documentElement().toInnerXml()) self.report_changed = False return QDialog.Accepted def _print_report(self): printer = QPrinter() print_dialog = QPrintDialog(printer, self) print_dialog.setWindowTitle("Print report") if print_dialog.exec_() != QDialog.Accepted: return self.report_view.print_(printer) def open_report(self): filename = QFileDialog.getOpenFileName(self, "Open Report", self.open_dir, "Report (*.report)") if not filename: return self.report_changed = False self.open_dir = os.path.dirname(filename) self.saveSettings() try: report = self.load(filename) except (IOError, AttributeError) as e: message_critical( self.tr("Could not load an Orange Report file"), title=self.tr("Error"), informative_text=self.tr("An unexpected error occurred " "while loading '%s'.") % filename, exc_info=True, parent=self) return self.set_instance(report) self = report self._build_html() self.table.selectRow(0) self.show() self.raise_() def save(self, filename): attributes = {} for key in ('last_scheme', 'open_dir'): attributes[key] = getattr(self, key, None) items = [ self.table_model.item(i) for i in range(self.table_model.rowCount()) ] report = dict(__version__=1, attributes=attributes, items=items) with open(filename, 'wb') as f: pickle.dump(report, f) @classmethod def load(cls, filename): with open(filename, 'rb') as f: report = pickle.load(f) if not isinstance(report, dict): return report self = cls() self.__dict__.update(report['attributes']) for item in report['items']: self.table_model.add_item( ReportItem(item.name, item.html, item.scheme, item.module, item.icon_name, item.comment)) return self def is_empty(self): return not self.table_model.rowCount() def is_changed(self): return self.report_changed @staticmethod def set_instance(report): app_inst = QApplication.instance() app_inst._report_window = report @staticmethod def get_instance(): app_inst = QApplication.instance() if not hasattr(app_inst, "_report_window"): report = OWReport() app_inst._report_window = report app_inst.sendPostedEvents(report, 0) app_inst.aboutToQuit.connect(report.deleteLater) return app_inst._report_window @staticmethod def get_canvas_instance(): for widget in QApplication.topLevelWidgets(): if isinstance(widget, CanvasMainWindow): return widget
class OWReport(OWWidget): name = "Report" save_dir = Setting("") open_dir = Setting("") def __init__(self): super().__init__() self._setup_ui_() self.report_changed = False index_file = pkg_resources.resource_filename(__name__, "index.html") self.report_html_template = open(index_file, "r").read() def _setup_ui_(self): self.table_model = ReportItemModel(0, len(Column.__members__)) self.table = ReportTable(self.controlArea) self.table.setModel(self.table_model) self.table.setShowGrid(False) self.table.setSelectionBehavior(QTableView.SelectRows) self.table.setSelectionMode(QTableView.SingleSelection) self.table.setWordWrap(False) self.table.setMouseTracking(True) self.table.verticalHeader().setResizeMode(QHeaderView.Fixed) self.table.verticalHeader().setDefaultSectionSize(20) self.table.verticalHeader().setVisible(False) self.table.horizontalHeader().setVisible(False) self.table.setFixedWidth(250) self.table.setColumnWidth(Column.item, 200) self.table.setColumnWidth(Column.remove, 23) self.table.setColumnWidth(Column.scheme, 25) self.table.clicked.connect(self._table_clicked) self.table.selectionModel().selectionChanged.connect( self._table_selection_changed) self.controlArea.layout().addWidget(self.table) self.last_scheme = None self.scheme_button = gui.button( self.controlArea, self, "Back to Last Scheme", callback=self._show_last_scheme ) box = gui.hBox(self.controlArea) box.setContentsMargins(-6, 0, -6, 0) self.save_button = gui.button( box, self, "Save", callback=self.save_report ) self.print_button = gui.button( box, self, "Print", callback=self._print_report ) self.report_view = WebView(self.mainArea, bridge=self) def __getstate__(self): rep_dict = self.__dict__.copy() for key in ('_OWWidget__env', 'controlArea', 'mainArea', 'report_view', 'table', 'table_model'): del rep_dict[key] items_len = self.table_model.rowCount() return rep_dict, [self.table_model.item(i) for i in range(items_len)] def __setstate__(self, state): rep_dict, items = state self.__dict__.update(rep_dict) self._setup_ui_() for i in range(len(items)): item = items[i] self.table_model.add_item( ReportItem(item.name, item.html, item.scheme, item.module, item.icon_name, item.comment) ) def _table_clicked(self, index): if index.column() == Column.remove: self._remove_item(index.row()) indexes = self.table.selectionModel().selectedIndexes() if indexes: item = self.table_model.item(indexes[0].row()) self._scroll_to_item(item) self._change_selected_item(item) if index.column() == Column.scheme: self._show_scheme(index.row()) def _table_selection_changed(self, new_selection, _): if new_selection.indexes(): item = self.table_model.item(new_selection.indexes()[0].row()) self._scroll_to_item(item) self._change_selected_item(item) def _remove_item(self, row): self.table_model.removeRow(row) self.report_changed = True self._build_html() def clear(self): self.table_model.clear() self.report_changed = True self._build_html() def _add_item(self, widget): name = widget.get_widget_name_extension() name = "{} - {}".format(widget.name, name) if name else widget.name item = ReportItem(name, widget.report_html, self._get_scheme(), widget.__module__, widget.icon) self.table_model.add_item(item) self.report_changed = True return item def _build_html(self): html = self.report_html_template html += "<body>" for i in range(self.table_model.rowCount()): item = self.table_model.item(i) html += "<div id='{}' class='normal' " \ "onClick='pybridge._select_item(this.id)'>{}<div " \ "class='textwrapper'><textarea required='required' " \ "placeholder='Write a comment...'" \ "onInput='pybridge._add_comment(this.parentNode." \ "parentNode.id, this.value)'>{}</textarea></div>" \ "</div>".format(item.id, item.html, item.comment) html += "</body></html>" self.report_view.setHtml(html) def _scroll_to_item(self, item): self.report_view.evalJS("document.getElementById('{}')." "scrollIntoView();".format(item.id)) def _change_selected_item(self, item): self.report_view.evalJS( "var sel_el = document.getElementsByClassName('selected')[0]; " "if (sel_el.id != {}) " " sel_el.className = 'normal';".format(item.id)) self.report_view.evalJS("document.getElementById('{}')." "className = 'selected';".format(item.id)) self.report_changed = True @pyqtSlot(str) def _select_item(self, item_id): item = self.table_model.get_item_by_id(item_id) self.table.selectRow(self.table_model.indexFromItem(item).row()) self._change_selected_item(item) @pyqtSlot(str, str) def _add_comment(self, item_id, value): item = self.table_model.get_item_by_id(item_id) item.comment = value self.report_changed = True def make_report(self, widget): item = self._add_item(widget) self._build_html() self._scroll_to_item(item) self.table.selectRow(self.table_model.rowCount() - 1) def _get_scheme(self): canvas = self.get_canvas_instance() return canvas.get_scheme_xml() if canvas else None def _show_scheme(self, row): scheme = self.table_model.item(row).scheme canvas = self.get_canvas_instance() if canvas: document = canvas.current_document() if document.isModifiedStrict(): self.last_scheme = canvas.get_scheme_xml() canvas.load_scheme_xml(scheme) def _show_last_scheme(self): if self.last_scheme: canvas = self.get_canvas_instance() if canvas: canvas.load_scheme_xml(self.last_scheme) def save_report(self): """Save report""" filename = QFileDialog.getSaveFileName( self, "Save Report", self.save_dir, "HTML (*.html);;PDF (*.pdf);;Report (*.report)") if not filename: return QDialog.Rejected self.save_dir = os.path.dirname(filename) self.saveSettings() _, extension = os.path.splitext(filename) if extension == ".pdf": printer = QPrinter() printer.setPageSize(QPrinter.A4) printer.setOutputFormat(QPrinter.PdfFormat) printer.setOutputFileName(filename) self.report_view.print_(printer) elif extension == ".report": with open(filename, 'wb') as f: pickle.dump(self, f) else: frame = self.report_view.page().currentFrame() with open(filename, "w") as f: f.write(frame.documentElement().toInnerXml()) self.report_changed = False return QDialog.Accepted def _print_report(self): printer = QPrinter() print_dialog = QPrintDialog(printer, self) print_dialog.setWindowTitle("Print report") if print_dialog.exec_() != QDialog.Accepted: return self.report_view.print_(printer) def open_report(self): filename = QFileDialog.getOpenFileName( self, "Open Report", self.open_dir, "Report (*.report)") if not filename: return self.report_changed = False self.open_dir = os.path.dirname(filename) self.saveSettings() try: with open(filename, 'rb') as f: report = pickle.load(f) except (IOError, AttributeError) as e: message_critical( self.tr("Could not load an Orange Report file"), title=self.tr("Error"), informative_text=self.tr("An unexpected error occurred " "while loading '%s'.") % filename, exc_info=True, parent=self) return self.set_instance(report) self = report self._build_html() self.table.selectRow(0) self.show() self.raise_() def is_empty(self): return not self.table_model.rowCount() def is_changed(self): return self.report_changed @staticmethod def set_instance(report): app_inst = QApplication.instance() app_inst._report_window = report @staticmethod def get_instance(): app_inst = QApplication.instance() if not hasattr(app_inst, "_report_window"): report = OWReport() app_inst._report_window = report app_inst.sendPostedEvents(report, 0) app_inst.aboutToQuit.connect(report.deleteLater) return app_inst._report_window @staticmethod def get_canvas_instance(): for widget in QApplication.topLevelWidgets(): if isinstance(widget, CanvasMainWindow): return widget