Exemplo n.º 1
0
class UiUnitChangeDialog(QDialog):
    def __init__(self, parent=None):
        super(UiUnitChangeDialog, self).__init__(parent)

        # Dialog settings
        self.setWindowTitle("Change Plot Units")

        self.layout_vertical = QVBoxLayout(self)
        self.form_layout = QFormLayout()
        self.layout_vertical.addLayout(self.form_layout)

        # Flux unit
        self.label_flux_unit = QLabel(self)
        self.line_edit_flux_unit = QLineEdit(self)

        self.label_flux_unit.setText("Flux Unit")

        self.form_layout.addRow(self.label_flux_unit, self.line_edit_flux_unit)

        # Dispersion unit
        self.label_disp_unit = QLabel(self)
        self.line_edit_disp_unit = QLineEdit(self)

        self.label_disp_unit.setText("Dispersion Unit")

        self.form_layout.addRow(self.label_disp_unit, self.line_edit_disp_unit)

        self.button_box = QDialogButtonBox(self)
        self.button_box.setOrientation(Qt.Horizontal)
        self.button_box.setStandardButtons(QDialogButtonBox.Cancel
                                           | QDialogButtonBox.Ok)
        self.layout_vertical.addWidget(self.button_box)

        self.button_box.accepted.connect(self.accept)
        self.button_box.rejected.connect(self.reject)
Exemplo n.º 2
0
class UiLayerArithmeticDialog(QDialog):
    def __init__(self, parent=None):
        super(UiLayerArithmeticDialog, self).__init__(parent)

        # Dialog settings
        self.setWindowTitle("Layer Arithmetic")
        self.resize(354, 134)

        self.layout_vertical = QVBoxLayout(self)

        # Arithmetic group box
        self.group_box_arithmetic = QGroupBox(self)
        self.group_box_arithmetic.setTitle("Formula")

        self.line_edit_formula = QLineEdit(self.group_box_arithmetic)

        self.layout_horizontal = QHBoxLayout(self.group_box_arithmetic)
        self.layout_horizontal.addWidget(self.line_edit_formula)
        self.layout_vertical.addWidget(self.group_box_arithmetic)

        # Buttons
        self.button_box = QDialogButtonBox(self)
        self.button_box.setOrientation(Qt.Horizontal)
        self.button_box.setStandardButtons(QDialogButtonBox.Cancel
                                           | QDialogButtonBox.Ok)
        self.button_box.accepted.connect(self.accept)
        self.button_box.rejected.connect(self.reject)

        self.layout_vertical.addWidget(self.button_box)
Exemplo n.º 3
0
class UiSmoothingDialog(QDialog):
    """
    Initialize all the TopAxisDialog Qt UI elements.
    """
    def __init__(self, *args, **kwargs):
        super(UiSmoothingDialog, self).__init__(*args, **kwargs)
        size_policy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
        size_policy.setHorizontalStretch(0)
        size_policy.setVerticalStretch(0)
        self.setSizePolicy(size_policy)

        # Dialog settings
        self.setWindowTitle("Smoothing Dialog")

        self.layout_vertical = QVBoxLayout(self)
        self.layout_horizontal = QHBoxLayout()
        self.layout_vertical.addLayout(self.layout_horizontal)

        # Define header selectors
        self.label_axis_mode = QLabel(self)
        self.combo_box_kernel = QComboBox(self)

        self.label_axis_mode.setText("Kernel")

        self.layout_horizontal.addWidget(self.label_axis_mode)
        self.layout_horizontal.addWidget(self.combo_box_kernel)
        self.layout_horizontal.setStretch(1, 1)

        # Define velocity
        self.group_box = QGroupBox(self)
        self.label_stddev = QLabel(self.group_box)
        self.line_edit_stddev = QLineEdit(self.group_box)

        self.group_box.setTitle("Parameters")
        self.label_stddev.setText("Standard Deviation")

        self.layout_horizontal_2 = QHBoxLayout(self.group_box)
        self.layout_horizontal_2.addWidget(self.label_stddev)
        self.layout_horizontal_2.addWidget(self.line_edit_stddev)

        self.layout_vertical.addWidget(self.group_box)

        # Add a spacer
        self.layout_vertical.addStretch(1)

        # Buttons
        self.button_box = QDialogButtonBox(self)
        self.button_box.setOrientation(Qt.Horizontal)
        self.button_box.setStandardButtons(QDialogButtonBox.Cancel
                                           | QDialogButtonBox.Ok)
        self.button_box.setObjectName("buttonBox")
        self.layout_vertical.addWidget(self.button_box)

        self.button_box.accepted.connect(self.accept)
        self.button_box.rejected.connect(self.reject)
Exemplo n.º 4
0
class NewModelDialog(QDialog):

    def __init__(self, parent=None):
        QDialog.__init__(
            self, parent, flags=Qt.WindowSystemMenuHint | Qt.WindowTitleHint)
        self.setWindowTitle('Create New Model')
        self.treeview = parent
        self.setAttribute(Qt.WA_DeleteOnClose)

        namelabel = QLabel(_("Model Name"))
        self.nameEdit = QLineEdit(self)
        self.importWidget = ImportAsWidget(self, self.nameEdit)

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setStandardButtons(
            QDialogButtonBox.Cancel|QDialogButtonBox.Ok)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)

        mainLayout = QGridLayout(self)
        mainLayout.addWidget(namelabel, 0, 0)
        mainLayout.addWidget(self.nameEdit, 0, 1)
        mainLayout.addWidget(self.importWidget, 1, 0, 1, 2)
        mainLayout.addWidget(self.buttonBox, 2, 0, 1, 2)
        self.setLayout(mainLayout)

    def accept(self) -> None:
        reply = {
            'accepted': True,
            'name': self.nameEdit.text(),
            'define_var': self.importWidget.shouldImport.isChecked(),
            'varname': self.importWidget.nameEdit.text()
        }
        if reply['define_var']:
            varname = reply['varname']
            if not check_varname(varname):
                QMessageBox.critical(
                    self,
                    'Error',
                    'Invalid variable name: %s' % varname
                )
                return
        self.treeview.reply = reply
        super().accept()

    def reject(self) -> None:
        self.treeview.reply = {'accepted': False}
        super().reject()
Exemplo n.º 5
0
class ImportNamesDialog(QDialog):

    def __init__(self, parent=None):
        QDialog.__init__(
            self, parent, flags=Qt.WindowSystemMenuHint | Qt.WindowTitleHint)
        self.setWindowTitle('Import Names')
        self.treeview = parent
        self.setAttribute(Qt.WA_DeleteOnClose)

        self.importSelected = QCheckBox(_("Import selected"), self)
        self.importSelected.setCheckState(Qt.Checked)
        self.importChildren = QCheckBox(_("Import children"), self)
        self.importChildren.setCheckState(Qt.Checked)
        self.replaceExisting = QCheckBox(_("Replace existing names"), self)
        self.replaceExisting.setCheckState(Qt.Checked)

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setStandardButtons(
            QDialogButtonBox.Cancel|QDialogButtonBox.Ok)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)

        mainLayout = QGridLayout(self)
        mainLayout.addWidget(self.importSelected)
        mainLayout.addWidget(self.importChildren)
        mainLayout.addWidget(self.replaceExisting)
        mainLayout.addWidget(self.buttonBox)
        self.setLayout(mainLayout)

    def accept(self) -> None:
        reply = {
            'accepted': True,
            'import_selected': self.importSelected.isChecked(),
            'import_children': self.importChildren.isChecked(),
            'replace_existing': self.replaceExisting.isChecked()
        }
        self.treeview.reply = reply
        super().accept()

    def reject(self) -> None:
        self.treeview.reply = {'accepted': False}
        super().reject()
Exemplo n.º 6
0
class FormulaPane(BaseCodePane):

    def __init__(self, parent, title='', code='', editor_type=MxCodeEditor):
        super().__init__(parent, title, code, editor_type)

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.saveButton = QPushButton(_("Save"))
        self.discardButton = QPushButton(_("Discard"))
        self.buttonBox.addButton(self.saveButton, QDialogButtonBox.AcceptRole)
        self.buttonBox.addButton(
            self.discardButton, QDialogButtonBox.RejectRole)

        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)

        self.bottomLayout = QHBoxLayout()
        self.bottomLayout.setContentsMargins(5, 0, 5, 5)
        self.status = QLabel()
        self.bottomLayout.addWidget(self.status)
        self.bottomLayout.addWidget(self.buttonBox)
        self.layout.addLayout(self.bottomLayout)
        self.clearCode()

    def setCode(self, source, reconnect=True):
        self.editor.set_text(source)
        self.resetModification()
        if reconnect:
            self.editor.modificationChanged.connect(self.activateActions)
        self.editor.setReadOnly(False)

    def clearCode(self):
        self.editor.set_text("")
        try:
            self.editor.modificationChanged.disconnect(self.activateActions)
        except TypeError:
            pass
        self.editor.setReadOnly(True)
        self.resetModification()

    def resetModification(self):
        self.editor.document().setModified(False)
        self.updateStatus()
        self.saveButton.setEnabled(False)
        self.discardButton.setEnabled(False)

    def updateStatus(self):
        modified = self.editor.document().isModified()
        if modified:
            self.status.setText("Modified")
        else:
            self.status.setText("")

    @Slot(bool)
    def activateActions(self, status):
        if status:
            self.saveButton.setEnabled(True)
            self.discardButton.setEnabled(True)
            self.updateStatus()

    def accept(self):
        self.parent().formula_updated()

    def reject(self):
        self.parent().shell.reload_mxproperty()
Exemplo n.º 7
0
class UiTopAxisDialog(QDialog):
    """
    Initialize all the TopAxisDialog Qt UI elements.
    """
    def __init__(self, *args, **kwargs):
        super(UiTopAxisDialog, self).__init__(*args, **kwargs)
        self.setObjectName("Top Axis Dialog")

        size_policy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
        size_policy.setHorizontalStretch(0)
        size_policy.setVerticalStretch(0)
        self.setSizePolicy(size_policy)

        # Dialog settings
        self.setWindowTitle("Axis Settings")

        self.layout_vertical = QVBoxLayout(self)
        self.layout_horizontal = QHBoxLayout()
        self.layout_vertical.addLayout(self.layout_horizontal)

        # Define header selectors
        self.label_axis_mode = QLabel(self)
        self.combo_box_axis_mode = QComboBox(self)

        self.label_axis_mode.setText("Axis mode")

        self.layout_horizontal.addWidget(self.label_axis_mode)
        self.layout_horizontal.addWidget(self.combo_box_axis_mode)

        # Define velocity
        self.group_box_velocity = QGroupBox(self)
        self.label_reference_wavelength = QLabel(self.group_box_velocity)
        self.line_edit_reference_wavelength = QLineEdit(
            self.group_box_velocity)

        self.group_box_velocity.setTitle("Velocity parameters")
        self.label_reference_wavelength.setText("Reference wavelength")

        self.layout_horizontal_2 = QHBoxLayout(self.group_box_velocity)
        self.layout_horizontal_2.addWidget(self.label_reference_wavelength)
        self.layout_horizontal_2.addWidget(self.line_edit_reference_wavelength)

        self.layout_vertical.addWidget(self.group_box_velocity)

        # Define redshift
        self.group_box_redshift = QGroupBox(self)
        self.label_redshift = QLabel(self.group_box_redshift)
        self.line_edit_redshift = QLineEdit(self.group_box_redshift)

        self.group_box_redshift.setTitle("Redshift parameters")
        self.label_redshift.setText("Amount")

        self.layout_horizontal_3 = QHBoxLayout(self.group_box_redshift)
        self.layout_horizontal_3.addWidget(self.label_redshift)
        self.layout_horizontal_3.addWidget(self.line_edit_redshift)

        self.layout_vertical.addWidget(self.group_box_redshift)

        # Add a spacer
        self.layout_vertical.addStretch(1)

        # Buttons
        self.button_box = QDialogButtonBox(self)
        self.button_box.setOrientation(Qt.Horizontal)
        self.button_box.setStandardButtons(QDialogButtonBox.Cancel
                                           | QDialogButtonBox.Ok)
        self.button_box.setObjectName("buttonBox")
        self.layout_vertical.addWidget(self.button_box)

        self.button_box.accepted.connect(self.accept)
        self.button_box.rejected.connect(self.reject)
