mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2025-06-20 17:15:51 +02:00
Merge branch 'kicad-api'
This commit is contained in:
commit
34fd611946
17 changed files with 263 additions and 50 deletions
|
@ -42,6 +42,7 @@
|
|||
PassEnv PROVIDER_TME_KEY PROVIDER_TME_SECRET PROVIDER_TME_CURRENCY PROVIDER_TME_LANGUAGE PROVIDER_TME_COUNTRY PROVIDER_TME_GET_GROSS_PRICES
|
||||
PassEnv PROVIDER_OCTOPART_CLIENT_ID PROVIDER_OCTOPART_SECRET PROVIDER_OCTOPART_CURRENCY PROVIDER_OCTOPART_COUNTRY PROVIDER_OCTOPART_SEARCH_LIMIT PROVIDER_OCTOPART_ONLY_AUTHORIZED_SELLERS
|
||||
PassEnv PROVIDER_MOUSER_KEY PROVIDER_MOUSER_SEARCH_OPTION PROVIDER_MOUSER_SEARCH_LIMIT PROVIDER_MOUSER_SEARCH_WITH_SIGNUP_LANGUAGE
|
||||
PassEnv EDA_KICAD_CATEGORY_DEPTH
|
||||
|
||||
# For most configuration files from conf-available/, which are
|
||||
# enabled or disabled at a global level, it is possible to
|
||||
|
|
9
.env
9
.env
|
@ -159,6 +159,15 @@ PROVIDER_MOUSER_SEARCH_LIMIT=50
|
|||
# Used when searching for keywords in the language specified when you signed up for Search API.
|
||||
PROVIDER_MOUSER_SEARCH_WITH_SIGNUP_LANGUAGE='true'
|
||||
|
||||
##################################################################################
|
||||
# EDA integration related settings
|
||||
##################################################################################
|
||||
|
||||
# This value determines the depth of the category tree, that is visible inside KiCad
|
||||
# 0 means that only the top level categories are visible. Set to a value > 0 to show more levels.
|
||||
# Set to -1, to show all parts of Part-DB inside a single category in KiCad
|
||||
EDA_KICAD_CATEGORY_DEPTH=0
|
||||
|
||||
###################################################################################
|
||||
# SAML Single sign on-settings
|
||||
###################################################################################
|
||||
|
|
|
@ -142,3 +142,4 @@ parameters:
|
|||
env(HISTORY_SAVE_REMOVED_DATA): 1
|
||||
env(HISTORY_SAVE_NEW_DATA): 1
|
||||
|
||||
env(EDA_KICAD_CATEGORY_DEPTH): 0
|
||||
|
|
|
@ -316,6 +316,13 @@ services:
|
|||
$global_locale: '%partdb.locale%'
|
||||
$global_timezone: '%partdb.timezone%'
|
||||
|
||||
####################################################################################################################
|
||||
# EDA system
|
||||
####################################################################################################################
|
||||
App\Services\EDA\KiCadHelper:
|
||||
arguments:
|
||||
$category_depth: '%env(int:EDA_KICAD_CATEGORY_DEPTH)%'
|
||||
|
||||
####################################################################################################################
|
||||
# Symfony overrides
|
||||
####################################################################################################################
|
||||
|
|
|
@ -128,6 +128,14 @@ then `HISTORY_SAVE_CHANGED_FIELDS`, `HISTORY_SAVE_CHANGED_DATA` and `HISTORY_SAV
|
|||
* `ERROR_PAGE_SHOW_HELP`: Set this 0, to disable the solution hints shown on an error page. These hints should not
|
||||
contain sensitive information, but could confuse end-users.
|
||||
|
||||
### EDA related settings
|
||||
|
||||
* `EDA_KICAD_CATEGORY_DEPTH`: A number, which determines how many levels of Part-DB categories should be shown inside KiCad.
|
||||
All parts in the selected category and all subcategories are shown in KiCad.
|
||||
For performance reason this value should not be too high. The default is 0, which means that only the top level categories are shown in KiCad.
|
||||
All parts in the selected category and all subcategories are shown in KiCad. Set this to a higher value, if you want to show more categories in KiCad.
|
||||
When you set this value to -1, all parts are shown inside a single category in KiCad.
|
||||
|
||||
### SAML SSO settings
|
||||
|
||||
The following settings can be used to enable and configure Single-Sign on via SAML. This allows users to log in to
|
||||
|
|
|
@ -25,7 +25,8 @@ You require a user account in Part-DB, which has the permission to access Part-D
|
|||
To connect KiCad with Part-DB do following steps:
|
||||
|
||||
1. Create an API token on the user settings page for the KiCAD application and copy/save it, when it is shown. Currently KiCAD can only read Part-DB database, so a token with read only scope is enough.
|
||||
2. Create a file `partd.kicad_httplib` (or similar, only the extension is important) with the following content:
|
||||
2. Add some EDA metadata to parts, categories or footprints. Only parts with useable info will show up in KiCad. See below for more info.
|
||||
3. Create a file `partd.kicad_httplib` (or similar, only the extension is important) with the following content:
|
||||
```
|
||||
{
|
||||
"meta": {
|
||||
|
@ -41,11 +42,11 @@ To connect KiCad with Part-DB do following steps:
|
|||
}
|
||||
}
|
||||
```
|
||||
3. Replace the `root_url` with the URL of your Part-DB instance plus `/en/kicad-api/`. You can find the right value for this in the Part-DB user settings page under "API endpoints" in the "API tokens" panel.
|
||||
4. Replace the `token` field value with the token you have generated in step 1.
|
||||
5. Open KiCad and add this created file as library in the KiCad symbol table under (Preferences --> Manage Symbol Libraries)
|
||||
4. Replace the `root_url` with the URL of your Part-DB instance plus `/en/kicad-api/`. You can find the right value for this in the Part-DB user settings page under "API endpoints" in the "API tokens" panel.
|
||||
5. Replace the `token` field value with the token you have generated in step 1.
|
||||
6. Open KiCad and add this created file as library in the KiCad symbol table under (Preferences --> Manage Symbol Libraries)
|
||||
|
||||
If you then place a new part, the library dialog opens and you should be able to see the categories and parts from Part-DB.
|
||||
If you then place a new part, the library dialog opens, and you should be able to see the categories and parts from Part-DB.
|
||||
|
||||
### How to associate footprints and symbols with parts
|
||||
|
||||
|
@ -55,4 +56,24 @@ You can define this on a per-part basis using the KiCad symbol and KiCad footpri
|
|||
|
||||
For example to configure the values for an BC547 transistor you would put `Transistor_BJT:BC547` on the parts Kicad symbol to give it the right schematic symbol in EEschema and `Package_TO_SOT_THT:TO-92` to give it the right footprint in PcbNew.
|
||||
|
||||
If you type in a character, you will get an autocomplete list of all symbols and footprints available in the kicad standard library. You can also input your own value.
|
||||
If you type in a character, you will get an autocomplete list of all symbols and footprints available in the kicad standard library. You can also input your own value.
|
||||
|
||||
### Parts and category visibility
|
||||
|
||||
Only parts and their categories, on which there is any kind of EDA metadata are defined show up in KiCad. So if you want to see parts in KiCad,
|
||||
you need to define at least a symbol, footprint, reference prefix or value on a part, category or footprint.
|
||||
|
||||
You can use the "Force visibility" checkbox on a part or category to override this behavior and force parts to be visible or hidden in KiCad.
|
||||
|
||||
*Please note that KiCad caches the library categories. So if you change something, which would change the visibile categories in KiCad, you have to reload EEschema to see the changes.*
|
||||
|
||||
### Category depth in KiCad
|
||||
|
||||
For performance reasons, only the most top level categories of Part-DB are shown as categories in KiCad. All parts in the subcategories are shown in the top level category.
|
||||
|
||||
You can configure the depth of the categories shown in KiCad, via the `EDA_KICAD_CATEGORY_DEPTH` env option. The default value is 0, which meabs only the top level categories are shown.
|
||||
To show more levels of categories, you can set this value to a higher number.
|
||||
|
||||
If you set this value to -1, all parts are shown inside a single category in KiCad, without any subcategories.
|
||||
|
||||
You can view the "real" category path of a part in the part details dialog in KiCad.
|
|
@ -25,7 +25,7 @@ namespace App\Controller;
|
|||
|
||||
use App\Entity\Parts\Category;
|
||||
use App\Entity\Parts\Part;
|
||||
use App\Services\EDAIntegration\KiCADHelper;
|
||||
use App\Services\EDA\KiCadHelper;
|
||||
use App\Services\Trees\NodesListBuilder;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
|
@ -36,7 +36,7 @@ use Symfony\Component\Routing\Annotation\Route;
|
|||
class KiCadApiController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly KiCADHelper $kiCADHelper,
|
||||
private readonly KiCadHelper $kiCADHelper,
|
||||
)
|
||||
{
|
||||
}
|
||||
|
@ -62,9 +62,13 @@ class KiCadApiController extends AbstractController
|
|||
}
|
||||
|
||||
#[Route('/parts/category/{category}.json', name: 'kicad_api_category')]
|
||||
public function categoryParts(Category $category): Response
|
||||
public function categoryParts(?Category $category): Response
|
||||
{
|
||||
$this->denyAccessUnlessGranted('read', $category);
|
||||
if ($category) {
|
||||
$this->denyAccessUnlessGranted('read', $category);
|
||||
} else {
|
||||
$this->denyAccessUnlessGranted('@categories.read');
|
||||
}
|
||||
$this->denyAccessUnlessGranted('@parts.read');
|
||||
|
||||
return $this->json($this->kiCADHelper->getCategoryParts($category));
|
||||
|
|
|
@ -38,10 +38,10 @@ class EDACategoryInfo
|
|||
#[Groups(['full', 'category:read', 'category:write'])]
|
||||
private ?string $reference_prefix = null;
|
||||
|
||||
/** @var bool|null If this is true, then this part is invisible for the EDA software */
|
||||
#[Column(type: Types::BOOLEAN, nullable: true)]
|
||||
/** @var bool|null Visibility of this part to EDA software in trinary logic. True=Visible, False=Invisible, Null=Auto */
|
||||
#[Column(name: 'invisible', type: Types::BOOLEAN, nullable: true)] //TODO: Rename column to visibility
|
||||
#[Groups(['full', 'category:read', 'category:write'])]
|
||||
private ?bool $invisible = null;
|
||||
private ?bool $visibility = null;
|
||||
|
||||
/** @var bool|null If this is set to true, then this part will be excluded from the BOM */
|
||||
#[Column(type: Types::BOOLEAN, nullable: true)]
|
||||
|
@ -74,14 +74,14 @@ class EDACategoryInfo
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function getInvisible(): ?bool
|
||||
public function getVisibility(): ?bool
|
||||
{
|
||||
return $this->invisible;
|
||||
return $this->visibility;
|
||||
}
|
||||
|
||||
public function setInvisible(?bool $invisible): EDACategoryInfo
|
||||
public function setVisibility(?bool $visibility): EDACategoryInfo
|
||||
{
|
||||
$this->invisible = $invisible;
|
||||
$this->visibility = $visibility;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
|
|
@ -43,10 +43,10 @@ class EDAPartInfo
|
|||
#[Groups(['full', 'eda_info:read', 'eda_info:write'])]
|
||||
private ?string $value = null;
|
||||
|
||||
/** @var bool|null If this is true, then this part is invisible for the EDA software */
|
||||
#[Column(type: Types::BOOLEAN, nullable: true)]
|
||||
/** @var bool|null Visibility of this part to EDA software in trinary logic. True=Visible, False=Invisible, Null=Auto */
|
||||
#[Column(name: 'invisible', type: Types::BOOLEAN, nullable: true)] //TODO: Rename column to visibility
|
||||
#[Groups(['full', 'eda_info:read', 'eda_info:write'])]
|
||||
private ?bool $invisible = null;
|
||||
private ?bool $visibility = null;
|
||||
|
||||
/** @var bool|null If this is set to true, then this part will be excluded from the BOM */
|
||||
#[Column(type: Types::BOOLEAN, nullable: true)]
|
||||
|
@ -100,14 +100,14 @@ class EDAPartInfo
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function getInvisible(): ?bool
|
||||
public function getVisibility(): ?bool
|
||||
{
|
||||
return $this->invisible;
|
||||
return $this->visibility;
|
||||
}
|
||||
|
||||
public function setInvisible(?bool $invisible): EDAPartInfo
|
||||
public function setVisibility(?bool $visibility): EDAPartInfo
|
||||
{
|
||||
$this->invisible = $invisible;
|
||||
$this->visibility = $visibility;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,8 +45,9 @@ class EDACategoryInfoType extends AbstractType
|
|||
]
|
||||
]
|
||||
)
|
||||
->add('invisible', TriStateCheckboxType::class, [
|
||||
'label' => 'eda_info.invisible',
|
||||
->add('visibility', TriStateCheckboxType::class, [
|
||||
'help' => 'eda_info.visibility.help',
|
||||
'label' => 'eda_info.visibility',
|
||||
])
|
||||
->add('exclude_from_bom', TriStateCheckboxType::class, [
|
||||
'label' => 'eda_info.exclude_from_bom',
|
||||
|
|
|
@ -50,8 +50,9 @@ class EDAPartInfoType extends AbstractType
|
|||
'placeholder' => t('eda_info.value.placeholder'),
|
||||
]
|
||||
])
|
||||
->add('invisible', TriStateCheckboxType::class, [
|
||||
'label' => 'eda_info.invisible',
|
||||
->add('visibility', TriStateCheckboxType::class, [
|
||||
'help' => 'eda_info.visibility.help',
|
||||
'label' => 'eda_info.visibility',
|
||||
])
|
||||
->add('exclude_from_bom', TriStateCheckboxType::class, [
|
||||
'label' => 'eda_info.exclude_from_bom',
|
||||
|
|
|
@ -64,6 +64,11 @@ abstract class AbstractPartsContainingRepository extends StructuralDBElementRepo
|
|||
return $this->getPartsCountRecursiveWithDepthN($element, self::RECURSION_LIMIT);
|
||||
}
|
||||
|
||||
public function getPartsRecursive(AbstractPartsContainingDBElement $element): array
|
||||
{
|
||||
return $this->getPartsRecursiveWithDepthN($element, self::RECURSION_LIMIT);
|
||||
}
|
||||
|
||||
/**
|
||||
* The implementation of the recursive function to get the parts count.
|
||||
* This function is used to limit the recursion depth (remaining_depth is decreased on each call).
|
||||
|
@ -91,6 +96,23 @@ abstract class AbstractPartsContainingRepository extends StructuralDBElementRepo
|
|||
return $count;
|
||||
}
|
||||
|
||||
protected function getPartsRecursiveWithDepthN(AbstractPartsContainingDBElement $element, int $remaining_depth): array
|
||||
{
|
||||
if ($remaining_depth <= 0) {
|
||||
throw new \RuntimeException('Recursion limit reached!');
|
||||
}
|
||||
|
||||
//Add direct parts
|
||||
$parts = $this->getParts($element);
|
||||
|
||||
//Then iterate over all children and add their parts
|
||||
foreach ($element->getChildren() as $child) {
|
||||
$parts = array_merge($parts, $this->getPartsRecursiveWithDepthN($child, $remaining_depth - 1));
|
||||
}
|
||||
|
||||
return $parts;
|
||||
}
|
||||
|
||||
protected function getPartsByField(object $element, array $order_by, string $field_name): array
|
||||
{
|
||||
if (!$element instanceof AbstractPartsContainingDBElement) {
|
||||
|
|
|
@ -21,19 +21,21 @@
|
|||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Services\EDAIntegration;
|
||||
namespace App\Services\EDA;
|
||||
|
||||
use App\Entity\Parts\Category;
|
||||
use App\Entity\Parts\Footprint;
|
||||
use App\Entity\Parts\Part;
|
||||
use App\Services\Cache\ElementCacheTagGenerator;
|
||||
use App\Services\Trees\NodesListBuilder;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
use Symfony\Contracts\Cache\ItemInterface;
|
||||
use Symfony\Contracts\Cache\TagAwareCacheInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
class KiCADHelper
|
||||
class KiCadHelper
|
||||
{
|
||||
|
||||
public function __construct(
|
||||
|
@ -43,6 +45,8 @@ class KiCADHelper
|
|||
private readonly ElementCacheTagGenerator $tagGenerator,
|
||||
private readonly UrlGeneratorInterface $urlGenerator,
|
||||
private readonly TranslatorInterface $translator,
|
||||
/** The maximum level of the shown categories. 0 Means only the top level categories are shown. -1 means only a single one containing */
|
||||
private readonly int $category_depth,
|
||||
) {
|
||||
}
|
||||
|
||||
|
@ -55,23 +59,48 @@ class KiCADHelper
|
|||
*/
|
||||
public function getCategories(): array
|
||||
{
|
||||
return $this->kicadCache->get('kicad_categories', function (ItemInterface $item) {
|
||||
return $this->kicadCache->get('kicad_categories_' . $this->category_depth, function (ItemInterface $item) {
|
||||
//Invalidate the cache on category changes
|
||||
$secure_class_name = $this->tagGenerator->getElementTypeCacheTag(Category::class);
|
||||
$item->tag($secure_class_name);
|
||||
|
||||
//If the category depth is smaller than 0, create only one dummy category
|
||||
if ($this->category_depth < 0) {
|
||||
return [
|
||||
[
|
||||
'id' => '0',
|
||||
'name' => 'Part-DB',
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
//Otherwise just get the categories and filter them
|
||||
|
||||
$categories = $this->nodesListBuilder->typeToNodesList(Category::class);
|
||||
$repo = $this->em->getRepository(Category::class);
|
||||
$result = [];
|
||||
foreach ($categories as $category) {
|
||||
//Skip invisible categories
|
||||
if ($category->getEdaInfo()->getInvisible() ?? false) {
|
||||
if ($category->getEdaInfo()->getVisibility() === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//Skip categories with a depth greater than the configured one
|
||||
if ($category->getLevel() > $this->category_depth) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/** @var $category Category */
|
||||
//Ensure that the category contains parts
|
||||
if ($repo->getPartsCount($category) < 1) {
|
||||
//For the last level, we need to use a recursive query, otherwise we can use a simple query
|
||||
/** @var Category $category */
|
||||
$parts_count = $category->getLevel() >= $this->category_depth ? $repo->getPartsCountRecursive($category) : $repo->getPartsCount($category);
|
||||
|
||||
if ($parts_count < 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//Check if the category should be visible
|
||||
if (!$this->shouldCategoryBeVisible($category)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -89,25 +118,43 @@ class KiCADHelper
|
|||
/**
|
||||
* Returns an array of objects containing all parts for the given category in the format required by KiCAD.
|
||||
* The result is cached for performance and invalidated on category or part changes.
|
||||
* @param Category $category
|
||||
* @param Category|null $category
|
||||
* @return array
|
||||
*/
|
||||
public function getCategoryParts(Category $category): array
|
||||
public function getCategoryParts(?Category $category): array
|
||||
{
|
||||
return $this->kicadCache->get('kicad_category_parts_'.$category->getID(),
|
||||
return $this->kicadCache->get('kicad_category_parts_'.($category?->getID() ?? 0) . '_' . $this->category_depth,
|
||||
function (ItemInterface $item) use ($category) {
|
||||
$item->tag([
|
||||
$this->tagGenerator->getElementTypeCacheTag(Category::class),
|
||||
$this->tagGenerator->getElementTypeCacheTag(Part::class)
|
||||
$this->tagGenerator->getElementTypeCacheTag(Part::class),
|
||||
//Visibility can change based on the footprint
|
||||
$this->tagGenerator->getElementTypeCacheTag(Footprint::class)
|
||||
]);
|
||||
|
||||
$category_repo = $this->em->getRepository(Category::class);
|
||||
$parts = $category_repo->getParts($category);
|
||||
if ($this->category_depth >= 0) {
|
||||
//Ensure that the category is set
|
||||
if (!$category) {
|
||||
throw new NotFoundHttpException('Category must be set, if category_depth is greater than 1!');
|
||||
}
|
||||
|
||||
$category_repo = $this->em->getRepository(Category::class);
|
||||
if ($category->getLevel() >= $this->category_depth) {
|
||||
//Get all parts for the category and its children
|
||||
$parts = $category_repo->getPartsRecursive($category);
|
||||
} else {
|
||||
//Get only direct parts for the category (without children), as the category is not collapsed
|
||||
$parts = $category_repo->getParts($category);
|
||||
}
|
||||
} else {
|
||||
//Get all parts
|
||||
$parts = $this->em->getRepository(Part::class)->findAll();
|
||||
}
|
||||
|
||||
$result = [];
|
||||
foreach ($parts as $part) {
|
||||
//If the part is invisible, then skip it
|
||||
if ($part->getEdaInfo()->getInvisible() ?? $part->getCategory()?->getEdaInfo()->getInvisible() ?? false) {
|
||||
if (!$this->shouldPartBeVisible($part)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -186,6 +233,91 @@ class KiCADHelper
|
|||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given part should be visible for the EDA.
|
||||
* @param Category $category
|
||||
* @return bool
|
||||
*/
|
||||
private function shouldCategoryBeVisible(Category $category): bool
|
||||
{
|
||||
$eda_info = $category->getEdaInfo();
|
||||
|
||||
//If the category visibility is explicitly set, then use it
|
||||
if ($eda_info->getVisibility() !== null) {
|
||||
return $eda_info->getVisibility();
|
||||
}
|
||||
|
||||
//try to check if the fields were set
|
||||
if ($eda_info->getKicadSymbol() !== null
|
||||
|| $eda_info->getReferencePrefix() !== null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//Check if there is any part in this category, which should be visible
|
||||
$category_repo = $this->em->getRepository(Category::class);
|
||||
if ($category->getLevel() >= $this->category_depth) {
|
||||
//Get all parts for the category and its children
|
||||
$parts = $category_repo->getPartsRecursive($category);
|
||||
} else {
|
||||
//Get only direct parts for the category (without children), as the category is not collapsed
|
||||
$parts = $category_repo->getParts($category);
|
||||
}
|
||||
|
||||
foreach ($parts as $part) {
|
||||
if ($this->shouldPartBeVisible($part)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//Otherwise the category should be not visible
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given part should be visible for the EDA.
|
||||
* @param Part $part
|
||||
* @return bool
|
||||
*/
|
||||
private function shouldPartBeVisible(Part $part): bool
|
||||
{
|
||||
$eda_info = $part->getEdaInfo();
|
||||
$category = $part->getCategory();
|
||||
|
||||
//If the user set a visibility, then use it
|
||||
if ($eda_info->getVisibility() !== null) {
|
||||
return $part->getEdaInfo()->getVisibility();
|
||||
}
|
||||
|
||||
//If the part has a category, then use the category visibility if possible
|
||||
if ($category && $category->getEdaInfo()->getVisibility() !== null) {
|
||||
return $category->getEdaInfo()->getVisibility();
|
||||
}
|
||||
|
||||
//If both are null, then we try to determine the visibility based on if fields are set
|
||||
if ($eda_info->getKicadSymbol() !== null
|
||||
|| $eda_info->getKicadFootprint() !== null
|
||||
|| $eda_info->getReferencePrefix() !== null
|
||||
|| $eda_info->getValue() !== null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//Check also if the fields are set for the category (if it exists)
|
||||
if ($category && (
|
||||
$category->getEdaInfo()->getKicadSymbol() !== null
|
||||
|| $category->getEdaInfo()->getReferencePrefix() !== null
|
||||
)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//And on the footprint
|
||||
if ($part->getFootprint() && $part->getFootprint()->getEdaInfo()->getKicadFootprint() !== null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//Otherwise the part should be not visible
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a boolean value to the format required by KiCAD.
|
||||
* @param bool $value
|
|
@ -41,7 +41,7 @@
|
|||
|
||||
<div class="row">
|
||||
<div class="col-sm-9 offset-sm-3">
|
||||
{{ form_row(form.eda_info.invisible) }}
|
||||
{{ form_row(form.eda_info.visibility) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
<div class="row">
|
||||
<div class="col-sm-9 offset-sm-3">
|
||||
{{ form_row(form.eda_info.invisible) }}
|
||||
{{ form_row(form.eda_info.visibility) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -92,7 +92,7 @@
|
|||
<br>
|
||||
<b>{% trans %}eda_info.value{% endtrans %}:</b> {{ part.edaInfo.value }}
|
||||
<br>
|
||||
<b>{% trans %}eda_info.invisible{% endtrans %}:</b> {{ helper.boolean_badge( part.edaInfo.invisible ?? part.category.edaInfo.invisible ?? false) }}
|
||||
<b>{% trans %}eda_info.visibility{% endtrans %}:</b> {{ helper.boolean_badge( part.edaInfo.visibility ?? part.category.edaInfo.visibility) }}
|
||||
<br>
|
||||
<b>{% trans %}eda_info.exclude_from_bom{% endtrans %}:</b> {{ helper.boolean_badge( part.edaInfo.excludeFromBom ?? part.category.edaInfo.excludeFromBom ?? false) }}
|
||||
<br>
|
||||
|
|
|
@ -12107,12 +12107,6 @@ Please note, that you can not impersonate a disabled user. If you try you will g
|
|||
<target>e.g. 100n</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Q8nJNWg" name="eda_info.invisible">
|
||||
<segment>
|
||||
<source>eda_info.invisible</source>
|
||||
<target>Invisible to EDA software</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="VphdbQ9" name="eda_info.exclude_from_bom">
|
||||
<segment>
|
||||
<source>eda_info.exclude_from_bom</source>
|
||||
|
@ -12179,5 +12173,17 @@ Please note, that you can not impersonate a disabled user. If you try you will g
|
|||
<target>KiCad API root URL</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="UXT_MIM" name="eda_info.visibility">
|
||||
<segment>
|
||||
<source>eda_info.visibility</source>
|
||||
<target>Force visibility</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="NN5DZ4F" name="eda_info.visibility.help">
|
||||
<segment>
|
||||
<source>eda_info.visibility.help</source>
|
||||
<target>By default, the visibility to the EDA software is automatically determined. With this checkbox, you can force the part to be visible or invisible.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
</file>
|
||||
</xliff>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue