Ejemplo n.º 1
0
    def __init__(self, parent, edge):
        """ EdgeLabelEmbed is for editing edge labels, but it takes Edge as its host,
        because there may be problems if the host item is not subclass of Saved. Use self.label
        to get access to edge.label_item.
        :param parent:
        :param ui_manager:
        :param edge:
        :param ui_key:
        """

        UIEmbed.__init__(self, parent, edge, 'Edit edge text')
        self.marker = None
        self.label = edge.label_item
        layout = QtWidgets.QVBoxLayout()
        layout.addLayout(self.top_row_layout)  # close-button from UIEmbed
        tt = 'Label for arrow'
        f = QtGui.QFont(qt_prefs.get_font(g.MAIN_FONT))
        f.setPointSize(f.pointSize() * 2)
        self.input_line_edit = EmbeddedLineEdit(self, tip=tt, font=f, prefill='label')
        hlayout = QtWidgets.QHBoxLayout()
        hlayout.addWidget(self.input_line_edit)
        self.enter_button = QtWidgets.QPushButton("↩")  # U+21A9 ↩
        self.ui_manager.connect_element_to_action(self.enter_button, 'edit_edge_label_enter_text')

        hlayout.addWidget(self.enter_button)
        layout.addLayout(hlayout)
        self.setLayout(layout)
        self.assumed_width = 200
        self.assumed_height = 37
        self.update_position()
Ejemplo n.º 2
0
    def __init__(self, parent, node):
        nname = node.display_name[0].lower()
        UIEmbed.__init__(self, parent, node, 'Edit ' + nname)
        layout = QtWidgets.QVBoxLayout()
        layout.addLayout(self.top_row_layout)
        layout.addSpacing(4)
        ui_p = self._palette
        ui_s = QtGui.QPalette(ui_p)
        ui_s.setColor(QtGui.QPalette.Text, ctrl.cm.secondary())
        smaller_font = qt_prefs.get_font(g.MAIN_FONT)
        big_font = QtGui.QFont(smaller_font)
        big_font.setPointSize(big_font.pointSize() * 2)
        ed = node.get_editing_template()
        sortable = [(item.get('order', 100), key) for key, item in ed.items()]
        sortable.sort()
        field_names = [key for order, key in sortable]
        self.fields = {}
        self.resize_target = None
        hlayout = None

        # Generate edit elements based on data, expand this as necessary
        for field_name in field_names:
            d = ed.get(field_name, {})
            if d.get('hidden', False) or not self.host.check_conditions(d):
                continue
            tt = d.get('tooltip', '')
            itype = d.get('input_type', 'text')
            prefill = d.get('prefill', '')
            syntactic = d.get('syntactic', False)
            on_edit = d.get('on_edit', None)
            if on_edit and isinstance(on_edit, str):
                on_edit = getattr(node, on_edit, None)
            field_first = False
            field = None
            if itype == 'text':
                width = d.get('width', 140)
                field = EmbeddedLineEdit(self, tip=tt, font=big_font, prefill=prefill, on_edit=on_edit)
                field.setMaximumWidth(width)
            elif itype == 'textarea':
                self._disable_effect = True
                template_width = d.get('width', 0)
                field = EmbeddedTextarea(self, tip=tt, font=smaller_font, prefill=prefill, on_edit=on_edit)
                max_w = 200
                if node.user_size:
                    w = node.user_size[0]
                elif template_width:
                    w = template_width
                else:
                    w = node.label_object.document().idealWidth()
                field.setFixedWidth(min(w, max_w))
                self.resize_target = field
            elif itype == 'expandingtext':
                field = ExpandingTextArea(self,
                                          tip=tt,
                                          font=smaller_font,
                                          prefill=prefill, on_edit=on_edit)
                template_width = d.get('width', 0)
                if template_width:
                    field.setFixedWidth(template_width)
                self.resize_target = field
            elif itype == 'multibutton':
                # currently not used, radio button is better
                width = d.get('width', 200)
                op_func = d.get('option_function')
                op_func = getattr(self.host, op_func, None) or getattr(self.syntactic_object,
                                                                       op_func, None)
                field = EmbeddedMultibutton(self, options=op_func())
                field.setMaximumWidth(width)
            elif itype == 'checkbox':
                field = QtWidgets.QCheckBox(self)
            elif itype == 'radiobutton':
                width = d.get('width', 200)
                op_func = d.get('option_function')
                op_func = getattr(self.host, op_func, None) or \
                          getattr(self.syntactic_object, op_func, None)
                field = EmbeddedRadiobutton(self, options=op_func())
                field.setMaximumWidth(width)
                field_first = False
            elif itype == 'preview':
                field = PreviewLabel(self, tip=tt, font=smaller_font)
            else:
                raise NotImplementedError

            if field:
                action = d.get('select_action')
                if action:
                    self.ui_manager.connect_element_to_action(field, action)
                if syntactic:
                    field.setPalette(ui_s)
                else:
                    field.setPalette(ui_p)

            align = d.get('align', 'newline')
            if align == 'newline':
                # new hlayout means new line, but before starting a new hlayout,
                # end the previous one.
                if hlayout:
                    layout.addLayout(hlayout)
                hlayout = QtWidgets.QHBoxLayout()
            self.fields[field_name] = field
            if field_first:
                hlayout.addWidget(field)
            ui_name = d.get('name', field_name)
            if ui_name:
                if syntactic:
                    palette = ui_s
                else:
                    palette = ui_p
                make_label(ui_name, self, hlayout, tt, field, palette)
            if not field_first:
                hlayout.addWidget(field)
        if hlayout:
            layout.addLayout(hlayout)
        hlayout = QtWidgets.QHBoxLayout()
        self.enter_button = QtWidgets.QPushButton("Keep ↩")  # U+21A9 ↩
        self.enter_button.setParent(self)
        self.ui_manager.connect_element_to_action(self.enter_button, 'finish_editing_node')
        hlayout.addStretch(0)
        hlayout.addWidget(self.enter_button, 0, QtCore.Qt.AlignRight)
        if self.resize_target:
            self.resize_handle = ResizeHandle(self, self.resize_target)
            hlayout.addWidget(self.resize_handle, 0, QtCore.Qt.AlignRight)
        layout.addLayout(hlayout)
        self.setLayout(layout)
        self.update_embed()
        self.update_position()
        self.hide()