Exemplo n.º 8
0
class AlarmTreeEditorDisplay(Display):
    def __init__(self, parent=None):
        super(AlarmTreeEditorDisplay, self).__init__(parent=parent)

        self.app = QApplication.instance()

        # set up the ui
        self.setup_ui()

        # allow add and remove row
        self.add_button.clicked.connect(self.insertChild)
        self.remove_button.clicked.connect(self.removeItem)
        self.remove_button.setEnabled(True)

        # connect save changes
        self.button_box.accepted.connect(self.save_property_changes)

        # upon tree view selection, change the item view
        self.tree_view.selectionModel().selectionChanged.connect(
            self.handle_selection)
        self.tree_view.tree_model.dataChanged.connect(self.item_change)

        self.file_dialog = QFileDialog()
        self.open_config_action = QAction("Open", self)
        self.open_config_action.triggered.connect(self.open_file)
        self.toolbar.addAction(self.open_config_action)

        self.save_config_action = QAction("Save", self)
        self.save_config_action.triggered.connect(self.save_configuration)
        self.toolbar.addAction(self.save_config_action)

        # update configuration name
        self.tree_label.editingFinished.connect(self._update_config_name)

        # default open size
        self.resize(800, 600)

        self.config_tool = PhoebusConfigTool()

    def setup_ui(self):
        self.main_layout = QGridLayout()
        self.setLayout(self.main_layout)

        # add toolbar
        self.toolbar = QToolBar()
        self.main_layout.setMenuBar(self.toolbar)

        # create the tree view layout and add/remove buttons
        self.tree_view_layout = QVBoxLayout()
        self.tree_view = PyDMAlarmTree(self,
                                       config_name="UNITITLED",
                                       edit_mode=True)
        self.tree_view.setEditTriggers(QAbstractItemView.DoubleClicked)
        self.tree_view.setSelectionMode(QAbstractItemView.SingleSelection)
        self.tree_view.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.tree_view.setHeaderHidden(True)

        # Drag/drop
        self.tree_view.setDragDropMode(QAbstractItemView.InternalMove)
        self.tree_view.setDragEnabled(True)
        self.tree_view.setAcceptDrops(True)

        # view sizing
        self.tree_view.setColumnWidth(0, 160)
        self.tree_view.setColumnWidth(1, 160)
        self.tree_view.setColumnWidth(2, 160)

        # lable for tree view
        configuration_indicator = QLabel("Configuration:")
        self.tree_label = QLineEdit("Untitled")

        self.tree_label_layout = QHBoxLayout()
        self.tree_label_layout.addWidget(configuration_indicator)
        self.tree_label_layout.addWidget(self.tree_label)

        self.tree_view_layout.addLayout(self.tree_label_layout)
        self.tree_view_layout.addWidget(self.tree_view)

        # add/ remove buttons
        self.add_remove_layout = QHBoxLayout()
        spacer = QSpacerItem(40, 20, QSizePolicy.Expanding,
                             QSizePolicy.Minimum)
        self.add_remove_layout.addItem(spacer)
        self.add_button = QPushButton("New", self)
        self.add_remove_layout.addWidget(self.add_button)
        self.remove_button = QPushButton("Remove", self)
        self.add_remove_layout.addWidget(self.remove_button)
        self.tree_view_layout.addLayout(self.add_remove_layout)

        # add the tree view to the window
        self.main_layout.addLayout(self.tree_view_layout, 0, 0)

        self.property_layout = QVBoxLayout()
        self.property_layout.addWidget(QLabel("Alarm Properties"))

        # crate property view
        self.property_data_layout = QStackedLayout()
        self.property_layout.addLayout(self.property_data_layout)

        self.property_widget_config = QWidget()
        self.property_widget_config.setWindowTitle("config")

        # create group widget
        self.property_widget_group = QWidget()
        self.property_widget_group.setWindowTitle("group")

        self.property_view_layout_group = QGridLayout()

        # add label
        self.label_edit_group = QLineEdit()
        self.label_label_group = QLabel("NAME")

        # add guidance
        self.guidance_edit_group = QLineEdit()
        self.guidance_label_group = QLabel("GUIDANCE")

        self.property_view_layout_group.addWidget(self.label_label_group, 1, 0)
        self.property_view_layout_group.addWidget(self.label_edit_group, 1, 1)

        self.property_view_layout_group.addWidget(self.guidance_label_group, 2,
                                                  0)
        self.property_view_layout_group.addWidget(self.guidance_edit_group, 2,
                                                  1)

        spacer = QSpacerItem(40, 200, QSizePolicy.Expanding,
                             QSizePolicy.Minimum)

        self.property_view_layout_group.addItem(spacer, 3, 0)
        self.property_view_layout_group.addItem(spacer, 4, 0)
        self.property_view_layout_group.addItem(spacer, 5, 0)
        self.property_view_layout_group.addItem(spacer, 6, 0)
        self.property_view_layout_group.addItem(spacer, 7, 0)
        self.property_view_layout_group.addItem(spacer, 8, 0)

        # create pv widget
        self.property_widget_pv = QWidget()
        self.property_widget_pv.setWindowTitle("pv")

        self.property_view_layout_pv = QGridLayout()

        # add label
        self.label_edit_pv = QLineEdit()
        self.label_label_pv = QLabel("NAME")

        # add guidance
        self.guidance_edit_pv = QLineEdit()
        self.guidance_label_pv = QLabel("GUIDANCE")

        self.property_view_layout_pv.addWidget(self.label_label_pv, 1, 0)
        self.property_view_layout_pv.addWidget(self.label_edit_pv, 1, 1, 1, 3)

        self.property_view_layout_pv.addWidget(self.guidance_label_pv, 2, 0)
        self.property_view_layout_pv.addWidget(self.guidance_edit_pv, 2, 1, 1,
                                               3)

        # add description
        self.description_edit = QLineEdit()
        self.description_label = QLabel("DESCRIPTION")
        self.property_view_layout_pv.addWidget(self.description_label, 3, 0)
        self.property_view_layout_pv.addWidget(self.description_edit, 3, 1, 1,
                                               3)

        # add delay
        self.delay_edit = QLineEdit()
        self.delay_label = QLabel("DELAY")
        self.property_view_layout_pv.addWidget(self.delay_label, 4, 0)
        self.property_view_layout_pv.addWidget(self.delay_edit, 4, 1, 1, 3)
        self.delay_edit.setValidator(QIntValidator())

        # add count
        self.count_edit = QLineEdit()
        self.count_label = QLabel("COUNT")
        self.property_view_layout_pv.addWidget(self.count_label, 5, 0)
        self.property_view_layout_pv.addWidget(self.count_edit, 5, 1, 1, 3)
        self.count_edit.setValidator(QIntValidator())

        # add filter/force pv
        self.filter_edit = QLineEdit()
        self.filter_label = QLabel("ENABLING FILTER")
        self.property_view_layout_pv.addWidget(self.filter_label, 6, 0)
        self.property_view_layout_pv.addWidget(self.filter_edit, 6, 1, 1, 3)

        # enabled, latching, annunciating
        self.enabled_check = QCheckBox("ENABLED")
        self.annunciating_check = QCheckBox("ANNUNCIATING")
        self.latching_check = QCheckBox("LATCHING")
        self.property_view_layout_pv.addWidget(self.enabled_check, 7, 0)
        self.property_view_layout_pv.addWidget(self.annunciating_check, 7, 1)
        self.property_view_layout_pv.addWidget(self.latching_check, 7, 2)

        self.property_view_layout_pv.addItem(spacer, 8, 0)

        # create save button
        self.button_box = QDialogButtonBox(self)
        self.button_box.setOrientation(Qt.Horizontal)
        self.button_box.addButton("Save Properties",
                                  QDialogButtonBox.AcceptRole)

        self.property_layout.addWidget(self.button_box)
        # self.property_layout.addLayout(self.property_view_layout)

        self.property_widget_pv.setLayout(self.property_view_layout_pv)
        self.property_widget_group.setLayout(self.property_view_layout_group)

        self.property_data_layout.addWidget(self.property_widget_config)
        self.property_data_layout.addWidget(self.property_widget_pv)
        self.property_data_layout.addWidget(self.property_widget_group)

        self.main_layout.addLayout(self.property_layout, 0, 1)

        self.setWindowTitle("Alarm Tree Editor")
        self.tree_view.expandAll()

    def minimumSizeHint(self):
        # This is the default recommended size
        # for this screen
        return QSize(400, 200)

    def insertChild(self):
        index = self.tree_view.selectionModel().currentIndex()
        model = self.tree_view.model()

        if model.columnCount(index) == 0:
            if not model.insertColumn(0, index):
                return

        if not model.insertRow(0, index):
            return

        for column in range(model.columnCount(index)):
            child = model.index(0, column, index)
            model.set_data(child, label="NEW_ITEM", role=Qt.EditRole)

    def removeItem(self):
        index = self.tree_view.selectionModel().currentIndex()
        self.tree_view.model().removeRow(index.row(), index.parent())

    @Slot()
    def save_property_changes(self):
        index = self.tree_view.selectionModel().currentIndex()
        item = self.tree_view.model().getItem(index)
        if item.is_group:
            guidance = self.guidance_edit_group.text()
            label = self.label_edit_group.text()
        else:
            guidance = self.guidance_edit_pv.text()
            label = self.label_edit_pv.text()

        self.tree_view.model().set_data(
            index,
            label=label,
            description=self.description_edit.text(),
            delay=self.delay_edit.text(),
            count=self.count_edit.text(),
            enabled=self.enabled_check.isChecked(),
            annunciating=self.annunciating_check.isChecked(),
            latching=self.latching_check.isChecked(),
            alarm_filter=self.filter_edit.text(),
            guidance=guidance,
            role=Qt.EditRole,
        )

    @Slot()
    def handle_selection(self):
        self.remove_button.setEnabled(
            self.tree_view.selectionModel().hasSelection())

        index = self.tree_view.selectionModel().currentIndex()
        item = self.tree_view.model().getItem(index)

        if item.is_group:
            self.guidance_edit_group.setText(item.guidance)
            self.label_edit_group.setText(item.label)
        else:
            self.guidance_edit_pv.setText(item.guidance)
            self.label_edit_pv.setText(item.label)

        if item.is_group:
            # black for configuration screen
            if not item.parent:
                self.property_data_layout.setCurrentWidget(
                    self.property_widget_config)
            # otherwise show group screen and set all disables
            else:
                self.property_data_layout.setCurrentWidget(
                    self.property_widget_group)
                self.description_edit.setEnabled(False)
                self.description_edit.setVisible(False)
                self.description_label.setVisible(False)

                self.count_edit.setEnabled(False)
                self.count_edit.setVisible(False)
                self.count_label.setVisible(False)

                self.delay_edit.setEnabled(False)
                self.delay_edit.setVisible(False)
                self.delay_label.setVisible(False)

                self.latching_check.setEnabled(False)
                self.latching_check.setVisible(False)

                self.annunciating_check.setEnabled(False)
                self.annunciating_check.setVisible(False)

                self.filter_edit.setEnabled(False)
                self.filter_edit.setVisible(False)
                self.filter_label.setVisible(False)

        # set pv enabled
        else:
            self.property_data_layout.setCurrentWidget(self.property_widget_pv)
            self.description_edit.setEnabled(True)
            self.description_edit.setVisible(True)
            self.description_label.setVisible(True)

            self.count_edit.setEnabled(True)
            self.count_edit.setVisible(True)
            self.count_label.setVisible(True)

            self.delay_edit.setEnabled(True)
            self.delay_edit.setVisible(True)
            self.delay_label.setVisible(True)

            self.latching_check.setEnabled(True)
            self.latching_check.setVisible(True)

            self.annunciating_check.setEnabled(True)
            self.annunciating_check.setVisible(True)

            self.filter_edit.setEnabled(True)
            self.filter_edit.setVisible(True)
            self.filter_label.setVisible(True)

            if item.enabled:
                self.enabled_check.setChecked(True)
            else:
                self.enabled_check.setChecked(False)

            if item.latching:
                self.latching_check.setChecked(True)
            else:
                self.latching_check.setChecked(False)

            if item.annunciating:
                self.annunciating_check.setChecked(True)
            else:
                self.annunciating_check.setChecked(False)

    @Slot()
    def item_change(self):
        index = self.tree_view.selectionModel().currentIndex()
        item = self.tree_view.model().getItem(index)

        if item.is_group:
            self.guidance_edit_group.setText(item.guidance)
            self.label_edit_group.setText(item.label)
        else:
            self.guidance_edit_pv.setText(item.guidance)
            self.label_edit_pv.setText(item.label)

        if item.is_group:
            if not item.parent():
                self.property_data_layout.setCurrentWidget(
                    self.property_widget_config)

            else:
                self.property_data_layout.setCurrentWidget(
                    self.property_widget_group)

            self.description_edit.setEnabled(False)
            self.description_edit.setVisible(False)
            self.description_label.setVisible(False)

            self.count_edit.setEnabled(False)
            self.count_edit.setVisible(False)
            self.count_label.setVisible(False)

            self.delay_edit.setEnabled(False)
            self.delay_edit.setVisible(False)
            self.delay_label.setVisible(False)

            self.latching_check.setEnabled(False)
            self.latching_check.setVisible(False)

            self.annunciating_check.setEnabled(False)
            self.annunciating_check.setVisible(False)

            self.filter_edit.setEnabled(False)
            self.filter_edit.setVisible(False)
            self.filter_label.setVisible(False)

        else:
            self.delay_edit.setText(item.delay)
            self.count_edit.setText(item.count)

            if item.enabled:
                self.enabled_check.setChecked(True)
            else:
                self.enabled_check.setChecked(False)

            self.property_data_layout.setCurrentWidget(self.property_widget_pv)
            self.description_edit.setEnabled(True)
            self.description_edit.setVisible(True)
            self.description_label.setVisible(True)

            self.count_edit.setEnabled(True)
            self.count_edit.setVisible(True)
            self.count_label.setVisible(True)

            self.delay_edit.setEnabled(True)
            self.delay_edit.setVisible(True)
            self.delay_label.setVisible(True)

            self.latching_check.setEnabled(True)
            self.latching_check.setVisible(True)

            self.annunciating_check.setEnabled(True)
            self.annunciating_check.setVisible(True)

            self.filter_edit.setEnabled(True)
            self.filter_edit.setVisible(True)
            self.filter_label.setVisible(True)

            if item.latching:
                self.latching_check.setChecked(True)
            else:
                self.latching_check.setChecked(False)

            if item.annunciating:
                self.annunciating_check.setChecked(True)
            else:
                self.annunciating_check.setChecked(False)

    def ui_filepath(self):
        # No UI file is being used
        return None

    @Slot(bool)
    def open_file(self, checked):
        modifiers = QApplication.keyboardModifiers()
        try:
            curr_file = self.current_file()
            folder = os.path.dirname(curr_file)
        except Exception:
            folder = os.getcwd()

        filename = QFileDialog.getOpenFileName(
            self, "Open File...", folder,
            "XML (*.xml);; ALH Config (*.alhConfig)")
        filename = filename[0] if isinstance(filename,
                                             (list, tuple)) else filename

        if filename:
            filename = str(filename)

            # if alh file selected, open conversion prompt
            if filename[-9:] == "alhConfig":
                self.legacy_window = LegacyWindow(filename)
                self.legacy_window.exec_()

                if self.legacy_window.converted_filename:
                    self.import_configuration(
                        self.legacy_window.converted_filename)

            else:
                self.import_configuration(filename)

    def import_configuration(self, filename):
        nodes = self.config_tool.parse_config(filename)
        self.tree_view.model().import_hierarchy(nodes)
        self.tree_label.setText(self.tree_view.model()._nodes[0].label)

    @Slot()
    def save_configuration(self):
        modifiers = QApplication.keyboardModifiers()
        try:
            curr_file = self.current_file()
            folder = os.path.dirname(curr_file)
        except Exception:
            folder = os.getcwd()

        filename = QFileDialog.getSaveFileName(self, "Save File...", folder,
                                               "Configration files (*.xml)")
        filename = filename[0] if isinstance(filename,
                                             (list, tuple)) else filename

        self.config_tool.save_configuration(self.tree_view.model()._root_item,
                                            filename)

    def _update_config_name(self):
        name = self.tree_label.text()
        self.tree_view.model()._nodes[0].label = name

    def _import_legacy_file(self):
        convert_alh_to_phoebus()
Exemplo n.º 9
0
class BasePlotCurveEditorDialog(QDialog):
    """QDialog that is used in Qt Designer to edit the properties of the
    curves in a waveform plot.  This dialog is shown when you double-click
    the plot, or when you right click it and choose 'edit curves'.

    This thing is mostly just a wrapper for a table view, with a couple
    buttons to add and remove curves, and a button to save the changes."""
    TABLE_MODEL_CLASS = BasePlotCurvesModel

    def __init__(self, plot, parent=None):
        super(BasePlotCurveEditorDialog, self).__init__(parent)
        self.plot = plot
        self.setup_ui()
        self.table_model = self.TABLE_MODEL_CLASS(self.plot)
        self.table_view.setModel(self.table_model)
        self.table_model.plot = plot
        # self.table_view.resizeColumnsToContents()
        self.add_button.clicked.connect(self.addCurve)
        self.remove_button.clicked.connect(self.removeSelectedCurve)
        self.remove_button.setEnabled(False)
        self.table_view.selectionModel().selectionChanged.connect(
            self.handleSelectionChange)
        self.table_view.doubleClicked.connect(self.handleDoubleClick)
        self.resize(800, 300)

    def setup_ui(self):
        self.vertical_layout = QVBoxLayout(self)
        self.table_view = QTableView(self)
        self.table_view.setEditTriggers(QAbstractItemView.DoubleClicked)
        self.table_view.setProperty("showDropIndicator", False)
        self.table_view.setDragDropOverwriteMode(False)
        self.table_view.setSelectionMode(QAbstractItemView.SingleSelection)
        self.table_view.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.table_view.setSortingEnabled(False)
        self.table_view.horizontalHeader().setStretchLastSection(True)
        self.table_view.verticalHeader().setVisible(False)
        self.table_view.setColumnWidth(0, 160)
        self.table_view.setColumnWidth(1, 160)
        self.table_view.setColumnWidth(2, 160)
        self.vertical_layout.addWidget(self.table_view)
        self.add_remove_layout = QHBoxLayout()
        spacer = QSpacerItem(40, 20, QSizePolicy.Expanding,
                             QSizePolicy.Minimum)
        self.add_remove_layout.addItem(spacer)
        self.add_button = QPushButton("Add Curve", self)
        self.add_remove_layout.addWidget(self.add_button)
        self.remove_button = QPushButton("Remove Curve", self)
        self.add_remove_layout.addWidget(self.remove_button)
        self.vertical_layout.addLayout(self.add_remove_layout)
        self.button_box = QDialogButtonBox(self)
        self.button_box.setOrientation(Qt.Horizontal)
        self.button_box.addButton("Done", QDialogButtonBox.AcceptRole)
        self.vertical_layout.addWidget(self.button_box)
        self.button_box.accepted.connect(self.saveChanges)
        self.button_box.rejected.connect(self.reject)
        self.setWindowTitle("Waveform Curve Editor")

    def setup_delegate_columns(self, index=2):
        symbol_delegate = SymbolColumnDelegate(self)
        self.table_view.setItemDelegateForColumn(index+3, symbol_delegate)
        line_delegate = LineColumnDelegate(self)
        self.table_view.setItemDelegateForColumn(index+1, line_delegate)
        color_delegate = ColorColumnDelegate(self)
        self.table_view.setItemDelegateForColumn(index, color_delegate)

    @Slot()
    def addCurve(self):
        self.table_model.append()

    @Slot()
    def removeSelectedCurve(self):
        self.table_model.removeAtIndex(self.table_view.currentIndex())

    @Slot(QItemSelection, QItemSelection)
    def handleSelectionChange(self, selected, deselected):
        self.remove_button.setEnabled(
            self.table_view.selectionModel().hasSelection())

    @Slot(QModelIndex)
    def handleDoubleClick(self, index):
        if self.table_model.needsColorDialog(index):
            # The table model returns a QBrush for BackgroundRole, not a QColor
            init_color = self.table_model.data(index,
                                               Qt.BackgroundRole).color()
            color = QColorDialog.getColor(init_color, self)
            if color.isValid():
                self.table_model.setData(index, color, role=Qt.EditRole)

    @Slot()
    def saveChanges(self):
        formWindow = QDesignerFormWindowInterface.findFormWindow(self.plot)
        if formWindow:
            formWindow.cursor().setProperty("curves", self.plot.curves)
        self.accept()
