Example #1
0
    def _iterate_scene_children(self,
                                idx: int,
                                node: NodeInfo,
                                parent_item: KnechtItem,
                                use_config: bool = False):
        child_idx = parent_item.childCount()
        parent_item.insertChildren(
            child_idx, 1,
            (f'{idx:03d}', node.name, node.pr_tags, node.trigger_rules))
        node_item = parent_item.child(child_idx)

        # -- Style Schaltgruppen
        if node.pr_tags:
            KnechtItemStyle.style_column(node_item, 'plmxml_item')

        # -- Style visible nodes in Config Display
        if use_config and node.visible:
            node_item.style_bg_green()

        # -- Skip invisible child nodes in Config Display
        if use_config and node.pr_tags and not node.visible:
            node_item.style_recursive()
            return

        for idx, child_node in enumerate(
                self.plmxml.iterate_child_nodes(node)):
            self._iterate_scene_children(idx, child_node, node_item,
                                         use_config)
Example #2
0
    def _build_material_tree(self, use_config: bool = False):
        material_root_item = KnechtItem(data=('', 'Material Name', 'PR-Tags',
                                              'Desc'))

        for idx, (name,
                  target) in enumerate(self.plmxml.look_lib.materials.items()):
            child_idx = material_root_item.childCount()

            material_root_item.insertChildren(child_idx, 1,
                                              (f'{idx:03d}', name, '', ''))
            target_item = material_root_item.child(child_idx)
            KnechtItemStyle.style_column(target_item, 'fakom_option')

            # -- Create Material Variants
            for c_idx, v in enumerate(target.variants):
                # -- Skip invisible variants in Config Display
                if use_config:
                    if v != target.visible_variant:
                        continue
                target_child_idx = target_item.childCount()
                target_item.insertChildren(
                    target_child_idx, 1,
                    (f'{c_idx:03d}', v.name, v.pr_tags, v.desc))
                if use_config:
                    variant_item = target_item.child(target_child_idx)
                    variant_item.style_bg_green()

        update_material_tree = UpdateModel(self.material_tree)
        update_material_tree.update(KnechtModel(material_root_item))
Example #3
0
    def _create_tree_item(self,
                          node,
                          parent_item: KnechtItem = None) -> KnechtItem:
        data = self._data_from_element_attribute(node)

        if parent_item is None:
            child_position = self.root_item.childCount()
            self.root_item.insertChildren(child_position, 1, data)
            parent_item = self.root_item.child(child_position)

            self.xml_id.update_preset_uuid(node, parent_item)
            return parent_item

        position = parent_item.childCount()
        result = parent_item.insertChildren(position, 1, data)

        if not result:
            LOGGER.error('Could not insert child %s %s', position,
                         parent_item.childCount())
            return parent_item

        self.xml_id.update_reference_uuid(node, parent_item.child(position))
        return parent_item
Example #4
0
    def create_presets(self):
        root_item = KnechtItem()

        for (src_index,
             item) in self.image_view.editor.iterator.iterate_view():
            if item.data(self.check_column, Qt.CheckStateRole) == Qt.Unchecked:
                continue

            name = item.data(Kg.NAME)
            data = (f'{root_item.childCount():03d}', name, '', 'preset', '',
                    Kid.convert_id(f'{root_item.childCount()}'))
            root_item.insertChildren(root_item.childCount(), 1, data)

        date = datetime.datetime.now().strftime('%Y%m%d')
        project = self._current_project_name.replace(' ', '_')
        self.finished.emit(KnechtModel(root_item),
                           Path(f'{date}_{project}.xml'))
Example #5
0
    def create_packages(self, trim: KnTrim, parent_item: KnechtItem,
                        filter_pkg_by_pr_family: bool):
        for pkg in trim.iterate_packages():
            if not pkg.child_count():
                continue

            pkg_item = self.create_package(trim, pkg, parent_item.childCount())
            pkg_item.parentItem = parent_item

            keep_package = True
            if not [
                    pr for pr in pkg.iterate_pr()
                    if pr.family in self.data.selected_pr_families
            ]:
                keep_package = False

            if pkg_item.childCount():
                if filter_pkg_by_pr_family and keep_package:
                    # Only create packages that contain at least one PR Family from pr family filter
                    parent_item.append_item_child(pkg_item)
                elif not filter_pkg_by_pr_family:
                    # Create all packages and do not apply any filtering
                    parent_item.append_item_child(pkg_item)