Ejemplo n.º 3
0
class ConstituentNodeEditEmbed(UIEmbed):
    """ Node edit embed creates editable elements based on templates provided by Node subclass.
    It allows easy UI generation for user-customized syntactic elements or Kataja Nodes.

    :param parent: QWidget where this editor lives, QGraphicsView of some sort
    :param ui_manager: UIManager instance that manages this editor
    :param ui_key: unique, but predictable key for accessing this editor
    :param node: node that is to be associated with this editor
    """
    can_fade = False  # fade and textareas don't work well together

    def __init__(self, parent, node):
        nname = node.display_name[0].lower()
        UIEmbed.__init__(self, parent, node, 'Edit ' + nname)
        layout = QtWidgets.QVBoxLayout()
        layout.addLayout(self.top_row_layout)
        layout.addSpacing(4)
        ui_p = self._palette
        self.setPalette(ui_p)
        ui_s = QtGui.QPalette(ui_p)
        ui_s.setColor(QtGui.QPalette.Text, ctrl.cm.secondary())
        smaller_font = qt_prefs.get_font(g.MAIN_FONT)
        big_font = QtGui.QFont(smaller_font)
        big_font.setPointSize(big_font.pointSize() * 2)
        self.view_buttons = QtWidgets.QButtonGroup(self)
        self.view_buttons.setExclusive(True)

        self.synframebutton = EyeButton(
            'synlabels', 'All nodes show their syntactic labels')
        self.synframebutton.setChecked(True)
        self.ui_manager.connect_element_to_action(self.synframebutton,
                                                  'set_synlabels_visible')
        self.view_buttons.addButton(self.synframebutton)
        hlayout = QtWidgets.QHBoxLayout()
        hlayout.addWidget(self.synframebutton)
        vlayout = QtWidgets.QVBoxLayout()
        hlayout.addLayout(vlayout)
        tt = 'Label used in syntactic computations, plain string. Visible in <i>syntactic mode</i> ' \
             'or if <i>Displayed label</i> is empty.'
        title = 'Syntactic label'
        self.synlabel = EmbeddedLineEdit(self,
                                         tip=tt,
                                         font=big_font,
                                         prefill='label',
                                         on_edit=self.synlabel_edited,
                                         on_finish=self.synlabel_finished,
                                         on_return=self.synlabel_finished)
        make_label(title, self, vlayout, tt, self.synlabel, ui_s)
        self.synlabel.setPalette(ui_p)
        vlayout.addWidget(self.synlabel)
        layout.addLayout(hlayout)

        self.nodeframebutton = EyeButton(
            'nodelabels', 'All nodes show their user-given labels')
        self.view_buttons.addButton(self.nodeframebutton)
        self.ui_manager.connect_element_to_action(self.nodeframebutton,
                                                  'set_node_labels_visible')
        tt = "Freeform label or text for node, has no effect for syntactic computation"
        title = 'User label'
        self.label = ExpandingTextArea(self,
                                       tip=tt,
                                       font=smaller_font,
                                       prefill='label',
                                       on_edit=self.label_edited,
                                       label=title,
                                       on_focus_out=self.label_finished)
        self.label.setPalette(ui_p)
        self.resize_target = self.label
        hlayout = QtWidgets.QHBoxLayout()
        hlayout.addWidget(self.nodeframebutton)
        hlayout.addWidget(self.label)
        layout.addLayout(hlayout)

        self.autoframebutton = EyeButton(
            'autolabels', 'All nodes show their autogenerated x-bar '
            'labels')
        self.ui_manager.connect_element_to_action(self.autoframebutton,
                                                  'set_autolabels_visible')
        self.view_buttons.addButton(self.autoframebutton)
        hlayout = QtWidgets.QHBoxLayout()
        hlayout.addWidget(self.autoframebutton)
        vlayout = QtWidgets.QVBoxLayout()
        hlayout.addLayout(vlayout)
        tt = "These are either XBar or Bare phrase structure labels that are updated " \
             "automatically based on projections."
        title = 'Generated label'
        self.autolabel = EmbeddedLineEdit(self,
                                          tip=tt,
                                          font=big_font,
                                          prefill='autolabel')
        self.autolabel.setReadOnly(True)
        make_label(title, self, vlayout, tt, self.autolabel)
        vlayout.addWidget(self.autolabel)

        vlayout = QtWidgets.QVBoxLayout()
        tt = 'Optional index for announcing link between multiple instances.'
        title = 'Index'
        self.index = EmbeddedLineEdit(self,
                                      tip=tt,
                                      font=big_font,
                                      prefill='i',
                                      on_finish=self.index_finished)
        self.index.setPalette(ui_p)
        self.index.setMaximumWidth(20)
        make_label(title, self, vlayout, tt, self.index)
        vlayout.addWidget(self.index)
        hlayout.addLayout(vlayout)
        layout.addLayout(hlayout)

        hlayout = QtWidgets.QHBoxLayout()
        hlayout.addSpacing(28)
        tt = 'Node can be projection from either or both of its children if those children are ' \
             'heads or projections from their children.'
        title = 'Projects from'
        self.projections = ProjectionButtons(self)
        self.projections.setMaximumWidth(200)

        vlayout = QtWidgets.QVBoxLayout()
        if not self.projections.empty:
            make_label(title, self, vlayout, tt)
        vlayout.addWidget(self.projections)
        hlayout.addLayout(vlayout)
        layout.addLayout(hlayout)
        self.ui_manager.connect_element_to_action(
            self.projections,
            'set_projection_at_embed_ui',
            connect_slot=self.projections.connect_slot)
        if self.resize_target:
            self.resize_handle = ResizeHandle(self, self.resize_target)
            layout.addWidget(self.resize_handle, 0, QtCore.Qt.AlignRight)
        self.setLayout(layout)
        self.update_embed()
        self.update_position()
        self.hide()

    def margin_x(self):
        """ Try to keep all of the host node visible, not covered by this editor.
        :return:
        """
        return (self.host.boundingRect().width() / 2) + 12

    def margin_y(self):
        """ Try to keep all of the host node visible, not covered by this editor.
        :return:
        """
        return self.host.boundingRect().height() / 2

    def update_fields(self):
        """ Update field values on embed form based on template """
        print('update fields called for ConstituentNodeEditEmbed')
        node = self.host
        self.label.setText(node.label)
        print('label: ', repr(node.label))
        self.synlabel.setText(node.get_syntactic_label())
        self.autolabel.setText(as_editable_html(node.autolabel))
        self.index.setText(node.index or '')

    def triangle_enabled(self):
        node = self.host
        if not node:
            return False
        elif not node.triangle_stack:
            return True
        elif node.triangle_stack[-1] == node:
            return True
        return False

    def synlabel_edited(self, *args, **kwargs):
        #print('synlabel edited')
        #print(args, kwargs)
        pass

    def synlabel_finished(self):
        text = self.synlabel.text()
        self.host.parse_edited_label('syntactic label', text)
        ctrl.forest.forest_edited()
        self.update_fields()

    def label_edited(self, *args, **kwargs):
        pass

    def label_finished(self):
        text = self.label.inode_text()
        self.host.parse_edited_label('node label', text)
        ctrl.forest.forest_edited()
        self.update_fields()

    def index_finished(self):
        text = self.index.text()
        self.host.parse_edited_label('index', text)
        ctrl.forest.forest_edited()
        self.update_fields()

    def submit_values(self):
        """ Possibly called if assuming we are in NodeEditEmbed. All of the changes in
        ConstituentNodeEditEmbed should take effect immediately, so separate submit is not needed.
        :return:
        """
        self.host.update_label()

    def focus_to_main(self):
        """ Find the main element to focus in this embed.
        :return:
        """
        m = ctrl.settings.get('label_text_mode')
        if m == g.SYN_LABELS or m == g.SYN_LABELS_FOR_LEAVES:
            self.synlabel.setFocus()
        elif m == g.NODE_LABELS_FOR_LEAVES or m == g.NODE_LABELS:
            self.label.setFocus()
        elif m == g.XBAR_LABELS:
            self.autolabel.setFocus()