Exemplo n.º 10
0
class NewCellsDialog(QDialog):

    def __init__(self, parent=None, parentList=(), currIndex=0):
        QDialog.__init__(
            self, parent, flags=Qt.WindowSystemMenuHint | Qt.WindowTitleHint)

        self.setAttribute(Qt.WA_DeleteOnClose)
        self.setWindowTitle('Create New Cells')
        self.treeview = parent

        parentLabel = QLabel(_("Parent"))
        self.parentBox = QComboBox(self)
        self.parentBox.addItems(parentList)
        self.parentBox.setCurrentIndex(currIndex)

        nameLabel = QLabel(_("Cells Name"))
        self.nameEdit = QLineEdit(self)
        self.importWidget = ImportAsWidget(self, self.nameEdit)

        self.formulaPane = BaseCodePane(parent, title='Formula')
        self.formulaPane.editor.setReadOnly(False)

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setStandardButtons(
            QDialogButtonBox.Cancel|QDialogButtonBox.Ok)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)

        mainLayout = QGridLayout(self)
        mainLayout.addWidget(parentLabel, 0, 0)
        mainLayout.addWidget(self.parentBox, 0, 1)
        mainLayout.addWidget(nameLabel, 1, 0)
        mainLayout.addWidget(self.nameEdit, 1, 1)
        mainLayout.addWidget(self.importWidget, 2, 0, 1, 2)
        mainLayout.addWidget(self.formulaPane, 3, 0, 1, 2)
        mainLayout.addWidget(self.buttonBox, 4, 0, 1, 2)
        mainLayout.setRowStretch(3, 1)
        self.setLayout(mainLayout)

    def accept(self) -> None:
        reply = {
            'accepted': True,
            'name': self.nameEdit.text(),
            'parent': self.parentBox.currentText(),
            'formula': self.formulaPane.editor.toPlainText(),
            'define_var': self.importWidget.shouldImport.isChecked(),
            'varname': self.importWidget.nameEdit.text()
        }
        varname = reply['varname']
        if not check_varname(varname):
            QMessageBox.critical(
                self,
                'Error',
                'Invalid variable name: %s' % varname
            )
            return
        self.treeview.reply = reply
        super().accept()

    def reject(self) -> None:
        self.treeview.reply = {
            'accepted': False
        }
        super().reject()
