Example #1
0
    def edit(self):
        """ Open an editor to edit the filter """

        if len(self._constraints) != 0:
            Out.warn('Editing filters that already have constraints is not yet supported')

        # create initial content
        initial_content = '# FILTER EDITOR\n'
        initial_content += '# - an asterisk (*) indicates "dont-care" fields\n'
        initial_content += '# - you may either\n'
        initial_content += '#    - simply specify a field such as value = 100n, or\n'
        initial_content += '#    - you can use regular expressiong i.e. ^R for getting all resistors\n\n'
        for field_name in Field.known_names:
            initial_content += '\'' + field_name + '\' = *\n'

        # run editor
        editor = Editor(initial_content)
        filter_file_content = editor.run()

        # parse content and add fields
        fields_dict = editor.parse(filter_file_content)
        for name, value in fields_dict.items():
            self.add_constraint(name, value)
Example #2
0
class Component(object):
    """
    Represents a component and offers methods to modify fields
    """

    def __init__(self, content):
        """ Take a list of lines to init component """

        self._editor = Editor()

        # lists containing lines of eeschema syntax including $Comp and $EndComp
        self._original_content = content
        self._new_content = []

        # lists containing parts of the original content list
        self._header = []
        self._trailer = []
        self._fields = []

        self._x_pos = -1
        self._y_pos = -1

        self._parse()

    def __repr__(self):
        return self.__str__()

    def __str__(self):
        return '%-5s: %s' %(self.get_field('Designator').value, self.get_field('Value').value)

    def _parse(self):
        line_number = 0

        # store header
        self._header = []
        while not re.match('^F 0 "', self._original_content[line_number]):
            self._header.append(self._original_content[line_number])
            line_number += 1

        # create fields
        while re.match('^F [0-9]', self._original_content[line_number]):
            line = self._original_content[line_number]

            # obtain position of the value
            if re.match('^F 1 "', line):
                tokens = line.split('"')
                tokens2 = tokens[2].split(' ')
                self._x_pos = int(tokens2[2])
                self._y_pos = int(tokens2[3])
                Out.fine('Detected component position [' + str(self._x_pos) + '|' + str(self._y_pos) + ']')

            # parse fields
            new_field = FieldParser.parse(line)
            self._fields.append(new_field)

            line_number += 1

        # store trailer
        last_line = '$EndComp'
        line = ''
        while line != last_line:
            line = self._original_content[line_number]
            self._trailer.append(line)
            line_number += 1

    def serialize(self):
        # create new_content
        new_content = list(self._header)
        for field in self._fields:
            new_content.append(field.serialize())
        new_content.extend(self._trailer)

        # assign new content to member
        self._new_content = new_content

        # return a string with new_content
        line_separator = '\n'
        return line_separator.join(self._new_content)

    def edit(self):
        """ Run an editor to let the user modify the fields """

        # prepare initial content
        initial_content  = '# COMPONENT EDITOR\n'
        initial_content += '# [' + self.get_field('Designator').value + ']\n\n'

        # add existing fields
        for field in self._fields:
            if field.name != 'Designator':
                initial_content += '\'' + field.name + '\' = ' + field.value + '\n'

        # add proposed fields as comments
        for field_name in Field.known_names:
            if self.get_field(field_name) is None:
                initial_content += '#\'' + field_name + '\' = \n'

        # run editor
        self._editor.initial_content = initial_content
        new_content = self._editor.run()

        # parse fields from editor and reset own fields
        new_fields_dict = self._editor.parse(new_content)
        self.reset_fields()

        # modify all fields
        for name, value in new_fields_dict.items():
            self.add_or_update_field(name, value)

    def reset_fields(self):
        """ Keep designator, reset native field values, remove all custom fields """
        new_fields = []
        designator_field = self.get_field('Designator')

        # reset values
        for field_name in ['Value', 'Footprint', 'Datasheet']:
            field = self.get_field(field_name)
            field.value = ''
            new_fields.append(field)

        # prepend designator
        new_fields.insert(0, designator_field)

        self._fields = new_fields

    def get_template(self):
        """ Return a copy of this component with no fields (except designator) """
        template = copy.deepcopy(self)
        template.reset_fields()
        return template

    def merge(self, source_component):
        """ Merges all fields from a given component into self """
        for field in source_component._fields:
            if field.name != 'Designator':
                self.add_or_update_field(field.name, field.value)

    def add_or_update_field(self, name, value):
        """ Add a new (custom) field or replace an existing field """

        # warn and return if name is empty
        if name == '':
            Out.warn('Will not add or update field in ' + self.get_field('Designator').value
                     + ' due to empty name')
            return
        # log when clearing a value
        elif value == '':
            Out.log('Clearing value of field "' + name + '" in ' 
                    + self.get_field('Designator').value + '.')

        # change value of name-matching fields
        Out.fine('Changing value of fields matching the name "' + name + '"')
        for index, field in enumerate(self._fields):
            if field.name == name:
                Out.fine('Overwriting value of field #' + str(index) + ' with ' + name + ':' + value)
                self._fields[index].value = value

                # only designator and value should be visible
                if name == 'Designator' or name == 'Value':
                    self._fields[index].set_visible(True)
                else:
                    self._fields[index].set_visible(False)

                return

        # Construct and add new custom field
        new_field = CustomField.copy(self.get_field('Designator'))
        new_field.name = name
        new_field.value = value
        new_field.number = len(self._fields)
        new_field.set_visible(False)
        Out.fine('Adding new custom field:' + new_field.serialize())
        self._fields.append(new_field)


    def get_field(self, name):
        """ Return field instance with a given name """

        matching_fields = list(filter(lambda field: field.name == name, self._fields))

        if len(matching_fields) == 1:
            return matching_fields[0]
        elif len(matching_fields) > 1:
            Out.warn('More than one field with name ' + name + ' defined!')
            return None
        else:
            Out.fine('No field with name ' + name)
            return None