Example #6
0
    def _xml_items_loaded(self, root_item: KnechtItem, error: str, file: Path):
        if not root_item.childCount():
            LOGGER.info('Could not load Xml. KnechtXml returned %s', error)
            self.load_aborted.emit(error, file)
            return

        # Transfer root_item to new_model
        new_model = KnechtModel(root_item)

        # Add recent file entry
        if self.create_recent_entries:
            KnechtSettings.add_recent_file(file.as_posix(), 'xml')
            KnechtSettings.app['current_path'] = file.parent.as_posix()

        # Output load info
        self.last_progress_time = time.time() - self.load_start_time

        LOGGER.info(
            f'Xml file {file.name} took {self.last_progress_time:.4}s to parse. {root_item.thread()}'
        )

        # Transfer model
        self.model_loaded.emit(new_model, file)
Example #7
0
class KnechtDataToModel:
    progress_signal = None

    def __init__(self, data: KnData):
        self.data = data

        self.id_gen = KnechtUuidGenerator()
        self.root_item = KnechtItem()

    def _show_progress(self, msg: str):
        if self.progress_signal is None:
            return
        self.progress_signal.emit(msg)

    def create_root_item(self):
        self.create_items()
        LOGGER.debug('Created %s items from ExcelData.',
                     self.root_item.childCount())
        return self.root_item

    def create_items(self):
        progress_idx = 0

        for trim in self.data.models:
            model = trim.model

            if model not in self.data.selected_models:
                continue

            progress_idx += 1
            self._show_progress(
                _('Erstelle Model {} {:02d}/{:02d}...').format(
                    model, progress_idx, len(self.data.selected_models)))

            # -- Create Trim line item --
            if self.data.read_trim:
                trim_item = self.create_trim(trim)
                self.root_item.append_item_child(trim_item)

            # -- Create options --
            if self.data.read_options:
                # Filter rows matching E
                options_item = self.create_trim_options(
                    trim, self.data.options_text_filter)
                self.root_item.append_item_child(options_item)

            # -- Create packages --
            if self.data.read_packages:
                self.create_packages(trim, self.root_item,
                                     self.data.pr_fam_filter_packages)

            if self.data.read_fakom:
                self.create_fakom(trim)

    def create_trim(self, trim: KnTrim) -> KnechtItem:
        # -- Create trim line item --
        data = (
            f'{self.root_item.childCount():03d}',  # Order
            trim.model_text,  # Name
            trim.model,  # Value
            'trim_setup',  # Type
            '',  # Ref ID
            self.id_gen.create_id(),  # ID
            f'{trim.market} - {trim.gearbox}'  # Description
        )

        trim_item = KnechtItem(self.root_item, data)
        trim_code_item = KnechtItem(trim_item, ('000', trim.model, 'on'))
        trim_item.append_item_child(trim_code_item)
        self.create_pr_options(trim.iterate_trim_pr(), trim_item)
        return trim_item

    def create_trim_options(self, trim, text_filter_options=False):
        # -- Create trim line options item --
        data = (f'{self.root_item.childCount():03d}',
                f'{trim.model_text} Options', trim.model, 'options', '',
                self.id_gen.create_id(), f'{trim.market} - {trim.gearbox}')
        options_item = KnechtItem(self.root_item, data)

        if text_filter_options:
            self.create_pr_options(trim.iterate_optional_filtered_pr(),
                                   options_item)
        else:
            self.create_pr_options(trim.iterate_optional_pr(), options_item)

        return options_item

    def create_package(self,
                       trim: KnTrim,
                       pkg: KnPackage,
                       order: int = 0) -> KnechtItem:
        data = (
            f'{order:03d}',  # Order
            f'{pkg.name} {pkg.desc} {trim.model} {trim.market}',  # Name
            pkg.name,  # Value
            'package',  # Type
            '',  # Ref ID
            self.id_gen.create_id()  # ID
        )
        pkg_item = KnechtItem(None, data)

        for pr in pkg.iterate_pr():
            pr_item = KnechtItem(pkg_item,
                                 (f'{pkg_item.childCount():03d}', pr.name,
                                  'on', pr.family, '', '', pr.desc))
            pkg_item.append_item_child(pr_item)

        return pkg_item

    def create_packages(self, trim: KnTrim, parent_item: KnechtItem,
                        filter_pkg_by_pr_family: bool):
        for pkg in trim.iterate_packages():
            if not pkg.child_count():
                continue

            pkg_item = self.create_package(trim, pkg, parent_item.childCount())
            pkg_item.parentItem = parent_item

            keep_package = True
            if not [
                    pr for pr in pkg.iterate_pr()
                    if pr.family in self.data.selected_pr_families
            ]:
                keep_package = False

            if pkg_item.childCount():
                if filter_pkg_by_pr_family and keep_package:
                    # Only create packages that contain at least one PR Family from pr family filter
                    parent_item.append_item_child(pkg_item)
                elif not filter_pkg_by_pr_family:
                    # Create all packages and do not apply any filtering
                    parent_item.append_item_child(pkg_item)

    def create_pr_options(self,
                          pr_iterator: List[KnPr],
                          parent_item: KnechtItem,
                          ignore_pr_family=False):
        for pr in pr_iterator:
            if not ignore_pr_family and pr.family not in self.data.selected_pr_families:
                continue

            pr_item = KnechtItem(parent_item,
                                 (f'{parent_item.childCount():03d}', pr.name,
                                  'on', pr.family, '', '', pr.desc))
            parent_item.append_item_child(pr_item)

    def create_fakom(self,
                     trim: KnTrim,
                     is_preset_wizard: bool = False,
                     parent_item: KnechtItem = None):
        model_short_desc = shorten_model_name(trim.model_text)

        # Create lists of List[KnPr] for SIB/VOS/LUM families
        sib_pr_ls = [
            pr for pr in trim.iterate_available_pr()
            if pr.family.casefold() == 'sib'
        ]
        sib_pr_codes = [pr.name for pr in sib_pr_ls]
        lum_pr_ls = [
            pr for pr in trim.iterate_available_pr()
            if pr.family.casefold() == 'lum'
        ]
        vos_pr_ls = [
            pr for pr in trim.iterate_available_pr()
            if pr.family.casefold() == 'vos'
        ]

        if not parent_item:
            parent_item = self.root_item

        for color, sib_set in self.data.fakom.iterate_colors():
            valid_sib_set = sib_set.intersection(sib_pr_codes)
            if not valid_sib_set:
                continue

            fa_parent, grp_item = parent_item, parent_item

            if is_preset_wizard:
                grp_item = KnechtItem(parent_item,
                                      (f'{parent_item.childCount():03d}',
                                       color, '', 'fakom_option'))
                grp_item.fixed_userType = Kg.group_item
                parent_item.append_item_child(grp_item)

            # --- Iterate SIB Codes ---
            for sib_pr in sib_pr_ls:
                if sib_pr.name not in valid_sib_set:
                    # Skip seat covers not matching
                    continue

                if is_preset_wizard:
                    sib_grp_item = KnechtItem(grp_item,
                                              (f'{grp_item.childCount():03d}',
                                               sib_pr.name, '', 'options'))
                    sib_grp_item.fixed_userType = Kg.group_item
                    grp_item.append_item_child(sib_grp_item)
                    fa_parent = sib_grp_item

                # --- Iterate VOS Codes ---
                for vos_pr in vos_pr_ls:

                    # --- Iterate LUM Codes ---
                    for lum_pr in lum_pr_ls:

                        # Determine if all options belong to standard equipment L
                        fakom_type = 'fakom_option'
                        if not {sib_pr.value, vos_pr.value, lum_pr.value
                                }.difference('L'):
                            fakom_type = 'fakom_setup'

                        fa_item = self.create_fakom_item(
                            fa_parent, trim.model, model_short_desc, color,
                            sib_pr.name, vos_pr.name, lum_pr.name, sib_pr.desc,
                            vos_pr.desc, lum_pr.desc, fakom_type,
                            is_preset_wizard)
                        if is_preset_wizard:
                            continue
                        fa_parent.append_item_child(fa_item)

    def create_fakom_item(self,
                          parent: Union[KnechtItem, None],
                          model,
                          model_desc,
                          color,
                          sib,
                          vos,
                          lum,
                          sib_text,
                          vos_text,
                          lum_text,
                          fakom_type,
                          preset_wizard: bool = False):
        name = f'{model_desc} {color}-{sib}-{vos}-{lum}'
        if preset_wizard:
            name = f'{color}-{sib}-{vos}-{lum}'

        order = 0
        if parent:
            order = parent.childCount()

        data = (f'{order:03d}', f'{name}', model, fakom_type, '',
                self.id_gen.create_id())

        # Create FaKom item
        fa_item = KnechtItem(parent, data)

        if preset_wizard:
            fa_item.fixed_userType = Kg.dialog_item
            if parent:
                parent.append_item_child(fa_item)
            return

        # Create FaKom item content
        color_item = KnechtItem(fa_item, ('000', color, 'on'))
        sib_item = KnechtItem(fa_item,
                              ('001', sib, 'on', 'SIB', '', '', sib_text))
        vos_item = KnechtItem(fa_item,
                              ('002', vos, 'on', 'VOS', '', '', vos_text))
        lum_item = KnechtItem(fa_item,
                              ('003', lum, 'on', 'LUM', '', '', lum_text))

        for i in (color_item, sib_item, vos_item, lum_item):
            fa_item.append_item_child(i)

        return fa_item