Exemplo n.º 11
0
class SelectFromListDialog(QDialog):
    """Dialog box for selecting multiple items.

    The original order of items are preserved in the candidate list.
    """

    def __init__(self, parent=None, allItems=(), selectedItems=()):
        QDialog.__init__(
            self, parent, flags=Qt.WindowSystemMenuHint | Qt.WindowTitleHint)

        self.allItems = allItems

        self.fromKeys = list(range(len(allItems)))
        self.selectedKeys = []
        for item in selectedItems:
            key = allItems.index(item)
            self.fromKeys.remove(key)
            self.selectedKeys.append(key)

        self.setAttribute(Qt.WA_DeleteOnClose)

        fromLabel = QLabel(_("Select from"))
        self.fromList = QListWidget(self)
        self.fromList.addItems(allItems[key] for key in self.fromKeys)

        selectedLabel = QLabel(_("Selected"))
        self.selectedList = QListWidget(self)
        self.selectedList.addItems(allItems[key] for key in self.selectedKeys)

        self.selectButton = QPushButton(_("Select"))
        self.deselectButton = QPushButton(_("Deselect"))
        self.selectBox = QDialogButtonBox(Qt.Vertical)
        self.selectBox.addButton(self.selectButton, QDialogButtonBox.ActionRole)
        self.selectBox.addButton(self.deselectButton, QDialogButtonBox.ActionRole)
        self.selectButton.clicked.connect(self.on_select)
        self.deselectButton.clicked.connect(self.on_deselect)

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setStandardButtons(
            QDialogButtonBox.Cancel|QDialogButtonBox.Ok)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)

        mainLayout = QGridLayout(self)
        mainLayout.addWidget(fromLabel, 0, 0)
        mainLayout.addWidget(selectedLabel, 0, 2)
        mainLayout.addWidget(self.fromList, 1, 0)
        mainLayout.addWidget(self.selectBox, 1, 1)
        mainLayout.addWidget(self.selectedList, 1, 2)
        mainLayout.addWidget(self.buttonBox, 2, 0, 1, 3)
        mainLayout.setAlignment(self.selectBox, Qt.AlignCenter)
        self.setLayout(mainLayout)

    def on_select(self):
        if len(self.fromList.selectedItems()):
            idx = self.fromList.currentRow()
            key = self.fromKeys.pop(idx)
            self.selectedKeys.append(key)
            item = self.fromList.takeItem(idx)
            self.selectedList.addItem(item)

    def on_deselect(self):
        if len(self.selectedList.selectedItems()):
            idx = self.selectedList.currentRow()
            item = self.selectedList.takeItem(idx)
            key = self.selectedKeys.pop(idx)
            idx = next((i for i, v in enumerate(self.fromKeys) if v > key),
                       len(self.fromKeys))
            self.fromKeys.insert(idx, key)
            self.fromList.insertItem(idx, item)