Ejemplo n.º 4
0
    def __init__(self, parent, node):
        nname = node.display_name[0].lower()
        UIEmbed.__init__(self, parent, node, 'Edit ' + nname)
        layout = QtWidgets.QVBoxLayout()
        layout.addLayout(self.top_row_layout)
        layout.addSpacing(4)
        ui_p = self._palette
        self.setPalette(ui_p)
        ui_s = QtGui.QPalette(ui_p)
        ui_s.setColor(QtGui.QPalette.Text, ctrl.cm.secondary())
        smaller_font = qt_prefs.get_font(g.MAIN_FONT)
        big_font = QtGui.QFont(smaller_font)
        big_font.setPointSize(big_font.pointSize() * 2)
        self.view_buttons = QtWidgets.QButtonGroup(self)
        self.view_buttons.setExclusive(True)

        self.synframebutton = EyeButton(
            'synlabels', 'All nodes show their syntactic labels')
        self.synframebutton.setChecked(True)
        self.ui_manager.connect_element_to_action(self.synframebutton,
                                                  'set_synlabels_visible')
        self.view_buttons.addButton(self.synframebutton)
        hlayout = QtWidgets.QHBoxLayout()
        hlayout.addWidget(self.synframebutton)
        vlayout = QtWidgets.QVBoxLayout()
        hlayout.addLayout(vlayout)
        tt = 'Label used in syntactic computations, plain string. Visible in <i>syntactic mode</i> ' \
             'or if <i>Displayed label</i> is empty.'
        title = 'Syntactic label'
        self.synlabel = EmbeddedLineEdit(self,
                                         tip=tt,
                                         font=big_font,
                                         prefill='label',
                                         on_edit=self.synlabel_edited,
                                         on_finish=self.synlabel_finished,
                                         on_return=self.synlabel_finished)
        make_label(title, self, vlayout, tt, self.synlabel, ui_s)
        self.synlabel.setPalette(ui_p)
        vlayout.addWidget(self.synlabel)
        layout.addLayout(hlayout)

        self.nodeframebutton = EyeButton(
            'nodelabels', 'All nodes show their user-given labels')
        self.view_buttons.addButton(self.nodeframebutton)
        self.ui_manager.connect_element_to_action(self.nodeframebutton,
                                                  'set_node_labels_visible')
        tt = "Freeform label or text for node, has no effect for syntactic computation"
        title = 'User label'
        self.label = ExpandingTextArea(self,
                                       tip=tt,
                                       font=smaller_font,
                                       prefill='label',
                                       on_edit=self.label_edited,
                                       label=title,
                                       on_focus_out=self.label_finished)
        self.label.setPalette(ui_p)
        self.resize_target = self.label
        hlayout = QtWidgets.QHBoxLayout()
        hlayout.addWidget(self.nodeframebutton)
        hlayout.addWidget(self.label)
        layout.addLayout(hlayout)

        self.autoframebutton = EyeButton(
            'autolabels', 'All nodes show their autogenerated x-bar '
            'labels')
        self.ui_manager.connect_element_to_action(self.autoframebutton,
                                                  'set_autolabels_visible')
        self.view_buttons.addButton(self.autoframebutton)
        hlayout = QtWidgets.QHBoxLayout()
        hlayout.addWidget(self.autoframebutton)
        vlayout = QtWidgets.QVBoxLayout()
        hlayout.addLayout(vlayout)
        tt = "These are either XBar or Bare phrase structure labels that are updated " \
             "automatically based on projections."
        title = 'Generated label'
        self.autolabel = EmbeddedLineEdit(self,
                                          tip=tt,
                                          font=big_font,
                                          prefill='autolabel')
        self.autolabel.setReadOnly(True)
        make_label(title, self, vlayout, tt, self.autolabel)
        vlayout.addWidget(self.autolabel)

        vlayout = QtWidgets.QVBoxLayout()
        tt = 'Optional index for announcing link between multiple instances.'
        title = 'Index'
        self.index = EmbeddedLineEdit(self,
                                      tip=tt,
                                      font=big_font,
                                      prefill='i',
                                      on_finish=self.index_finished)
        self.index.setPalette(ui_p)
        self.index.setMaximumWidth(20)
        make_label(title, self, vlayout, tt, self.index)
        vlayout.addWidget(self.index)
        hlayout.addLayout(vlayout)
        layout.addLayout(hlayout)

        hlayout = QtWidgets.QHBoxLayout()
        hlayout.addSpacing(28)
        tt = 'Node can be projection from either or both of its children if those children are ' \
             'heads or projections from their children.'
        title = 'Projects from'
        self.projections = ProjectionButtons(self)
        self.projections.setMaximumWidth(200)

        vlayout = QtWidgets.QVBoxLayout()
        if not self.projections.empty:
            make_label(title, self, vlayout, tt)
        vlayout.addWidget(self.projections)
        hlayout.addLayout(vlayout)
        layout.addLayout(hlayout)
        self.ui_manager.connect_element_to_action(
            self.projections,
            'set_projection_at_embed_ui',
            connect_slot=self.projections.connect_slot)
        if self.resize_target:
            self.resize_handle = ResizeHandle(self, self.resize_target)
            layout.addWidget(self.resize_handle, 0, QtCore.Qt.AlignRight)
        self.setLayout(layout)
        self.update_embed()
        self.update_position()
        self.hide()
