Skip to content

Commit 58a34e3

Browse files
Add custom KiCad autocomplete list settings (#1342)
* Add admin editor for KiCad autocomplete lists * Add custom KiCad autocomplete list settings * Ignore the footprints_custom.txt and symbols_custom.txt in git and create them on the fly if needed Otherwise it breaks the update mechanism * Added comments * Include kicad custom files in config backup command --------- Co-authored-by: Jan Böhmer <mail@jan-boehmer.de>
1 parent 35dcb29 commit 58a34e3

14 files changed

Lines changed: 665 additions & 3 deletions

File tree

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,10 @@ phpstan.neon
5555

5656
.claude/
5757
CLAUDE.md
58+
59+
.codex
60+
migrations/.codex
61+
docker-data/
62+
scripts/
63+
db/
64+
docker-compose.yaml

docs/usage/eda_integration.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ You can define this on a per-part basis using the KiCad symbol and KiCad footpri
6767
For example, to configure the values for a BC547 transistor you would put `Transistor_BJT:BC547` in the part's KiCad symbol field to give it the right schematic symbol in Eeschema and `Package_TO_SOT_THT:TO-92` to give it the right footprint in Pcbnew.
6868

6969
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.
70+
If you want to keep custom suggestions across updates, open the server settings page and use the "Autocomplete settings" page. There you can edit `public/kicad/footprints_custom.txt` and `public/kicad/symbols_custom.txt` and enable the "Use custom autocomplete lists" option to use those files instead of the autogenerated defaults.
7071

7172
### Parts and category visibility
7273

public/kicad/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# They are user generated and should not be tracked by git
2+
footprints_custom.txt
3+
symbols_custom.txt

src/Command/BackupCommand.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,10 @@ protected function backupConfig(ZipFile $zip, SymfonyStyle $io): void
201201
$config_dir = $this->project_dir.'/config';
202202
$zip->addFile($config_dir.'/parameters.yaml', 'config/parameters.yaml');
203203
$zip->addFile($config_dir.'/banner.md', 'config/banner.md');
204+
205+
//Add kicad custom footprints and symbols files
206+
$zip->addFile($this->project_dir . '/public/kicad/footprints_custom.txt', 'public/kicad/footprints_custom.txt');
207+
$zip->addFile($this->project_dir . '/public/kicad/symbols_custom.txt', 'public/kicad/symbols_custom.txt');
204208
}
205209

206210
protected function backupAttachments(ZipFile $zip, SymfonyStyle $io): void
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<?php
2+
/*
3+
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
4+
*
5+
* Copyright (C) 2019 - 2024 Jan Böhmer (https://github.com/jbtronics)
6+
*
7+
* This program is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU Affero General Public License as published
9+
* by the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU Affero General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Affero General Public License
18+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
19+
*/
20+
21+
declare(strict_types=1);
22+
23+
namespace App\Controller;
24+
25+
use App\Form\Settings\KicadListEditorType;
26+
use App\Settings\MiscSettings\KiCadEDASettings;
27+
use App\Services\EDA\KicadListFileManager;
28+
use Jbtronics\SettingsBundle\Exception\SettingsNotValidException;
29+
use Jbtronics\SettingsBundle\Manager\SettingsManagerInterface;
30+
use RuntimeException;
31+
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
32+
use Symfony\Component\HttpFoundation\Request;
33+
use Symfony\Component\HttpFoundation\Response;
34+
use Symfony\Component\Routing\Attribute\Route;
35+
36+
use function Symfony\Component\Translation\t;
37+
38+
final class KicadListEditorController extends AbstractController
39+
{
40+
public function __construct(
41+
private readonly SettingsManagerInterface $settingsManager,
42+
) {
43+
}
44+
45+
#[Route('/settings/misc/kicad-lists', name: 'settings_kicad_lists')]
46+
public function __invoke(Request $request, KicadListFileManager $fileManager): Response
47+
{
48+
$this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY');
49+
$this->denyAccessUnlessGranted('@config.change_system_settings');
50+
51+
/** @var KiCadEDASettings $settings */
52+
$settings = $this->settingsManager->createTemporaryCopy(KiCadEDASettings::class);
53+
$form = $this->createForm(KicadListEditorType::class, [
54+
'useCustomList' => $settings->useCustomList,
55+
'customFootprints' => $fileManager->getCustomFootprintsContent(),
56+
'customSymbols' => $fileManager->getCustomSymbolsContent(),
57+
], [
58+
'default_footprints' => $fileManager->getFootprintsContent(),
59+
'default_symbols' => $fileManager->getSymbolsContent(),
60+
]);
61+
62+
$form->handleRequest($request);
63+
64+
if ($form->isSubmitted() && $form->isValid()) {
65+
$data = $form->getData();
66+
67+
try {
68+
$fileManager->saveCustom($data['customFootprints'], $data['customSymbols']);
69+
$settings->useCustomList = (bool) $data['useCustomList'];
70+
$this->settingsManager->mergeTemporaryCopy($settings);
71+
$this->settingsManager->save($settings);
72+
$this->addFlash('success', t('settings.flash.saved'));
73+
74+
return $this->redirectToRoute('settings_kicad_lists');
75+
} catch (RuntimeException|SettingsNotValidException $exception) {
76+
$this->addFlash('error', $exception->getMessage());
77+
}
78+
}
79+
80+
if ($form->isSubmitted() && !$form->isValid()) {
81+
$this->addFlash('error', t('settings.flash.invalid'));
82+
}
83+
84+
return $this->render('settings/kicad_list_editor.html.twig', [
85+
'form' => $form,
86+
]);
87+
}
88+
}