Exemplo n.º 12
0
class NewSpaceDialog(QDialog):

    def __init__(self, parent=None, parentList=(), currIndex=0):
        QDialog.__init__(
            self, parent, flags=Qt.WindowSystemMenuHint | Qt.WindowTitleHint)

        self.setAttribute(Qt.WA_DeleteOnClose)
        self.setWindowTitle('Create New Space')
        self.treeview = parent
        self.reply = None

        parentLabel = QLabel(_("Parent"))
        self.parentBox = QComboBox(self)
        self.parentBox.addItems(parentList)
        self.parentBox.setCurrentIndex(currIndex)

        nameLabel = QLabel(_("Space Name"))
        self.nameEdit = QLineEdit(self)
        self.importWidget = ImportAsWidget(self, self.nameEdit)

        basesTitle = QLabel(_("Base Spaces"))
        self.basesLine = QLineEdit()
        self.basesLine.setReadOnly(True)
        self.basesLine.setEnabled(False)
        self.basesEditButton = QPushButton(_("Edit"))
        self.basesEditButton.clicked.connect(self.on_base_edit)

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setStandardButtons(
            QDialogButtonBox.Cancel|QDialogButtonBox.Ok)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)

        mainLayout = QGridLayout(self)
        mainLayout.addWidget(parentLabel, 0, 0)
        mainLayout.addWidget(self.parentBox, 0, 1)
        mainLayout.addWidget(nameLabel, 1, 0)
        mainLayout.addWidget(self.nameEdit, 1, 1)
        mainLayout.addWidget(self.importWidget, 2, 0, 1, 2)
        mainLayout.addWidget(basesTitle, 3, 0)
        mainLayout.addWidget(self.basesLine, 3, 1)
        mainLayout.addWidget(self.basesEditButton, 3, 2)
        mainLayout.addWidget(self.buttonBox, 4, 0, 1, 2)
        self.setLayout(mainLayout)

    def accept(self) -> None:

        reply = {
            'accepted': True,
            'parent': self.parentBox.currentText(),
            'name': self.nameEdit.text(),
            'bases': self.basesLine.text(),
            'define_var': self.importWidget.shouldImport.isChecked(),
            'varname': self.importWidget.nameEdit.text()
        }
        if reply['define_var']:
            varname = reply['varname']
            if not check_varname(varname):
                QMessageBox.critical(
                    self,
                    'Error',
                    'Invalid variable name: %s' % varname
                )
                return
        self.treeview.reply = reply
        super().accept()

    def reject(self) -> None:
        self.treeview.reply = {'accepted': False}
        super().reject()

    def on_base_edit(self):
        selected = self.basesLine.text().strip()
        if selected:
            selected = [base.strip() for base in selected.split(",")]
        else:
            selected = []

        if self.treeview.model():
            allItems = self.treeview.model().rootItem.getChildSpaceList()
        else:
            allItems = []

        dialog = SelectBaseSpacesDialog(
            self,
            allItems=allItems,
            selectedItems=selected
        )
        dialog.exec()
        if self.reply['accepted']:
            self.basesLine.setText(self.reply['value'])
Exemplo n.º 13
0
class WriteModelDialog(QDialog):

    def __init__(self, parent=None):
        QDialog.__init__(
            self, parent, flags=Qt.WindowSystemMenuHint | Qt.WindowTitleHint)
        self.setWindowTitle('Write Model')
        self.treeview = parent
        self.setAttribute(Qt.WA_DeleteOnClose)

        fixed_dir_layout = QHBoxLayout()
        browse_btn = QPushButton(ima.icon('DirOpenIcon'), '', self)
        browse_btn.setToolTip(_("Select model directory"))
        browse_btn.clicked.connect(self.select_directory)
        self.wd_edit = QLineEdit()
        fixed_dir_layout.addWidget(self.wd_edit)
        fixed_dir_layout.addWidget(browse_btn)
        fixed_dir_layout.setContentsMargins(0, 0, 0, 0)

        namelabel = QLabel(_("Folder Name"))
        self.nameEdit = QLineEdit(self)

        self.backupCheck = QCheckBox(_("Back up old folder"))
        self.backupCheck.setCheckState(Qt.Checked)

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setStandardButtons(
            QDialogButtonBox.Cancel|QDialogButtonBox.Ok)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)

        mainLayout = QGridLayout(self)
        mainLayout.addLayout(fixed_dir_layout, 0, 0, 1, 2)
        mainLayout.addWidget(namelabel, 1, 0)
        mainLayout.addWidget(self.nameEdit, 1, 1)
        mainLayout.addWidget(self.backupCheck, 2, 0, 1, 2)
        mainLayout.addWidget(self.buttonBox, 3, 0, 1, 2)
        # mainLayout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(mainLayout)

    def accept(self) -> None:
        reply = {
            'accepted': True,
            'directory': self.wd_edit.text(),
            'name': self.nameEdit.text(),
            'backup': self.backupCheck.isChecked()
        }
        self.treeview.reply = reply
        super().accept()

    def reject(self) -> None:
        self.treeview.reply = {'accepted': False}
        super().reject()

    def select_directory(self):
        """Select directory"""
        basedir = to_text_string(self.wd_edit.text())
        if not os.path.isdir(basedir):
            basedir = getcwd_or_home()
        directory = getexistingdirectory(self, _("Select directory"), basedir)
        if directory:
            self.wd_edit.setText(directory)