Ejemplo n.º 5
0
    def __init__(self, parent, node):
        nname = node.display_name[0].lower()
        UIEmbed.__init__(self, parent, node, 'Edit ' + nname)
        layout = QtWidgets.QVBoxLayout()
        layout.addLayout(self.top_row_layout)
        layout.addSpacing(4)
        ui_p = self._palette
        ui_s = QtGui.QPalette(ui_p)
        ui_s.setColor(QtGui.QPalette.Text, ctrl.cm.secondary())
        smaller_font = qt_prefs.get_font(g.MAIN_FONT)
        big_font = QtGui.QFont(smaller_font)
        big_font.setPointSize(big_font.pointSize() * 2)
        ed = node.get_editing_template()
        sortable = [(item.get('order', 100), key) for key, item in ed.items()]
        sortable.sort()
        field_names = [key for order, key in sortable]
        self.fields = {}
        self.resize_target = None
        hlayout = None

        # Generate edit elements based on data, expand this as necessary
        for field_name in field_names:
            d = ed.get(field_name, {})
            if d.get('hidden', False) or not self.host.check_conditions(d):
                continue
            tt = d.get('tooltip', '')
            itype = d.get('input_type', 'text')
            prefill = d.get('prefill', '')
            syntactic = d.get('syntactic', False)
            on_edit = d.get('on_edit', None)
            if on_edit and isinstance(on_edit, str):
                on_edit = getattr(node, on_edit, None)
            field_first = False
            field = None
            if itype == 'text':
                width = d.get('width', 140)
                field = EmbeddedLineEdit(self,
                                         tip=tt,
                                         font=big_font,
                                         prefill=prefill,
                                         on_edit=on_edit)
                field.setMaximumWidth(width)
            elif itype == 'textarea':
                self._disable_effect = True
                template_width = d.get('width', 0)
                field = EmbeddedTextarea(self,
                                         tip=tt,
                                         font=smaller_font,
                                         prefill=prefill,
                                         on_edit=on_edit)
                max_w = 200
                if node.user_size:
                    w = node.user_size[0]
                elif template_width:
                    w = template_width
                else:
                    w = node.label_object.document().idealWidth()
                field.setFixedWidth(min(w, max_w))
                self.resize_target = field
            elif itype == 'expandingtext':
                field = ExpandingTextArea(self,
                                          tip=tt,
                                          font=smaller_font,
                                          prefill=prefill,
                                          on_edit=on_edit)
                template_width = d.get('width', 0)
                if template_width:
                    field.setFixedWidth(template_width)
                self.resize_target = field
            elif itype == 'multibutton':
                width = d.get('width', 200)
                op_func = d.get('option_function')
                op_func = getattr(self.host, op_func, None) or getattr(
                    self.syntactic_object, op_func, None)
                field = EmbeddedMultibutton(self, options=op_func())
                field.setMaximumWidth(width)
            elif itype == 'projection_buttons':
                width = d.get('width', 200)
                field = ProjectionButtons(self)
                field.setMaximumWidth(width)
            elif itype == 'checkbox':
                field = QtWidgets.QCheckBox(self)
            elif itype == 'radiobutton':
                width = d.get('width', 200)
                op_func = d.get('option_function')
                op_func = getattr(self.host, op_func, None) or \
                          getattr(self.syntactic_object, op_func, None)
                field = EmbeddedRadiobutton(self, options=op_func())
                field.setMaximumWidth(width)
                field_first = False
            elif itype == 'preview':
                field = PreviewLabel(self, tip=tt, font=smaller_font)
            elif itype == 'spinbox':
                field = QtWidgets.QSpinBox(self)
                field.setMinimum(d.get('min', -1))
                field.setMaximum(d.get('max', 4))
            else:
                raise NotImplementedError

            if field:
                action = d.get('select_action')
                if action:
                    connect_slot = getattr(field, 'connect_slot', None)
                    self.ui_manager.connect_element_to_action(
                        field, action, connect_slot=connect_slot)
                if syntactic:
                    field.setPalette(ui_s)
                else:
                    field.setPalette(ui_p)

            align = d.get('align', 'newline')
            if align == 'newline':
                # new hlayout means new line, but before starting a new hlayout,
                # end the previous one.
                if hlayout:
                    layout.addLayout(hlayout)
                hlayout = QtWidgets.QHBoxLayout()
            self.fields[field_name] = field
            if field_first:
                hlayout.addWidget(field)
            ui_name = d.get('name', field_name)
            if ui_name:
                if syntactic:
                    palette = ui_s
                else:
                    palette = ui_p
                make_label(ui_name, self, hlayout, tt, field, palette)
            if not field_first:
                hlayout.addWidget(field)
        if hlayout:
            layout.addLayout(hlayout)
        hlayout = QtWidgets.QHBoxLayout()
        self.enter_button = QtWidgets.QPushButton("Keep ↩")  # U+21A9 &#8617;
        self.enter_button.setParent(self)
        self.ui_manager.connect_element_to_action(self.enter_button,
                                                  'finish_editing_node')
        hlayout.addStretch(0)
        hlayout.addWidget(self.enter_button, 0, QtCore.Qt.AlignRight)
        if self.resize_target:
            self.resize_handle = ResizeHandle(self, self.resize_target)
            hlayout.addWidget(self.resize_handle, 0, QtCore.Qt.AlignRight)
        layout.addLayout(hlayout)
        self.setLayout(layout)
        self.update_embed()
        self.update_position()
        self.hide()