Example #8
0
class KnechtXmlReader:
    """ Read RenderKnecht Xml

        :param: error: String containing the error message for the user
    """
    def __init__(self):
        # Helper class to convert and create QUuids
        self.xml_id = KnechtXmlId()
        # Temporary item stores -currently- iterated preset item
        self.__preset_item = None
        # Loaded items temporary root item
        self.root_item = KnechtItem()
        # Store error message
        self.error = str()

    def read_xml(self, file: Union[Path, str, bytes]) -> KnechtItem:
        """ Read RenderKnecht Xml and return list of KnechtItem's

            Stores Xml read errors in class attribute errors.

            :param: file: Xml file to load or utf-8 encoded Xml string
            :type: file: Path or str
            :rtype: KnechtItem: KnechtItem Root Node
            :returns: tree root node
        """
        xml = None

        if path_is_xml_string(file):
            try:
                xml = Et.fromstring(file)
            except Exception as e:
                LOGGER.error('Error parsing Xml string data: %s', e)
                self.set_error(0)
                return self.root_item

        if xml is None:
            try:
                xml = Et.parse(file.as_posix())
            except Exception as e:
                LOGGER.error('Error parsing Xml document:\n%s', e)
                self.set_error(0)
                return self.root_item

        if not self._validate_renderknecht_xml(xml):
            self.set_error(1)
            return self.root_item

        # Transfer Xml to self.root_item
        self._xml_to_items(xml)

        if not self.root_item.childCount():
            self.set_error(2)

        # Return the list of item data
        return self.root_item

    def _xml_to_items(self, xml):
        for e in xml.iterfind('./*//'):
            self._read_node(e)

    def _read_node(self, node: Et.Element):
        # Re-write order with leading zeros
        if 'order' in node.attrib.keys():
            node.set('order', f'{int(node.attrib["order"]):03d}')

        # Backwards compatible, value stored in tag text
        if node.tag == KgTags.variant_tag and node.text:
            node.set('value', node.text)

        if node.tag in KgTags.preset_tags:
            # Create preset item: node, parent
            self.__preset_item = self._create_tree_item(node)

        elif node.tag == KgTags.render_preset_tag:
            self.__preset_item = self._create_tree_item(node)

        elif node.tag in KgTags.separator_tags:
            self._create_tree_item(node)

        elif node.tag in KgTags.sub_separator_tags:
            node.attrib['type'] = 'sub_separator'
            self._create_tree_item(node, self.__preset_item)

        elif node.tag in KgTags.render_setting_tags:
            self._create_tree_item(node, self.__preset_item)

        elif node.tag in KgTags.variants_tags:
            if node.getparent().tag == Kg.xml_dom_tags['level_1']:
                # Parse orphans aswell for session load / variants widget
                self._create_tree_item(node)
            else:
                # Create variant / reference with parent: last preset_item
                self._create_tree_item(node, self.__preset_item)

    def _create_tree_item(self,
                          node,
                          parent_item: KnechtItem = None) -> KnechtItem:
        data = self._data_from_element_attribute(node)

        if parent_item is None:
            child_position = self.root_item.childCount()
            self.root_item.insertChildren(child_position, 1, data)
            parent_item = self.root_item.child(child_position)

            self.xml_id.update_preset_uuid(node, parent_item)
            return parent_item

        position = parent_item.childCount()
        result = parent_item.insertChildren(position, 1, data)

        if not result:
            LOGGER.error('Could not insert child %s %s', position,
                         parent_item.childCount())
            return parent_item

        self.xml_id.update_reference_uuid(node, parent_item.child(position))
        return parent_item

    def set_error(self, error_type: int = 0):
        error_msg = {
            0:
            _('Das gewählte Xml Dokument ist kein gültiges Xml Dokument und konnte nicht gelesen werden.'
              ),
            1:
            _('Das gewählte Xml Dokument enthält nicht die erwarteten Daten. Es ist kein RenderKnecht '
              'kompatibles Xml Dokument.'),
            2:
            _('Das gewählte Xml Dokument ist gültig, enthält aber kein Daten.'
              ),
        }

        self.error = error_msg[error_type]

    @staticmethod
    def _data_from_element_attribute(node) -> tuple:
        data = list()

        for key in Kg.column_keys:
            data.append(node.attrib.get(key) or '')

        return tuple(data)

    @staticmethod
    def _validate_renderknecht_xml(xml):
        root = xml.find('.')
        if root.tag != Kg.xml_dom_tags['root']:
            LOGGER.error(
                'Can not load Xml document. Expected xml root tag: %s, received: %s',
                Kg.xml_dom_tags['root'], root.tag)
            return False
        return True