Exemplo n.º 14
0
class ReadModelDialog(QDialog):

    def __init__(self, parent=None):
        QDialog.__init__(
            self, parent, flags=Qt.WindowSystemMenuHint | Qt.WindowTitleHint)
        self.setWindowTitle('Read Model')
        self.treeview = parent
        self.setAttribute(Qt.WA_DeleteOnClose)

        fixed_dir_layout = QHBoxLayout()
        browse_btn = QPushButton(ima.icon('DirOpenIcon'), '', self)
        browse_btn.setToolTip(_("Select model directory"))
        browse_btn.clicked.connect(self.select_directory)
        self.wd_edit = QLineEdit()
        fixed_dir_layout.addWidget(self.wd_edit)
        fixed_dir_layout.addWidget(browse_btn)
        fixed_dir_layout.setContentsMargins(0, 0, 0, 0)

        namelabel = QLabel(_("Model Name"))
        self.nameEdit = QLineEdit(self)
        self.importWidget = ImportAsWidget(self, self.nameEdit)

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setStandardButtons(
            QDialogButtonBox.Cancel|QDialogButtonBox.Ok)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)

        mainLayout = QGridLayout(self)
        mainLayout.addLayout(fixed_dir_layout, 0, 0, 1, 2)
        mainLayout.addWidget(namelabel, 1, 0)
        mainLayout.addWidget(self.nameEdit, 1, 1)
        mainLayout.addWidget(self.importWidget, 2, 0, 1, 2)
        mainLayout.addWidget(self.buttonBox, 3, 0, 1, 2)
        # mainLayout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(mainLayout)

    def accept(self) -> None:
        reply = {
            'accepted': True,
            'directory': self.wd_edit.text(),
            'name': self.nameEdit.text(),
            'define_var': self.importWidget.shouldImport.isChecked(),
            'varname': self.importWidget.nameEdit.text()
        }
        if reply['define_var']:
            varname = reply['varname']
            if not check_varname(varname):
                QMessageBox.critical(
                    self,
                    'Error',
                    'Invalid variable name: %s' % varname
                )
                return
        self.treeview.reply = reply
        super().accept()

    def reject(self) -> None:
        self.treeview.reply = {'accepted': False}
        super().reject()

    def select_directory(self):
        """Select directory"""
        basedir = to_text_string(self.wd_edit.text())
        if not os.path.isdir(basedir):
            basedir = getcwd_or_home()
        directory = getexistingdirectory(self, _("Select directory"), basedir)
        if directory:
            self.wd_edit.setText(directory)
Exemplo n.º 15
0
class BasePlotCurveEditorDialog(QDialog):
    """QDialog that is used in Qt Designer to edit the properties of the
    curves in a waveform plot.  This dialog is shown when you double-click
    the plot, or when you right click it and choose 'edit curves'.

    This thing is mostly just a wrapper for a table view, with a couple
    buttons to add and remove curves, and a button to save the changes."""
    TABLE_MODEL_CLASS = BasePlotCurvesModel

    def __init__(self, plot, parent=None):
        super(BasePlotCurveEditorDialog, self).__init__(parent)
        self.plot = plot
        self.setup_ui()
        self.table_model = self.TABLE_MODEL_CLASS(self.plot)
        self.table_view.setModel(self.table_model)
        self.table_model.plot = plot
        # self.table_view.resizeColumnsToContents()
        self.add_button.clicked.connect(self.addCurve)
        self.remove_button.clicked.connect(self.removeSelectedCurve)
        self.remove_button.setEnabled(False)
        self.table_view.selectionModel().selectionChanged.connect(
            self.handleSelectionChange)
        self.table_view.doubleClicked.connect(self.handleDoubleClick)
        self.resize(800, 300)

    def setup_ui(self):
        self.vertical_layout = QVBoxLayout(self)
        self.table_view = QTableView(self)
        self.table_view.setEditTriggers(QAbstractItemView.DoubleClicked)
        self.table_view.setProperty("showDropIndicator", False)
        self.table_view.setDragDropOverwriteMode(False)
        self.table_view.setSelectionMode(QAbstractItemView.SingleSelection)
        self.table_view.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.table_view.setSortingEnabled(False)
        self.table_view.horizontalHeader().setStretchLastSection(True)
        self.table_view.verticalHeader().setVisible(False)
        self.table_view.setColumnWidth(0, 160)
        self.table_view.setColumnWidth(1, 160)
        self.table_view.setColumnWidth(2, 160)
        self.vertical_layout.addWidget(self.table_view)
        self.add_remove_layout = QHBoxLayout()
        spacer = QSpacerItem(40, 20, QSizePolicy.Expanding,
                             QSizePolicy.Minimum)
        self.add_remove_layout.addItem(spacer)
        self.add_button = QPushButton("Add Curve", self)
        self.add_remove_layout.addWidget(self.add_button)
        self.remove_button = QPushButton("Remove Curve", self)
        self.add_remove_layout.addWidget(self.remove_button)
        self.vertical_layout.addLayout(self.add_remove_layout)
        self.button_box = QDialogButtonBox(self)
        self.button_box.setOrientation(Qt.Horizontal)
        self.button_box.addButton("Done", QDialogButtonBox.AcceptRole)
        self.vertical_layout.addWidget(self.button_box)
        self.button_box.accepted.connect(self.saveChanges)
        self.button_box.rejected.connect(self.reject)
        self.setWindowTitle("Waveform Curve Editor")

    def setup_delegate_columns(self, index=2):
        symbol_delegate = SymbolColumnDelegate(self)
        self.table_view.setItemDelegateForColumn(index + 3, symbol_delegate)
        line_delegate = LineColumnDelegate(self)
        self.table_view.setItemDelegateForColumn(index + 1, line_delegate)
        color_delegate = ColorColumnDelegate(self)
        self.table_view.setItemDelegateForColumn(index, color_delegate)

    @Slot()
    def addCurve(self):
        self.table_model.append()

    @Slot()
    def removeSelectedCurve(self):
        self.table_model.removeAtIndex(self.table_view.currentIndex())

    @Slot(QItemSelection, QItemSelection)
    def handleSelectionChange(self, selected, deselected):
        self.remove_button.setEnabled(
            self.table_view.selectionModel().hasSelection())

    @Slot(QModelIndex)
    def handleDoubleClick(self, index):
        if self.table_model.needsColorDialog(index):
            # The table model returns a QBrush for BackgroundRole, not a QColor
            init_color = self.table_model.data(index,
                                               Qt.BackgroundRole).color()
            color = QColorDialog.getColor(init_color, self)
            if color.isValid():
                self.table_model.setData(index, color, role=Qt.EditRole)

    @Slot()
    def saveChanges(self):
        formWindow = QDesignerFormWindowInterface.findFormWindow(self.plot)
        if formWindow:
            formWindow.cursor().setProperty("curves", self.plot.curves)
        self.accept()