src/Form/Part/EDA/KicadFieldAutocompleteType.php

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
namespace App\Form\Part\EDA;
2525

2626
use App\Form\Type\StaticFileAutocompleteType;
27+
use App\Settings\MiscSettings\KiCadEDASettings;
2728
use Symfony\Component\Form\AbstractType;
2829
use Symfony\Component\OptionsResolver\Options;
2930
use Symfony\Component\OptionsResolver\OptionsResolver;
@@ -39,6 +40,13 @@ class KicadFieldAutocompleteType extends AbstractType
3940
//Do not use a leading slash here! otherwise it will not work under prefixed reverse proxies
4041
public const FOOTPRINT_PATH = 'kicad/footprints.txt';
4142
public const SYMBOL_PATH = 'kicad/symbols.txt';
43+
public const CUSTOM_FOOTPRINT_PATH = 'kicad/footprints_custom.txt';
44+
public const CUSTOM_SYMBOL_PATH = 'kicad/symbols_custom.txt';
45+
46+
public function __construct(
47+
private readonly KiCadEDASettings $kiCadEDASettings,
48+
) {
49+
}
4250

4351
public function configureOptions(OptionsResolver $resolver): void
4452
{
@@ -47,8 +55,8 @@ public function configureOptions(OptionsResolver $resolver): void
4755

4856
$resolver->setDefaults([
4957
'file' => fn(Options $options) => match ($options['type']) {
50-
self::TYPE_FOOTPRINT => self::FOOTPRINT_PATH,
51-
self::TYPE_SYMBOL => self::SYMBOL_PATH,
58+
self::TYPE_FOOTPRINT => $this->kiCadEDASettings->useCustomList ? self::CUSTOM_FOOTPRINT_PATH : self::FOOTPRINT_PATH,
59+
self::TYPE_SYMBOL => $this->kiCadEDASettings->useCustomList ? self::CUSTOM_SYMBOL_PATH : self::SYMBOL_PATH,
5260
default => throw new \InvalidArgumentException('Invalid type'),
5361
}
5462
]);
@@ -58,4 +66,4 @@ public function getParent(): string
5866
{
5967
return StaticFileAutocompleteType::class;
6068
}
61-
}
69+
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
<?php
2+
/*
3+
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
4+
*
5+
* Copyright (C) 2019 - 2024 Jan Böhmer (https://github.com/jbtronics)
6+
*
7+
* This program is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU Affero General Public License as published
9+
* by the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU Affero General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Affero General Public License
18+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
19+
*/
20+
21+
declare(strict_types=1);
22+
23+
namespace App\Form\Settings;
24+
25+
use Symfony\Component\Form\AbstractType;
26+
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
27+
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
28+
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
29+
use Symfony\Component\Form\FormBuilderInterface;
30+
use Symfony\Component\OptionsResolver\OptionsResolver;
31+
32+
/**
33+
* Form type for editing the custom KiCad footprints and symbols lists.
34+
*/
35+
final class KicadListEditorType extends AbstractType
36+
{
37+
public function buildForm(FormBuilderInterface $builder, array $options): void
38+
{
39+
$builder
40+
->add('useCustomList', CheckboxType::class, [
41+
'label' => 'settings.misc.kicad_eda.use_custom_list',
42+
'help' => 'settings.misc.kicad_eda.use_custom_list.help',
43+
'required' => false,
44+
])
45+
->add('customFootprints', TextareaType::class, [
46+
'label' => 'settings.misc.kicad_eda.editor.custom_footprints',
47+
'help' => 'settings.misc.kicad_eda.editor.footprints.help',
48+
'attr' => [
49+
'rows' => 16,
50+
'spellcheck' => 'false',
51+
'class' => 'font-monospace',
52+
],
53+
])
54+
->add('defaultFootprints', TextareaType::class, [
55+
'label' => 'settings.misc.kicad_eda.editor.default_footprints',
56+
'help' => 'settings.misc.kicad_eda.editor.default_files_help',
57+
'disabled' => true,
58+
'mapped' => false,
59+
'data' => $options['default_footprints'],
60+
'attr' => [
61+
'rows' => 16,
62+
'spellcheck' => 'false',
63+
'class' => 'font-monospace',
64+
'readonly' => 'readonly',
65+
],
66+
])
67+
->add('customSymbols', TextareaType::class, [
68+
'label' => 'settings.misc.kicad_eda.editor.custom_symbols',
69+
'help' => 'settings.misc.kicad_eda.editor.symbols.help',
70+
'attr' => [
71+
'rows' => 16,
72+
'spellcheck' => 'false',
73+
'class' => 'font-monospace',
74+
],
75+
])
76+
->add('defaultSymbols', TextareaType::class, [
77+
'label' => 'settings.misc.kicad_eda.editor.default_symbols',
78+
'help' => 'settings.misc.kicad_eda.editor.default_files_help',
79+
'disabled' => true,
80+
'mapped' => false,
81+
'data' => $options['default_symbols'],
82+
'attr' => [
83+
'rows' => 16,
84+
'spellcheck' => 'false',
85+
'class' => 'font-monospace',
86+
'readonly' => 'readonly',
87+
],
88+
])
89+
->add('save', SubmitType::class, [
90+
'label' => 'save',
91+
]);
92+
}
93+
94+
public function configureOptions(OptionsResolver $resolver): void
95+
{
96+
$resolver->setDefaults([
97+
'default_footprints' => '',
98+
'default_symbols' => '',
99+
]);
100+
$resolver->setAllowedTypes('default_footprints', 'string');
101+
$resolver->setAllowedTypes('default_symbols', 'string');
102+
}
103+
}

0 commit comments

Comments
 (0)