Example #9
0
    def collect_result(self):
        kn_data = self.session.data.import_data
        converter = KnechtDataToModel(kn_data)
        trim_items = dict()

        # --- Create Trim Setups ---
        for model_code in self.session.data.fakom_selection.keys():
            trim = self._get_trim_from_models(kn_data.models, model_code)
            trim_items[model_code] = dict()
            trim_item = converter.create_trim(trim)
            trim_item.refresh_id_data()
            trim_items[model_code]['trim_setup'] = trim_item
            trim_items[model_code][
                'trim_option'] = converter.create_trim_options(
                    trim, kn_data.options_text_filter)
            trim_items[model_code]['packages'] = list()
            trim_items[model_code]['fakom'] = dict()

        # -- Create FaKom Items --
        for preset_page in self.session.iterate_preset_pages():
            fakom_ls = preset_page.fakom.split('-')
            if len(fakom_ls) < 4:
                continue
            trim = self._get_trim_from_models(kn_data.models,
                                              preset_page.model)

            # Create lists of List[KnPr] for SIB/VOS/LUM families
            sib_pr_ls = [
                pr for pr in trim.iterate_available_pr()
                if pr.family.casefold() == 'sib'
            ]
            lum_pr_ls = [
                pr for pr in trim.iterate_available_pr()
                if pr.family.casefold() == 'lum'
            ]
            vos_pr_ls = [
                pr for pr in trim.iterate_available_pr()
                if pr.family.casefold() == 'vos'
            ]

            fa, sib, vos, lum = fakom_ls
            LOGGER.debug('Creating Fakom Item %s %s %s %s', fa, sib, vos, lum)
            sib_pr = self._get_pr_from_list(sib_pr_ls, sib)
            vos_pr = self._get_pr_from_list(vos_pr_ls, vos)
            lum_pr = self._get_pr_from_list(lum_pr_ls, lum)

            fakom_type = 'fakom_option'
            if not {sib_pr.value, vos_pr.value, lum_pr.value}.difference('L'):
                fakom_type = 'fakom_setup'

            fa_item = converter.create_fakom_item(None, trim.model,
                                                  trim.model_text, fa, sib,
                                                  vos, lum, sib_pr.desc,
                                                  vos_pr.desc, lum_pr.desc,
                                                  fakom_type, False)
            fa_item.refresh_id_data()
            trim_items[preset_page.model]['fakom'][preset_page.fakom] = fa_item

        # --- Prepare presets ---
        preset_items = list()
        for preset_page in self.session.iterate_preset_pages():
            # -- Create Preset item --
            preset_item = KnechtItem(
                None, ('000', preset_page.subTitle(), '',
                       Kg.type_keys[Kg.preset], '', Kid.create_id()))
            # -- Add reference to trim setup --
            trim_ref = trim_items[preset_page.model]['trim_setup'].copy(
                copy_children=False)
            trim_ref.convert_to_reference()
            trim_ref.setData(0, '000')
            preset_item.append_item_child(trim_ref)

            # -- Add reference to fakom item --
            fa_ref = trim_items[preset_page.model]['fakom'][
                preset_page.fakom].copy(copy_children=False)
            fa_ref.convert_to_reference()
            fa_ref.setData(0, '001')
            preset_item.append_item_child(fa_ref)

            # -- Collect preset content --
            for _, pr_item in preset_page.preset_tree.editor.iterator.iterate_view(
            ):
                if pr_item.userType == Kg.variant:
                    # --- Add PR-option ---
                    pr_item_copy = pr_item.copy()
                    pr_item_copy.setData(0, f'{preset_item.childCount():03d}')
                    preset_item.append_item_child(pr_item_copy)
                else:
                    # --- Add package reference ---
                    pkg_ref = pr_item.copy(copy_children=False)
                    pkg_ref.convert_to_reference()
                    pkg_ref.setData(0, f'{preset_item.childCount():03d}')
                    preset_item.append_item_child(pkg_ref)
                    # --- Add package ---
                    trim_items[preset_page.model]['packages'].append(
                        pr_item.copy())

            preset_items.append(preset_item)

        # --- Create trim, package and fakom items ---
        root_item = KnechtItem()

        for model_code in self.session.data.fakom_selection.keys():
            # -- Add trim setup --
            trim_item = trim_items[model_code]['trim_setup']
            trim_item.setData(Kg.ORDER, f'{root_item.childCount():03d}')
            root_item.append_item_child(trim_item)

            # -- Add trim options --
            trim_options = trim_items[model_code]['trim_option']
            trim_options.setData(Kg.ORDER, f'{root_item.childCount():03d}')
            root_item.append_item_child(trim_options)

            # -- Add Packages --
            for pkg_item in trim_items[model_code]['packages']:
                pkg_item.setData(Kg.ORDER, f'{root_item.childCount():03d}')
                root_item.append_item_child(pkg_item)

            # -- Add FaKom Items --
            for fa_item in trim_items[model_code]['fakom'].values():
                fa_item.setData(Kg.ORDER, f'{root_item.childCount():03d}')
                root_item.append_item_child(fa_item)

            # -- Add separator --
            root_item.append_item_child(
                KnechtItem(
                    None,
                    (f'{root_item.childCount():03d}', '', '', 'separator')))

        # -- Create default Reset --
        reset_item = create_reset_item(root_item.childCount())
        root_item.append_item_child(reset_item)

        # -- Add separator --
        root_item.append_item_child(
            KnechtItem(None,
                       (f'{root_item.childCount():03d}', '', '', 'separator')))

        # --- Create Preset items ---
        for preset_item in preset_items:
            preset_item.setData(Kg.ORDER, f'{root_item.childCount():03d}')
            root_item.append_item_child(preset_item)

        UpdateModel(self.result_tree).update(KnechtModel(root_item))