コード例 #1
0
ファイル: widget.py プロジェクト: samueljackson92/mantid
class AlgorithmProgressWidget(QWidget):
    """
    Widget consisting of a progress bar and a button.
    """
    def __init__(self, parent=None):
        super(AlgorithmProgressWidget, self).__init__(parent)
        self.progress_bar = None
        self.details_button = QPushButton('Details')
        self.details_button.clicked.connect(self.show_dialog)
        self.layout = QHBoxLayout()
        self.layout.addStretch()
        self.layout.addWidget(self.details_button)
        self.setLayout(self.layout)
        self.presenter = AlgorithmProgressPresenter(self)

    def show_progress_bar(self):
        if self.progress_bar is None:
            self.progress_bar = QProgressBar()
            self.progress_bar.setAlignment(Qt.AlignHCenter)
            self.layout.insertWidget(0, self.progress_bar)
            self.layout.removeItem(self.layout.takeAt(1))

    def hide_progress_bar(self):
        if self.progress_bar is not None:
            self.layout.insertStretch(0)
            self.layout.removeWidget(self.progress_bar)
            self.progress_bar.close()
            self.progress_bar = None

    def show_dialog(self):
        dialog = AlgorithmMonitorDialog(self, self.presenter.model)
        dialog.show()
コード例 #2
0
ファイル: flux_units.py プロジェクト: kassin/cubeviz
class ConvertFluxUnitGUI(QDialog):
    """
    GUI for unit conversions
    """
    def __init__(self, controller, parent=None):
        super(ConvertFluxUnitGUI, self).__init__(parent=parent)
        self.setWindowFlags(self.windowFlags() | Qt.Tool)
        self.title = "Unit Conversion"
        self.setMinimumSize(400, 270)

        self.cubeviz_layout = controller.cubeviz_layout
        self._hub = self.cubeviz_layout.session.hub

        self.controller = controller
        self.data = controller.data
        self.controller_components = controller._components

        self.current_unit = None

        self._init_ui()

    def _init_ui(self):
        # LINE 1: Data component drop down
        self.component_prompt = QLabel("Data Component:")
        self.component_prompt.setWordWrap(True)
        # Add the data component labels to the drop down, with the ComponentID
        # set as the userData:
        if self.parent is not None and hasattr(self.parent, 'data_components'):
            self.label_data = [(str(cid), cid) for cid in self.parent.data_components]
        else:
            self.label_data = [(str(cid), cid) for cid in self.data.visible_components]

        default_index = 0
        self.component_combo = QComboBox()
        self.component_combo.setFixedWidth(200)
        update_combobox(self.component_combo, self.label_data, default_index=default_index)
        self.component_combo.currentIndexChanged.connect(self.update_unit_layout)

        # hbl is short for Horizontal Box Layout
        hbl1 = QHBoxLayout()
        hbl1.addWidget(self.component_prompt)
        hbl1.addWidget(self.component_combo)
        hbl1.addStretch(1)

        # LINE 2: Unit conversion layout
        # This layout is filled by CubeVizUnit
        self.unit_layout = QHBoxLayout()  # this is hbl2

        # LINE 3: Message box
        self.message_box = QLabel("")
        hbl3 = QHBoxLayout()
        hbl3.addWidget(self.message_box)
        hbl3.addStretch(1)

        # Line 4: Buttons
        self.okButton = QPushButton("Convert Units")
        self.okButton.clicked.connect(self.call_main)
        self.okButton.setDefault(True)

        self.cancelButton = QPushButton("Cancel")
        self.cancelButton.clicked.connect(self.cancel)

        hbl4 = QHBoxLayout()
        hbl4.addStretch(1)
        hbl4.addWidget(self.cancelButton)
        hbl4.addWidget(self.okButton)

        vbl = QVBoxLayout()
        vbl.addLayout(hbl1)
        vbl.addLayout(self.unit_layout)
        vbl.addLayout(hbl3)
        vbl.addLayout(hbl4)
        self.setLayout(vbl)
        self.vbl = vbl

        self.update_unit_layout(default_index)

        self.show()

    def update_unit_layout(self, index):
        """
        Call back for component selection drop down.
        """
        component_id = str(self.component_combo.currentData())

        # STEP1: Clean up widgets from last component
        widgets = (self.unit_layout.itemAt(i) for i in range(self.unit_layout.count()))
        for w in widgets:
            if isinstance(w, QSpacerItem):
                self.unit_layout.removeItem(w)
                continue
            elif isinstance(w, QWidgetItem):
                w = w.widget()

            if hasattr(w, "deleteLater"):
                w.deleteLater()

        self.message_box.setText("")

        if self.current_unit:
            self.current_unit.reset_widgets()

        # STEP2: Add now component and connect to CubeVizUnit
        #        so that new widgets are populated.
        if component_id in self.controller_components:
            cubeviz_unit = self.controller_components[component_id]
            self.current_unit = cubeviz_unit
            cubeviz_unit.set_message_box(self.message_box)
            cubeviz_unit.populate_unit_layout(self.unit_layout, self)
            if cubeviz_unit.is_convertible:
                self.okButton.setEnabled(True)
            else:
                self.okButton.setEnabled(False)
        else:
            self.current_unit = None
            default_message = "CubeViz can not convert this unit."
            default_label = QLabel(default_message)
            self.unit_layout.addWidget(default_label)
            self.okButton.setEnabled(False)

        self.unit_layout.update()
        self.vbl.update()

    def call_main(self):
        """
        Calls CubeVizUnit.change_units to finalize
        conversions. Updates plots with new units.
        :return:
        """
        success = self.current_unit.change_units()
        if not success:
            # Todo: Warning should pop up
            return

        component_id = self.component_combo.currentData()
        self.data.get_component(component_id).units = self.current_unit.unit_string
        msg = FluxUnitsUpdateMessage(self, self.current_unit.unit, component_id)
        self._hub.broadcast(msg)
        self.close()

    def cancel(self):
        self.close()
コード例 #3
0
class ConvertFluxUnitGUI(QDialog):
    """
    GUI for unit conversions
    """
    def __init__(self, controller, parent=None, convert_data=False):
        super(ConvertFluxUnitGUI, self).__init__(parent=parent)
        self.setWindowFlags(self.windowFlags() | Qt.Tool)
        self.title = "Unit Conversion"
        self.setMinimumSize(400, 270)

        self.convert_data = convert_data

        self.cubeviz_layout = controller.cubeviz_layout
        self._hub = self.cubeviz_layout.session.hub

        self.controller = controller
        self.data = controller.data
        self.controller_components = controller._components

        self.current_unit = None
        self.current_layout = None

        self._init_ui()

    def _init_ui(self):
        # LINE 1: Data component drop down
        self.component_prompt = QLabel("Data Component:")
        self.component_prompt.setWordWrap(True)
        # Add the data component labels to the drop down, with the ComponentID
        # set as the userData:
        if self.parent is not None and hasattr(self.parent, 'data_components'):
            self.label_data = [(str(cid), cid) for cid in self.parent.data_components]
        else:
            self.label_data = [(str(cid), cid) for cid in self.data.visible_components]

        default_index = 0
        self.component_combo = QComboBox()
        self.component_combo.setFixedWidth(200)
        update_combobox(self.component_combo, self.label_data, default_index=default_index)
        self.component_combo.currentIndexChanged.connect(self.update_unit_layout)

        # hbl is short for Horizontal Box Layout
        hbl1 = QHBoxLayout()
        hbl1.addWidget(self.component_prompt)
        hbl1.addWidget(self.component_combo)
        hbl1.addStretch(1)

        # LINE 2: Unit conversion layout
        # This layout is filled by CubeVizUnit
        self.unit_layout = QHBoxLayout()  # this is hbl2

        # LINE 3: Message box
        self.message_box = QLabel("")
        hbl3 = QHBoxLayout()
        hbl3.addWidget(self.message_box)
        hbl3.addStretch(1)

        # Line 4: Buttons
        ok_text = "Convert Data" if self.convert_data else "Convert Displayed Units"
        ok_function = self.convert_data_units if self.convert_data else self.convert_displayed_units
        self.okButton = QPushButton(ok_text)
        self.okButton.clicked.connect(ok_function)
        self.okButton.setDefault(True)

        self.cancelButton = QPushButton("Cancel")
        self.cancelButton.clicked.connect(self.cancel)

        hbl4 = QHBoxLayout()
        hbl4.addStretch(1)
        hbl4.addWidget(self.cancelButton)
        hbl4.addWidget(self.okButton)

        vbl = QVBoxLayout()
        vbl.addLayout(hbl1)
        vbl.addLayout(self.unit_layout)
        vbl.addLayout(hbl3)
        vbl.addLayout(hbl4)
        self.setLayout(vbl)
        self.vbl = vbl

        self.update_unit_layout(default_index)

        self.show()

    def update_unit_layout(self, index):
        """
        Call back for component selection drop down.
        """
        component_id = self.component_combo.currentData()

        # STEP1: Clean up widgets from last component
        widgets = (self.unit_layout.itemAt(i) for i in range(self.unit_layout.count()))
        for w in widgets:
            if isinstance(w, QSpacerItem):
                self.unit_layout.removeItem(w)
                continue
            elif isinstance(w, QWidgetItem):
                w = w.widget()

            if hasattr(w, "deleteLater"):
                w.deleteLater()

        self.message_box.setText("")

        if self.current_layout:
            self.current_layout.reset_widgets()

        # STEP2: Add now component and connect to CubeVizUnit
        #        so that new widgets are populated.
        if component_id in self.controller_components:
            cubeviz_unit = self.controller_components[component_id]
            self.current_unit = cubeviz_unit

            wave = self.controller.wave
            pixel_area = self.controller.pixel_area
            layout = assign_cubeviz_unit_layout(cubeviz_unit,
                                                wave=wave,
                                                pixel_area=pixel_area)
            layout.set_message_box(self.message_box)
            layout.populate_unit_layout(self.unit_layout, self)
            self.current_layout = layout
            if ASTROPY_CubeVizUnit == cubeviz_unit.type:
                self.okButton.setEnabled(True)
            else:
                self.okButton.setEnabled(False)
        else:
            self.current_unit = None
            default_message = "CubeViz can not convert this unit."
            default_label = QLabel(default_message)
            self.unit_layout.addWidget(default_label)
            self.okButton.setEnabled(False)

        self.unit_layout.update()
        self.vbl.update()

    def convert_displayed_units(self):
        """
        Calls CubeVizUnit.change_units to finalize
        conversions. Updates plots with new units.
        :return:
        """
        success = self.current_layout.change_units()
        if not success:
            info = QMessageBox.critical(self, "Error", "Conversion failed.")
            return

        new_unit = self.current_layout.new_unit
        self.current_unit.unit = new_unit
        self.current_unit.unit_string = str(new_unit)

        component_id = self.component_combo.currentData()
        self.data.get_component(component_id).units = self.current_unit.unit_string
        msg = FluxUnitsUpdateMessage(self, self.current_unit, component_id)
        self._hub.broadcast(msg)
        self.close()

    def convert_data_units(self):
        """
        Calls CubeVizUnit.change_units to finalize
        conversions. Updates plots with new units.
        :return:
        """
        success = self.current_layout.change_units()
        if not success:
            info = QMessageBox.critical(self, "Error", "Conversion failed.")
            return

        new_unit = self.current_layout.new_unit
        self.current_unit.unit = new_unit
        self.current_unit.unit_string = str(new_unit)

        component_id = self.component_combo.currentData()
        component = component_id.parent.get_component(component_id)

        old_array = component._data.copy()
        old_array.flags.writeable = True

        wavelengths = self.controller.construct_3d_wavelengths(old_array)

        new_array = self.current_unit.convert_value(old_array, wave=wavelengths)

        component._data = new_array

        self.current_unit = self.controller.add_component_unit(component_id, new_unit)
        component.units = self.current_unit.unit_string
        msg = FluxUnitsUpdateMessage(self, self.current_unit, component_id)
        self._hub.broadcast(msg)
        self.close()

    def cancel(self):
        self.close()
コード例 #4
0
class CodePreviewWidget(QWidget):
    def __init__(self, main_window, flow):
        super(CodePreviewWidget, self).__init__()

        self.codes = {
            # structure:
            #
            #   <node>: {
            #       <object>: {                 (the node instance or some widget instance)
            #           'title': str,           (for faster widget building)
            #           'original': str,        (original code comes from Node.__class_codes__)
            #           'edited': str(None),    (initially None)
            #       }
            #   }
        }
        self.node = None  # currently displayed node
        self.current_obj = None  # reference to the currently shown/edited object
        self.radio_buttons = []  # the radio buttons to select a source

        flow.nodes_selection_changed.connect(self.set_selected_nodes)

        self.text_edit = CodeEditorWidget(main_window.theme)
        self.setup_ui()

        self.set_node(None)

    def setup_ui(self):

        secondary_layout = QHBoxLayout()

        # class radio buttons widget
        self.class_selection_layout = QHBoxLayout()  # QGridLayout()

        secondary_layout.addLayout(self.class_selection_layout)
        self.class_selection_layout.setAlignment(Qt.AlignLeft)
        # secondary_layout.setAlignment(self.class_selection_layout, Qt.AlignLeft)

        # edit source code buttons
        self.edit_code_button = QPushButton('edit')
        self.edit_code_button.setProperty('class', 'small_button')
        self.edit_code_button.setMaximumWidth(100)
        self.edit_code_button.clicked.connect(self.edit_code_button_clicked)
        self.override_code_button = QPushButton('override')
        self.override_code_button.setProperty('class', 'small_button')
        self.override_code_button.setMaximumWidth(100)
        self.override_code_button.setEnabled(False)
        self.override_code_button.clicked.connect(
            self.override_code_button_clicked)
        self.reset_code_button = QPushButton('reset')
        self.reset_code_button.setProperty('class', 'small_button')
        self.reset_code_button.setMaximumWidth(206)
        self.reset_code_button.setEnabled(False)
        self.reset_code_button.clicked.connect(self.reset_code_button_clicked)

        edit_buttons_layout = QHBoxLayout()
        # edit_buttons_layout.addWidget(self.highlight_code_button)
        edit_buttons_layout.addWidget(self.edit_code_button)
        edit_buttons_layout.addWidget(self.override_code_button)
        edit_buttons_layout.addWidget(self.reset_code_button)
        # edit_buttons_layout.addWidget(self.highlight_code_button)

        secondary_layout.addLayout(edit_buttons_layout)
        edit_buttons_layout.setAlignment(Qt.AlignRight)

        main_layout = QVBoxLayout()
        main_layout.addLayout(secondary_layout)
        main_layout.addWidget(self.text_edit)
        self.setLayout(main_layout)

    def set_selected_nodes(self, nodes):
        if len(nodes) == 0:
            self.set_node(None)
        else:
            self.set_node(nodes[-1])

    def set_node(self, node):

        self.node = node

        if node is None or node.__class_codes__ is None:  # no node selected / only imported nodes have __class_codes__
            # clear view
            self.text_edit.set_code('')
            self.edit_code_button.setEnabled(False)
            self.override_code_button.setEnabled(False)
            self.reset_code_button.setEnabled(False)
            self.clear_class_layout()
            return

        if node not in self.codes:  # node not yet registered

            # save class sources for all objects (node, main_widget, custom input widgets)

            # saving it in this structure enables easy view updates and src code overrides

            node_objects = {
                node: {
                    'title': 'node',
                    'original cls': node.__class_codes__['node cls'],
                    'original mod': node.__class_codes__['node mod'],
                    'modified cls': None,
                },
            }

            if node.main_widget():
                node_objects[node.main_widget()] = {
                    'title': 'main widget',
                    'original cls': node.__class_codes__['main widget cls'],
                    'original mod': node.__class_codes__['main widget mod'],
                    'modified cls': None
                }

            for i in range(len(node.inputs)):
                iw = node.item.inputs[i].widget
                if iw:
                    # find code
                    code = ''
                    for name, cls in node.input_widget_classes.items():
                        if cls == iw.__class__:
                            code = node.__class_codes__[
                                'custom input widgets'][name]['cls']
                            break

                    else:  # no break -> no custom widget (builtin widget) -> ignore
                        continue

                    node_objects[iw] = {
                        'title': f'inp {i}',
                        'original cls': code,
                        'modified cls': None,
                    }

            self.codes[node] = node_objects

        self.rebuild_class_selection(node)
        self.update_edit_statuses()

        self.edit_code_button.setEnabled(True)

        self.update_code(node, node)

    def update_code(self, node, obj):
        """
        Updates the 'modified' field in the nodes dict
        """

        self.disable_editing()
        self.text_edit.disable_highlighting()

        self.current_obj = obj

        orig = self.codes[node][obj]['original cls']
        modf = self.codes[node][obj]['modified cls']

        if modf:
            code = modf
            self.reset_code_button.setEnabled(True)
        else:
            code = orig
            self.reset_code_button.setEnabled(False)

        self.text_edit.set_code(code)

    def rebuild_class_selection(self, node):

        self.clear_class_layout()

        self.radio_buttons.clear()

        for obj, d in self.codes[node].items():
            rb = LinkedRadioButton(d['title'], node, obj)
            rb.toggled.connect(self.class_RB_toggled)
            self.class_selection_layout.addWidget(rb)
            self.radio_buttons.append(rb)

        self.radio_buttons[0].setChecked(True)

    def clear_class_layout(self):

        # clear layout
        for i in range(self.class_selection_layout.count()):
            item = self.class_selection_layout.itemAt(0)
            widget = item.widget()
            widget.hide()
            self.class_selection_layout.removeItem(item)

    def update_edit_statuses(self):
        """
        Draws radio buttons referring to modified objects bold
        """

        for b in self.radio_buttons:
            if self.codes[b.node][b.obj]['modified cls']:
                # o.setStyleSheet('color: #3B9CD9;')
                f = b.font()
                f.setBold(True)
                b.setFont(f)
            else:
                # o.setStyleSheet('color: white;')
                f = b.font()
                f.setBold(False)
                b.setFont(f)

    def class_RB_toggled(self, checked):
        if checked:
            self.update_code(self.sender().node, self.sender().obj)

    def edit_code_button_clicked(self):
        if not EditSrcCodeInfoDialog.dont_show_again:
            info_dialog = EditSrcCodeInfoDialog(self)
            accepted = info_dialog.exec_()
            if not accepted:
                return
        self.enable_editing()

    def enable_editing(self):
        self.text_edit.enable_editing()
        self.override_code_button.setEnabled(True)

    def disable_editing(self):
        self.text_edit.disable_editing()
        self.override_code_button.setEnabled(False)

    def override_code_button_clicked(self):

        new_code = self.text_edit.get_code()

        SrcCodeUpdater.override_code(
            obj=self.current_obj,
            new_class_src=new_code,
        )

        self.codes[self.node][self.current_obj]['modified cls'] = new_code

        self.disable_editing()

        self.reset_code_button.setEnabled(True)
        self.update_edit_statuses()

    def reset_code_button_clicked(self):

        code = self.codes[self.node][self.current_obj]['original cls']

        SrcCodeUpdater.override_code(obj=self.current_obj, new_class_src=code)

        self.codes[self.node][self.current_obj]['modified cls'] = None

        self.update_code(self.node, self.current_obj)
        self.update_edit_statuses()