Compare commits

..

263 Commits

Author SHA1 Message Date
Wayne Stambaugh fda292bd08 Tag stable version 9.0.5. 2025-10-01 15:09:57 -04:00
Alex Shvartzkop c666bf8626 STEP export: paint board body in soldermask color if soldermask export is off
Was broken in 54e9a97b26

Fixes (part of) https://gitlab.com/kicad/code/kicad/-/issues/21865
2025-10-01 21:56:34 +03:00
Alex Shvartzkop 96f20d102b Update translations 2025-09-30 15:10:36 +03:00
Henrik Kauhanen f57cdb52dd Translated using Weblate (Swedish)
Currently translated at 99.8% (10061 of 10080 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/sv/
2025-09-30 14:06:53 +02:00
Frank Sonnenberg a5d2294ec3 Translated using Weblate (German)
Currently translated at 100.0% (10080 of 10080 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/de/
2025-09-30 14:06:53 +02:00
Frank Sonnenberg 72fdb41b73 Translated using Weblate (German)
Currently translated at 100.0% (10080 of 10080 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/de/
2025-09-30 14:06:53 +02:00
Pferd O 2ca04123d4 Translated using Weblate (German)
Currently translated at 100.0% (10080 of 10080 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/de/
2025-09-30 14:06:53 +02:00
2tama3 07a4710363 Translated using Weblate (Japanese)
Currently translated at 100.0% (10080 of 10080 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/ja/
2025-09-30 14:06:52 +02:00
Sárkány Lőrinc c01e37304f Translated using Weblate (Hungarian)
Currently translated at 39.2% (3960 of 10080 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/hu/
2025-09-30 14:06:52 +02:00
Stefan Bjornelund the Gnome 52b57b1145 Translated using Weblate (Swedish)
Currently translated at 99.8% (10060 of 10080 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/sv/
2025-09-30 14:06:52 +02:00
2tama3 7b4e444f6c Translated using Weblate (Japanese)
Currently translated at 100.0% (10080 of 10080 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/ja/
2025-09-30 14:06:52 +02:00
Sárkány Lőrinc a9f4f85746 Translated using Weblate (Hungarian)
Currently translated at 39.2% (3955 of 10080 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/hu/
2025-09-30 14:06:52 +02:00
Pferd O bc7ece44eb Translated using Weblate (German)
Currently translated at 99.9% (10070 of 10080 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/de/
2025-09-30 14:06:52 +02:00
Sárkány Lőrinc 51cc22a4f2 Translated using Weblate (Hungarian)
Currently translated at 39.1% (3951 of 10080 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/hu/
2025-09-30 14:06:52 +02:00
Frank Sonnenberg 38f2541a3f Translated using Weblate (German)
Currently translated at 99.9% (10070 of 10080 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/de/
2025-09-30 14:06:52 +02:00
Ivan Chuba a05e3de852 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (10080 of 10080 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/uk/
2025-09-30 14:06:52 +02:00
co8 j 908e7205e7 Translated using Weblate (Japanese)
Currently translated at 100.0% (10080 of 10080 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/ja/
2025-09-30 14:06:52 +02:00
Sárkány Lőrinc a80e410683 Translated using Weblate (Hungarian)
Currently translated at 39.1% (3947 of 10080 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/hu/
2025-09-30 14:06:52 +02:00
Frank Sonnenberg fa234e4b58 Translated using Weblate (German)
Currently translated at 99.9% (10070 of 10080 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/de/
2025-09-30 14:06:52 +02:00
Pferd O fb82e722e1 Translated using Weblate (German)
Currently translated at 99.9% (10070 of 10080 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/de/
2025-09-30 14:06:52 +02:00
Максим Горпиніч b45f9e7392 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (10080 of 10080 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/uk/
2025-09-30 14:06:52 +02:00
dsa-t d496b281ef Translated using Weblate (Russian)
Currently translated at 100.0% (10080 of 10080 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/ru/
2025-09-30 14:06:51 +02:00
Sárkány Lőrinc 2a46ff370a Translated using Weblate (Hungarian)
Currently translated at 39.1% (3942 of 10080 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/hu/
2025-09-30 14:06:51 +02:00
Pferd O 44d0b27544 Translated using Weblate (German)
Currently translated at 99.8% (10064 of 10080 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/de/
2025-09-30 14:06:51 +02:00
Jeff Young 7d76868c5c Fix latent bug in UpdatePins().
(It was failing to update the unit and bodystyle.)

(cherry picked from commit 3f1999795c)
2025-09-29 17:30:49 +01:00
Jeff Young e4d9d1829f Honour alternate pin definitions.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/21618

(cherry picked from commit 19133bc6bd)
2025-09-27 13:36:42 +01:00
Jeff Young e585948861 Formatting.
(cherry picked from commit d140261ab1)
2025-09-27 13:15:02 +01:00
Jeff Young e31b177335 Static cast safety.
(cherry picked from commit 48c9145177)
2025-09-27 13:09:29 +01:00
jean-pierre charras 4624d57bc2 FRAME_FOOTPRINT_CHOOSER and FRAME_FOOTPRINT_VIEWER: fix incorrect save settings
They were saved in cvpcb.json instead of pcbnew.json, and especially for
FRAME_FOOTPRINT_CHOOSER, some settings were incorrectly retrieved because
not actually updated.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/21818

(cherry picked from commit 8f8edf8d69)
2025-09-26 12:40:21 +02:00
jean-pierre charras 4f2d1ec5a1 French translation update 2025-09-24 08:36:57 +02:00
Alex Shvartzkop 5bcb3edae1 Update translations 2025-09-23 13:55:59 +03:00
Sárkány Lőrinc 30fbfd53c1 Translated using Weblate (Hungarian)
Currently translated at 39.0% (3931 of 10069 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/hu/
2025-09-23 12:53:01 +02:00
Sárkány Lőrinc dc979be459 Translated using Weblate (Hungarian)
Currently translated at 36.5% (3679 of 10069 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/hu/
2025-09-23 12:53:01 +02:00
Frank Sonnenberg 450c4517b5 Translated using Weblate (German)
Currently translated at 100.0% (10069 of 10069 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/de/
2025-09-23 12:53:01 +02:00
Sárkány Lőrinc 47cd4d6b7a Translated using Weblate (Hungarian)
Currently translated at 36.2% (3648 of 10069 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/hu/
2025-09-23 12:53:01 +02:00
Pferd O 8842c575c3 Translated using Weblate (German)
Currently translated at 100.0% (10069 of 10069 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/de/
2025-09-23 12:53:01 +02:00
CloverGit 858c23f731 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 99.9% (10063 of 10069 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/zh_Hans/
2025-09-23 12:53:01 +02:00
Toni Laiho 1d879d51c5 Translated using Weblate (Finnish)
Currently translated at 97.7% (9842 of 10069 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/fi/
2025-09-23 12:53:00 +02:00
Pferd O 6e0df489eb Translated using Weblate (German)
Currently translated at 99.9% (10060 of 10069 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/de/
2025-09-23 12:53:00 +02:00
Henrik Kauhanen a9be5c5759 Translated using Weblate (Swedish)
Currently translated at 99.8% (10057 of 10069 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/sv/
2025-09-23 12:53:00 +02:00
Stefan De Raedemaeker 258e2fd46f Translated using Weblate (Dutch)
Currently translated at 90.6% (9127 of 10069 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/nl/
2025-09-23 12:53:00 +02:00
Pferd O f5852f0869 Translated using Weblate (German)
Currently translated at 99.9% (10059 of 10069 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/de/
2025-09-23 12:53:00 +02:00
Henrik Kauhanen 1d0adbc5d6 Translated using Weblate (Swedish)
Currently translated at 99.8% (10056 of 10069 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/sv/
2025-09-23 12:53:00 +02:00
Pferd O 34834fd963 Translated using Weblate (German)
Currently translated at 99.8% (10058 of 10069 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/de/
2025-09-23 12:53:00 +02:00
Frank Sonnenberg 2f095aeafb Translated using Weblate (German)
Currently translated at 99.8% (10058 of 10069 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/de/
2025-09-23 12:53:00 +02:00
CloverGit 47bb72179f Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 99.9% (10063 of 10069 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/zh_Hans/
2025-09-23 12:53:00 +02:00
Pferd O 9f7af4a3a7 Translated using Weblate (German)
Currently translated at 99.9% (10060 of 10069 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/de/
2025-09-23 12:53:00 +02:00
Frank Sonnenberg dda127ceec Translated using Weblate (German)
Currently translated at 99.9% (10060 of 10069 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/de/
2025-09-23 12:53:00 +02:00
Максим Горпиніч 68e6e0a742 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (10069 of 10069 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/uk/
2025-09-23 12:53:00 +02:00
2tama3 a844ba713a Translated using Weblate (Japanese)
Currently translated at 100.0% (10069 of 10069 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/ja/
2025-09-23 12:53:00 +02:00
Frank Sonnenberg 5d75bd0f0a Translated using Weblate (German)
Currently translated at 99.9% (10060 of 10069 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/de/
2025-09-23 12:53:00 +02:00
jean-pierre charras c492565ee8 DIALOG_LIB_SYMBOL_PROPERTIES: fix incorrect handling of vertical pos. of fields
The Y pos was negated twice when saving the field position.
Note also this is a fast fix. A better fix should be removing these Y pos sign
change in dialog because they are now not needed, but it will wait 9.0.6.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/21781
2025-09-21 16:43:20 +02:00
Wayne Stambaugh 879d2bef4b Tag stable version 9.0.5 release candidate 1. 2025-09-20 15:52:28 -04:00
Olliver Schinagl 05376a39ac export_vrml: Skip missing 3D models with warning
(cherry picked from commit 98d77db5ae)
2025-09-20 11:43:55 -04:00
oskarwires 9c01c2aeb8 Fix pin length change and push
(cherry picked from commit abba11031a)
2025-09-20 11:36:25 -04:00
Alex Shvartzkop 72db7bfedc Fix some warnings. 2025-09-19 17:07:47 +03:00
Alex Shvartzkop 95cfe2cc2e STEP export: don't return non-zero error code on non-fatal errors. 2025-09-19 17:06:38 +03:00
Mark Roszko c6f5daf87f Make ERC/DRC jobs default to fail on violation count
(cherry picked from commit 94856f1ffa)

Co-authored-by: Mark Roszko <mark.roszko@gmail.com>
2025-09-19 12:01:51 +00:00
Seth Hillbrand b1711d692a Do not hang onto previous elements
When using multi-label input or repeat commands, the previous element
should be deselected so that we can properly transform the current
element

Fixes https://gitlab.com/kicad/code/kicad/-/issues/21765

(cherry picked from commit 5ed46b823b)
2025-09-18 12:28:55 -07:00
Seth Hillbrand d538182f1f Fix Windows Builds 2025-09-18 11:15:52 -07:00
Wayne Stambaugh b4b87b5c38 Prevent crash dereferencing null pointer when creating schematic table. 2025-09-18 14:05:05 -04:00
Seth Hillbrand eed95e612d Skip exterior segments when splitting
We need to avoid fracture points when choosing how to split exterior
segments

(cherry picked from commit 50274352b1)
2025-09-18 10:30:43 -07:00
Seth Hillbrand 68d3c7f5c2 Force type in wxString 2025-09-17 21:05:39 -07:00
Seth Hillbrand 848d5484d8 Fix mocks 2025-09-17 13:42:22 -07:00
Alexander Boehm d3b84f219c generate rule areas dialog: vertical scroll bars
With many entries the dialog could not be resized by dragging
nor were scroll bars displayed (at least under Linux).

Fixes https://gitlab.com/kicad/code/kicad/-/issues/20195

(cherry picked from commit 4111140f93)
2025-09-17 11:38:04 -07:00
Seth Hillbrand 58ccf62d2f Unify sheet name validators and apply to properties
Properties panel and properties dialog now share a validator with shared
strings

Fixes https://gitlab.com/kicad/code/kicad/issues/21689

(cherry picked from commit 733a379ca3)
2025-09-17 11:36:53 -07:00
Seth Hillbrand 021229647f Prevent lines from drawing on netclass layer
Only wires and busses get netclasses

Fixes https://gitlab.com/kicad/code/kicad/issues/21731

(cherry picked from commit 5fdfff2b9c)
2025-09-17 11:19:58 -07:00
Seth Hillbrand 9a812bc63c Remove noise from orthographic projection raytracing
We generally add some jitter to the raytracing lines in order to smooth
out over multiple iterations some of the imperfections.  However, when
we do this to an orthographic projection (where all lines are parallel
to start, we don't average and just introduce noticeable noise in the
render

Fixes https://gitlab.com/kicad/code/kicad/issues/8863

(cherry picked from commit abf3438ed6)
2025-09-17 11:18:47 -07:00
Seth Hillbrand 8a9201b79c Update properties to show units
The function duplicated our built-in funcitonality and did not properly
handly outputs

Fixes https://gitlab.com/kicad/code/kicad/issues/21685

(cherry picked from commit 3f8abe3744)
2025-09-17 11:06:25 -07:00
Jeff Young f8e9b3402f Comboboxes for units and body styles.
Also for pin-types in pad properties.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/19904

Fixes https://gitlab.com/kicad/code/kicad/-/issues/19905

(cherry picked from commit ec155c00f3)
2025-09-17 11:05:57 -07:00
Seth Hillbrand 808c645933 Don't convert URI slashes on Windows
We auto-convert paths for windows boxes but this should not happen for
uri schemes that have the form <URI>://<path>

Fixes https://gitlab.com/kicad/code/kicad/-/issues/20381

(cherry picked from commit e85a8056f5)
2025-09-17 10:46:41 -07:00
Adrián García ea467c1bac Fix crash in LIB_SYMBOL::SetUnitCount when reducing unit count
When decreasing the number of units in a symbol, the previous code erased
items directly from m_drawings using a single iterator. Because m_drawings
is a MULTIVECTOR, this could invalidate iterators and attempt to erase
from the wrong bucket, leading to segmentation faults.

This patch iterates bucket by bucket and erases items belonging to units
greater than the requested count. This ensures iterator safety and avoids
accessing invalid memory.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/21631

(cherry picked from commit fb558eee3c)
2025-09-17 10:46:14 -07:00
Seth Hillbrand c51b6a0cd2 Prevent GTK from providing stale position
When the library name and symbol/footprint name both match the filter,
we try to display both but ensure visible can move things to the wrong
place.  We need to ensure the filtered list is up to date prior to
moving by ensureVisible

Fixes https://gitlab.com/kicad/code/kicad/-/issues/18000

(cherry picked from commit dc7e0665c3)
2025-09-17 10:45:40 -07:00
Seth Hillbrand 10f16ed82e Prevent modifying teardrops on lock/unlock
This action doesn't affect geometry, so don't dirty the teardrops

Fixes https://gitlab.com/kicad/code/kicad/issues/21342

(cherry picked from commit ad80113f47)
2025-09-17 10:45:17 -07:00
Seth Hillbrand ab9cf326e8 Consider visibility when colliding in DRC
Most places we check this but we should also check it in physical
clearance

Fixes https://gitlab.com/kicad/code/kicad/-/issues/21625

(cherry picked from commit d9741fd46a)
2025-09-17 10:44:53 -07:00
Seth Hillbrand 4e6087c183 Prevent main KiCad window from expanding based on DPI events
Fixes https://gitlab.com/kicad/code/kicad/-/issues/21602

(cherry picked from commit f5904cf2ac)
2025-09-17 10:44:32 -07:00
Seth Hillbrand e7abf472ba Make properties panel obey free pads setting
Pads should almost never be moved without their parent.  Only allow this
in the case where free pads has explicitly been checked

Fixes https://gitlab.com/kicad/code/kicad/-/issues/21591

(cherry picked from commit b22f259ccb)
2025-09-17 10:42:58 -07:00
Addo White f0c6b57ab9 Fix for Cursor rendering on Linux+EGL+Nvidia in accelerated graphics mode
EGL/NVidia can sometimes clip the cursor based on its plane regardless
of the depth mask.  This avoids the issue by forcing the cursor up over the existing plane.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/12183

(cherry picked from commit 843eea259d)
2025-09-17 10:42:13 -07:00
Seth Hillbrand e830709cda Make Expand Connection respect the filter
Prevents expansion that would require traversing elements that are
disabled in the selection filter

Fixes https://gitlab.com/kicad/code/kicad/-/issues/21581

(cherry picked from commit a811f61c39)
2025-09-17 10:39:58 -07:00
Seth Hillbrand 415aac7fc5 Fix Chessboard splitting
Due to a bug(?) in Clipper2, 45° collinear edges may not be detected.
See https://github.com/AngusJohnson/Clipper2/issues/1008 for current
status.  In the meantime, we pre-process these to remove the extraneous
joints preventing our triangulation from getting mixed up

Fixes https://gitlab.com/kicad/code/kicad/-/issues/18176

(cherry picked from commit 408e1feae2)
2025-09-17 10:37:44 -07:00
modbw 21f15c3b2a Fix net assignment messed up in Eagle import
When there is a polygon in the Eagle project withput any pad connected
netCode was not incremented and so the wrong nets were assigned to the
following elements.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/21243

(cherry picked from commit 57ad779797)
2025-09-17 10:36:17 -07:00
Seth Hillbrand 0f8df0bcee Ensure that we check tracks exiting pads for gaps
The DP gap check should look for sections of track that are coupled by
wider than a given spacing.  Our primitive check of looking for
collisions on the segment between the start poins causes tracks exiting
but not entering pads to be excluded.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/21561

(cherry picked from commit 1e76f1a11d)
2025-09-17 10:34:50 -07:00
Seth Hillbrand d6ef6252a2 Maintain group membership when shoving
Keep track of the original group membership and assign this to the newly
created element as well

Fixes https://gitlab.com/kicad/code/kicad/-/issues/20862

(cherry picked from commit 2db8c6eca0)
2025-09-17 10:33:36 -07:00
Seth Hillbrand f13c9cbd49 Prevent stale names in fp browser
When switching libraries, if there is an additional footprint with the
same name, we don't want to select it by default as this will prevent
updating the footprint display.  Instead, force the update

Fixes https://gitlab.com/kicad/code/kicad/-/issues/9763

(cherry picked from commit cb620338db)
2025-09-17 10:29:31 -07:00
Seth Hillbrand c2af66a44b Specialize the pad wall drawing
Avoids slowdown when zoom/pan with many THTs as everything remains
cached.  Still slow in Cairo but this is expected

Fixes https://gitlab.com/kicad/code/kicad/-/issues/20506

(cherry picked from commit 3ef862f7b6)
2025-09-17 10:27:56 -07:00
Seth Hillbrand 40c50c94fb Help is always valid
Return 0 and no error, just help when the --help flag is present

Fixes https://gitlab.com/kicad/code/kicad/-/issues/21538

(cherry picked from commit 9dc76f658d)
2025-09-17 10:27:21 -07:00
Seth Hillbrand 0103f92d0e Add more parent safety checks
Fixes https://gitlab.com/kicad/code/kicad/-/issues/21317

(cherry picked from commit e346139301)
2025-09-17 10:26:51 -07:00
Seth Hillbrand 0f27f8b7fc Enforce board-level hole to hole on diff pairs
Makes the router behave like the DRC

Fixes https://gitlab.com/kicad/code/kicad/-/issues/21240

(cherry picked from commit cac334bb45)
2025-09-17 10:25:56 -07:00
Seth Hillbrand 5631b61dbc Find the proper line split
And avoid leaving duplicate tracks when overlapping

Fixes https://gitlab.com/kicad/code/kicad/-/issues/10422

(cherry picked from commit 8acdcafe90)
2025-09-17 10:25:32 -07:00
Seth Hillbrand da659f5d05 Manually check pad layers before inserting
We do not rely on GetEffectiveShape(layer) to return null for layers
that the pad does not exist on.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/21523

(cherry picked from commit 2e1910ca86)
2025-09-17 10:23:46 -07:00
Seth Hillbrand 2029c5389f Move IPC2581 output to REPORTER
Adds a wx_reporter_panel to the 2581 output window, shunt messages
through the reporter instance

Fixes https://gitlab.com/kicad/code/kicad/-/issues/16314

(cherry picked from commit 44228bd580)
2025-09-17 10:23:21 -07:00
Seth Hillbrand 4205e70775 Update cache when modifying schematic
Fixes https://gitlab.com/kicad/code/kicad/-/issues/18297

(cherry picked from commit 2347b290cb)
2025-09-17 10:17:08 -07:00
Seth Hillbrand 4f66225de7 Allow multiple pad->single pin in 2581 correctly
Grouped pads by pin number in the IPC-2581 exporter so only one pin node
is created per number.  Still output multiple pad shapes with the same
number.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/18688

(cherry picked from commit c1cd4dd157)
2025-09-17 10:16:42 -07:00
Seth Hillbrand 18e4682c3a Set embedded delegate to update view properly
When embedding a 3d model we want to be able to see it immediately but
this requires getting the embedded files from the delegate model

Fixes https://gitlab.com/kicad/code/kicad/-/issues/19991

(cherry picked from commit bd86f979ed)
2025-09-17 10:16:17 -07:00
Seth Hillbrand 6b540ae1e3 Add embed option to standard file dialog for 3dmodels
Fixes https://gitlab.com/kicad/code/kicad/-/issues/20025

(cherry picked from commit 09cdca876c)
2025-09-17 10:15:51 -07:00
Seth Hillbrand 1f12b6c17d Force overlapping wires to share labels
Crossing wires with pathological label in the center are actually
connected for the netlist.  This is an ERC error but we should keep
things consistent.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/21494

(cherry picked from commit c995d47c87)
2025-09-17 10:11:43 -07:00
Seth Hillbrand e2c23c70f1 Allow soldermask bridging between nettie items
Previously we only allowed graphical items but within the net-tie we
need to allow bridging for connected items as well

Fixes https://gitlab.com/kicad/code/kicad/-/issues/19288

(cherry picked from commit 8faf1b4d0e)
2025-09-17 10:06:32 -07:00
Seth Hillbrand f60f0394be Fix preferential coordinates in rule display
Fixes https://gitlab.com/kicad/code/kicad/-/issues/11546

(cherry picked from commit eb89d7ffcc)
2025-09-17 10:06:23 -07:00
Seth Hillbrand bd64bcf446 Keep the ruler measurements on screen
Fixes https://gitlab.com/kicad/code/kicad/-/issues/11546

(cherry picked from commit b2fbb326b0)
2025-09-17 10:04:42 -07:00
Seth Hillbrand 176d0f5820 Slight modification to followTrivialPath
Now keeps track of branch points, recursing through them to find the
longest path it can in both directions.  This helps to ignore
overlapping segments

Fixes https://gitlab.com/kicad/code/kicad/-/issues/7809

(cherry picked from commit 4c5b44545f)
2025-09-17 10:04:13 -07:00
Seth Hillbrand 118ee1c072 Prevent autosave error from cluttering the screen
Once per session, per editor we can show the error.  After that, assume
that the designer has seen and knows about the issue.

Fixes https://gitlab.com/kicad/code/kicad/issues/21464

(cherry picked from commit 9f2b04c7e2)
2025-09-17 09:57:32 -07:00
Seth Hillbrand fd15a1108b Allow wildcard matching for Netclass naming
Fixes https://gitlab.com/kicad/code/kicad/issues/21455

(cherry picked from commit fcd2da354d)
2025-09-17 09:56:46 -07:00
Seth Hillbrand 43b5d4d91f Ensure archives without ext are given .zip
Fixes https://gitlab.com/kicad/code/kicad/-/issues/21423

(cherry picked from commit 2ded7b87af)
2025-09-17 09:56:19 -07:00
Seth Hillbrand d11ab8201f Allow generator actions to affect children
Changing the generator will often modify the underlying children's
properties.  We should store these data in the stack.  Also add the
ability to change layers

Fixes https://gitlab.com/kicad/code/kicad/-/issues/21476

(cherry picked from commit 3ec380d93c)
2025-09-17 09:55:52 -07:00
Seth Hillbrand 86bae558b4 Fix broken cherry-pick 2025-09-17 09:55:52 -07:00
Seth Hillbrand 68991a7644 Make move tool obey snap settings
Fixes https://gitlab.com/kicad/code/kicad/-/issues/21192

(cherry picked from commit 8bf7975440)
2025-09-17 09:40:06 -07:00
Seth Hillbrand 0701640c5a Prevent error message when backpropagating
Need to allow only processing other fields

Fixes https://gitlab.com/kicad/code/kicad/issues/21467

(cherry picked from commit 8a081f60b1)
2025-09-17 09:39:14 -07:00
Seth Hillbrand 9fe656a33c Remove namespacing from IPC2581 output
Because some readers maintain global namespace per the standard, we make
sure that we don't overlap names between namespaces but keep the minimum
viable name for each element

Fixes https://gitlab.com/kicad/code/kicad/-/issues/19914

(cherry picked from commit 8f625086b1)
2025-09-17 09:38:48 -07:00
Seth Hillbrand 3fb8f22fd3 Have Find dialog update its cache on board mod
We don't want to find stale references

Fixes https://gitlab.com/kicad/code/kicad/-/issues/21445

(cherry picked from commit 1a8dac9296)
2025-09-17 09:30:30 -07:00
Seth Hillbrand 929930fb3a Show inherited fields in symbols
When working with derived symbols, make sure that we show all of the
fields, not just the ones that are defined in the current level since
they are all attached to the output.

Inherited fields are shown in italics until changed

Fixes https://gitlab.com/kicad/code/kicad/-/issues/11422

(cherry picked from commit ff5a309386)
2025-09-17 09:12:09 -07:00
Seth Hillbrand 4195b874d5 Properly order netlist pages
We cannot reorder these without updating the defines.  So, keep the GUI
in line with the definitions

Fixes https://gitlab.com/kicad/code/kicad/issues/21730

(cherry picked from commit 497afffd48)
2025-09-17 17:59:08 +02:00
Jeff Young ae0d6c80dd Don't overwrite footprint filters created from multiple tokens in footprint column.
(cherry picked from commit 9ddb5465e1)
2025-09-17 13:13:23 +01:00
Jeff Young 4e2f84727c ADDED: support for multiple footprints in the footprint json from HTTP libraries
These are semi-colon-separated.

This is different from the footprint_filters dict entry, which is space-separated.

The first footprint in the footprint dict entry
will go into the "Footprint" field, while the rest
will go into the symbol's footprint filters.

(cherry picked from commit 91405ae34d)
2025-09-17 13:13:17 +01:00
Jeff Young 35889130e8 Formatting and naming conventions.
(cherry picked from commit 2eb3518e49)
2025-09-17 13:10:56 +01:00
Jeff Young 2e7145cc4b ADDED: handling of meta-data items in REST libraries.
"description" and "keywords" must hold string values;
"footprint_filters" can either hold a (space-
separated) string value, or an array of strings.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/20750

(cherry picked from commit 1f1f490887)
2025-09-17 13:02:09 +01:00
Jeff Young e0d955993c Catch all errors thrown by nanodbc.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/21707

(cherry picked from commit 37df36be62)
2025-09-17 13:00:45 +01:00
Mark Roszko cd7a646fcc Fix up arm assembly compiling on windows 2025-09-15 21:01:50 -04:00
Mark Roszko cb2a09d17c Edit ConfigurePlatform.cmake
(cherry picked from commit bda994c00a)

Co-authored-by: Mark Roszko <mark.roszko@gmail.com>
2025-09-15 23:47:12 +00:00
Mark Roszko d0cb210427 Also set CMAKE_SYSTEM_PROCESSOR in win cross compile
(cherry picked from commit e02008630f)

Co-authored-by: Mark Roszko <mark.roszko@gmail.com>
2025-09-15 23:43:55 +00:00
Seth Hillbrand b89d77bf36 Do not leave stale edges floating around
We assume that all net edges are valid in too many places

Fixes https://gitlab.com/kicad/code/kicad/-/issues/21745
2025-09-15 07:01:18 -07:00
Mark Roszko 7fdeb4796a Manually set CMAKE_CROSSCOMPILING on MSVC.
(cherry picked from commit accb0ddcd1)

Co-authored-by: Mark Roszko <mark.roszko@gmail.com>
2025-09-14 15:00:49 +00:00
Roberto Fernandez Bautista e82088a59b Windows CI: custom vcpkg triplet to ensure shareable binary cache
(cherry picked from commit 8d8bd7253f)
2025-09-13 23:45:41 +02:00
Seth Hillbrand 5a5191361f Second pass at fixing warping and grids
First attempt caused additional problems for #21535

Fixes https://gitlab.com/kicad/code/kicad/-/issues/18196

(cherry picked from commit 2cdeb0cd7c)
2025-09-12 10:52:36 +02:00
jean-pierre charras b47f8f4504 Revert "Remove the forced ancillary grid"
This reverts commit 7b602142b1.
2025-09-12 10:51:29 +02:00
jean-pierre charras 00ae91d6b5 Gerbview: fix broken behavior for deprecated command IPPOS and IPNEG
Fixes https://gitlab.com/kicad/code/kicad/-/issues/21715

(cherry picked from commit 45166bf5c3)
2025-09-11 14:32:17 +02:00
Jeff Young 097e0eadf1 LIBEVAL::CONTEXT manages its own local VALUEs.
Don't use std::unique_ptr as we'll just free the
value right after storing it.

Also, don't try to execute a non-existent function.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/21697

(cherry picked from commit 6ab6283e2e)
2025-09-11 12:50:31 +01:00
Jeff Young c8c293dca8 Don't allow stack addresses to escape via long-life handlers.
(cherry picked from commit cff261ce2e)
2025-09-09 14:57:13 +01:00
Jeff Young e6cfd1cdcf Formatting.
(cherry picked from commit b98621c8c8)
2025-09-09 14:57:13 +01:00
Jeff Young 905170b4f4 Only test parameters under the same conditions as we'd write them to the file.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/21520

(cherry picked from commit 8ae2ad3586)
2025-09-09 14:57:12 +01:00
Jeff Young 57fa8ea2b9 Use WX_GRID::ClearRows() to avoid assertions.
Fixes KICAD-VM1.

(cherry picked from commit 0b102fc085)
2025-09-09 14:57:12 +01:00
Jeff Young c7730a00c4 Fix typo.
(cherry picked from commit 330361d0cb)
2025-09-09 14:57:12 +01:00
Alex Shvartzkop beaaf3b5be Update translations 2025-09-09 01:19:33 +03:00
dsa-t b644f15d7f Translated using Weblate (Hungarian)
Currently translated at 36.0% (3630 of 10066 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/hu/
2025-09-09 00:18:33 +02:00
Sárkány Lőrinc af398762db Translated using Weblate (Hungarian)
Currently translated at 36.0% (3630 of 10066 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/hu/
2025-09-09 00:18:33 +02:00
CloverGit dfd40b566d Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (10066 of 10066 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/zh_Hans/
2025-09-09 00:16:32 +02:00
KB e056ef2693 Translated using Weblate (Hungarian)
Currently translated at 36.0% (3630 of 10066 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/hu/
2025-09-09 00:16:32 +02:00
ZbeeGin 02d0944546 Translated using Weblate (Polish)
Currently translated at 99.5% (10019 of 10066 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/pl/
2025-09-09 00:16:32 +02:00
Nguyễn Ngọc Khánh 1aba70ca37 Translated using Weblate (Vietnamese)
Currently translated at 23.5% (2368 of 10066 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/vi/
2025-09-09 00:16:32 +02:00
Frank Sonnenberg ff8b82d060 Translated using Weblate (German)
Currently translated at 99.9% (10065 of 10066 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/de/
2025-09-09 00:16:31 +02:00
ssantos 68d1e3223a Translated using Weblate (Portuguese)
Currently translated at 98.5% (9922 of 10066 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/pt/
2025-09-09 00:16:31 +02:00
Frank Sonnenberg 9e64d52a38 Translated using Weblate (German)
Currently translated at 99.9% (10065 of 10066 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/de/
2025-09-09 00:16:31 +02:00
CloverGit f7b3c0226b Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (10066 of 10066 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/zh_Hans/
2025-09-09 00:16:31 +02:00
Frank Sonnenberg 17fc05ec45 Translated using Weblate (German)
Currently translated at 99.9% (10065 of 10066 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/de/
2025-09-09 00:16:31 +02:00
Pferd O b64f1f2bd3 Translated using Weblate (German)
Currently translated at 99.9% (10063 of 10066 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/de/
2025-09-09 00:16:31 +02:00
Frank Sonnenberg b32d8862da Translated using Weblate (German)
Currently translated at 99.9% (10063 of 10066 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/de/
2025-09-09 00:16:31 +02:00
Hesham Eina Abdalla ff061e51a0 Translated using Weblate (Arabic)
Currently translated at 1.1% (117 of 10066 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/ar/
2025-09-09 00:16:31 +02:00
Ivan Chuba 6020e6d6f9 Translated using Weblate (Estonian)
Currently translated at 3.5% (357 of 10066 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/et/
2025-09-09 00:16:31 +02:00
Frank Sonnenberg a3fffc868f Translated using Weblate (German)
Currently translated at 99.9% (10065 of 10066 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/de/
2025-09-09 00:16:31 +02:00
Frank Sonnenberg 9670aa1b8a Translated using Weblate (German)
Currently translated at 99.9% (10065 of 10066 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/de/
2025-09-09 00:16:30 +02:00
Frank Sonnenberg 85ba5ae406 Translated using Weblate (German)
Currently translated at 99.9% (10065 of 10066 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/de/
2025-09-09 00:16:30 +02:00
Pferd O faa3287fd6 Translated using Weblate (German)
Currently translated at 99.9% (10065 of 10066 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/de/
2025-09-09 00:16:30 +02:00
ZbeeGin 33ab1d9242 Translated using Weblate (Polish)
Currently translated at 99.5% (10018 of 10066 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/pl/
2025-09-09 00:16:30 +02:00
Frank Sonnenberg 01aa2d7e42 Translated using Weblate (German)
Currently translated at 99.9% (10065 of 10066 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/de/
2025-09-09 00:16:30 +02:00
Sárkány Lőrinc b24e2ac00d Translated using Weblate (Hungarian)
Currently translated at 35.9% (3617 of 10066 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/hu/
2025-09-09 00:16:30 +02:00
Frank Sonnenberg 2bc3ef82dc Translated using Weblate (German)
Currently translated at 99.9% (10065 of 10066 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/de/
2025-09-09 00:16:30 +02:00
Sárkány Lőrinc 672ba5cd41 Translated using Weblate (Hungarian)
Currently translated at 35.6% (3591 of 10066 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/hu/
2025-09-09 00:16:30 +02:00
Pferd O 905b9ae6c5 Translated using Weblate (German)
Currently translated at 100.0% (10066 of 10066 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/de/
2025-09-09 00:16:30 +02:00
CloverGit f81a203c22 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (10066 of 10066 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/zh_Hans/
2025-09-09 00:16:29 +02:00
Sárkány Lőrinc 7aa0431a60 Translated using Weblate (Hungarian)
Currently translated at 34.3% (3459 of 10066 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/hu/
2025-09-09 00:16:29 +02:00
Pferd O 57505674f8 Translated using Weblate (German)
Currently translated at 100.0% (10066 of 10066 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/de/
2025-09-09 00:16:29 +02:00
2tama3 558bef00cc Translated using Weblate (Japanese)
Currently translated at 100.0% (10066 of 10066 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/ja/
2025-09-09 00:16:29 +02:00
Sárkány Lőrinc 28f9bd797a Translated using Weblate (Hungarian)
Currently translated at 34.2% (3446 of 10066 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/hu/
2025-09-09 00:16:29 +02:00
CloverGit 52d6fc66f1 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (10066 of 10066 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/zh_Hans/
2025-09-09 00:16:28 +02:00
Максим Горпиніч ab49e9b29d Translated using Weblate (Ukrainian)
Currently translated at 100.0% (10066 of 10066 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/uk/
2025-09-09 00:16:28 +02:00
Henrik Kauhanen f6710e64de Translated using Weblate (Swedish)
Currently translated at 99.9% (10058 of 10066 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/sv/
2025-09-09 00:16:28 +02:00
dsa-t 804154e21d Translated using Weblate (Russian)
Currently translated at 100.0% (10066 of 10066 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/ru/
2025-09-09 00:16:28 +02:00
2tama3 03cb8521bc Translated using Weblate (Japanese)
Currently translated at 100.0% (10066 of 10066 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/ja/
2025-09-09 00:16:28 +02:00
Sárkány Lőrinc 3ee940e3fb Translated using Weblate (Hungarian)
Currently translated at 34.2% (3445 of 10066 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/hu/
2025-09-09 00:16:28 +02:00
Frank Sonnenberg 8b25c3b0fe Translated using Weblate (German)
Currently translated at 100.0% (10066 of 10066 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/de/
2025-09-09 00:16:28 +02:00
Pferd O 529cf246d2 Translated using Weblate (German)
Currently translated at 100.0% (10066 of 10066 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/de/
2025-09-09 00:16:27 +02:00
Mark Roszko 7e7c281a64 Fix unit binder dropdown not working on windows
Fixes https://gitlab.com/kicad/code/kicad/-/issues/20626


(cherry picked from commit 0f97f51ba1)

Co-authored-by: Mark Roszko <mark.roszko@gmail.com>
2025-09-08 10:41:03 +00:00
Mark Roszko 350925f10a Shoehorn an improvement to table sorting to keep files more stable
Fixes https://gitlab.com/kicad/code/kicad/-/issues/21652
2025-09-07 10:34:12 -04:00
Mark Roszko 5e8982600a Update ngspice to 45.2
(cherry picked from commit 922699f388)

Co-authored-by: Mark Roszko <mark.roszko@gmail.com>
2025-09-06 17:41:01 +00:00
Mark Roszko e633af9216 Update kicad-vcpkg and ngspice 2025-09-06 12:49:44 +00:00
jean-pierre charras b0f21e5452 DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR_BASE: fix a incorrect widgets type
Fixes https://gitlab.com/kicad/code/kicad/-/issues/21662

From master branch
2025-09-06 13:28:41 +02:00
jean-pierre charras d2d582cc00 PCB_DIM_CENTER: fix incorrect bounding box size for 90deg cross.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/21643

From master branch
2025-09-05 10:03:44 +02:00
jean-pierre charras 4f11681c4a French translation: fix typo 2025-09-05 09:51:45 +02:00
Mark Roszko 897ebee00f Fix position of package properties that must follow packages
(cherry picked from commit 9f1aa612ec)

Co-authored-by: Mark Roszko <mark.roszko@gmail.com>
2025-09-04 11:16:28 +00:00
Mark Roszko be0a42a09a Fix typo in allegro output for nets
(cherry picked from commit 9de2548064)

Co-authored-by: Mark Roszko <mark.roszko@gmail.com>
2025-09-04 11:09:35 +00:00
Mark Roszko 3069799a2d Fix double quoting tol for some reason
(cherry picked from commit a899da7cb7)

Co-authored-by: Mark Roszko <mark.roszko@gmail.com>
2025-09-04 03:00:05 +00:00
Mark Roszko ad22e53518 Fix the allegro netlist export and move mostly to {fmt}
Weirdly $PACKAGES header got shifted out of position.
Drop generating empty references.
2025-09-03 22:56:25 -04:00
Seth Hillbrand 2ef05eb191 Fix image pasting for MacOS
Apparently, GetImage() on MacOS does not always convert the image
properly.  So do a two-step here to get the Bitmap first, forcing the
conversion and then going back to an image

(cherry picked from commit 9f06d1f66b)
2025-09-03 09:20:12 -07:00
Seth Hillbrand 235e583182 Prevent crash in nettie
We need to avoid collecting invalid layers in the net ties regardless of
their origins

(cherry picked from commit 826f15a103)
2025-09-02 19:19:50 -07:00
Seth Hillbrand 76ce4ec535 Prevent pads from moving inappropriately
Free pads is a setting unless we are in the footprint editor and needs
to be respected by the alignmen tool

Fixes https://gitlab.com/kicad/code/kicad/-/issues/21626

(cherry picked from commit 1f1f8699e0)
2025-09-02 09:11:48 -07:00
Jeff Young 0226481156 Give Mac dock icon menu a kick.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/17596

(cherry picked from commit 98b63389c1)
2025-09-01 22:36:37 +01:00
Seth Hillbrand 8fab2d8ca3 Disable snap when moving with keyboard
Keyboard movement is for precision control, so avoid snapping behavior

Fixes https://gitlab.com/kicad/code/kicad/-/issues/21235

(cherry picked from commit 9e326c29db)
2025-09-01 14:23:36 -07:00
Jeff Young 1c6d8b3f5e Don't reference stack variables from a long-life lambda.
In particular, a lambda for conditional menus should
never capture more than `[this]`.  Even the tool's
frame pointer could change.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/21615
2025-09-01 12:37:43 +01:00
Jeff Young 32e9ab9b75 Don't reference stack variables from a long-life lambda. 2025-09-01 12:37:43 +01:00
Jon Evans ca0207016e API: Add ability to set enabled board layers and copper layer count 2025-08-31 22:18:53 -04:00
Mark Roszko 9ca1bf63d9 jobsets: fix Replace button to overwrite existing files (#19900)
(cherry picked from commit 5fb55ccb30)

1ea009e6 jobsets: allow replacing existing jobset files

Co-authored-by: Adrián García <adrgarcia@outlook.com>
2025-09-01 01:14:25 +00:00
Jeff Young 7e13870ae3 Allow stitching of graphic shapes.
(cherry picked from commit 1309b436da)
2025-08-31 19:34:22 +01:00
Jeff Young 3c907b5589 Set free vias to graphic net if available.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/21578

(cherry picked from commit c47b7459aa)
2025-08-31 19:34:19 +01:00
Jeff Young e9efd9971c Don't set point to a value we're not going to keep.
It just causes flicker.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/19947

(cherry picked from commit a2e98fb53c)
2025-08-31 17:15:17 +01:00
Jeff Young 2bf9a6f5d1 Better interactive feedback.
Don't wait for mouse to move before refreshing after a command.

Also fixes a crash bug deleting an item after an
Unstage() (the Unstage() has already deleted the item).

Also fixes a crash when changing label type during
creation of a label produces a mess.

Also Keep cursor aligned to grid when not warping
back to original point.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/16828

(cherry picked from commit 9d7db3d135)
2025-08-31 16:13:07 +01:00
jean-pierre charras 42c67b40b1 fix issues in ROUNDRECT: Fix incorrect ROUNDRECT Ctor.
- Do not throw  an error in CTor: this is not the place. It is much easy to
fix the value of incorrect radius.
Moreover, the Ctor is called without catching a throw-ed error in code.
- fix the test about radius validity, broken.

From master branch.
2025-08-31 08:25:14 +02:00
jean-pierre charras 5ae3c55a99 Step exporter: fix overzealous validity test.
When converting poly shapes with arcs in STEP_PCB_MODEL::MakeShapes,
when an error happens, a second try is made using a full polygonal shape.
However a fatal error was emitted at the first attempt, before the second try.
Now at first try, only a debug message is emitted on error. The fatal error
is emitted only if the second try fails.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/21589

(cherry picked from commit aeafbe48fe)
2025-08-31 08:00:06 +02:00
Jeff Young 54e9a97b26 ADDED: separate front/back silk and mask colours for STEP export.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/21593

(cherry picked from commit acc7b1e508)
2025-08-30 17:46:42 +01:00
Jeff Young 1e3b879d93 Run collision check on correct layer.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/21586
2025-08-29 17:12:33 +01:00
Seth Hillbrand 7ca6a93436 Don't both designers with unneeded changes
If we are not asking for fields to be removed when updating, then don't
say we're doing anything if all we have to do is remove fields

(cherry picked from commit ea8206eca5)
2025-08-27 13:31:59 -07:00
jean-pierre charras 05c11d023f GERBER_JOBFILE_WRITER: fix incorrect layer id in File Attributes for inner layers.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/21569

(cherry picked from commit 9725ac2215)
2025-08-27 13:28:55 +02:00
jean-pierre charras 996c3d7fa1 PAD: better HitTest( const VECTOR2I& aPosition, int aAccuracy, PCB_LAYER_ID aLayer )
(cherry picked from commit b349f1988a)
2025-08-27 13:27:45 +02:00
jean-pierre charras b204742fe3 Pcbnew: fix teardrop generation for pads having different shapes by layer.
Teardrop generator used pad::HitTest not testing the hit of a specific layer.
It created false test for some complex pads. Now use a test specific to a layer.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/21560

(cherry picked from commit 963aa47778)
2025-08-27 11:35:07 +02:00
Emmanuel Vera 2b8e62e0b9 Update power filter for power symbols placement
(cherry picked from commit b5df0ad3eb)
2025-08-27 08:52:24 +02:00
jean-pierre charras c3d122becf French translation cleanup and update 2025-08-27 08:48:02 +02:00
John Beard 43c828474a Pcbnew: fix sensitivity of via placement to large grids
Another case where large grids are overly "grabby" for snaps.

In this case, because the via was moved to the grid-snap first,
and then THAT position was used to look for things like pad-snaps,
the pad snaps would not be found if a coarse grid meant the cursor
was outside the pad.

Instead, use the mouse position when looking for the non-grid snaps
in VIA_PLACER::SnapItem.

Fixes: https://gitlab.com/kicad/code/kicad/-/issues/18626
(cherry picked from commit 0f0527bd03)
2025-08-26 23:50:35 +08:00
John Beard 8073185c36 Pcbnew: use R-tree for pad checks in via place tool
Otherwise this is an O(n-pads-on-board) operation for every new
candidate via position.

(cherry picked from commit 3d8803f579)
2025-08-26 23:50:35 +08:00
Jeff Young f1ddcfe799 Expose shape in prop inspector for sheet pins.
(cherry picked from commit 3058bc6355)
2025-08-25 17:21:04 +01:00
jean-pierre charras 9d6f9c84d0 French translation update 2025-08-23 12:41:37 +02:00
jean-pierre charras 680a693c04 DIALOG_CHANGE_SYMBOLS: fix hanging is some cases and shows a better message.
When (happens after converting old schematics to the new format) trying to
update symbols having a bad lib id can hang Eeschema (infinite loop)
It can easily happens when the user has badly converted the schematic.
Also display a error message when happens.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/21536

(cherry picked from commit 61aeea9237)
2025-08-23 12:40:48 +02:00
Alex Shvartzkop 4f72dd421a REPORTER's HasMessage indicates that any message got reported, not stored. 2025-08-23 00:27:41 +03:00
dsa-t bc533de0a3 Revert "Use board stackup colors by default in 3D render job."
This reverts commit f7380ae015
2025-08-23 00:09:53 +03:00
dsa-t c08109d63e Revert "Add FOLLOW_PCB, FOLLOW_PLOT_SETTINGS appearance presets to 3D render job dialog."
This reverts commit efc6c3e45e
2025-08-22 21:26:51 +03:00
Jeff Young b11f0a31b9 Read legacy tokens before current tokens.
(So current can overwrite.)

Fixes https://gitlab.com/kicad/code/kicad/-/issues/21525

(cherry picked from commit 03c230dd64)
2025-08-22 17:03:32 +01:00
Jeff Young f6fabdc8ee Don't double mirror groups.
Also removes previous fix, which had side-effects.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/8121

Fixes https://gitlab.com/kicad/code/kicad/-/issues/20465

(cherry picked from commit 3f85071f91)
2025-08-22 17:03:25 +01:00
Jeff Young 965abb46d0 Avoid div-by-zero.
(cherry picked from commit c287d9a222)
2025-08-22 17:00:04 +01:00
Jeff Young c9f53c607e Fix missing initialization.
(cherry picked from commit de1c6c86ab)
2025-08-22 16:59:45 +01:00
Jeff Young 7b91b51bcf Add spacing for Mac file dialog custom controls.
(cherry picked from commit e841ca1906)
2025-08-22 16:59:29 +01:00
Jeff Young a3354dc352 Always provide a SCH_SCREEN to SCH_COMMIT.
Fixes KICAD-YKY

(cherry picked from commit a0940b10d4)
2025-08-22 16:57:17 +01:00
Jeff Young 6723964cdd Fix copy/pasta.
(cherry picked from commit c2f953e3f7)
2025-08-22 16:48:19 +01:00
Jeff Young df5f4ba541 Improve quasimodal comment.
(cherry picked from commit c85e5c08e4)
2025-08-22 16:46:39 +01:00
Jeff Young 926f41a0f5 Don't show locked shadow in pad preview.
(cherry picked from commit 60dbfd3eec)
2025-08-22 16:44:19 +01:00
Jeff Young db801c8d7e Remove stale comment.
(cherry picked from commit 3f1f9e8e72)
2025-08-22 16:43:35 +01:00
Jeff Young ad433b9468 ADDED: follow-pcb and follow-plot-settings to render job settings.
Also added Follow-board-stackup-colors to both
render job settings and render CLI arguments

Fixes https://gitlab.com/kicad/code/kicad/-/issues/21341

(cherry picked from commit 2e629ca55c)
2025-08-22 16:41:58 +01:00
Jeff Young 1eefb2b70a Allow deletion of nested embedded files.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/20581

(cherry picked from commit ea84879b06)
2025-08-22 16:40:10 +01:00
Jeff Young 3d6527c1be Formatting.
(cherry picked from commit 7240128130)
2025-08-22 16:40:07 +01:00
Jeff Young 319530ad01 Grid is already updated by AddFile() callback.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/20565

(cherry picked from commit 2c3408aad5)
2025-08-22 16:38:19 +01:00
Jeff Young 24efca1db1 Focus second column control after property grid navigation.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/20651

(cherry picked from commit 95da436ddd)
2025-08-22 16:37:49 +01:00
Alex Shvartzkop a009d859d0 Fix some warnings. 2025-08-22 17:40:37 +03:00
Alex Shvartzkop 44a3bb9274 Prevent jobs from affecting each other via reporters when running jobsets from CLI. 2025-08-22 17:40:12 +03:00
Alex Shvartzkop 72e1904708 Fix ODB++ path creation. 2025-08-22 15:07:38 +03:00
Alex Shvartzkop 279a30974e Increase default precision in ODB++ export job dialog. 2025-08-22 14:34:43 +03:00
Alex Shvartzkop efc6c3e45e Add FOLLOW_PCB, FOLLOW_PLOT_SETTINGS appearance presets to 3D render job dialog. 2025-08-22 13:35:14 +03:00
Alex Shvartzkop f7380ae015 Use board stackup colors by default in 3D render job. 2025-08-22 13:34:25 +03:00
Alex Shvartzkop 26b6c28bef EasyEDA import: Add footprint Reference text on F_Fab. 2025-08-21 17:40:53 +03:00
Alex Shvartzkop 8cd7b73b2a EasyEDA import: Build basic Courtyard box for footprints. 2025-08-21 17:08:41 +03:00
Alex Shvartzkop c2d31699bf EasyEDA import: Place component shape and marking on F_Fab. 2025-08-21 17:04:23 +03:00
Alex Shvartzkop 47c5918c3d Add green color indication to length tuning status popup. 2025-08-21 15:38:08 +03:00
Alex Shvartzkop 12cf3f9301 router: Inline drag by track end even if cursor is slightly outside the track shape. 2025-08-21 13:56:25 +03:00
Alex Shvartzkop 013aab58d6 Update golden ERC QA files after 316a9511e8 2025-08-21 12:30:38 +03:00
Alex Shvartzkop 316a9511e8 Show errors before warnings in DRC/ERC. 2025-08-21 00:24:21 +03:00
Alex Shvartzkop 29fadcb931 Update translations 2025-08-21 00:16:37 +03:00
Pedro Moreira d73fecd2a1 Translated using Weblate (Korean)
Currently translated at 98.6% (9933 of 10065 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/ko/
2025-08-20 23:15:12 +02:00
CloverGit 35caf91c31 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 99.9% (10059 of 10065 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/zh_Hans/
2025-08-20 23:15:12 +02:00
2tama3 352cf21ffc Translated using Weblate (Japanese)
Currently translated at 100.0% (10065 of 10065 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/ja/
2025-08-20 23:15:12 +02:00
CloverGit 21335f604f Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 99.9% (10059 of 10065 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/zh_Hans/
2025-08-20 23:15:12 +02:00
Henrik Kauhanen c6b7f90408 Translated using Weblate (Swedish)
Currently translated at 99.9% (10058 of 10065 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/sv/
2025-08-20 23:15:12 +02:00
2tama3 a5dee0c2b1 Translated using Weblate (Japanese)
Currently translated at 100.0% (10065 of 10065 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/ja/
2025-08-20 23:15:12 +02:00
Ettore Atalan bf73ad42ca Translated using Weblate (German)
Currently translated at 99.9% (10062 of 10065 strings)

Translation: KiCad EDA/v9
Translate-URL: https://hosted.weblate.org/projects/kicad/v9/de/
2025-08-20 23:15:11 +02:00
John Beard 7d905948f5 Pcbnew: fix refdes ordering in arrays
The first cell of the array needs to not be reannotated, or it will
skips its own number(s) and take what we expect for the second cell.
The repeats until the last entry, which didn't reannotate anything,
leaving the original numbers. Producing a 'rotation' like 2,3,4,5,1
rather than the expected 1,2,3,4,5.

Fixes: https://gitlab.com/kicad/code/kicad/-/issues/20935
(cherry picked from commit f31a109ab4)
2025-08-21 00:26:50 +08:00
John Beard 5c8c0e0648 Pcbnew: fix occasional failure-to-select for dragging
In the Drag tool client filter function, sometimes,
GuessSelectionCandidates trims the collector's item list.
But we used the old contents of the per-type vectors to make
judgements about what was connected.

If a call came in with 2 tracks (e.g. near a knee) and one
was removed by GuessSelectionCandidates, sometimes the
other one would be the one selected for removal in the
2 tracks/0 via case. This leaves the collector empty.

The other case, where the item removed by GuessSelectionCandidates
was removed from the collector is silent, as removing an item
not in the collector is a no-op.

Fixes: https://gitlab.com/kicad/code/kicad/-/issues/21517
(cherry picked from commit 105b9fcfe8)
2025-08-20 20:40:01 +08:00
Alex Shvartzkop 4cfa2e3a38 Remove unnecessary newlines in STEP exporter logging. 2025-08-20 14:54:27 +03:00
Alex Shvartzkop eecf0cd685 Remove a Message_Printer holding a stale REPORTER pointer from OCCT.
Fixes KICAD-V8A
2025-08-20 13:57:48 +03:00
Alex Shvartzkop 91e5e81bb4 Record execute command job input and error streams in the log.
Also print the resolved command.
2025-08-20 13:07:29 +03:00
JamesJCode 5b3cd96641 Don't assume SCH_SYMBOLs have a LIB_SYMBOL when resolving embedded files
Fixes https://gitlab.com/kicad/code/kicad/-/issues/21497

(cherry picked from commit ee9e94df04)
2025-08-19 14:17:02 +01:00
John Beard db0967d5c9 Pcbnew: fix bug in private layer selection
USer-defined layers now occur in steps of 2, otherwise
illegal layers for the grid get used.
2025-08-19 16:25:02 +08:00
jean-pierre charras 5165ced528 Eeschema: Reset m_ercRun flag when cleaning all markers.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/21113

(cherry picked from commit 54085c4e50)
2025-08-18 17:33:30 +02:00
Alex Shvartzkop eb4f9fa093 Wrap command text control in execute command job dialog. 2025-08-18 17:06:17 +03:00
Alex Shvartzkop 47381f3d90 Disable ibeam cursor setter for search fields on non-OSX.
The ibeam cursor gets stuck on MSW when mouse leaves the field.
2025-08-18 15:53:37 +03:00
jean-pierre charras e697339bc6 PLOT_CONTROLLER::PlotLayer(): fix bug when drill marks must be plotted.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/21474

(cherry picked from commit 20d8c9c7f9) and
(cherry picked from commit 2afd752bbc)
2025-08-18 11:48:07 +02:00
jean-pierre charras 6159cee2b0 Kicad manager: display the number of GDI objects in About Dialog (Windows only)
On Windows, if the number of GDI objects reach a limit (usually 10000) some can
be not shown, thus creating  a strange behavior not easy to diagnose.
Displaying the number in use can help.

(cherry picked from commit de208b3f00)
2025-08-18 09:07:31 +02:00
jean-pierre charras 3460b33ccf DIALOG_IMPORT_SETTINGS: fix some minor issues.
From master branch.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/21483
2025-08-18 08:43:40 +02:00
jean-pierre charras 5baaa89131 Reapply "SHAPE_ARC::GetCentralAngle(): better algo to calculate actual arc."
This new algo is now tested since more than 2 months, so it should be good.
This reverts commit 88ad461514.
2025-08-18 08:25:33 +02:00
Wayne Stambaugh d45a38f086 Begin version 9.0.5 development. 2025-08-17 15:48:17 -04:00
314 changed files with 100250 additions and 109143 deletions
+4
View File
@@ -8,6 +8,7 @@ win64_build:
interruptible: false
image: registry.gitlab.com/kicad/kicad-ci/windows-build-image/ltsc2022-msvc:latest
variables:
VCPKG_BINARY_SOURCES: 'nuget,gitlab,readwrite'
# Switch the compressor to fastzip and reduce the compression level
FF_USE_FASTZIP: "true"
CACHE_COMPRESSION_LEVEL: "fast"
@@ -23,6 +24,7 @@ win64_build:
script:
- C:\builder\build.ps1 -Env -Arch x64
- $vcpkgCache=Join-Path -Path (Get-Location) -ChildPath ".vcpkgCache";$env:VCPKG_DEFAULT_BINARY_CACHE=$vcpkgCache;New-Item -ItemType Directory -Force -Path $vcpkgCache
- nuget.exe sources add -Name gitlab -Source "https://gitlab.com/api/v4/projects/27426693/packages/nuget/index.json" -UserName gitlab-ci-token -Password $env:CI_JOB_TOKEN
- mkdir -p build/windows -Force
- cd build/windows
- cmake `
@@ -34,6 +36,8 @@ win64_build:
-DKICAD_BUILD_PNS_DEBUG_TOOL=ON `
-DKICAD_USE_3DCONNEXION=ON `
-DVCPKG_BUILD_TYPE=debug `
-DVCPKG_INSTALL_OPTIONS="--x-abi-tools-use-exact-versions" `
-DVCPKG_OVERLAY_TRIPLETS="$Env:CI_PROJECT_DIR/tools/custom_vcpkg_triplets" `
../../
- cmake --build . 2>&1 | tee compilation_log.txt
- cd ../../
@@ -486,9 +486,12 @@ void RENDER_3D_RAYTRACE_BASE::renderBlockTracing( uint8_t* ptrPBO, signed int iB
// Initialize ray packets
const SFVEC2UI& blockPos = m_blockPositions[iBlock];
const SFVEC2I blockPosI = SFVEC2I( blockPos.x + m_xoffset, blockPos.y + m_yoffset );
const SFVEC2F randDisp = ( m_camera.GetProjection() == PROJECTION_TYPE::ORTHO ) ?
SFVEC2F( 0.0f, 0.0f ) :
SFVEC2F( DISP_FACTOR, DISP_FACTOR );
RAYPACKET blockPacket( m_camera, (SFVEC2F) blockPosI + SFVEC2F( DISP_FACTOR, DISP_FACTOR ),
SFVEC2F( DISP_FACTOR, DISP_FACTOR ) /* Displacement random factor */ );
RAYPACKET blockPacket( m_camera, (SFVEC2F) blockPosI + randDisp,
randDisp /* Displacement random factor */ );
HITINFO_PACKET hitPacket_X0Y0[RAYPACKET_RAYS_PER_PACKET];
@@ -566,7 +569,7 @@ void RENDER_3D_RAYTRACE_BASE::renderBlockTracing( uint8_t* ptrPBO, signed int iB
HITINFO_PACKET_init( hitPacket_AA_X1Y1 );
RAYPACKET blockPacket_AA_X1Y1( m_camera, (SFVEC2F) blockPosI + SFVEC2F( 0.5f, 0.5f ),
SFVEC2F( DISP_FACTOR, DISP_FACTOR ) );
randDisp );
if( !m_accelerator->Intersect( blockPacket_AA_X1Y1, hitPacket_AA_X1Y1 ) )
{
@@ -603,16 +606,16 @@ void RENDER_3D_RAYTRACE_BASE::renderBlockTracing( uint8_t* ptrPBO, signed int iB
RAY blockRayPck_AA_X1Y1_half[RAYPACKET_RAYS_PER_PACKET];
RAYPACKET_InitRays_with2DDisplacement(
m_camera, (SFVEC2F) blockPosI + SFVEC2F( 0.5f - DISP_FACTOR, DISP_FACTOR ),
SFVEC2F( DISP_FACTOR, DISP_FACTOR ), blockRayPck_AA_X1Y0 );
m_camera, (SFVEC2F) blockPosI + SFVEC2F( 0.5f - randDisp.x, randDisp.y ),
randDisp, blockRayPck_AA_X1Y0 );
RAYPACKET_InitRays_with2DDisplacement(
m_camera, (SFVEC2F) blockPosI + SFVEC2F( DISP_FACTOR, 0.5f - DISP_FACTOR ),
SFVEC2F( DISP_FACTOR, DISP_FACTOR ), blockRayPck_AA_X0Y1 );
m_camera, (SFVEC2F) blockPosI + SFVEC2F( randDisp.x, 0.5f - randDisp.y ),
randDisp, blockRayPck_AA_X0Y1 );
RAYPACKET_InitRays_with2DDisplacement(
m_camera, (SFVEC2F) blockPosI + SFVEC2F( 0.25f - DISP_FACTOR, 0.25f - DISP_FACTOR ),
SFVEC2F( DISP_FACTOR, DISP_FACTOR ), blockRayPck_AA_X1Y1_half );
m_camera, (SFVEC2F) blockPosI + SFVEC2F( 0.25f - randDisp.x, 0.25f - randDisp.y ),
randDisp, blockRayPck_AA_X1Y1_half );
renderAntiAliasPackets( bgColor, hitPacket_X0Y0, hitPacket_AA_X1Y1, blockRayPck_AA_X1Y0,
hitColor_AA_X1Y0 );
@@ -657,6 +657,12 @@ void PANEL_PREVIEW_3D_MODEL::UpdateDummyFootprint( bool aReloadRequired )
}
void PANEL_PREVIEW_3D_MODEL::SetEmbeddedFilesDelegate( EMBEDDED_FILES* aDelegate )
{
m_dummyBoard->SetEmbeddedFilesDelegate( aDelegate );
}
void PANEL_PREVIEW_3D_MODEL::onModify()
{
KIWAY_HOLDER* kiwayHolder = dynamic_cast<KIWAY_HOLDER*>( wxGetTopLevelParent( this ) );
@@ -59,6 +59,7 @@ wxDECLARE_EVENT( wxCUSTOM_PANEL_SHOWN_EVENT, wxCommandEvent );
class WX_INFOBAR;
class S3D_CACHE;
class FILENAME_RESOLVER;
class EMBEDDED_FILES;
class BOARD;
class BOARD_ADAPTER;
class FOOTPRINT;
@@ -97,6 +98,8 @@ public:
*/
void UpdateDummyFootprint( bool aRelaodRequired = true );
void SetEmbeddedFilesDelegate( EMBEDDED_FILES* aDelegate );
/**
* Get the dummy footprint that is used for previewing the 3D model.
* We use this to hold the temporary 3D model shapes.
+6 -1
View File
@@ -22,7 +22,12 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
cmake_minimum_required( VERSION 3.21 FATAL_ERROR )
if( MSVC )
# CMake 3.28.1 or higher required for MSVC ARM builds for armasm64.exe support
cmake_minimum_required( VERSION 3.28.1 FATAL_ERROR )
else()
cmake_minimum_required( VERSION 3.21 FATAL_ERROR )
endif()
# Generate DEPFILES without transforming relative paths
cmake_policy( SET CMP0116 OLD )
+38 -3
View File
@@ -6,7 +6,12 @@
},
{
"environment": "vcpkg",
"VcPkgDir": "D:/vcpkg/"
"VcPkgDir": "D:/vcpkg/",
"VCPKG_BINARY_SOURCES": "nuget,kicad-gitlab,read"
},
{
"environment": "swig",
"SwigExePath": "D:/swigwin-4.1.1/swig.exe"
}
],
"configurations": [
@@ -14,7 +19,7 @@
"name": "x64-Debug",
"generator": "Ninja",
"configurationType": "Debug",
"inheritEnvironments": [ "msvc_x64_x64", "vcpkg" ],
"inheritEnvironments": [ "msvc_x64_x64", "vcpkg", "swig"],
"buildRoot": "${env.BuildDir}\\${name}",
"installRoot": "${env.InstallDir}\\${name}",
"cmakeCommandArgs": "",
@@ -30,6 +35,21 @@
"name": "KICAD_WIN32_DPI_AWARE",
"value": "ON",
"type": "BOOL"
},
{
"name": "SWIG_EXECUTABLE",
"value": "${env.SwigExePath}",
"type": "STRING"
},
{
"name": "VCPKG_OVERLAY_TRIPLETS",
"value": "${workspaceRoot}/tools/custom_vcpkg_triplets",
"type": "STRING"
},
{
"name": "VCPKG_INSTALL_OPTIONS",
"value": "--x-abi-tools-use-exact-versions",
"type": "STRING"
}
],
"cmakeToolchain": "${env.VcPkgDir}/scripts/buildsystems/vcpkg.cmake"
@@ -38,7 +58,7 @@
"name": "x64-Release",
"generator": "Ninja",
"configurationType": "RelWithDebInfo",
"inheritEnvironments": [ "msvc_x64_x64", "vcpkg" ],
"inheritEnvironments": [ "msvc_x64_x64", "vcpkg", "swig"],
"buildRoot": "${env.BuildDir}\\${name}",
"installRoot": "${env.InstallDir}\\${name}",
"cmakeCommandArgs": "",
@@ -54,6 +74,21 @@
"name": "KICAD_WIN32_DPI_AWARE",
"value": "ON",
"type": "BOOL"
},
{
"name": "SWIG_EXECUTABLE",
"value": "${env.SwigExePath}",
"type": "STRING"
},
{
"name": "VCPKG_OVERLAY_TRIPLETS",
"value": "${workspaceRoot}/tools/custom_vcpkg_triplets",
"type": "STRING"
},
{
"name": "VCPKG_INSTALL_OPTIONS",
"value": "--x-abi-tools-use-exact-versions",
"type": "STRING"
}
],
"cmakeToolchain": "${env.VcPkgDir}/scripts/buildsystems/vcpkg.cmake"
+33
View File
@@ -42,12 +42,45 @@ message BoardStackupResponse
kiapi.board.BoardStackup stackup = 1;
}
// Changes the stackup for the given board according to the contents of the message (**not yet implemented**)
// WARNING: any existing content on layers that are removed by this call is deleted. This operation cannot be undone.
// Returns BoardStackupResponse with the updated stackup, in normalized form
message UpdateBoardStackup
{
kiapi.common.types.DocumentSpecifier board = 1;
kiapi.board.BoardStackup stackup = 2;
}
message GetBoardEnabledLayers
{
kiapi.common.types.DocumentSpecifier board = 1;
}
message BoardEnabledLayersResponse
{
// The number of copper layers enabled in this board.
uint32 copper_layer_count = 1;
// A list of all layers enabled in this board, including copper layers and ones which cannot be disabled.
repeated kiapi.board.types.BoardLayer layers = 2;
}
// Changes which layers are enabled in the board stackup
// WARNING: any existing content on layers that are removed by this call is deleted. This operation cannot be undone.
// Returns BoardEnabledLayersResponse with the updated layer set.
message SetBoardEnabledLayers
{
kiapi.common.types.DocumentSpecifier board = 1;
// The number of copper layers to enable in the board. Currently, this must be an even number >= 2.
uint32 copper_layer_count = 2;
// The non-copper layers to enable. Note that any copper layers in this list are ignored; copper layers are enabled
// by setting copper_layer_count. Note that the F/B.Courtyard, Edge.Cuts, and Margin layers cannot be disabled and
// will be present in the board even if they are omitted from this list.
repeated kiapi.board.types.BoardLayer layers = 3;
}
message GetGraphicsDefaults
{
kiapi.common.types.DocumentSpecifier board = 1;
+15 -29
View File
@@ -36,7 +36,13 @@ if( MSVC )
set( KICAD_HOST_ARCH "x64" )
set( KICAD_HOST_ARCH_X64 1 )
else()
message(FATAL_ERROR "Failed to determine the host architecture: ${CMAKE_SYSTEM_PROCESSOR}")
message(FATAL_ERROR "Failed to determine the host architecture: ${CMAKE_HOST_SYSTEM_PROCESSOR}")
endif()
if( NOT KICAD_BUILD_ARCH STREQUAL KICAD_HOST_ARCH )
set( CMAKE_CROSSCOMPILING TRUE )
string(TOUPPER ${KICAD_BUILD_ARCH} CMAKE_SYSTEM_PROCESSOR)
endif()
else()
if ( NOT CMAKE_SIZEOF_VOID_P EQUAL 8 )
@@ -58,38 +64,18 @@ if( MSVC )
# cmake release AND when MSVC ships said cmake release
if(KICAD_BUILD_ARCH_ARM)
message( "Configuring ARM assembler" )
# Explicitly specify the assembler to be used for Arm32 compile
file(TO_CMAKE_PATH "$ENV{VCToolsInstallDir}\\bin\\HostX86\\arm\\armasm.exe" CMAKE_ASM_COMPILER)
set(CMAKE_ASM_MASM_COMPILER ${CMAKE_ASM_COMPILER})
message("CMAKE_ASM_MASM_COMPILER explicitly set to: ${CMAKE_ASM_MASM_COMPILER}")
# Enable generic assembly compilation to avoid CMake generate VS proj files that explicitly
# use ml[64].exe as the assembler.
enable_language(ASM)
set(CMAKE_ASM_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreaded "")
set(CMAKE_ASM_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDLL "")
set(CMAKE_ASM_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebug "")
set(CMAKE_ASM_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebugDLL "")
set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> -g <INCLUDES> <FLAGS> -o <OBJECT> <SOURCE>")
enable_language(ASM_MARMASM)
# Bugfix for CMake < 29.1
set(ASM_DIALECT "_MARMASM")
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OBJECT "<CMAKE_ASM${ASM_DIALECT}_COMPILER> <INCLUDES> <FLAGS> -o <OBJECT> <SOURCE>")
elseif(KICAD_BUILD_ARCH_ARM64)
message( "Configuring ARM64 assembler" )
# Explicitly specify the assembler to be used for Arm64 compile
file(TO_CMAKE_PATH "$ENV{VCToolsInstallDir}\\bin\\HostX86\\arm64\\armasm64.exe" CMAKE_ASM_COMPILER)
set(CMAKE_ASM_MASM_COMPILER ${CMAKE_ASM_COMPILER})
message("CMAKE_ASM_MASM_COMPILER explicitly set to: ${CMAKE_ASM_MASM_COMPILER}")
# Enable generic assembly compilation to avoid CMake generate VS proj files that explicitly
# use ml[64].exe as the assembler.
enable_language(ASM)
set(CMAKE_ASM_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreaded "")
set(CMAKE_ASM_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDLL "")
set(CMAKE_ASM_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebug "")
set(CMAKE_ASM_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebugDLL "")
set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> -g <INCLUDES> <FLAGS> -o <OBJECT> <SOURCE>")
enable_language(ASM_MARMASM)
# Bugfix for CMake < 29.1
set(ASM_DIALECT "_MARMASM")
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OBJECT "<CMAKE_ASM${ASM_DIALECT}_COMPILER> <INCLUDES> <FLAGS> -o <OBJECT> <SOURCE>")
else()
message( "Configuring MASM assembler" )
if(KICAD_BUILD_ARCH_X86)
+1 -1
View File
@@ -37,7 +37,7 @@
# KiCad.
#
# Note: This version string should follow the semantic versioning system
set( KICAD_SEMANTIC_VERSION "9.0.4" )
set( KICAD_SEMANTIC_VERSION "9.0.5" )
# Default the version to the semantic version.
# This is overridden by the git repository tag though (if using git)
-51
View File
@@ -1,51 +0,0 @@
# compile_asm(TARGET target ASM_FILES file1 [file2 ...] OUTPUT_OBJECTS [variableName])
# CMake does not support the ARM or ARM64 assemblers on Windows when using the
# MSBuild generator. When the MSBuild generator is in use, we manually compile the assembly files
# using this function.
#
# Borrowed from dotnet/runtime, licensed under MIT
# Copyright (c) .NET Foundation and Contributors
# https://github.com/dotnet/runtime/blob/main/eng/native/functions.cmake
function(compile_asm)
set(options "")
set(oneValueArgs TARGET OUTPUT_OBJECTS)
set(multiValueArgs ASM_FILES)
cmake_parse_arguments(COMPILE_ASM "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGV})
get_include_directories_asm(ASM_INCLUDE_DIRECTORIES)
set (ASSEMBLED_OBJECTS "")
foreach(ASM_FILE ${COMPILE_ASM_ASM_FILES})
get_filename_component(name ${ASM_FILE} NAME_WE)
# Produce object file where CMake would store .obj files for an OBJECT library.
# ex: artifacts\obj\coreclr\windows.arm64.Debug\src\vm\wks\cee_wks.dir\Debug\AsmHelpers.obj
set (OBJ_FILE "${CMAKE_CURRENT_BINARY_DIR}/${COMPILE_ASM_TARGET}.dir/${CMAKE_CFG_INTDIR}/${name}.obj")
# Need to compile asm file using custom command as include directories are not provided to asm compiler
add_custom_command(OUTPUT ${OBJ_FILE}
COMMAND "${CMAKE_ASM_COMPILER}" -g ${ASM_INCLUDE_DIRECTORIES} -o ${OBJ_FILE} ${ASM_FILE}
DEPENDS ${ASM_FILE}
COMMENT "Assembling ${ASM_FILE} ---> \"${CMAKE_ASM_COMPILER}\" -g ${ASM_INCLUDE_DIRECTORIES} -o ${OBJ_FILE} ${ASM_FILE}")
# mark obj as source that does not require compile
set_source_files_properties(${OBJ_FILE} PROPERTIES EXTERNAL_OBJECT TRUE)
# Add the generated OBJ in the dependency list so that it gets consumed during linkage
list(APPEND ASSEMBLED_OBJECTS ${OBJ_FILE})
endforeach()
set(${COMPILE_ASM_OUTPUT_OBJECTS} ${ASSEMBLED_OBJECTS} PARENT_SCOPE)
endfunction()
# Build a list of include directories for consumption by the assembler
function(get_include_directories_asm IncludeDirectories)
get_directory_property(dirs INCLUDE_DIRECTORIES)
foreach(dir IN LISTS dirs)
list(APPEND INC_DIRECTORIES -I${dir};)
endforeach()
set(${IncludeDirectories} ${INC_DIRECTORIES} PARENT_SCOPE)
endfunction(get_include_directories_asm)
+3 -2
View File
@@ -24,6 +24,7 @@
#include "clipboard.h"
#include <wx/clipbrd.h>
#include <wx/dataobj.h>
#include <wx/image.h>
#include <wx/log.h>
@@ -84,10 +85,10 @@ std::unique_ptr<wxImage> GetImageFromClipboard()
{
if( wxTheClipboard->IsSupported( wxDF_BITMAP ) )
{
wxImageDataObject data;
wxBitmapDataObject data;
if( wxTheClipboard->GetData( data ) )
{
image = std::make_unique<wxImage>( data.GetImage() );
image = std::make_unique<wxImage>( data.GetBitmap().ConvertToImage() );
}
}
else if( wxTheClipboard->IsSupported( wxDF_FILENAME ) )
+14 -13
View File
@@ -161,7 +161,7 @@ bool DATABASE_CONNECTION::Connect()
m_conn = std::make_unique<nanodbc::connection>( cs, m_timeout );
}
}
catch( nanodbc::database_error& e )
catch( std::exception& e )
{
m_lastError = e.what();
return false;
@@ -188,7 +188,7 @@ bool DATABASE_CONNECTION::Disconnect()
{
m_conn->disconnect();
}
catch( boost::locale::conv::conversion_error& exc )
catch( std::exception& exc )
{
wxLogTrace( traceDatabase, wxT( "Disconnect() error \"%s\" occured." ), exc.what() );
return false;
@@ -250,7 +250,7 @@ bool DATABASE_CONNECTION::CacheTableInfo( const std::string& aTable,
return false;
}
}
catch( nanodbc::database_error& e )
catch( std::exception& e )
{
m_lastError = e.what();
wxLogTrace( traceDatabase, wxT( "Exception while caching table info: %s" ), m_lastError );
@@ -277,8 +277,9 @@ bool DATABASE_CONNECTION::getQuoteChar()
wxLogTrace( traceDatabase, wxT( "Quote char retrieved: %c" ), m_quoteChar );
}
catch( nanodbc::database_error& )
catch( std::exception& e )
{
m_lastError = e.what();
wxLogTrace( traceDatabase, wxT( "Exception while querying quote char: %s" ), m_lastError );
return false;
}
@@ -401,14 +402,14 @@ bool DATABASE_CONNECTION::SelectOne( const std::string& aTable,
statement.prepare( *m_conn, query );
statement.bind( 0, aWhere.second.c_str() );
}
catch( nanodbc::database_error& e )
catch( std::exception& e )
{
m_lastError = e.what();
wxLogTrace( traceDatabase, wxT( "Exception while preparing statement for SelectOne: %s" ),
m_lastError );
// Exception may be due to a connection error; nanodbc won't auto-reconnect
m_conn->disconnect();
Disconnect();
return false;
}
@@ -422,14 +423,14 @@ bool DATABASE_CONNECTION::SelectOne( const std::string& aTable,
{
results = nanodbc::execute( statement );
}
catch( nanodbc::database_error& e )
catch( std::exception& e )
{
m_lastError = e.what();
wxLogTrace( traceDatabase, wxT( "Exception while executing statement for SelectOne: %s" ),
m_lastError );
// Exception may be due to a connection error; nanodbc won't auto-reconnect
m_conn->disconnect();
Disconnect();
return false;
}
@@ -480,7 +481,7 @@ bool DATABASE_CONNECTION::SelectOne( const std::string& aTable,
}
}
}
catch( nanodbc::database_error& e )
catch( std::exception& e )
{
m_lastError = e.what();
wxLogTrace( traceDatabase, wxT( "Exception while parsing results from SelectOne: %s" ),
@@ -507,7 +508,7 @@ bool DATABASE_CONNECTION::selectAllAndCache( const std::string& aTable, const st
{
statement.prepare( query );
}
catch( nanodbc::database_error& e )
catch( std::exception& e )
{
m_lastError = e.what();
wxLogTrace( traceDatabase,
@@ -515,7 +516,7 @@ bool DATABASE_CONNECTION::selectAllAndCache( const std::string& aTable, const st
m_lastError );
// Exception may be due to a connection error; nanodbc won't auto-reconnect
m_conn->disconnect();
Disconnect();
return false;
}
@@ -526,7 +527,7 @@ bool DATABASE_CONNECTION::selectAllAndCache( const std::string& aTable, const st
{
results = nanodbc::execute( statement );
}
catch( nanodbc::database_error& e )
catch( std::exception& e )
{
m_lastError = e.what();
wxLogTrace( traceDatabase,
@@ -534,7 +535,7 @@ bool DATABASE_CONNECTION::selectAllAndCache( const std::string& aTable, const st
m_lastError );
// Exception may be due to a connection error; nanodbc won't auto-reconnect
m_conn->disconnect();
Disconnect();
return false;
}
+13 -2
View File
@@ -22,7 +22,6 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <build_version.h>
#include <eda_base_frame.h>
#include <wx/clipbrd.h>
@@ -108,8 +107,20 @@ DIALOG_ABOUT::DIALOG_ABOUT( EDA_BASE_FRAME *aParent, ABOUT_APP_INFO& aAppInfo )
m_titleName = aParent->GetAboutTitle();
m_untranslatedTitleName = aParent->GetUntranslatedAboutTitle();
m_staticTextAppTitle->SetLabel( m_titleName );
// On windows, display the number of GDI objects in use. Can be useful when some GDI objects
// are not displayed because the max count of GDI objects (usually 10000) is reached
// So displaying this number can help to diagnose strange display issues
wxString extraInfo;
#if defined( _WIN32 )
uint32_t gdi_count = GetGuiResources( GetCurrentProcess(), GR_GDIOBJECTS );
extraInfo.Printf( _( "GDI objects in use %u" ), gdi_count );
extraInfo.Prepend( wxT( "\n" ) );
#endif
m_staticTextBuildVersion->SetLabel( wxS( "Version: " ) + m_info.GetBuildVersion() );
m_staticTextLibVersion->SetLabel( m_info.GetLibVersion() );
m_staticTextLibVersion->SetLabel( m_info.GetLibVersion() + extraInfo );
SetTitle( wxString::Format( _( "About %s" ), m_titleName ) );
createNotebooks();
+5 -2
View File
@@ -494,14 +494,17 @@ int DIALOG_SHIM::ShowModal()
}
/*
Quasi-Modal Mode Explained:
QuasiModal Mode Explained:
The gtk calls in wxDialog::ShowModal() cause event routing problems if that
modal dialog then tries to use KIWAY_PLAYER::ShowModal(). The latter shows up
and mostly works but does not respond to the window decoration close button.
There is no way to get around this without reversing the gtk calls temporarily.
Quasi-Modal mode is our own almost modal mode which disables only the parent
There are also issues with the Scintilla text editor putting up autocomplete
popups, which appear behind the dialog window if QuasiModal is not used.
QuasiModal mode is our own almost modal mode which disables only the parent
of the DIALOG_SHIM, leaving other frames operable and while staying captured in the
nested event loop. This avoids the gtk calls and leaves event routing pure
and sufficient to operate the KIWAY_PLAYER::ShowModal() properly. When using
+48 -8
View File
@@ -21,6 +21,8 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <eda_item.h>
#include <confirm.h>
#include <bitmaps.h>
#include <dialogs/panel_embedded_files.h>
#include <embedded_files.h>
@@ -161,9 +163,7 @@ void PANEL_EMBEDDED_FILES::resizeGrid()
bool PANEL_EMBEDDED_FILES::TransferDataToWindow()
{
m_files_grid->ClearGrid();
if( m_files_grid->GetNumberRows() > 0 )
m_files_grid->DeleteRows( 0, m_files_grid->GetNumberRows() );
m_files_grid->ClearRows();
int ii = 0;
for( auto& [name, file] : m_localFiles->EmbeddedFileMap() )
@@ -187,6 +187,51 @@ bool PANEL_EMBEDDED_FILES::TransferDataToWindow()
bool PANEL_EMBEDDED_FILES::TransferDataFromWindow()
{
std::optional<bool> deleteReferences;
auto confirmDelete =
[&]() -> bool
{
if( EDA_ITEM* parent = dynamic_cast<EDA_ITEM*>( m_files ) )
{
if( parent->Type() == PCB_T )
{
return IsOK( m_parent, _( "Deleted embedded files are also referenced in some footprints.\n"
"Delete from footprints as well?" ) );
}
else if( parent->Type() == SCHEMATIC_T )
{
return IsOK( m_parent, _( "Deleted embedded files are also referenced in some symbols.\n"
"Delete from symbols as well?" ) );
}
}
wxFAIL_MSG( wxT( "Unexpected embedded files owner" ) );
return false;
};
for( const auto& [name, file] : m_files->EmbeddedFileMap() )
{
if( !m_localFiles->HasFile( name ) )
{
m_files->RunOnNestedEmbeddedFiles(
[&]( EMBEDDED_FILES* nested_files )
{
if( nested_files->HasFile( name ) )
{
if( !deleteReferences.has_value() )
deleteReferences = confirmDelete();
if( deleteReferences.value() )
nested_files->RemoveFile( name, true );
}
} );
}
if( deleteReferences.has_value() && deleteReferences.value() == false )
break;
}
m_files->ClearEmbeddedFiles();
std::vector<EMBEDDED_FILES::EMBEDDED_FILE*> files;
@@ -247,11 +292,6 @@ void PANEL_EMBEDDED_FILES::onFontEmbedClick( wxCommandEvent& event )
font->GetFileName() ) );
continue;
}
m_files_grid->AppendRows( 1 );
int ii = m_files_grid->GetNumberRows() - 1;
m_files_grid->SetCellValue( ii, 0, result->name );
m_files_grid->SetCellValue( ii, 1, result->GetLink() );
}
}
+1
View File
@@ -141,6 +141,7 @@ void EDA_BASE_FRAME::commonInit( FRAME_T aFrameType )
m_isNonUserClose = false;
m_autoSaveTimer = new wxTimer( this, ID_AUTO_SAVE_TIMER );
m_autoSaveRequired = false;
m_autoSavePermissionError = false;
m_mruPath = PATHS::GetDefaultUserProjectsPath();
m_frameSize = defaultSize( aFrameType, this );
m_displayIndex = -1;
+6
View File
@@ -322,6 +322,12 @@ void CAIRO_GAL_BASE::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& a
}
void CAIRO_GAL_BASE::DrawHoleWall( const VECTOR2D& aCenterPoint, double aRadius, double aWallWidth )
{
DrawCircle( aCenterPoint, aRadius + aWallWidth );
}
void CAIRO_GAL_BASE::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius )
{
syncLineWidth();
@@ -67,6 +67,7 @@ GAL::GAL( GAL_DISPLAY_OPTIONS& aDisplayOptions ) :
SetLayerDepth( 0.0 );
SetFlip( false, false );
SetLineWidth( 1.0f );
SetMinLineWidth( 1.0f );
computeWorldScale();
SetAxesEnabled( false );
+61 -12
View File
@@ -413,10 +413,13 @@ OPENGL_GAL::OPENGL_GAL( const KIGFX::VC_SETTINGS& aVcSettings, GAL_DISPLAY_OPTIO
SetTarget( TARGET_NONCACHED );
// Avoid uninitialized variables:
ufm_worldPixelSize = 1;
ufm_screenPixelSize = 1;
ufm_pixelSizeMultiplier = 1;
ufm_antialiasingOffset = 1;
ufm_worldPixelSize = -1;
ufm_screenPixelSize = -1;
ufm_pixelSizeMultiplier = -1;
ufm_antialiasingOffset = -1;
ufm_minLinePixelWidth = -1;
ufm_fontTexture = -1;
ufm_fontTextureWidth = -1;
m_swapInterval = 0;
}
@@ -672,14 +675,6 @@ void OPENGL_GAL::BeginDrawing()
glActiveTexture( GL_TEXTURE0 );
}
// Set shader parameter
GLint ufm_fontTexture = m_shader->AddParameter( "u_fontTexture" );
GLint ufm_fontTextureWidth = m_shader->AddParameter( "u_fontTextureWidth" );
ufm_worldPixelSize = m_shader->AddParameter( "u_worldPixelSize" );
ufm_screenPixelSize = m_shader->AddParameter( "u_screenPixelSize" );
ufm_pixelSizeMultiplier = m_shader->AddParameter( "u_pixelSizeMultiplier" );
ufm_antialiasingOffset = m_shader->AddParameter( "u_antialiasingOffset" );
m_shader->Use();
m_shader->SetParameter( ufm_fontTexture, (int) FONT_TEXTURE_UNIT );
m_shader->SetParameter( ufm_fontTextureWidth, (int) font_image.width );
@@ -700,6 +695,7 @@ void OPENGL_GAL::BeginDrawing()
renderingOffset.x *= screenPixelSize.x;
renderingOffset.y *= screenPixelSize.y;
m_shader->SetParameter( ufm_antialiasingOffset, renderingOffset );
m_shader->SetParameter( ufm_minLinePixelWidth, GetMinLineWidth() );
m_shader->Deactivate();
// Something between BeginDrawing and EndDrawing seems to depend on
@@ -716,6 +712,18 @@ void OPENGL_GAL::BeginDrawing()
#endif /* KICAD_GAL_PROFILE */
}
void OPENGL_GAL::SetMinLineWidth( float aLineWidth )
{
GAL::SetMinLineWidth( aLineWidth );
if( m_shader && ufm_minLinePixelWidth != -1 )
{
m_shader->Use();
m_shader->SetParameter( ufm_minLinePixelWidth, aLineWidth );
m_shader->Deactivate();
}
}
void OPENGL_GAL::EndDrawing()
{
@@ -907,6 +915,25 @@ void OPENGL_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius )
}
void OPENGL_GAL::DrawHoleWall( const VECTOR2D& aCenterPoint, double aHoleRadius,
double aWallWidth )
{
if( m_isFillEnabled )
{
m_currentManager->Color( m_fillColor.r, m_fillColor.g, m_fillColor.b, m_fillColor.a );
m_currentManager->Shader( SHADER_HOLE_WALL, 1.0, aHoleRadius, aWallWidth );
m_currentManager->Vertex( aCenterPoint.x, aCenterPoint.y, m_layerDepth );
m_currentManager->Shader( SHADER_HOLE_WALL, 2.0, aHoleRadius, aWallWidth );
m_currentManager->Vertex( aCenterPoint.x, aCenterPoint.y, m_layerDepth );
m_currentManager->Shader( SHADER_HOLE_WALL, 3.0, aHoleRadius, aWallWidth );
m_currentManager->Vertex( aCenterPoint.x, aCenterPoint.y, m_layerDepth );
}
}
void OPENGL_GAL::drawCircle( const VECTOR2D& aCenterPoint, double aRadius, bool aReserve )
{
if( m_isFillEnabled )
@@ -2662,6 +2689,10 @@ void OPENGL_GAL::blitCursor()
glLineWidth( 1.0 );
glColor4d( color.r, color.g, color.b, color.a );
glMatrixMode( GL_PROJECTION );
glPushMatrix();
glTranslated( 0, 0, -0.5 );
glBegin( GL_LINES );
glVertex2d( cursorCenter.x, cursorBegin.y );
glVertex2d( cursorCenter.x, cursorEnd.y );
@@ -2669,6 +2700,8 @@ void OPENGL_GAL::blitCursor()
glVertex2d( cursorBegin.x, cursorCenter.y );
glVertex2d( cursorEnd.x, cursorCenter.y );
glEnd();
glPopMatrix();
}
@@ -2753,6 +2786,9 @@ void OPENGL_GAL::init()
if( !m_shader->IsLinked() && !m_shader->Link() )
throw std::runtime_error( "Cannot link the shaders!" );
// Set up shader parameters after linking
setupShaderParameters();
// Check if video card supports textures big enough to fit the font atlas
int maxTextureSize;
glGetIntegerv( GL_MAX_TEXTURE_SIZE, &maxTextureSize );
@@ -2781,6 +2817,19 @@ void OPENGL_GAL::init()
}
void OPENGL_GAL::setupShaderParameters()
{
// Initialize shader uniform parameter locations
ufm_fontTexture = m_shader->AddParameter( "u_fontTexture" );
ufm_fontTextureWidth = m_shader->AddParameter( "u_fontTextureWidth" );
ufm_worldPixelSize = m_shader->AddParameter( "u_worldPixelSize" );
ufm_screenPixelSize = m_shader->AddParameter( "u_screenPixelSize" );
ufm_pixelSizeMultiplier = m_shader->AddParameter( "u_pixelSizeMultiplier" );
ufm_antialiasingOffset = m_shader->AddParameter( "u_antialiasingOffset" );
ufm_minLinePixelWidth = m_shader->AddParameter( "u_minLinePixelWidth" );
}
// Callback functions for the tesselator. Compare Redbook Chapter 11.
void CALLBACK VertexCallback( GLvoid* aVertexPtr, void* aData )
{
+5
View File
@@ -35,6 +35,7 @@ const float SHADER_FILLED_CIRCLE = 2.0;
const float SHADER_STROKED_CIRCLE = 3.0;
const float SHADER_FONT = 4.0;
const float SHADER_LINE_A = 5.0;
const float SHADER_HOLE_WALL = 11.0;
varying vec4 v_shaderParams;
varying vec2 v_circleCoords;
@@ -124,6 +125,10 @@ void main()
{
strokedCircle( v_circleCoords, v_shaderParams[2], v_shaderParams[3] );
}
else if( mode == SHADER_HOLE_WALL )
{
strokedCircle( v_circleCoords, v_shaderParams[2], v_shaderParams[3] );
}
else if( mode == SHADER_FONT )
{
vec2 tex = v_shaderParams.yz;
+58 -4
View File
@@ -36,6 +36,7 @@ const float SHADER_LINE_C = 7.0;
const float SHADER_LINE_D = 8.0;
const float SHADER_LINE_E = 9.0;
const float SHADER_LINE_F = 10.0;
const float SHADER_HOLE_WALL = 11.0;
// Minimum line width
const float MIN_WIDTH = 1.0;
@@ -72,8 +73,8 @@ void computeLineCoords( bool posture, vec2 vs, vec2 vp, vec2 texcoord, vec2 dir,
vec2 s = sign( vec2( gl_ModelViewProjectionMatrix[0][0], gl_ModelViewProjectionMatrix[1][1] ) );
if( pixelWidth < 1.0 )
pixelWidth = 1.0;
if( pixelWidth < u_minLinePixelWidth )
pixelWidth = u_minLinePixelWidth;
if ( pixelWidth > 1.0 || u_pixelSizeMultiplier > 1.0 )
{
@@ -126,8 +127,59 @@ void computeCircleCoords( float mode, float vertexIndex, float radius, float lin
vec4 adjust = vec4(-1, -1, 0, 0);
if( pixelWidth < 1.0 )
pixelWidth = 1.0;
if( pixelWidth < u_minLinePixelWidth )
pixelWidth = u_minLinePixelWidth;
if( vertexIndex == 1.0 )
{
v_circleCoords = vec2( -sqrt( 3.0 ), -1.0 );
delta = vec4( -pixelR * sqrt(3.0), -pixelR, 0, 0 );
}
else if( vertexIndex == 2.0 )
{
v_circleCoords = vec2( sqrt( 3.0 ), -1.0 );
delta = vec4( pixelR * sqrt( 3.0 ), -pixelR, 0, 0 );
}
else if( vertexIndex == 3.0 )
{
v_circleCoords = vec2( 0.0, 2.0 );
delta = vec4( 0, 2 * pixelR, 0, 0 );
}
else if( vertexIndex == 4.0 )
{
v_circleCoords = vec2( -sqrt( 3.0 ), 0.0 );
delta = vec4( 0, 0, 0, 0 );
}
else if( vertexIndex == 5.0 )
{
v_circleCoords = vec2( sqrt( 3.0 ), 0.0 );
delta = vec4( 0, 0, 0, 0 );
}
else if( vertexIndex == 6.0 )
{
v_circleCoords = vec2( 0.0, 2.0 );
delta = vec4( 0, 0, 0, 0 );
}
v_shaderParams[2] = pixelR;
v_shaderParams[3] = pixelWidth;
delta.x *= u_screenPixelSize.x;
delta.y *= u_screenPixelSize.y;
gl_Position = center + delta + adjust;
gl_FrontColor = gl_Color;
}
void computeHoleWallCoords( float vertexIndex, float radius, float lineWidth )
{
vec4 delta;
vec4 center = roundv( gl_ModelViewProjectionMatrix * gl_Vertex + vec4(1, 1, 0, 0), u_screenPixelSize );
float pixelWidth = roundr( lineWidth / u_worldPixelSize, 1.0 );
if( pixelWidth < u_minLinePixelWidth )
pixelWidth = u_minLinePixelWidth;
float pixelR = roundr( radius / u_worldPixelSize, 1.0 ) + pixelWidth;
vec4 adjust = vec4(-1, -1, 0, 0);
if( vertexIndex == 1.0 )
{
@@ -195,6 +247,8 @@ void main()
computeLineCoords( posture, vs, vp, vec2( -1, 1 ), vec2( -1, 0 ), lineWidth, true );
else if( mode == SHADER_LINE_F )
computeLineCoords( posture, -vs, vp, vec2( 1, 1 ), vec2( -1, 0 ), lineWidth, false );
else if( mode == SHADER_HOLE_WALL )
computeHoleWallCoords( v_shaderParams.y, v_shaderParams.z, v_shaderParams.w );
else if( mode == SHADER_FILLED_CIRCLE || mode == SHADER_STROKED_CIRCLE)
computeCircleCoords( mode, v_shaderParams.y, v_shaderParams.z, v_shaderParams.w );
else
+39 -59
View File
@@ -40,19 +40,11 @@ HTTP_LIB_CONNECTION::HTTP_LIB_CONNECTION( const HTTP_LIB_SOURCE& aSource, bool a
m_source = aSource;
if( aTestConnectionNow )
{
ValidateHTTPLibraryEndpoints();
}
validateHttpLibraryEndpoints();
}
HTTP_LIB_CONNECTION::~HTTP_LIB_CONNECTION()
{
// Do nothing
}
bool HTTP_LIB_CONNECTION::ValidateHTTPLibraryEndpoints()
bool HTTP_LIB_CONNECTION::validateHttpLibraryEndpoints()
{
m_endpointValid = false;
std::string res = "";
@@ -78,11 +70,8 @@ bool HTTP_LIB_CONNECTION::ValidateHTTPLibraryEndpoints()
nlohmann::json response = nlohmann::json::parse( res );
// Check that the endpoints exist, if not fail.
if( !response.at( http_endpoint_categories ).empty()
&& !response.at( http_endpoint_parts ).empty() )
{
if( !response.at( "categories" ).empty() && !response.at( "parts" ).empty() )
m_endpointValid = true;
}
}
}
catch( const std::exception& e )
@@ -90,29 +79,19 @@ bool HTTP_LIB_CONNECTION::ValidateHTTPLibraryEndpoints()
m_lastError += wxString::Format( _( "Error: %s" ) + "\n" + _( "API Response: %s" ) + "\n",
e.what(), res );
wxLogTrace( traceHTTPLib,
wxT( "ValidateHTTPLibraryEndpoints: Exception occurred while testing the API "
"connection: %s" ),
wxLogTrace( traceHTTPLib, wxT( "validateHttpLibraryEndpoints: Exception while testing API connection: %s" ),
m_lastError );
m_endpointValid = false;
}
if( m_endpointValid )
{
syncCategories();
}
return m_endpointValid;
}
bool HTTP_LIB_CONNECTION::IsValidEndpoint() const
{
return m_endpointValid;
}
bool HTTP_LIB_CONNECTION::syncCategories()
{
if( !IsValidEndpoint() )
@@ -124,7 +103,7 @@ bool HTTP_LIB_CONNECTION::syncCategories()
std::string res = "";
std::unique_ptr<KICAD_CURL_EASY> curl = createCurlEasyObject();
curl->SetURL( m_source.root_url + http_endpoint_categories + ".json" );
curl->SetURL( m_source.root_url + "categories.json" );
try
{
@@ -133,9 +112,7 @@ bool HTTP_LIB_CONNECTION::syncCategories()
res = curl->GetBuffer();
if( !checkServerResponse( curl ) )
{
return false;
}
nlohmann::json response = nlohmann::json::parse( res );
@@ -162,9 +139,7 @@ bool HTTP_LIB_CONNECTION::syncCategories()
m_lastError += wxString::Format( _( "Error: %s" ) + "\n" + _( "API Response: %s" ) + "\n",
e.what(), res );
wxLogTrace( traceHTTPLib,
wxT( "syncCategories: Exception occurred while syncing categories: %s" ),
m_lastError );
wxLogTrace( traceHTTPLib, wxT( "syncCategories: Exception while syncing categories: %s" ), m_lastError );
m_categories.clear();
@@ -187,8 +162,7 @@ bool HTTP_LIB_CONNECTION::SelectOne( const std::string& aPartID, HTTP_LIB_PART&
if( m_cachedParts.find( aPartID ) != m_cachedParts.end() )
{
// check if it's outdated, if so re-fetch
if( std::difftime( std::time( nullptr ), m_cachedParts[aPartID].lastCached )
< m_source.timeout_parts )
if( std::difftime( std::time( nullptr ), m_cachedParts[aPartID].lastCached ) < m_source.timeout_parts )
{
aFetchedPart = m_cachedParts[aPartID];
return true;
@@ -198,7 +172,7 @@ bool HTTP_LIB_CONNECTION::SelectOne( const std::string& aPartID, HTTP_LIB_PART&
std::string res = "";
std::unique_ptr<KICAD_CURL_EASY> curl = createCurlEasyObject();
std::string url = m_source.root_url + fmt::format( "{}/{}.json", http_endpoint_parts, aPartID );
std::string url = m_source.root_url + fmt::format( "parts/{}.json", aPartID );
curl->SetURL( url );
try
@@ -208,9 +182,7 @@ bool HTTP_LIB_CONNECTION::SelectOne( const std::string& aPartID, HTTP_LIB_PART&
res = curl->GetBuffer();
if( !checkServerResponse( curl ) )
{
return false;
}
nlohmann::ordered_json response = nlohmann::ordered_json::parse( res );
std::string key = "";
@@ -225,13 +197,9 @@ bool HTTP_LIB_CONNECTION::SelectOne( const std::string& aPartID, HTTP_LIB_PART&
// API might not want to return an optional name.
if( response.contains( "name" ) )
{
aFetchedPart.name = response.at( "name" );
}
else
{
aFetchedPart.name = aFetchedPart.id;
}
aFetchedPart.symbolIdStr = response.at( "symbolIdStr" );
@@ -285,18 +253,36 @@ bool HTTP_LIB_CONNECTION::SelectOne( const std::string& aPartID, HTTP_LIB_PART&
}
// Add field to fields list
aFetchedPart.fields.push_back(
std::make_pair( key, std::make_tuple( value, visible ) ) );
aFetchedPart.fields.push_back( std::make_pair( key, std::make_tuple( value, visible ) ) );
}
if( response.contains( "description" ) )
aFetchedPart.desc = response.at( "description" );
if( response.contains( "keywords" ) )
aFetchedPart.keywords = response.at( "keywords" );
if( response.contains( "footprint_filters" ) )
{
nlohmann::json filters_json = response.at( "footprint_filters" );
if( filters_json.is_array() )
{
for( const auto& val : filters_json )
aFetchedPart.fp_filters.push_back( val );
}
else
{
aFetchedPart.fp_filters.push_back( filters_json );
}
}
}
catch( const std::exception& e )
{
m_lastError += wxString::Format( _( "Error: %s" ) + "\n" + _( "API Response: %s" ) + "\n",
m_lastError += wxString::Format( _( "Error: %s" ) + "\n" + _( "API Response: %s" ) + "\n",
e.what(), res );
wxLogTrace( traceHTTPLib,
wxT( "SelectOne: Exception occurred while retrieving part from REST API: %s" ),
m_lastError );
wxLogTrace( traceHTTPLib, wxT( "SelectOne: Exception while fetching part: %s" ), m_lastError );
return false;
}
@@ -307,8 +293,7 @@ bool HTTP_LIB_CONNECTION::SelectOne( const std::string& aPartID, HTTP_LIB_PART&
}
bool HTTP_LIB_CONNECTION::SelectAll( const HTTP_LIB_CATEGORY& aCategory,
std::vector<HTTP_LIB_PART>& aParts )
bool HTTP_LIB_CONNECTION::SelectAll( const HTTP_LIB_CATEGORY& aCategory, std::vector<HTTP_LIB_PART>& aParts )
{
if( !IsValidEndpoint() )
{
@@ -320,8 +305,7 @@ bool HTTP_LIB_CONNECTION::SelectAll( const HTTP_LIB_CATEGORY& aCategory,
std::unique_ptr<KICAD_CURL_EASY> curl = createCurlEasyObject();
curl->SetURL( m_source.root_url
+ fmt::format( "{}/category/{}.json", http_endpoint_parts, aCategory.id ) );
curl->SetURL( m_source.root_url + fmt::format( "parts/category/{}.json", aCategory.id ) );
try
{
@@ -341,19 +325,15 @@ bool HTTP_LIB_CONNECTION::SelectAll( const HTTP_LIB_CATEGORY& aCategory,
if( item.contains( "description" ) )
{
// At this point we don't display anything so just set it to false
part.fields.push_back( std::make_pair(
"description", std::make_tuple( item.at( "description" ), false ) ) );
part.fields.push_back( std::make_pair( "description",
std::make_tuple( item.at( "description" ), false ) ) );
}
// API might not want to return an optional name.
if( item.contains( "name" ) )
{
part.name = item.at( "name" );
}
else
{
part.name = part.id;
}
// add to cache
m_cache[part.name] = std::make_tuple( part.id, aCategory.id );
@@ -363,11 +343,10 @@ bool HTTP_LIB_CONNECTION::SelectAll( const HTTP_LIB_CATEGORY& aCategory,
}
catch( const std::exception& e )
{
m_lastError += wxString::Format( _( "Error: %s" ) + "\n" + _( "API Response: %s" ) + "\n",
m_lastError += wxString::Format( _( "Error: %s" ) + "\n" + _( "API Response: %s" ) + "\n",
e.what(), res );
wxLogTrace( traceHTTPLib, wxT( "Exception occurred while syncing parts from REST API: %s" ),
m_lastError );
wxLogTrace( traceHTTPLib, wxT( "Exception occurred while syncing parts: %s" ), m_lastError );
return false;
}
@@ -379,6 +358,7 @@ bool HTTP_LIB_CONNECTION::SelectAll( const HTTP_LIB_CATEGORY& aCategory,
bool HTTP_LIB_CONNECTION::checkServerResponse( std::unique_ptr<KICAD_CURL_EASY>& aCurl )
{
int statusCode = aCurl->GetResponseStatusCode();
if( statusCode != 200 )
{
m_lastError += wxString::Format( _( "API responded with error code: %s" ) + "\n",
+3 -5
View File
@@ -35,10 +35,9 @@ const int httplibSchemaVersion = 1;
HTTP_LIB_SETTINGS::HTTP_LIB_SETTINGS( const std::string& aFilename ) :
JSON_SETTINGS( aFilename, SETTINGS_LOC::NONE, httplibSchemaVersion )
{
m_params.emplace_back( new PARAM<std::string>( "source.type", &sourceType, "" ) );
m_params.emplace_back( new PARAM<std::string>( "source.type", &m_sourceType, "" ) );
m_params.emplace_back(
new PARAM<std::string>( "source.api_version", &m_Source.api_version, "" ) );
m_params.emplace_back( new PARAM<std::string>( "source.api_version", &m_Source.api_version, "" ) );
m_params.emplace_back( new PARAM<std::string>( "source.root_url", &m_Source.root_url, "" ) );
@@ -46,8 +45,7 @@ HTTP_LIB_SETTINGS::HTTP_LIB_SETTINGS( const std::string& aFilename ) :
m_params.emplace_back( new PARAM<int>( "source.timeout_parts_seconds", &m_Source.timeout_parts, 30 ) );
m_params.emplace_back( new PARAM<int>( "source.timeout_categories_seconds",
&m_Source.timeout_categories, 600 ) );
m_params.emplace_back( new PARAM<int>( "source.timeout_categories_seconds", &m_Source.timeout_categories, 600 ) );
}
+1 -1
View File
@@ -41,7 +41,7 @@ JOB_EXPORT_PCB_ODB::JOB_EXPORT_PCB_ODB() :
m_filename(),
m_drawingSheet(),
m_units( ODB_UNITS::MM ),
m_precision( 2 ),
m_precision( 4 ),
m_compressionMode( ODB_COMPRESSION::ZIP )
{
m_params.emplace_back( new JOB_PARAM<wxString>( "drawing_sheet", &m_drawingSheet, m_drawingSheet ) );
+1
View File
@@ -85,6 +85,7 @@ JOB_PCB_RENDER::JOB_PCB_RENDER() :
{
m_params.emplace_back( new JOB_PARAM<FORMAT>( "format", &m_format, m_format ) );
m_params.emplace_back( new JOB_PARAM<std::string>( "preset", &m_appearancePreset, m_appearancePreset ) );
m_params.emplace_back( new JOB_PARAM<bool>( "use_board_stackup_colors", &m_useBoardStackupColors, m_useBoardStackupColors ) );
m_params.emplace_back( new JOB_PARAM<QUALITY>( "quality", &m_quality, m_quality ) );
m_params.emplace_back( new JOB_PARAM<BG_STYLE>( "bg_style", &m_bgStyle, m_bgStyle ) );
m_params.emplace_back( new JOB_PARAM<SIDE>( "side", &m_side, m_side ) );
+1
View File
@@ -87,6 +87,7 @@ public:
int m_width = 0;
int m_height = 0;
std::string m_appearancePreset;
bool m_useBoardStackupColors = true;
SIDE m_side = SIDE::TOP;
double m_zoom = 1.0;
bool m_perspective = false;
+1 -1
View File
@@ -39,7 +39,7 @@ JOB_RC::JOB_RC( const std::string& aType ) :
m_units( JOB_RC::UNITS::MM ),
m_severity( RPT_SEVERITY_ERROR | RPT_SEVERITY_WARNING ),
m_format( OUTPUT_FORMAT::REPORT ),
m_exitCodeViolations( false )
m_exitCodeViolations( true ) // this ensures GUI jobs default to treat violations as job failure, cli will default false elsewhere
{
m_params.emplace_back( new JOB_PARAM<UNITS>( "units", &m_units, m_units ) );
m_params.emplace_back( new JOB_PARAM<int>( "severity", &m_severity, m_severity ) );
+3
View File
@@ -24,6 +24,7 @@
#include <wx/zipstrm.h>
#include <gestfich.h>
#include <common.h>
#include <wildcards_and_files_ext.h>
JOBS_OUTPUT_ARCHIVE::JOBS_OUTPUT_ARCHIVE() :
JOBS_OUTPUT_HANDLER(),
@@ -52,6 +53,8 @@ bool JOBS_OUTPUT_ARCHIVE::HandleOutputs( const wxString& baseTempPath, PROJECT*
if( outputPath.StartsWith( "~" ) )
outputPath.Replace( "~", wxGetHomeDir(), false );
outputPath = EnsureFileExtension( outputPath, FILEEXT::ArchiveFileExtension );
wxFFileOutputStream ostream( outputPath );
if( !ostream.IsOk() ) // issue to create the file. Perhaps not writable dir
+1 -18
View File
@@ -134,29 +134,12 @@ LIB_TREE_NODE::LIB_TREE_NODE()
LIB_TREE_NODE_UNIT::LIB_TREE_NODE_UNIT( LIB_TREE_NODE* aParent, LIB_TREE_ITEM* aItem, int aUnit )
{
static void* locale = nullptr;
static wxString namePrefix;
// Fetching translations can take a surprising amount of time when loading libraries,
// so only do it when necessary.
if( Pgm().GetLocale() != locale )
{
namePrefix = _( "Unit" );
locale = Pgm().GetLocale();
}
m_Parent = aParent;
m_Type = TYPE::UNIT;
m_Unit = aUnit;
m_LibId = aParent->m_LibId;
m_Name = namePrefix + " " + aItem->GetUnitReference( aUnit );
if( aItem->HasUnitDisplayName( aUnit ) )
m_Desc = aItem->GetUnitDisplayName( aUnit );
else
m_Desc = wxEmptyString;
m_Name = aItem->GetUnitName( aUnit );
m_IntrinsicRank = -aUnit;
}
+10
View File
@@ -32,6 +32,7 @@
#include <wx/wupdlock.h>
#include <wx/settings.h>
#include <wx/dc.h>
#include <wx/log.h>
#include <string_utils.h>
@@ -308,6 +309,15 @@ void LIB_TREE_MODEL_ADAPTER::UpdateSearchString( const wxString& aSearch, bool a
const LIB_TREE_NODE* firstMatch = ShowResults();
#ifdef __WXGTK__
// Ensure the control is repainted with the updated data. Without an explicit
// refresh the Gtk port can display stale rows until the user interacts with
// them, leading to mismatched tree contents.
m_widget->Refresh();
m_widget->Update();
wxYield();
#endif
if( firstMatch )
{
wxDataViewItem item = ToItem( firstMatch );
+6 -6
View File
@@ -1150,7 +1150,9 @@ void UOP::Exec( CONTEXT* ctx )
return;
case TR_OP_METHOD_CALL:
m_func( ctx, m_ref.get() );
if( m_func )
m_func( ctx, m_ref.get() );
return;
default:
@@ -1283,9 +1285,8 @@ VALUE* UCODE::Run( CONTEXT* ctx )
}
catch(...)
{
// rules which fail outright should not be fired
std::unique_ptr<VALUE> temp_false = std::make_unique<VALUE>( 0 );
return ctx->StoreValue( temp_false.get() );
// rules which fail outright should not be fired; return 0/false
return ctx->StoreValue( new VALUE( 0 ) );
}
if( ctx->SP() == 1 )
@@ -1301,8 +1302,7 @@ VALUE* UCODE::Run( CONTEXT* ctx )
wxASSERT( ctx->SP() == 1 );
// non-well-formed rules should not be fired on a release build
std::unique_ptr<VALUE> temp_false = std::make_unique<VALUE>( 0 );
return ctx->StoreValue( temp_false.get() );
return ctx->StoreValue( new VALUE( 0 ) );
}
}
+1 -1
View File
@@ -278,7 +278,7 @@ bool NETCLASS::ContainsNetclassWithName( const wxString& netclass ) const
return std::any_of( m_constituents.begin(), m_constituents.end(),
[&netclass]( const NETCLASS* nc )
{
return nc && nc->GetName() == netclass;
return nc && nc->GetName().Matches( netclass );
} );
}
+25
View File
@@ -55,6 +55,31 @@ enum class ELECTRICAL_PINTYPE
#define ELECTRICAL_PINTYPES_TOTAL ( static_cast<int>( ELECTRICAL_PINTYPE::PT_LAST_OPTION ) + 1 )
inline wxString GetCanonicalElectricalTypeName( ELECTRICAL_PINTYPE aType )
{
// These strings are the canonical name of the electrictal type
// Not translated, no space in name, only ASCII chars.
// to use when the string name must be known and well defined
// must have same order than enum ELECTRICAL_PINTYPE (see sch_pin.h)
static const wxChar* msgPinElectricType[] =
{
wxT( "input" ),
wxT( "output" ),
wxT( "bidirectional" ),
wxT( "tri_state" ),
wxT( "passive" ),
wxT( "free" ),
wxT( "unspecified" ),
wxT( "power_in" ),
wxT( "power_out" ),
wxT( "open_collector" ),
wxT( "open_emitter" ),
wxT( "no_connect" )
};
return msgPinElectricType[static_cast<int>( aType )];
}
enum class GRAPHIC_PINSHAPE
{
LINE,
+80 -1
View File
@@ -335,7 +335,86 @@ void RULER_ITEM::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const
VECTOR2D rulerVec( end - origin );
wxArrayString cursorStrings = GetDimensionStrings();
DrawTextNextToCursor( aView, end, -rulerVec, cursorStrings, drawingDropShadows );
// Choose a text quadrant that keeps the measurement text on-screen while avoiding
// overlapping the ruler geometry. Start with the preferred direction (away from the
// origin) and fall back to other quadrants as needed to keep the label visible.
int prefX = rulerVec.y < 0.0 ? -1 : 1;
int prefY = rulerVec.x < 0.0 ? 1 : -1;
double scale = gal->GetWorldScale();
TEXT_DIMS dims = GetConstantGlyphHeight( gal );
KIFONT::FONT* font = KIFONT::FONT::GetFont();
double width = 0.0;
for( const wxString& s : cursorStrings )
{
VECTOR2I extents = font->StringBoundaryLimits( s, dims.GlyphSize, dims.StrokeWidth, false, false,
KIFONT::METRICS::Default() );
width = std::max( width, (double) extents.x );
}
double height = dims.LinePitch * cursorStrings.size();
// Convert to screen coordinates for visibility checks
VECTOR2D cursorScreen = gal->ToScreen( end );
VECTOR2I screenSize = gal->GetScreenPixelSize();
double offsetX = 15.0; // same as DrawTextNextToCursor()
double offsetY = dims.LinePitch * scale; // vertical spacing from cursor
auto fits = [&]( int sx, int sy )
{
double left, right, top, bottom;
double xStart = cursorScreen.x + ( sx < 0 ? offsetX : -offsetX );
if( sx < 0 )
{
left = xStart;
right = left + width * scale;
}
else
{
right = xStart;
left = right - width * scale;
}
if( sy > 0 ) // above cursor
{
bottom = cursorScreen.y - offsetY;
top = bottom - height * scale;
}
else // below cursor
{
top = cursorScreen.y + offsetY;
bottom = top + height * scale;
}
return left >= 0 && right <= screenSize.x && top >= 0 && bottom <= screenSize.y;
};
std::vector<VECTOR2I> candidates = { { prefX, prefY }, { -prefX, prefY },
{ prefX, -prefY }, { -prefX, -prefY } };
VECTOR2I chosen = candidates[0];
double bestDot = -1.0;
for( const VECTOR2I& c : candidates )
{
double dot = c.x * prefX + c.y * prefY;
if( dot >= 0 && fits( c.x, c.y ) )
{
if( dot > bestDot )
{
bestDot = dot;
chosen = c;
}
}
}
VECTOR2D quadrant( chosen.x, chosen.y );
DrawTextNextToCursor( aView, end, quadrant, cursorStrings, drawingDropShadows );
// basic tick size
double minorTickLen = 5.0 / gal->GetWorldScale();
+46 -77
View File
@@ -25,10 +25,15 @@
#include <properties/property.h>
#include <algorithm>
#include <ranges>
#include <utility>
#include <wx/wx.h>
static wxString EMPTY_STRING( wxEmptyString );
// Global to prevent simultaneous multi-threaded static initialization
static const std::vector<PROPERTY_BASE*> EMPTY_PROP_LIST;
static const std::map<PROPERTY_BASE*, int> EMPTY_PROP_DISPLAY_ORDER;
std::vector<wxString> EMPTY_GROUP_DISPLAY_ORDER;
void PROPERTY_MANAGER::RegisterType( TYPE_ID aType, const wxString& aName )
@@ -38,13 +43,6 @@ void PROPERTY_MANAGER::RegisterType( TYPE_ID aType, const wxString& aName )
}
const wxString& PROPERTY_MANAGER::ResolveType( TYPE_ID aType ) const
{
auto it = m_classNames.find( aType );
return it != m_classNames.end() ? it->second : EMPTY_STRING;
}
PROPERTY_BASE* PROPERTY_MANAGER::GetProperty( TYPE_ID aType, const wxString& aProperty ) const
{
if( m_dirty )
@@ -67,31 +65,29 @@ PROPERTY_BASE* PROPERTY_MANAGER::GetProperty( TYPE_ID aType, const wxString& aPr
}
const PROPERTY_LIST& PROPERTY_MANAGER::GetProperties( TYPE_ID aType ) const
const std::vector<PROPERTY_BASE*>& PROPERTY_MANAGER::GetProperties( TYPE_ID aType ) const
{
if( m_dirty )
const_cast<PROPERTY_MANAGER*>( this )->Rebuild();
static const PROPERTY_LIST empty;
auto it = m_classes.find( aType );
if( it == m_classes.end() )
return empty;
return EMPTY_PROP_LIST;
return it->second.m_allProperties;
}
const PROPERTY_DISPLAY_ORDER& PROPERTY_MANAGER::GetDisplayOrder( TYPE_ID aType ) const
const std::map<PROPERTY_BASE*, int>& PROPERTY_MANAGER::GetDisplayOrder( TYPE_ID aType ) const
{
if( m_dirty )
const_cast<PROPERTY_MANAGER*>( this )->Rebuild();
static const PROPERTY_DISPLAY_ORDER empty;
auto it = m_classes.find( aType );
if( it == m_classes.end() )
return empty;
return EMPTY_PROP_DISPLAY_ORDER;
return it->second.m_displayOrder;
}
@@ -102,11 +98,10 @@ const std::vector<wxString>& PROPERTY_MANAGER::GetGroupDisplayOrder( TYPE_ID aTy
if( m_dirty )
const_cast<PROPERTY_MANAGER*>( this )->Rebuild();
static const std::vector<wxString> empty;
auto it = m_classes.find( aType );
if( it == m_classes.end() )
return empty;
return EMPTY_GROUP_DISPLAY_ORDER;
return it->second.m_groupDisplayOrder;
}
@@ -122,7 +117,7 @@ const void* PROPERTY_MANAGER::TypeCast( const void* aSource, TYPE_ID aBase, TYPE
if( classDesc == m_classes.end() )
return aSource;
auto& converters = classDesc->second.m_typeCasts;
const std::map<TYPE_ID, std::unique_ptr<TYPE_CAST_BASE>>& converters = classDesc->second.m_typeCasts;
auto converter = converters.find( aTarget );
if( converter == converters.end() ) // explicit type cast not found
@@ -135,8 +130,9 @@ const void* PROPERTY_MANAGER::TypeCast( const void* aSource, TYPE_ID aBase, TYPE
PROPERTY_BASE& PROPERTY_MANAGER::AddProperty( PROPERTY_BASE* aProperty, const wxString& aGroup )
{
const wxString& name = aProperty->Name();
TYPE_ID hash = aProperty->OwnerHash();
CLASS_DESC& classDesc = getClass( hash );
TYPE_ID hash = aProperty->OwnerHash();
CLASS_DESC& classDesc = getClass( hash );
classDesc.m_ownProperties.emplace( name, aProperty );
classDesc.m_ownDisplayOrder.emplace_back( aProperty );
@@ -153,8 +149,8 @@ PROPERTY_BASE& PROPERTY_MANAGER::AddProperty( PROPERTY_BASE* aProperty, const wx
}
PROPERTY_BASE& PROPERTY_MANAGER::ReplaceProperty( size_t aBase, const wxString& aName,
PROPERTY_BASE* aNew, const wxString& aGroup )
PROPERTY_BASE& PROPERTY_MANAGER::ReplaceProperty( size_t aBase, const wxString& aName, PROPERTY_BASE* aNew,
const wxString& aGroup )
{
CLASS_DESC& classDesc = getClass( aNew->OwnerHash() );
classDesc.m_replaced.insert( std::make_pair( aBase, aName ) );
@@ -164,31 +160,30 @@ PROPERTY_BASE& PROPERTY_MANAGER::ReplaceProperty( size_t aBase, const wxString&
void PROPERTY_MANAGER::AddTypeCast( TYPE_CAST_BASE* aCast )
{
TYPE_ID derivedHash = aCast->DerivedHash();
TYPE_ID derivedHash = aCast->DerivedHash();
CLASS_DESC& classDesc = getClass( aCast->BaseHash() );
auto& typeCasts = classDesc.m_typeCasts;
wxASSERT_MSG( typeCasts.count( derivedHash ) == 0, "Such converter already exists" );
typeCasts.emplace( derivedHash, aCast );
wxASSERT_MSG( classDesc.m_typeCasts.count( derivedHash ) == 0, wxT( "Such converter already exists" ) );
classDesc.m_typeCasts.emplace( derivedHash, aCast );
}
void PROPERTY_MANAGER::InheritsAfter( TYPE_ID aDerived, TYPE_ID aBase )
{
wxASSERT_MSG( aDerived != aBase, "Class cannot inherit from itself" );
wxASSERT_MSG( aDerived != aBase, wxT( "Class cannot inherit from itself" ) );
CLASS_DESC& derived = getClass( aDerived );
CLASS_DESC& base = getClass( aBase );
derived.m_bases.push_back( base );
derived.m_bases.push_back( getClass( aBase ) );
m_dirty = true;
wxASSERT_MSG( derived.m_bases.size() == 1 || derived.m_typeCasts.count( aBase ) == 1,
"You need to add a TYPE_CAST for classes inheriting from multiple bases" );
wxT( "You need to add a TYPE_CAST for classes inheriting from multiple bases" ) );
}
void PROPERTY_MANAGER::Mask( TYPE_ID aDerived, TYPE_ID aBase, const wxString& aName )
{
wxASSERT_MSG( aDerived != aBase, "Class cannot mask from itself" );
wxASSERT_MSG( aDerived != aBase, wxT( "Class cannot mask from itself" ) );
CLASS_DESC& derived = getClass( aDerived );
derived.m_maskedBaseProperties.insert( std::make_pair( aBase, aName ) );
@@ -196,11 +191,10 @@ void PROPERTY_MANAGER::Mask( TYPE_ID aDerived, TYPE_ID aBase, const wxString& aN
}
void PROPERTY_MANAGER::OverrideAvailability( TYPE_ID aDerived, TYPE_ID aBase,
const wxString& aName,
void PROPERTY_MANAGER::OverrideAvailability( TYPE_ID aDerived, TYPE_ID aBase, const wxString& aName,
std::function<bool( INSPECTABLE* )> aFunc )
{
wxASSERT_MSG( aDerived != aBase, "Class cannot override from itself" );
wxASSERT_MSG( aDerived != aBase, wxT( "Class cannot override from itself" ) );
CLASS_DESC& derived = getClass( aDerived );
derived.m_availabilityOverrides[std::make_pair( aBase, aName )] = std::move( aFunc );
@@ -208,11 +202,10 @@ void PROPERTY_MANAGER::OverrideAvailability( TYPE_ID aDerived, TYPE_ID aBase,
}
void PROPERTY_MANAGER::OverrideWriteability( TYPE_ID aDerived, TYPE_ID aBase,
const wxString& aName,
void PROPERTY_MANAGER::OverrideWriteability( TYPE_ID aDerived, TYPE_ID aBase, const wxString& aName,
std::function<bool( INSPECTABLE* )> aFunc )
{
wxASSERT_MSG( aDerived != aBase, "Class cannot override from itself" );
wxASSERT_MSG( aDerived != aBase, wxT( "Class cannot override from itself" ) );
CLASS_DESC& derived = getClass( aDerived );
derived.m_writeabilityOverrides[std::make_pair( aBase, aName )] = std::move( aFunc );
@@ -220,16 +213,14 @@ void PROPERTY_MANAGER::OverrideWriteability( TYPE_ID aDerived, TYPE_ID aBase,
}
bool PROPERTY_MANAGER::IsAvailableFor( TYPE_ID aItemClass, PROPERTY_BASE* aProp,
INSPECTABLE* aItem )
bool PROPERTY_MANAGER::IsAvailableFor( TYPE_ID aItemClass, PROPERTY_BASE* aProp, INSPECTABLE* aItem )
{
if( !aProp->Available( aItem ) )
return false;
CLASS_DESC& derived = getClass( aItemClass );
auto it = derived.m_availabilityOverrides.find( std::make_pair( aProp->BaseHash(),
aProp->Name() ) );
auto it = derived.m_availabilityOverrides.find( std::make_pair( aProp->BaseHash(), aProp->Name() ) );
if( it != derived.m_availabilityOverrides.end() )
return it->second( aItem );
@@ -238,16 +229,14 @@ bool PROPERTY_MANAGER::IsAvailableFor( TYPE_ID aItemClass, PROPERTY_BASE* aProp,
}
bool PROPERTY_MANAGER::IsWriteableFor( TYPE_ID aItemClass, PROPERTY_BASE* aProp,
INSPECTABLE* aItem )
bool PROPERTY_MANAGER::IsWriteableFor( TYPE_ID aItemClass, PROPERTY_BASE* aProp, INSPECTABLE* aItem )
{
if( !aProp->Writeable( aItem ) )
return false;
CLASS_DESC& derived = getClass( aItemClass );
auto it = derived.m_writeabilityOverrides.find( std::make_pair( aProp->BaseHash(),
aProp->Name() ) );
auto it = derived.m_writeabilityOverrides.find( std::make_pair( aProp->BaseHash(), aProp->Name() ) );
if( it != derived.m_writeabilityOverrides.end() )
return it->second( aItem );
@@ -265,7 +254,7 @@ bool PROPERTY_MANAGER::IsOfType( TYPE_ID aDerived, TYPE_ID aBase ) const
wxCHECK( derived != m_classes.end(), false ); // missing class description
// traverse the hierarchy seeking for the base class
for( auto& base : derived->second.m_bases )
for( const std::reference_wrapper<CLASS_DESC>& base : derived->second.m_bases )
{
if( IsOfType( base.get().m_id, aBase ) )
return true;
@@ -297,8 +286,8 @@ PROPERTY_MANAGER::CLASS_DESC& PROPERTY_MANAGER::getClass( TYPE_ID aTypeId )
void PROPERTY_MANAGER::CLASS_DESC::rebuild()
{
PROPERTY_SET replaced;
PROPERTY_SET masked;
std::set<std::pair<size_t, wxString>> replaced;
std::set<std::pair<size_t, wxString>> masked;
m_allProperties.clear();
collectPropsRecur( m_allProperties, replaced, m_displayOrder, masked );
@@ -338,10 +327,10 @@ void PROPERTY_MANAGER::CLASS_DESC::rebuild()
}
void PROPERTY_MANAGER::CLASS_DESC::collectPropsRecur( PROPERTY_LIST& aResult,
PROPERTY_SET& aReplaced,
PROPERTY_DISPLAY_ORDER& aDisplayOrder,
PROPERTY_SET& aMasked ) const
void PROPERTY_MANAGER::CLASS_DESC::collectPropsRecur( std::vector<PROPERTY_BASE*>& aResult,
std::set<std::pair<size_t, wxString>>& aReplaced,
std::map<PROPERTY_BASE*, int>& aDisplayOrder,
std::set<std::pair<size_t, wxString>>& aMasked ) const
{
for( const std::pair<size_t, wxString>& replacedEntry : m_replaced )
aReplaced.emplace( replacedEntry );
@@ -371,8 +360,8 @@ void PROPERTY_MANAGER::CLASS_DESC::collectPropsRecur( PROPERTY_LIST& aResult,
for( PROPERTY_BASE* property : m_ownDisplayOrder )
{
PROPERTY_SET::key_type propertyKey = std::make_pair( property->OwnerHash(),
property->Name() );
std::set<std::pair<size_t, wxString>>::key_type propertyKey = std::make_pair( property->OwnerHash(),
property->Name() );
// Do not store replaced properties
if( aReplaced.count( propertyKey ) )
continue;
@@ -386,28 +375,8 @@ void PROPERTY_MANAGER::CLASS_DESC::collectPropsRecur( PROPERTY_LIST& aResult,
}
// Iterate backwards so that replaced properties appear before base properties
for( auto it = m_bases.rbegin(); it != m_bases.rend(); ++it )
it->get().collectPropsRecur( aResult, aReplaced, aDisplayOrder, aMasked );
}
std::vector<TYPE_ID> PROPERTY_MANAGER::GetMatchingClasses( PROPERTY_BASE* aProperty )
{
std::vector<TYPE_ID> ids;
/*
for( auto& cls : m_classes )
{
CLASS_INFO info;
for( auto prop : cls.second.m_allProperties )
info.properties.push_back(prop);
}
*/
return ids;
for( std::reference_wrapper<CLASS_DESC> base : std::ranges::reverse_view( m_bases ) )
base.get().collectPropsRecur( aResult, aReplaced, aDisplayOrder, aMasked );
}
@@ -458,7 +427,7 @@ void PROPERTY_MANAGER::PropertyChanged( INSPECTABLE* aObject, PROPERTY_BASE* aPr
PROPERTY_COMMIT_HANDLER::PROPERTY_COMMIT_HANDLER( COMMIT* aCommit )
{
wxCHECK2_MSG( PROPERTY_MANAGER::Instance().m_managedCommit == nullptr,
return, "Can't have more than one managed commit at a time!" );
return, wxT( "Can't have more than one managed commit at a time!" ) );
PROPERTY_MANAGER::Instance().m_managedCommit = aCommit;
}
@@ -467,7 +436,7 @@ PROPERTY_COMMIT_HANDLER::PROPERTY_COMMIT_HANDLER( COMMIT* aCommit )
PROPERTY_COMMIT_HANDLER::~PROPERTY_COMMIT_HANDLER()
{
wxASSERT_MSG( PROPERTY_MANAGER::Instance().m_managedCommit != nullptr,
"Something went wrong: m_managedCommit already null!" );
wxT( "Something went wrong: m_managedCommit already null!" ) );
PROPERTY_MANAGER::Instance().m_managedCommit = nullptr;
}
+11 -21
View File
@@ -65,12 +65,6 @@ REPORTER& WX_TEXT_CTRL_REPORTER::Report( const wxString& aText, SEVERITY aSeveri
}
bool WX_TEXT_CTRL_REPORTER::HasMessage() const
{
return !m_textCtrl->IsEmpty();
}
REPORTER& WX_STRING_REPORTER::Report( const wxString& aText, SEVERITY aSeverity )
{
REPORTER::Report( aText, aSeverity );
@@ -93,12 +87,6 @@ void WX_STRING_REPORTER::Clear()
}
bool WX_STRING_REPORTER::HasMessage() const
{
return !m_string.IsEmpty();
}
REPORTER& NULL_REPORTER::Report( const wxString& aText, SEVERITY aSeverity )
{
return REPORTER::Report( aText, aSeverity );
@@ -211,6 +199,17 @@ REPORTER& WXLOG_REPORTER::GetInstance()
}
REPORTER& REDIRECT_REPORTER::Report( const wxString& aText, SEVERITY aSeverity )
{
REPORTER::Report( aText, aSeverity );
if( m_redirectTarget )
m_redirectTarget->Report( aText, aSeverity );
return *this;
}
REPORTER& STATUSBAR_REPORTER::Report( const wxString& aText, SEVERITY aSeverity )
{
REPORTER::Report( aText, aSeverity );
@@ -220,12 +219,3 @@ REPORTER& STATUSBAR_REPORTER::Report( const wxString& aText, SEVERITY aSeverity
return *this;
}
bool STATUSBAR_REPORTER::HasMessage() const
{
if( m_statusBar )
return !m_statusBar->GetStatusText( m_position ).IsEmpty();
return false;
}
+12 -9
View File
@@ -182,35 +182,38 @@ void GRID_HELPER::SetAuxAxes( bool aEnable, const VECTOR2I& aOrigin )
VECTOR2I GRID_HELPER::AlignGrid( const VECTOR2I& aPoint ) const
{
return computeNearest( aPoint, GetGrid() );
return computeNearest( aPoint, GetGrid(), GetOrigin() );
}
VECTOR2I GRID_HELPER::AlignGrid( const VECTOR2I& aPoint, const VECTOR2D& aGrid ) const
VECTOR2I GRID_HELPER::AlignGrid( const VECTOR2I& aPoint, const VECTOR2D& aGrid,
const VECTOR2D& aOffset ) const
{
return computeNearest( aPoint, aGrid );
return computeNearest( aPoint, aGrid, aOffset );
}
VECTOR2I GRID_HELPER::computeNearest( const VECTOR2I& aPoint, const VECTOR2I& aGrid ) const
VECTOR2I GRID_HELPER::computeNearest( const VECTOR2I& aPoint, const VECTOR2I& aGrid,
const VECTOR2I& aOffset ) const
{
return VECTOR2I( KiROUND( static_cast<double>( aPoint.x ) / aGrid.x ) * aGrid.x,
KiROUND( static_cast<double>( aPoint.y ) / aGrid.y ) * aGrid.y );
return VECTOR2I( KiROUND( (double) ( aPoint.x - aOffset.x ) / aGrid.x ) * aGrid.x + aOffset.x,
KiROUND( (double) ( aPoint.y - aOffset.y ) / aGrid.y ) * aGrid.y + aOffset.y );
}
VECTOR2I GRID_HELPER::Align( const VECTOR2I& aPoint ) const
{
return Align( aPoint, GetGrid() );
return Align( aPoint, GetGrid(), GetOrigin() );
}
VECTOR2I GRID_HELPER::Align( const VECTOR2I& aPoint, const VECTOR2D& aGrid ) const
VECTOR2I GRID_HELPER::Align( const VECTOR2I& aPoint, const VECTOR2D& aGrid,
const VECTOR2D& aOffset ) const
{
if( !canUseGrid() )
return aPoint;
VECTOR2I nearest = AlignGrid( aPoint, aGrid );
VECTOR2I nearest = AlignGrid( aPoint, aGrid, aOffset );
if( !m_auxAxis )
return nearest;
+79 -56
View File
@@ -362,18 +362,26 @@ bool FIELD_VALIDATOR::Validate( wxWindow* aParent )
}
bool FIELD_VALIDATOR::DoValidate( const wxString& aValue, wxWindow* aParent )
wxString GetFieldValidationErrorMessage( int aFieldId, const wxString& aValue )
{
wxString msg;
FIELD_VALIDATOR validator( aFieldId );
wxString msg;
if( HasFlag( wxFILTER_EMPTY ) && aValue.empty() )
msg.Printf( _( "The value of the field cannot be empty." ) );
if( validator.HasFlag( wxFILTER_EMPTY ) && aValue.empty() )
{
switch( aFieldId )
{
case SHEETNAME_V: msg = _( "A sheet must have a name." ); break;
case SHEETFILENAME_V: msg = _( "A sheet must have a file specified." ); break;
default: msg = _( "The value of the field cannot be empty." ); break;
}
}
if( HasFlag( wxFILTER_EXCLUDE_CHAR_LIST ) && ContainsExcludedCharacters( aValue ) )
if( msg.empty() && validator.HasFlag( wxFILTER_EXCLUDE_CHAR_LIST ) )
{
wxArrayString badCharsFound;
for( const wxUniCharRef& excludeChar : GetCharExcludes() )
for( const wxUniCharRef& excludeChar : validator.GetCharExcludes() )
{
if( aValue.Find( excludeChar ) != wxNOT_FOUND )
{
@@ -390,68 +398,83 @@ bool FIELD_VALIDATOR::DoValidate( const wxString& aValue, wxWindow* aParent )
}
}
wxString badChars;
for( size_t i = 0; i < badCharsFound.GetCount(); i++ )
if( !badCharsFound.IsEmpty() )
{
if( !badChars.IsEmpty() )
wxString badChars;
for( size_t i = 0; i < badCharsFound.GetCount(); i++ )
{
if( badCharsFound.GetCount() == 2 )
if( !badChars.IsEmpty() )
{
badChars += _( " or " );
}
else
{
if( i < badCharsFound.GetCount() - 2 )
badChars += _( ", or " );
if( badCharsFound.GetCount() == 2 )
{
badChars += _( " or " );
}
else
badChars += wxT( ", " );
{
if( i < badCharsFound.GetCount() - 2 )
badChars += _( ", or " );
else
badChars += wxT( ", " );
}
}
badChars += badCharsFound.Item( i );
}
badChars += badCharsFound.Item( i );
switch( aFieldId )
{
case REFERENCE_FIELD:
msg.Printf( _( "The reference designator cannot contain %s character(s)." ), badChars );
break;
case VALUE_FIELD:
msg.Printf( _( "The value field cannot contain %s character(s)." ), badChars );
break;
case FOOTPRINT_FIELD:
msg.Printf( _( "The footprint field cannot contain %s character(s)." ), badChars );
break;
case DATASHEET_FIELD:
msg.Printf( _( "The datasheet field cannot contain %s character(s)." ), badChars );
break;
case SHEETNAME_V:
msg.Printf( _( "The sheet name cannot contain %s character(s)." ), badChars );
break;
case SHEETFILENAME_V:
msg.Printf( _( "The sheet filename cannot contain %s character(s)." ), badChars );
break;
default:
msg.Printf( _( "The field cannot contain %s character(s)." ), badChars );
break;
};
}
}
switch( m_fieldId )
if( msg.empty() )
{
if( aFieldId == REFERENCE_FIELD && aValue.Contains( wxT( "${" ) ) )
{
case REFERENCE_FIELD:
msg.Printf( _( "The reference designator cannot contain %s character(s)." ), badChars );
break;
case VALUE_FIELD:
msg.Printf( _( "The value field cannot contain %s character(s)." ), badChars );
break;
case FOOTPRINT_FIELD:
msg.Printf( _( "The footprint field cannot contain %s character(s)." ), badChars );
break;
case DATASHEET_FIELD:
msg.Printf( _( "The datasheet field cannot contain %s character(s)." ), badChars );
break;
case SHEETNAME_V:
msg.Printf( _( "The sheet name cannot contain %s character(s)." ), badChars );
break;
case SHEETFILENAME_V:
msg.Printf( _( "The sheet filename cannot contain %s character(s)." ), badChars );
break;
default:
msg.Printf( _( "The field cannot contain %s character(s)." ), badChars );
break;
};
}
else if( m_fieldId == REFERENCE_FIELD && aValue.Contains( wxT( "${" ) ) )
{
msg.Printf( _( "The reference designator cannot contain text variable references" ) );
}
else if( m_fieldId == REFERENCE_FIELD && UTIL::GetRefDesPrefix( aValue ).IsEmpty() )
{
msg.Printf( _( "References must start with a letter." ) );
msg.Printf( _( "The reference designator cannot contain text variable references" ) );
}
else if( aFieldId == REFERENCE_FIELD && UTIL::GetRefDesPrefix( aValue ).IsEmpty() )
{
msg.Printf( _( "References must start with a letter." ) );
}
}
return msg;
}
bool FIELD_VALIDATOR::DoValidate( const wxString& aValue, wxWindow* aParent )
{
wxString msg = GetFieldValidationErrorMessage( m_fieldId, aValue );
if( !msg.empty() )
{
if( m_validatorWindow )
+4 -2
View File
@@ -326,7 +326,9 @@ void COLOR_SWATCH::GetNewSwatchColor()
void COLOR_SWATCH::OnDarkModeToggle()
{
m_checkerboardBg = m_parent->GetBackgroundColour();
wxWindow* parent = GetParent();
m_checkerboardBg = parent ? parent->GetBackgroundColour() : wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW );
m_swatch->SetBitmap( makeBitmap() );
if( m_swatch )
m_swatch->SetBitmap( makeBitmap() );
}
+27 -7
View File
@@ -443,7 +443,8 @@ public:
TEXT_BUTTON_FILE_BROWSER( wxWindow* aParent, DIALOG_SHIM* aParentDlg, WX_GRID* aGrid,
wxString* aCurrentDir, const wxString& aFileFilter = wxEmptyString,
bool aNormalize = false,
const wxString& aNormalizeBasePath = wxEmptyString ) :
const wxString& aNormalizeBasePath = wxEmptyString,
std::function<wxString( const wxString& )> aEmbedCallback = nullptr ) :
wxComboCtrl( aParent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 0, 0 ),
wxTE_PROCESS_ENTER | wxBORDER_NONE ),
m_dlg( aParentDlg ),
@@ -451,7 +452,8 @@ public:
m_currentDir( aCurrentDir ),
m_normalize( aNormalize ),
m_normalizeBasePath( aNormalizeBasePath ),
m_fileFilter( aFileFilter )
m_fileFilter( aFileFilter ),
m_embedCallback( std::move( aEmbedCallback ) )
{
SetButtonBitmaps( KiBitmapBundle( BITMAPS::small_folder ) );
@@ -463,7 +465,8 @@ public:
wxString* aCurrentDir,
std::function<wxString( WX_GRID* grid, int row )> aFileFilterFn,
bool aNormalize = false,
const wxString& aNormalizeBasePath = wxEmptyString ) :
const wxString& aNormalizeBasePath = wxEmptyString,
std::function<wxString( const wxString& )> aEmbedCallback = nullptr ) :
wxComboCtrl( aParent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 0, 0 ),
wxTE_PROCESS_ENTER | wxBORDER_NONE ),
m_dlg( aParentDlg ),
@@ -471,7 +474,8 @@ public:
m_currentDir( aCurrentDir ),
m_normalize( aNormalize ),
m_normalizeBasePath( aNormalizeBasePath ),
m_fileFilterFn( std::move( aFileFilterFn ) )
m_fileFilterFn( std::move( aFileFilterFn ) ),
m_embedCallback( std::move( aEmbedCallback ) )
{
SetButtonBitmaps( KiBitmapBundle( BITMAPS::small_folder ) );
@@ -502,16 +506,30 @@ protected:
if( !m_fileFilter.IsEmpty() )
{
FILEDLG_OPEN_EMBED_FILE customize( false );
wxFileDialog dlg( m_dlg, _( "Select a File" ), fn.GetPath(), fn.GetFullName(),
m_fileFilter, wxFD_FILE_MUST_EXIST | wxFD_OPEN );
if( m_embedCallback )
dlg.SetCustomizeHook( customize );
if( dlg.ShowModal() == wxID_OK )
{
wxString filePath = dlg.GetPath();
wxString lastPath = dlg.GetDirectory();
wxString relPath = wxEmptyString;
if( m_normalize )
if( m_embedCallback && customize.GetEmbed() )
{
relPath = m_embedCallback( filePath );
if( relPath.IsEmpty() )
{
m_dlg->CleanupAfterModalSubDialog();
return;
}
}
else if( m_normalize )
{
relPath = NormalizePath( filePath, &Pgm().GetLocalEnvVariables(),
m_normalizeBasePath );
@@ -573,6 +591,7 @@ protected:
wxString m_fileFilter;
std::function<wxString( WX_GRID* aGrid, int aRow )> m_fileFilterFn;
std::function<wxString( const wxString& )> m_embedCallback;
};
@@ -583,12 +602,13 @@ void GRID_CELL_PATH_EDITOR::Create( wxWindow* aParent, wxWindowID aId,
{
m_control = new TEXT_BUTTON_FILE_BROWSER( aParent, m_dlg, m_grid, m_currentDir,
m_fileFilterFn, m_normalize,
m_normalizeBasePath );
m_normalizeBasePath, m_embedCallback );
}
else
{
m_control = new TEXT_BUTTON_FILE_BROWSER( aParent, m_dlg, m_grid, m_currentDir,
m_fileFilter, m_normalize, m_normalizeBasePath );
m_fileFilter, m_normalize, m_normalizeBasePath,
m_embedCallback );
}
WX_GRID::CellEditorSetMargins( Combo() );
+49 -33
View File
@@ -122,17 +122,14 @@ PROPERTIES_PANEL::PROPERTIES_PANEL( wxWindow* aParent, EDA_BASE_FRAME* aFrame )
m_grid->CenterSplitter();
Connect( wxEVT_CHAR_HOOK, wxKeyEventHandler( PROPERTIES_PANEL::onCharHook ), nullptr, this );
Connect( wxEVT_PG_CHANGED, wxPropertyGridEventHandler( PROPERTIES_PANEL::valueChanged ),
nullptr, this );
Connect( wxEVT_PG_CHANGING, wxPropertyGridEventHandler( PROPERTIES_PANEL::valueChanging ),
nullptr, this );
Connect( wxEVT_PG_CHANGED, wxPropertyGridEventHandler( PROPERTIES_PANEL::valueChanged ), nullptr, this );
Connect( wxEVT_PG_CHANGING, wxPropertyGridEventHandler( PROPERTIES_PANEL::valueChanging ), nullptr, this );
Connect( wxEVT_SHOW, wxShowEventHandler( PROPERTIES_PANEL::onShow ), nullptr, this );
Bind( wxEVT_PG_COL_END_DRAG,
[&]( wxPropertyGridEvent& )
{
m_splitter_key_proportion =
static_cast<float>( m_grid->GetSplitterPosition() ) / m_grid->GetSize().x;
m_splitter_key_proportion = static_cast<float>( m_grid->GetSplitterPosition() ) / m_grid->GetSize().x;
} );
Bind( wxEVT_SIZE,
@@ -225,33 +222,27 @@ void PROPERTIES_PANEL::rebuildProperties( const SELECTION& aSelection )
wxCHECK( !types.empty(), /* void */ ); // already guarded above, but Coverity doesn't know that
PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance();
std::set<PROPERTY_BASE*> commonProps;
const PROPERTY_LIST& allProperties = propMgr.GetProperties( *types.begin() );
PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance();
std::set<PROPERTY_BASE*> commonProps;
const std::vector<PROPERTY_BASE*>& allProperties = propMgr.GetProperties( *types.begin() );
copy( allProperties.begin(), allProperties.end(),
inserter( commonProps, commonProps.begin() ) );
copy( allProperties.begin(), allProperties.end(), inserter( commonProps, commonProps.begin() ) );
PROPERTY_DISPLAY_ORDER displayOrder = propMgr.GetDisplayOrder( *types.begin() );
std::vector<wxString> groupDisplayOrder = propMgr.GetGroupDisplayOrder( *types.begin() );
std::set<wxString> groups( groupDisplayOrder.begin(), groupDisplayOrder.end() );
std::map<PROPERTY_BASE*, int> displayOrder = propMgr.GetDisplayOrder( *types.begin() );
std::vector<wxString> groupDisplayOrder = propMgr.GetGroupDisplayOrder( *types.begin() );
std::set<wxString> groups( groupDisplayOrder.begin(), groupDisplayOrder.end() );
std::set<PROPERTY_BASE*> availableProps;
// Get all possible properties
for( const TYPE_ID& type : types )
{
const PROPERTY_LIST& itemProps = propMgr.GetProperties( type );
const std::vector<PROPERTY_BASE*>& itemProps = propMgr.GetProperties( type );
const std::map<PROPERTY_BASE*, int>& itemDisplayOrder = propMgr.GetDisplayOrder( type );
const PROPERTY_DISPLAY_ORDER& itemDisplayOrder = propMgr.GetDisplayOrder( type );
copy( itemDisplayOrder.begin(), itemDisplayOrder.end(), inserter( displayOrder, displayOrder.begin() ) );
copy( itemDisplayOrder.begin(), itemDisplayOrder.end(),
inserter( displayOrder, displayOrder.begin() ) );
const std::vector<wxString>& itemGroups = propMgr.GetGroupDisplayOrder( type );
for( const wxString& group : itemGroups )
for( const wxString& group : propMgr.GetGroupDisplayOrder( type ) )
{
if( !groups.count( group ) )
{
@@ -305,9 +296,10 @@ void PROPERTIES_PANEL::rebuildProperties( const SELECTION& aSelection )
if( !property )
continue;
wxVariant commonVal;
wxVariant commonVal;
wxPGChoices choices;
extractValueAndWritability( aSelection, property, commonVal, writeable );
extractValueAndWritability( aSelection, property, commonVal, writeable, choices );
pgProp->SetValue( commonVal );
pgProp->Enable( writeable );
@@ -326,13 +318,17 @@ void PROPERTIES_PANEL::rebuildProperties( const SELECTION& aSelection )
for( PROPERTY_BASE* property : availableProps )
{
wxPGProperty* pgProp = createPGProperty( property );
wxVariant commonVal;
wxVariant commonVal;
wxPGChoices choices;
if( !extractValueAndWritability( aSelection, property, commonVal, writeable ) )
if( !extractValueAndWritability( aSelection, property, commonVal, writeable, choices ) )
continue;
if( pgProp )
{
if( choices.GetCount() )
pgProp->SetChoices( choices );
pgProp->SetValue( commonVal );
pgProp->Enable( writeable );
m_displayed.push_back( property );
@@ -403,13 +399,12 @@ bool PROPERTIES_PANEL::getItemValue( EDA_ITEM* aItem, PROPERTY_BASE* aProperty,
}
bool PROPERTIES_PANEL::extractValueAndWritability( const SELECTION& aSelection,
PROPERTY_BASE* aProperty,
wxVariant& aValue, bool& aWritable )
bool PROPERTIES_PANEL::extractValueAndWritability( const SELECTION& aSelection, PROPERTY_BASE* aProperty,
wxVariant& aValue, bool& aWritable, wxPGChoices& aChoices )
{
PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance();
bool different = false;
wxVariant commonVal;
bool first = true;
aWritable = true;
@@ -421,6 +416,22 @@ bool PROPERTIES_PANEL::extractValueAndWritability( const SELECTION& aSelection,
if( aProperty->IsHiddenFromPropertiesManager() )
return false;
wxPGChoices choices = aProperty->GetChoices( item );
if( first )
{
aChoices = choices;
first = false;
}
else
{
wxArrayString labels = choices.GetLabels();
wxArrayInt values = choices.GetValuesForStrings( labels );
if( labels != aChoices.GetLabels() || values != aChoices.GetValuesForStrings( labels ) )
return false;
}
// If read-only for any of the selection, read-only for the whole selection.
if( !propMgr.IsWriteableFor( TYPE_HASH( *item ), aProperty, item ) )
aWritable = false;
@@ -494,10 +505,15 @@ void PROPERTIES_PANEL::onCharHook( wxKeyEvent& aEvent )
}
}
if( aEvent.GetKeyCode() == WXK_RETURN || aEvent.GetKeyCode() == WXK_NUMPAD_ENTER )
if( aEvent.GetKeyCode() == WXK_RETURN || aEvent.GetKeyCode() == WXK_NUMPAD_ENTER
|| aEvent.GetKeyCode() == WXK_DOWN || aEvent.GetKeyCode() == WXK_UP )
{
m_grid->CommitChangesFromEditor();
/* don't skip this one; if we're not the last property we'll also go to the next row */
CallAfter( [this]()
{
m_grid->SelectProperty( m_grid->GetSelectedProperty(), true );
} );
}
aEvent.Skip();
+1 -1
View File
@@ -102,7 +102,7 @@ protected:
* @return true if the property is available for all the items in the selection
*/
bool extractValueAndWritability( const SELECTION& aSelection, PROPERTY_BASE* aProperty,
wxVariant& aValue, bool& aWritable );
wxVariant& aValue, bool& aWritable, wxPGChoices& aChoices );
public:
int m_SuppressGridChangeEvents;
+5 -1
View File
@@ -230,7 +230,11 @@ void UNIT_BINDER::onComboBox( wxCommandEvent& aEvent )
const long long int conv =
EDA_UNIT_UTILS::UI::ValueFromString( *m_iuScale, m_units, value, m_dataType );
SetValue( conv );
CallAfter(
[this, conv]
{
SetValue( conv );
} );
aEvent.Skip();
}
+2 -2
View File
@@ -253,7 +253,7 @@ HANDLER_RESULT<ItemRequestStatus> API_HANDLER_SCH::handleCreateUpdateItemsIntern
if( aCreate )
{
item->Serialize( newItem );
commit->Add( item.release() );
commit->Add( item.release(), screen );
if( !m_activeClients.count( aClientName ) )
pushCurrentCommit( aClientName, _( "Added items via API" ) );
@@ -266,7 +266,7 @@ HANDLER_RESULT<ItemRequestStatus> API_HANDLER_SCH::handleCreateUpdateItemsIntern
{
schItem->SwapData( static_cast<SCH_ITEM*>( item.get() ) );
schItem->Serialize( newItem );
commit->Modify( schItem );
commit->Modify( schItem, screen );
}
else
{
+81 -60
View File
@@ -1141,21 +1141,22 @@ void CONNECTION_GRAPH::updateItemConnectivity( const SCH_SHEET_PATH& aSheet,
aSheet.Last()->GetFileName(), aItemList.size() );
std::map<VECTOR2I, std::vector<SCH_ITEM*>> connection_map;
auto updatePin = [&]( SCH_PIN* aPin, SCH_CONNECTION* aConn )
{
aConn->SetType( CONNECTION_TYPE::NET );
auto updatePin =
[&]( SCH_PIN* aPin, SCH_CONNECTION* aConn )
{
aConn->SetType( CONNECTION_TYPE::NET );
// because calling the first time is not thread-safe
wxString name = aPin->GetDefaultNetName( aSheet );
aPin->ClearConnectedItems( aSheet );
// because calling the first time is not thread-safe
wxString name = aPin->GetDefaultNetName( aSheet );
aPin->ClearConnectedItems( aSheet );
// power symbol pins need to be post-processed later
if( aPin->IsGlobalPower() )
{
aConn->SetName( name );
m_global_power_pins.emplace_back( std::make_pair( aSheet, aPin ) );
}
};
// power symbol pins need to be post-processed later
if( aPin->IsGlobalPower() )
{
aConn->SetName( name );
m_global_power_pins.emplace_back( std::make_pair( aSheet, aPin ) );
}
};
for( SCH_ITEM* item : aItemList )
{
@@ -1227,17 +1228,41 @@ void CONNECTION_GRAPH::updateItemConnectivity( const SCH_SHEET_PATH& aSheet,
for( const VECTOR2I& point : points )
connection_map[ point ].push_back( item );
/// Special case for labels that overlap wires
/// While this is an ERC error as there is not an explicit junction,
/// we want to enforce connectivity for all items under the label position.
if( dynamic_cast<SCH_LABEL_BASE*>( item ) )
{
VECTOR2I point = item->GetPosition();
SCH_SCREEN* screen = aSheet.LastScreen();
auto items = screen->Items().Overlapping( point );
std::vector<SCH_ITEM*> overlapping_items;
std::copy_if( items.begin(), items.end(), std::back_inserter( overlapping_items ),
[&]( SCH_ITEM* test_item )
{
return test_item->Type() == SCH_LINE_T
&& test_item->HitTest( point, -1 );
} );
// We need at least two connnectable lines that are not the label here
// Otherwise, the label will be normally assigned to one or the other
if( overlapping_items.size() < 2 ) continue;
for( SCH_ITEM* test_item : overlapping_items )
connection_map[point].push_back( test_item );
}
}
}
for( const auto& it : connection_map )
for( auto& [point, connection_vec] : connection_map )
{
std::vector<SCH_ITEM*> connection_vec = it.second;
std::sort( connection_vec.begin(), connection_vec.end() );
alg::remove_duplicates( connection_vec );
// Pre-scan to see if we have a bus at this location
SCH_LINE* busLine = aSheet.LastScreen()->GetBus( it.first );
SCH_LINE* busLine = aSheet.LastScreen()->GetBus( point );
std::mutex update_mutex;
@@ -1264,7 +1289,6 @@ void CONNECTION_GRAPH::updateItemConnectivity( const SCH_SHEET_PATH& aSheet,
}
}
}
// Bus-to-bus entries are treated just like bus wires
else if( connected_item->Type() == SCH_BUS_BUS_ENTRY_T )
{
@@ -1274,7 +1298,7 @@ void CONNECTION_GRAPH::updateItemConnectivity( const SCH_SHEET_PATH& aSheet,
{
auto bus_entry = static_cast<SCH_BUS_BUS_ENTRY*>( connected_item );
if( it.first == bus_entry->GetPosition() )
if( point == bus_entry->GetPosition() )
bus_entry->m_connected_bus_items[0] = busLine;
else
bus_entry->m_connected_bus_items[1] = busLine;
@@ -1285,7 +1309,6 @@ void CONNECTION_GRAPH::updateItemConnectivity( const SCH_SHEET_PATH& aSheet,
}
}
}
// Change junctions to be on bus junction layer if they are touching a bus
else if( connected_item->Type() == SCH_JUNCTION_T )
{
@@ -1321,9 +1344,9 @@ void CONNECTION_GRAPH::updateItemConnectivity( const SCH_SHEET_PATH& aSheet,
bus_connection_ok = !busLine || connected_item->GetLayer() == LAYER_BUS;
}
if( connected_item->ConnectionPropagatesTo( test_item ) &&
test_item->ConnectionPropagatesTo( connected_item ) &&
bus_connection_ok )
if( connected_item->ConnectionPropagatesTo( test_item )
&& test_item->ConnectionPropagatesTo( connected_item )
&& bus_connection_ok )
{
connected_item->AddConnectionTo( aSheet, test_item );
}
@@ -1339,7 +1362,7 @@ void CONNECTION_GRAPH::updateItemConnectivity( const SCH_SHEET_PATH& aSheet,
if( !bus_entry->m_connected_bus_item )
{
SCH_SCREEN* screen = aSheet.LastScreen();
SCH_LINE* bus = screen->GetBus( it.first );
SCH_LINE* bus = screen->GetBus( point );
if( bus )
bus_entry->m_connected_bus_item = bus;
@@ -1378,11 +1401,8 @@ void CONNECTION_GRAPH::buildItemSubGraphs()
// Build subgraphs from items (on a per-sheet basis)
for( SCH_ITEM* item : m_items )
{
for( const auto& it : item->m_connection_map )
for( const auto& [sheet, connection] : item->m_connection_map )
{
const SCH_SHEET_PATH& sheet = it.first;
SCH_CONNECTION* connection = it.second;
if( connection->SubgraphCode() == 0 )
{
CONNECTION_SUBGRAPH* subgraph = new CONNECTION_SUBGRAPH( this );
@@ -1448,7 +1468,6 @@ void CONNECTION_GRAPH::buildItemSubGraphs()
}
}
}
}
@@ -1467,44 +1486,45 @@ void CONNECTION_GRAPH::resolveAllDrivers()
std::vector<std::future<size_t>> returns( dirty_graphs.size() );
auto update_lambda = []( CONNECTION_SUBGRAPH* subgraph ) -> size_t
{
if( !subgraph->m_dirty )
return 0;
// Special processing for some items
for( SCH_ITEM* item : subgraph->m_items )
{
switch( item->Type() )
auto update_lambda =
[]( CONNECTION_SUBGRAPH* subgraph ) -> size_t
{
case SCH_NO_CONNECT_T:
subgraph->m_no_connect = item;
break;
if( !subgraph->m_dirty )
return 0;
case SCH_BUS_WIRE_ENTRY_T:
subgraph->m_bus_entry = item;
break;
// Special processing for some items
for( SCH_ITEM* item : subgraph->m_items )
{
switch( item->Type() )
{
case SCH_NO_CONNECT_T:
subgraph->m_no_connect = item;
break;
case SCH_PIN_T:
{
auto pin = static_cast<SCH_PIN*>( item );
case SCH_BUS_WIRE_ENTRY_T:
subgraph->m_bus_entry = item;
break;
if( pin->GetType() == ELECTRICAL_PINTYPE::PT_NC )
subgraph->m_no_connect = item;
case SCH_PIN_T:
{
auto pin = static_cast<SCH_PIN*>( item );
break;
}
if( pin->GetType() == ELECTRICAL_PINTYPE::PT_NC )
subgraph->m_no_connect = item;
default:
break;
}
}
break;
}
subgraph->ResolveDrivers( true );
subgraph->m_dirty = false;
default:
break;
}
}
return 1;
};
subgraph->ResolveDrivers( true );
subgraph->m_dirty = false;
return 1;
};
thread_pool& tp = GetKiCadThreadPool();
@@ -2304,8 +2324,9 @@ void CONNECTION_GRAPH::buildConnectionGraph( std::function<void( SCH_ITEM* )>* a
[&]( CONNECTION_SUBGRAPH* subgraph ) -> size_t
{
// Make sure weakly-driven single-pin nets get the unconnected_ prefix
if( !subgraph->m_strong_driver && subgraph->m_drivers.size() == 1 &&
subgraph->m_driver->Type() == SCH_PIN_T )
if( !subgraph->m_strong_driver
&& subgraph->m_drivers.size() == 1
&& subgraph->m_driver->Type() == SCH_PIN_T )
{
SCH_PIN* pin = static_cast<SCH_PIN*>( subgraph->m_driver );
wxString name = pin->GetDefaultNetName( subgraph->m_sheet, true );
+14 -2
View File
@@ -590,7 +590,16 @@ int DIALOG_CHANGE_SYMBOLS::processSymbols( SCH_COMMIT* aCommit,
{
SCH_SYMBOL* symbol = it->first;
wxCHECK2( symbol && it->second.m_LibId.IsValid(), continue );
wxCHECK2( symbol, ++it; continue );
if( !it->second.m_LibId.IsValid() )
{
msg = getSymbolReferences( *symbol, it->second.m_LibId );
msg << wxT( ": " ) << _( "*** symbol lib id not valid ***" );
m_messagePanel->Report( msg, RPT_SEVERITY_ERROR );
it = symbols.erase( it );
continue;
}
LIB_SYMBOL* libSymbol = frame->GetLibSymbol( it->second.m_LibId );
@@ -647,10 +656,13 @@ int DIALOG_CHANGE_SYMBOLS::processSymbols( SCH_COMMIT* aCommit,
// Remember initial link before changing for diags purpose
wxString initialLibLinkName = UnescapeString( symbol->GetLibId().Format() );
LIB_SYMBOL* libSymbol = frame->GetLibSymbol( symbol_change_info.m_LibId );
wxCHECK2( libSymbol, continue );
if( symbol_change_info.m_LibId != symbol->GetLibId() )
symbol->SetLibId( symbol_change_info.m_LibId );
LIB_SYMBOL* libSymbol = frame->GetLibSymbol( symbol_change_info.m_LibId );
std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
SCH_SCREEN* screen = symbol_change_info.m_Instances[0].LastScreen();
+1
View File
@@ -325,6 +325,7 @@ void DIALOG_ERC::OnDeleteAllClick( wxCommandEvent& event )
}
deleteAllMarkers( includeExclusions );
m_ercRun = false;
// redraw the schematic
redrawDrawPanel();
+5 -5
View File
@@ -232,16 +232,16 @@ DIALOG_EXPORT_NETLIST::DIALOG_EXPORT_NETLIST( SCH_EDIT_FRAME* aEditFrame, wxWind
page->m_LeftBoxSizer->Add( label, 0, wxBOTTOM, 10 );
m_PanelNetType[PANELALLEGRO] = page;
page = new EXPORT_NETLIST_PAGE( m_NoteBook, wxT( "PADS" ), NET_TYPE_PADS, false );
label = new wxStaticText( page, wxID_ANY, _( "Export netlist in PADS format" ) );
page->m_LeftBoxSizer->Add( label, 0, wxBOTTOM, 10 );
m_PanelNetType[PANELPADS] = page;
page = new EXPORT_NETLIST_PAGE( m_NoteBook, wxT( "CadStar" ), NET_TYPE_CADSTAR, false );
label = new wxStaticText( page, wxID_ANY, _( "Export netlist in CadStar format" ) );
page->m_LeftBoxSizer->Add( label, 0, wxBOTTOM, 10 );
m_PanelNetType[PANELCADSTAR] = page;
page = new EXPORT_NETLIST_PAGE( m_NoteBook, wxT( "PADS" ), NET_TYPE_PADS, false );
label = new wxStaticText( page, wxID_ANY, _( "Export netlist in PADS format" ) );
page->m_LeftBoxSizer->Add( label, 0, wxBOTTOM, 10 );
m_PanelNetType[PANELPADS] = page;
InstallPageSpice();
InstallPageSpiceModel();
+1 -6
View File
@@ -463,12 +463,7 @@ bool DIALOG_FIELD_PROPERTIES::TransferDataToWindow()
const SCH_SYMBOL* symbol = static_cast<const SCH_SYMBOL*>( m_field->GetParentSymbol() );
for( int ii = 1; ii <= symbol->GetUnitCount(); ii++ )
{
if( symbol->HasUnitDisplayName( ii ) )
m_unitChoice->Append( symbol->GetUnitDisplayName( ii ) );
else
m_unitChoice->Append( symbol->SubReference( ii, false ) );
}
m_unitChoice->Append( symbol->GetUnitDisplayName( ii, false ) );
if( symbol->GetUnit() <= ( int )m_unitChoice->GetCount() )
m_unitChoice->SetSelection( symbol->GetUnit() - 1 );
@@ -827,7 +827,7 @@ DIALOG_LIB_EDIT_PIN_TABLE::DIALOG_LIB_EDIT_PIN_TABLE( SYMBOL_EDIT_FRAME* parent,
m_unitFilter->Append( UNITS_ALL );
for( int ii = 0; ii < aSymbol->GetUnitCount(); ++ii )
m_unitFilter->Append( aSymbol->GetUnitReference( ii + 1 ) );
m_unitFilter->Append( LIB_SYMBOL::LetterSubReference( ii + 1, 'A' ) );
m_unitFilter->SetSelection( -1 );
}
+106 -20
View File
@@ -84,6 +84,7 @@ DIALOG_LIB_SYMBOL_PROPERTIES::DIALOG_LIB_SYMBOL_PROPERTIES( SYMBOL_EDIT_FRAME* a
} ) );
m_grid->SetSelectionMode( wxGrid::wxGridSelectRows );
// Show/hide columns according to the user's preference
SYMBOL_EDITOR_SETTINGS* cfg = m_Parent->GetSettings();
m_grid->ShowHideColumns( cfg->m_EditSymbolVisibleColumns );
@@ -110,8 +111,11 @@ DIALOG_LIB_SYMBOL_PROPERTIES::DIALOG_LIB_SYMBOL_PROPERTIES( SYMBOL_EDIT_FRAME* a
// wxFormBuilder doesn't include this event...
m_grid->Connect( wxEVT_GRID_CELL_CHANGING,
wxGridEventHandler( DIALOG_LIB_SYMBOL_PROPERTIES::OnGridCellChanging ),
nullptr, this );
wxGridEventHandler( DIALOG_LIB_SYMBOL_PROPERTIES::OnGridCellChanging ), nullptr, this );
m_grid->Connect( wxEVT_GRID_CELL_CHANGED,
wxGridEventHandler( DIALOG_LIB_SYMBOL_PROPERTIES::OnGridCellChanged ), nullptr, this );
m_grid->GetGridWindow()->Bind( wxEVT_MOTION, &DIALOG_LIB_SYMBOL_PROPERTIES::OnGridMotion, this );
// Forward the delete button to the tricks
m_deleteFilterButton->Bind( wxEVT_BUTTON,
@@ -161,8 +165,10 @@ DIALOG_LIB_SYMBOL_PROPERTIES::~DIALOG_LIB_SYMBOL_PROPERTIES()
m_grid->DestroyTable( m_fields );
m_grid->Disconnect( wxEVT_GRID_CELL_CHANGING,
wxGridEventHandler( DIALOG_LIB_SYMBOL_PROPERTIES::OnGridCellChanging ),
nullptr, this );
wxGridEventHandler( DIALOG_LIB_SYMBOL_PROPERTIES::OnGridCellChanging ), nullptr, this );
m_grid->Disconnect( wxEVT_GRID_CELL_CHANGED,
wxGridEventHandler( DIALOG_LIB_SYMBOL_PROPERTIES::OnGridCellChanged ), nullptr, this );
m_grid->GetGridWindow()->Unbind( wxEVT_MOTION, &DIALOG_LIB_SYMBOL_PROPERTIES::OnGridMotion, this );
// Delete the GRID_TRICKS.
m_grid->PopEventHandler( true );
@@ -174,9 +180,58 @@ bool DIALOG_LIB_SYMBOL_PROPERTIES::TransferDataToWindow()
if( !wxDialog::TransferDataToWindow() )
return false;
// Push a copy of each field into m_updateFields
// Ensure the fields vector is empty before (re)loading. Constructor no longer
// pre-populates fields to avoid double insertion of mandatory fields.
if( m_fields->size() > 0 )
{
// Clear existing entries; we recreate inheritance metadata via push_back()
// Note: We cannot simply reuse existing entries because alias inheritance
// state may have changed if the parent was edited prior to dialog open.
m_fields->clear();
}
// Load current symbol fields (mandatory first, then user fields)
m_libEntry->CopyFields( *m_fields );
// Handle alias (derived) symbol inherited fields. We only inherit non-mandatory fields
// and mark any matching names as inherited rather than duplicating them.
if( m_libEntry->IsAlias() )
{
if( LIB_SYMBOL_SPTR parent = m_libEntry->GetParent().lock() )
{
std::vector<SCH_FIELD*> parentFields;
parent->GetFields( parentFields );
for( SCH_FIELD* pf : parentFields )
{
if( pf->IsMandatory() )
continue; // Never inherit mandatory fields
bool found = false;
for( size_t jj = 0; jj < m_fields->size(); ++jj )
{
SCH_FIELD& f = m_fields->at( jj );
if( f.IsMandatory() )
continue; // Skip mandatory in child list for inheritance match
if( f.GetCanonicalName() == pf->GetCanonicalName() )
{
m_fields->SetFieldInherited( jj, *pf );
found = true;
break;
}
}
if( !found )
m_fields->AddInheritedField( *pf );
}
}
}
// Fields already loaded above; avoid re-copying to prevent duplication.
std::set<wxString> defined;
for( SCH_FIELD& field : *m_fields )
@@ -416,37 +471,40 @@ bool DIALOG_LIB_SYMBOL_PROPERTIES::TransferDataFromWindow()
m_Parent->SaveCopyInUndoList( _( "Edit Symbol Properties" ), m_libEntry );
}
// The Y axis for components in lib is from bottom to top while the screen axis is top
// to bottom: we must change the y coord sign when writing back to the library
for( int ii = 0; ii < (int) m_fields->size(); ++ii )
{
VECTOR2I pos = m_fields->at( ii ).GetPosition();
pos.y = -pos.y;
m_fields->at( ii ).SetPosition( pos );
m_fields->at( ii ).SetId( ii );
}
std::vector<SCH_FIELD> fieldsToSave;
for( int ii = m_fields->GetNumberRows() - 1; ii >= 0; ii-- )
{
SCH_FIELD& field = m_fields->at( ii );
if( field.IsMandatory() )
continue;
// The Y axis for components in lib is from bottom to top while the screen axis is top
// to bottom: we must change the y coord sign when writing back to the library
VECTOR2I pos = field.GetPosition();
pos.y = -pos.y;
field.SetPosition( pos );
const wxString& fieldName = field.GetCanonicalName();
// if( !field.IsMandatory() )
field.SetId( ii );
wxString fieldName = field.GetCanonicalName();
if( m_fields->IsInherited( ii ) && field == m_fields->ParentField( ii ) )
continue; // Skip inherited fields
if( field.GetText().IsEmpty() )
{
if( fieldName.IsEmpty() || m_addedTemplateFields.contains( fieldName ) )
m_fields->erase( m_fields->begin() + ii );
continue; // Skip empty fields that are not mandatory or template fields
}
else if( fieldName.IsEmpty() )
{
field.SetName( _( "untitled" ) );
field.SetName( _( "untitled" ) ); // Set a default name for unnamed fields
}
fieldsToSave.push_back( field );
}
m_libEntry->SetFields( *m_fields );
m_libEntry->SetFields( fieldsToSave );
// Update the parent for inherited symbols
if( m_libEntry->IsAlias() )
@@ -517,6 +575,27 @@ bool DIALOG_LIB_SYMBOL_PROPERTIES::TransferDataFromWindow()
}
void DIALOG_LIB_SYMBOL_PROPERTIES::OnGridMotion( wxMouseEvent& aEvent )
{
aEvent.Skip();
wxPoint pos = aEvent.GetPosition();
wxPoint unscolled_pos = m_grid->CalcUnscrolledPosition( pos );
int row = m_grid->YToRow( unscolled_pos.y );
int col = m_grid->XToCol( unscolled_pos.x );
if( row == wxNOT_FOUND || col == wxNOT_FOUND || !m_fields->IsInherited( row ) )
{
m_grid->SetToolTip( "" );
return;
}
m_grid->SetToolTip(
wxString::Format( _( "This field is inherited from '%s'." ),
m_fields->ParentField( row ).GetName() ) );
}
void DIALOG_LIB_SYMBOL_PROPERTIES::OnGridCellChanging( wxGridEvent& event )
{
wxGridCellEditor* editor = m_grid->GetCellEditor( event.GetRow(), event.GetCol() );
@@ -555,6 +634,13 @@ void DIALOG_LIB_SYMBOL_PROPERTIES::OnGridCellChanging( wxGridEvent& event )
}
void DIALOG_LIB_SYMBOL_PROPERTIES::OnGridCellChanged( wxGridEvent& event )
{
m_grid->ForceRefresh();
OnModify();
}
void DIALOG_LIB_SYMBOL_PROPERTIES::OnSymbolNameText( wxCommandEvent& event )
{
if( m_OptionPower->IsChecked() )
@@ -68,6 +68,8 @@ private:
void OnEditFootprintFilter( wxCommandEvent& event ) override;
void OnSizeGrid( wxSizeEvent& event ) override;
void OnGridCellChanging( wxGridEvent& event );
void OnGridCellChanged( wxGridEvent& event );
void OnGridMotion( wxMouseEvent& event );
void OnEditSpiceModel( wxCommandEvent& event ) override;
void OnUpdateUI( wxUpdateUIEvent& event ) override;
void OnCancelButtonClick( wxCommandEvent& event ) override;
+2
View File
@@ -1003,6 +1003,7 @@ void DIALOG_SIM_COMMAND::OnFilterText( wxCommandEvent& aEvent )
void DIALOG_SIM_COMMAND::OnFilterMouseMoved( wxMouseEvent& aEvent )
{
#if defined( __WXOSX__ ) || wxCHECK_VERSION( 3, 3, 0 ) // Doesn't work properly on other ports
wxPoint pos = aEvent.GetPosition();
wxRect ctrlRect = m_inputSignalsFilter->GetScreenRect();
int buttonWidth = ctrlRect.GetHeight(); // Presume buttons are square
@@ -1014,6 +1015,7 @@ void DIALOG_SIM_COMMAND::OnFilterMouseMoved( wxMouseEvent& aEvent )
SetCursor( wxCURSOR_ARROW );
else
SetCursor( wxCURSOR_IBEAM );
#endif
}
+2 -1
View File
@@ -88,7 +88,8 @@ DIALOG_SIM_MODEL<T>::DIALOG_SIM_MODEL( wxWindow* aParent, EDA_BASE_FRAME* aFrame
m_filesStack.push_back( symbol->Schematic()->GetEmbeddedFiles() );
}
m_filesStack.push_back( aSymbol.GetEmbeddedFiles() );
if( EMBEDDED_FILES* symbolEmbeddedFiles = aSymbol.GetEmbeddedFiles() )
m_filesStack.push_back( symbolEmbeddedFiles );
m_libraryModelsMgr.SetFilesStack( m_filesStack );
m_builtinModelsMgr.SetFilesStack( m_filesStack );
@@ -878,6 +878,7 @@ void DIALOG_SYMBOL_FIELDS_TABLE::OnFilterText( wxCommandEvent& aEvent )
void DIALOG_SYMBOL_FIELDS_TABLE::OnFilterMouseMoved( wxMouseEvent& aEvent )
{
#if defined( __WXOSX__ ) || wxCHECK_VERSION( 3, 3, 0 ) // Doesn't work properly on other ports
wxPoint pos = aEvent.GetPosition();
wxRect ctrlRect = m_filter->GetScreenRect();
int buttonWidth = ctrlRect.GetHeight(); // Presume buttons are square
@@ -889,6 +890,7 @@ void DIALOG_SYMBOL_FIELDS_TABLE::OnFilterMouseMoved( wxMouseEvent& aEvent )
SetCursor( wxCURSOR_ARROW );
else
SetCursor( wxCURSOR_IBEAM );
#endif
}
@@ -484,12 +484,7 @@ bool DIALOG_SYMBOL_PROPERTIES::TransferDataToWindow()
m_symbol->SetUnit( m_symbol->GetUnitSelection( &GetParent()->GetCurrentSheet() ) );
for( int ii = 1; ii <= m_symbol->GetUnitCount(); ii++ )
{
if( m_symbol->HasUnitDisplayName( ii ) )
m_unitChoice->Append( m_symbol->GetUnitDisplayName( ii ) );
else
m_unitChoice->Append( m_symbol->SubReference( ii, false ) );
}
m_unitChoice->Append( m_symbol->GetUnitDisplayName( ii, false ) );
if( m_symbol->GetUnit() <= ( int )m_unitChoice->GetCount() )
m_unitChoice->SetSelection( m_symbol->GetUnit() - 1 );
@@ -131,7 +131,7 @@ void DIALOG_UPDATE_SYMBOL_FIELDS::onOkButtonClicked( wxCommandEvent& aEvent )
wxBusyCursor dummy;
SCH_COMMIT commit( m_editFrame );
commit.Modify( m_symbol );
commit.Modify( m_symbol, m_editFrame->GetScreen() );
// Create the set of fields to be updated
m_updateFields.clear();
+31 -39
View File
@@ -112,28 +112,28 @@ const wxString CommentERC_V[] =
// i.e. pin type = ELECTRICAL_PINTYPE::PT_INPUT, but not PT_POWER_IN
// that need only a PT_POWER_OUT pin type to be driven
const std::set<ELECTRICAL_PINTYPE> DrivingPinTypes =
{
ELECTRICAL_PINTYPE::PT_OUTPUT,
ELECTRICAL_PINTYPE::PT_POWER_OUT,
ELECTRICAL_PINTYPE::PT_PASSIVE,
ELECTRICAL_PINTYPE::PT_TRISTATE,
ELECTRICAL_PINTYPE::PT_BIDI
};
{
ELECTRICAL_PINTYPE::PT_OUTPUT,
ELECTRICAL_PINTYPE::PT_POWER_OUT,
ELECTRICAL_PINTYPE::PT_PASSIVE,
ELECTRICAL_PINTYPE::PT_TRISTATE,
ELECTRICAL_PINTYPE::PT_BIDI
};
// List of pin types that are considered drivers for power pins
// In fact only a ELECTRICAL_PINTYPE::PT_POWER_OUT pin type can drive
// power input pins
const std::set<ELECTRICAL_PINTYPE> DrivingPowerPinTypes =
{
ELECTRICAL_PINTYPE::PT_POWER_OUT
};
{
ELECTRICAL_PINTYPE::PT_POWER_OUT
};
// List of pin types that require a driver elsewhere on the net
const std::set<ELECTRICAL_PINTYPE> DrivenPinTypes =
{
ELECTRICAL_PINTYPE::PT_INPUT,
ELECTRICAL_PINTYPE::PT_POWER_IN
};
{
ELECTRICAL_PINTYPE::PT_INPUT,
ELECTRICAL_PINTYPE::PT_POWER_IN
};
extern void CheckDuplicatePins( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
UNITS_PROVIDER* aUnitsProvider );
@@ -574,11 +574,11 @@ int ERC_TESTER::TestMissingUnits()
{
if( ii++ == 3 )
{
missing_pin_units += wxS( "....." );
missing_pin_units += wxS( "..." );
break;
}
missing_pin_units += libSymbol->GetUnitDisplayName( missing_unit ) + ", " ;
missing_pin_units += libSymbol->GetUnitDisplayName( missing_unit, false ) + ", " ;
}
missing_pin_units.Truncate( missing_pin_units.length() - 2 );
@@ -692,8 +692,7 @@ int ERC_TESTER::TestMissingNetclasses()
std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_UNDEFINED_NETCLASS );
ercItem->SetItems( item );
ercItem->SetErrorMessage( wxString::Format( _( "Netclass %s is not defined" ),
netclass ) );
ercItem->SetErrorMessage( wxString::Format( _( "Netclass %s is not defined" ), netclass ) );
SCH_MARKER* marker = new SCH_MARKER( ercItem, item->GetPosition() );
sheet.LastScreen()->Append( marker );
@@ -886,7 +885,7 @@ int ERC_TESTER::TestNoConnectPins()
for( SCH_PIN* pin : symbol->GetPins( &sheet ) )
{
if( pin->GetLibPin()->GetType() == ELECTRICAL_PINTYPE::PT_NC )
if( pin->GetType() == ELECTRICAL_PINTYPE::PT_NC )
pinMap[pin->GetPosition()].emplace_back( pin );
}
}
@@ -899,7 +898,7 @@ int ERC_TESTER::TestNoConnectPins()
for( SCH_PIN* pin : symbol->GetPins( &sheet ) )
{
if( pin->GetLibPin()->GetType() != ELECTRICAL_PINTYPE::PT_NC )
if( pin->GetType() != ELECTRICAL_PINTYPE::PT_NC )
addOther( pin->GetPosition(), pin );
}
}
@@ -1042,16 +1041,12 @@ int ERC_TESTER::TestPinToPin()
if( erc != PIN_ERROR::OK && m_settings.IsTestEnabled( ERCE_PIN_TO_PIN_WARNING ) )
{
pin_mismatches.emplace_back(
std::tuple<iterator_t, iterator_t, PIN_ERROR>{ refIt, testIt, erc } );
pin_mismatches.emplace_back( std::tuple<iterator_t, iterator_t, PIN_ERROR>{ refIt, testIt, erc } );
if( m_settings.GetERCSortingMetric() == ERC_PIN_SORTING_METRIC::SM_HEURISTICS )
{
pin_mismatch_counts[refIt] =
m_settings.GetPinTypeWeight( ( *refIt ).Pin()->GetType() );
pin_mismatch_counts[testIt] =
m_settings.GetPinTypeWeight( ( *testIt ).Pin()->GetType() );
pin_mismatch_counts[refIt] = m_settings.GetPinTypeWeight( ( *refIt ).Pin()->GetType() );
pin_mismatch_counts[testIt] = m_settings.GetPinTypeWeight( ( *testIt ).Pin()->GetType() );
}
else
{
@@ -1132,17 +1127,15 @@ int ERC_TESTER::TestPinToPin()
{
SCH_PIN* other_pin = ( *nearest_pin ).Pin();
std::shared_ptr<ERC_ITEM> ercItem =
ERC_ITEM::Create( erc == PIN_ERROR::WARNING ? ERCE_PIN_TO_PIN_WARNING
: ERCE_PIN_TO_PIN_ERROR );
auto ercItem = ERC_ITEM::Create( erc == PIN_ERROR::WARNING ? ERCE_PIN_TO_PIN_WARNING
: ERCE_PIN_TO_PIN_ERROR );
ercItem->SetItems( pin, other_pin );
ercItem->SetSheetSpecificPath( ( *pinIt ).Sheet() );
ercItem->SetItemsSheetPaths( ( *pinIt ).Sheet(), ( *nearest_pin ).Sheet() );
ercItem->SetErrorMessage(
wxString::Format( _( "Pins of type %s and %s are connected" ),
ElectricalPinTypeGetText( pin->GetType() ),
ElectricalPinTypeGetText( other_pin->GetType() ) ) );
ercItem->SetErrorMessage( wxString::Format( _( "Pins of type %s and %s are connected" ),
ElectricalPinTypeGetText( pin->GetType() ),
ElectricalPinTypeGetText( other_pin->GetType() ) ) );
SCH_MARKER* marker = new SCH_MARKER( ercItem, pin->GetPosition() );
pinToScreenMap[pin]->Append( marker );
@@ -1162,7 +1155,7 @@ int ERC_TESTER::TestPinToPin()
ercItem->SetSheetSpecificPath( needsDriver.Sheet() );
ercItem->SetItemsSheetPaths( needsDriver.Sheet() );
SCH_MARKER* marker = new SCH_MARKER( ercItem, needsDriver.Pin()->GetPosition() );
SCH_MARKER* marker = new SCH_MARKER( std::move( ercItem ), needsDriver.Pin()->GetPosition() );
pinToScreenMap[needsDriver.Pin()]->Append( marker );
errors++;
}
@@ -1195,8 +1188,7 @@ int ERC_TESTER::TestMultUnitPinConflicts()
if( !pin->GetLibPin()->GetParentSymbol()->IsMulti() )
continue;
wxString name = pin->GetParentSymbol()->GetRef( &sheet ) +
+ ":" + pin->GetShownNumber();
wxString name = pin->GetParentSymbol()->GetRef( &sheet ) + ":" + pin->GetShownNumber();
if( !pinToNetMap.count( name ) )
{
@@ -1273,7 +1265,7 @@ int ERC_TESTER::TestSameLocalGlobalLabel()
ercItem->SetSheetSpecificPath( globalItem.second );
ercItem->SetItemsSheetPaths( globalItem.second, localItem.second );
SCH_MARKER* marker = new SCH_MARKER( ercItem, globalItem.first->GetPosition() );
SCH_MARKER* marker = new SCH_MARKER( std::move( ercItem ), globalItem.first->GetPosition() );
globalItem.second.LastScreen()->Append( marker );
errCount++;
@@ -1670,7 +1662,7 @@ int ERC_TESTER::TestFootprintFilters()
wxJoin( filters, ' ' ) );
ercItem->SetErrorMessage( msg );
ercItem->SetItems( sch_symbol );
markers.emplace_back( new SCH_MARKER( ercItem, sch_symbol->GetPosition() ) );
markers.emplace_back( new SCH_MARKER( std::move( ercItem ), sch_symbol->GetPosition() ) );
}
}
+8
View File
@@ -19,6 +19,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <algorithm>
#include <erc/erc_item.h>
#include <erc/erc_settings.h>
#include <schematic.h>
@@ -397,6 +398,13 @@ void SHEETLIST_ERC_ITEMS_PROVIDER::SetSeverities( int aSeverities )
if( markerSeverity & m_severities )
m_filteredMarkers.push_back( aMarker );
} );
// Sort markers so that errors appear before warnings
std::stable_sort( m_filteredMarkers.begin(), m_filteredMarkers.end(),
[]( const SCH_MARKER* a, const SCH_MARKER* b )
{
return a->GetSeverity() > b->GetSeverity();
} );
}
+144 -24
View File
@@ -225,6 +225,15 @@ int FIELDS_GRID_TABLE::GetMandatoryRowCount() const
}
void FIELDS_GRID_TABLE::push_back( const SCH_FIELD& aField )
{
std::vector<SCH_FIELD>::push_back( aField );
m_isInherited.resize( size() );
m_parentFields.resize( size() );
}
void FIELDS_GRID_TABLE::initGrid( WX_GRID* aGrid )
{
// Build the various grid cell attributes.
@@ -399,6 +408,9 @@ FIELDS_GRID_TABLE::~FIELDS_GRID_TABLE()
m_fontAttr->DecRef();
m_colorAttr->DecRef();
for( SCH_FIELD& field : m_parentFields )
field.SetParent( nullptr );
m_frame->Unbind( EDA_EVT_UNITS_CHANGED, &FIELDS_GRID_TABLE::onUnitsChanged, this );
}
@@ -538,33 +550,34 @@ wxGridCellAttr* FIELDS_GRID_TABLE::GetAttr( int aRow, int aCol, wxGridCellAttr::
wxCHECK( aRow < GetNumberRows(), nullptr );
const SCH_FIELD& field = getField( aRow );
wxGridCellAttr* tmp;
wxGridCellAttr* attr = nullptr;
switch( aCol )
{
case FDC_NAME:
if( field.IsMandatory() )
{
tmp = m_fieldNameAttr->Clone();
tmp->SetReadOnly( true );
return enhanceAttr( tmp, aRow, aCol, aKind );
attr = m_fieldNameAttr->Clone();
attr->SetReadOnly( true );
}
else
{
m_fieldNameAttr->IncRef();
return enhanceAttr( m_fieldNameAttr, aRow, aCol, aKind );
attr = m_fieldNameAttr;
}
break;
case FDC_VALUE:
if( m_parentType == SCH_SYMBOL_T && field.GetId() == REFERENCE_FIELD )
{
m_referenceAttr->IncRef();
return enhanceAttr( m_referenceAttr, aRow, aCol, aKind );
attr = m_referenceAttr;
}
else if( m_parentType == SCH_SYMBOL_T && field.GetId() == VALUE_FIELD )
{
m_valueAttr->IncRef();
return enhanceAttr( m_valueAttr, aRow, aCol, aKind );
attr = m_valueAttr;
}
else if( m_parentType == SCH_SYMBOL_T && field.GetId() == FOOTPRINT_FIELD )
{
@@ -574,34 +587,34 @@ wxGridCellAttr* FIELDS_GRID_TABLE::GetAttr( int aRow, int aCol, wxGridCellAttr::
if( m_part && m_part->IsPower() )
{
m_readOnlyAttr->IncRef();
return enhanceAttr( m_readOnlyAttr, aRow, aCol, aKind );
attr = m_readOnlyAttr;
}
else
{
m_footprintAttr->IncRef();
return enhanceAttr( m_footprintAttr, aRow, aCol, aKind );
attr = m_footprintAttr;
}
}
else if( m_parentType == SCH_SYMBOL_T && field.GetId() == DATASHEET_FIELD )
{
m_urlAttr->IncRef();
return enhanceAttr( m_urlAttr, aRow, aCol, aKind );
attr = m_urlAttr;
}
else if( m_parentType == SCH_SHEET_T && field.GetId() == SHEETNAME )
{
m_referenceAttr->IncRef();
return enhanceAttr( m_referenceAttr, aRow, aCol, aKind );
attr = m_referenceAttr;
}
else if( m_parentType == SCH_SHEET_T && field.GetId() == SHEETFILENAME )
{
m_filepathAttr->IncRef();
return enhanceAttr( m_filepathAttr, aRow, aCol, aKind );
attr = m_filepathAttr;
}
else if( ( m_parentType == SCH_LABEL_LOCATE_ANY_T )
&& field.GetCanonicalName() == wxT( "Netclass" ) )
{
m_netclassAttr->IncRef();
return enhanceAttr( m_netclassAttr, aRow, aCol, aKind );
attr = m_netclassAttr;
}
else
{
@@ -615,31 +628,36 @@ wxGridCellAttr* FIELDS_GRID_TABLE::GetAttr( int aRow, int aCol, wxGridCellAttr::
if( ( templateFn && templateFn->m_URL ) || field.IsHypertext() )
{
m_urlAttr->IncRef();
return enhanceAttr( m_urlAttr, aRow, aCol, aKind );
attr = m_urlAttr;
}
else
{
m_nonUrlAttr->IncRef();
return enhanceAttr( m_nonUrlAttr, aRow, aCol, aKind );
attr = m_nonUrlAttr;
}
}
break;
case FDC_TEXT_SIZE:
case FDC_POSX:
case FDC_POSY:
return enhanceAttr( nullptr, aRow, aCol, aKind );
break;
case FDC_H_ALIGN:
m_hAlignAttr->IncRef();
return enhanceAttr( m_hAlignAttr, aRow, aCol, aKind );
attr = m_hAlignAttr;
break;
case FDC_V_ALIGN:
m_vAlignAttr->IncRef();
return enhanceAttr( m_vAlignAttr, aRow, aCol, aKind );
attr = m_vAlignAttr;
break;
case FDC_ORIENTATION:
m_orientationAttr->IncRef();
return enhanceAttr( m_orientationAttr, aRow, aCol, aKind );
attr = m_orientationAttr;
break;
case FDC_SHOWN:
case FDC_SHOW_NAME:
@@ -648,20 +666,50 @@ wxGridCellAttr* FIELDS_GRID_TABLE::GetAttr( int aRow, int aCol, wxGridCellAttr::
case FDC_ALLOW_AUTOPLACE:
case FDC_PRIVATE:
m_boolAttr->IncRef();
return enhanceAttr( m_boolAttr, aRow, aCol, aKind );
attr = m_boolAttr;
break;
case FDC_FONT:
m_fontAttr->IncRef();
return enhanceAttr( m_fontAttr, aRow, aCol, aKind );
attr = m_fontAttr;
break;
case FDC_COLOR:
m_colorAttr->IncRef();
return enhanceAttr( m_colorAttr, aRow, aCol, aKind );
attr = m_colorAttr;
break;
default:
wxFAIL;
return enhanceAttr( nullptr, aRow, aCol, aKind );
attr = nullptr;
break;
}
if( !attr )
return nullptr;
attr = enhanceAttr( attr, aRow, aCol, aKind );
if( IsInherited( aRow ) )
{
wxGridCellAttr* text_attr = attr ? attr->Clone() : new wxGridCellAttr;
wxFont font;
if( !text_attr->HasFont() )
font = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT );
else
font = text_attr->GetFont();
font.MakeItalic();
text_attr->SetFont( font );
text_attr->SetTextColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) );
if( attr )
attr->DecRef();
attr = text_attr;
}
return attr;
}
@@ -1042,10 +1090,82 @@ bool FIELDS_GRID_TABLE::BoolFromString( const wxString& aValue ) const
}
SCH_FIELD* FIELDS_GRID_TABLE::GetField( MANDATORY_FIELD_T aFieldId )
{
for( SCH_FIELD& field : *this )
{
if( field.GetId() == aFieldId )
return &field;
}
return nullptr;
}
int FIELDS_GRID_TABLE::GetFieldRow( MANDATORY_FIELD_T aFieldId )
{
for( int ii = 0; ii < (int) this->size(); ++ii )
{
if( this->at( ii ).GetId() == aFieldId )
return ii;
}
return -1;
}
void FIELDS_GRID_TABLE::AddInheritedField( const SCH_FIELD& aParent )
{
push_back( aParent );
back().SetParent( m_part );
m_isInherited.back() = true;
m_parentFields.back() = aParent;
}
bool FIELDS_GRID_TABLE::EraseRow( size_t aRow )
{
if( m_isInherited.size() > aRow )
{
// You can't erase inherited fields, but you can reset them to the parent value.
if( m_isInherited[aRow] )
{
at( aRow ) = m_parentFields[aRow];
return false;
}
m_isInherited.erase( m_isInherited.begin() + aRow );
}
if( m_parentFields.size() > aRow )
m_parentFields.erase( m_parentFields.begin() + aRow );
std::vector<SCH_FIELD>::erase( begin() + aRow );
return true;
}
void FIELDS_GRID_TABLE::SwapRows( size_t a, size_t b )
{
wxCHECK( a < this->size() && b < this->size(), /*void*/ );
std::swap( at( a ), at( b ) );
bool tmpInherited = m_isInherited[a];
m_isInherited[a] = m_isInherited[b];
m_isInherited[b] = tmpInherited;
std::swap( m_parentFields[a], m_parentFields[b] );
}
void FIELDS_GRID_TABLE::DetachFields()
{
for( SCH_FIELD& field : *this )
field.SetParent( nullptr );
for( SCH_FIELD& field : m_parentFields )
field.SetParent( nullptr );
}
+35
View File
@@ -28,6 +28,7 @@
#include <sch_symbol.h>
#include <grid_tricks.h>
#include <validators.h>
#include <vector>
class SCH_BASE_FRAME;
class DIALOG_SHIM;
@@ -120,6 +121,37 @@ public:
wxString StringFromBool( bool aValue ) const;
bool BoolFromString( const wxString& aValue ) const;
SCH_FIELD* GetField( MANDATORY_FIELD_T aFieldId );
int GetFieldRow( MANDATORY_FIELD_T aFieldId );
void AddInheritedField( const SCH_FIELD& aParent );
void SetFieldInherited( size_t aRow, const SCH_FIELD& aParent )
{
m_isInherited.resize( aRow + 1, false );
m_parentFields.resize( aRow + 1 );
m_parentFields[aRow] = aParent;
m_isInherited[aRow] = true;
}
bool IsInherited( size_t aRow ) const
{
if( aRow >= m_isInherited.size() || aRow >= m_parentFields.size() )
return false;
return m_isInherited[aRow] && m_parentFields[aRow].GetText() == at( aRow ).GetText();
}
const SCH_FIELD& ParentField( size_t row ) const { return m_parentFields[row]; }
void push_back( const SCH_FIELD& field );
// For std::vector compatibility, but we don't use it directly.
void emplace_back( const SCH_FIELD& field ) { push_back( field ); }
bool EraseRow( size_t row );
void SwapRows( size_t a, size_t b );
void DetachFields();
protected:
@@ -164,6 +196,9 @@ private:
wxGridCellAttr* m_fontAttr;
wxGridCellAttr* m_colorAttr;
std::vector<bool> m_isInherited;
std::vector<SCH_FIELD> m_parentFields;
std::unique_ptr<NUMERIC_EVALUATOR> m_eval;
std::map< std::pair<int, int>, wxString > m_evalOriginal;
};
+25 -1
View File
@@ -1230,8 +1230,18 @@ bool SCH_EDIT_FRAME::doAutoSave()
if( !tmp.IsOk() )
return false;
if( !IsWritable( tmp ) )
if( !IsWritable( tmp, false ) )
{
if( !m_autoSavePermissionError )
{
DisplayError( this, wxString::Format(
_( "Could not autosave files to read-only folder: '%s'" ),
tmp.GetPath() ) );
m_autoSavePermissionError = true;
}
return false;
}
wxString title = GetTitle(); // Save frame title, that can be modified by the save process
@@ -1246,6 +1256,20 @@ bool SCH_EDIT_FRAME::doAutoSave()
// Auto save file name is the normal file name prefixed with GetAutoSavePrefix().
fn.SetName( FILEEXT::AutoSaveFilePrefix + fn.GetName() );
if( !IsWritable( fn, false ) )
{
if( !m_autoSavePermissionError )
{
DisplayError( this, wxString::Format(
_( "Could not autosave files to read-only folder: '%s'" ),
fn.GetPath() ) );
m_autoSavePermissionError = true;
}
autoSaveOk = false;
continue;
}
if( saveSchematicFile( screens.GetSheet( i ), fn.GetFullPath() ) )
{
// This was only an auto-save, not a real save. Reset the modified flag.
+31 -20
View File
@@ -281,24 +281,31 @@ LIB_SYMBOL_SPTR LIB_SYMBOL::GetRootSymbol() const
}
wxString LIB_SYMBOL::GetUnitReference( int aUnit )
{
return LIB_SYMBOL::LetterSubReference( aUnit, 'A' );
}
bool LIB_SYMBOL::HasUnitDisplayName( int aUnit )
bool LIB_SYMBOL::HasUnitDisplayName( int aUnit ) const
{
return ( m_unitDisplayNames.count( aUnit ) == 1 );
}
wxString LIB_SYMBOL::GetUnitDisplayName( int aUnit )
wxString LIB_SYMBOL::GetUnitDisplayName( int aUnit, bool aLabel ) const
{
if( HasUnitDisplayName( aUnit ) )
return m_unitDisplayNames[aUnit];
if( m_unitDisplayNames.contains( aUnit ) )
return m_unitDisplayNames.at( aUnit );
else if( aLabel )
return wxString::Format( _( "Unit %s" ), LIB_SYMBOL::LetterSubReference( aUnit, 'A' ) );
else
return wxString::Format( _( "Unit %s" ), GetUnitReference( aUnit ) );
return LIB_SYMBOL::LetterSubReference( aUnit, 'A' );
}
wxString LIB_SYMBOL::GetBodyStyleDescription( int aBodyStyle, bool aLabel ) const
{
if( aBodyStyle == BODY_STYLE::DEMORGAN )
return aLabel ? _( "Alternate" ) : wxString( _HKI( "Alternate" ) );
else if( aBodyStyle == BODY_STYLE::BASE )
return aLabel ? _( "Standard" ) : wxString( _HKI( "Standard" ) );
else
return wxT( "?" );
}
@@ -480,7 +487,7 @@ void LIB_SYMBOL::SetNormal()
}
wxString LIB_SYMBOL::LetterSubReference( int aUnit, int aFirstId )
wxString LIB_SYMBOL::LetterSubReference( int aUnit, wxChar aInitialLetter )
{
// use letters as notation. To allow more than 26 units, the sub ref
// use one letter if letter = A .. Z or a ... z, and 2 letters otherwise
@@ -491,7 +498,7 @@ wxString LIB_SYMBOL::LetterSubReference( int aUnit, int aFirstId )
do
{
u = ( aUnit - 1 ) % 26;
suffix = wxChar( aFirstId + u ) + suffix;
suffix = wxChar( aInitialLetter + u ) + suffix;
aUnit = ( aUnit - u ) / 26;
} while( aUnit > 0 );
@@ -1419,14 +1426,18 @@ void LIB_SYMBOL::SetUnitCount( int aCount, bool aDuplicateDrawItems )
if( aCount < m_unitCount )
{
LIB_ITEMS_CONTAINER::ITERATOR i = m_drawings.begin();
while( i != m_drawings.end() )
// Iterate each drawing-type bucket and erase items that belong to units > aCount.
for( int type = LIB_ITEMS_CONTAINER::FIRST_TYPE; type <= LIB_ITEMS_CONTAINER::LAST_TYPE; ++type )
{
if( i->m_unit > aCount )
i = m_drawings.erase( i );
else
++i;
auto it = m_drawings.begin( type );
while( it != m_drawings.end( type ) )
{
if( it->m_unit > aCount )
it = m_drawings.erase( it ); // returns next iterator
else
++it;
}
}
}
else if( aDuplicateDrawItems )
+10 -8
View File
@@ -554,20 +554,22 @@ public:
void SetUnitCount( int aCount, bool aDuplicateDrawItems = true );
int GetUnitCount() const override;
/**
* Return an identifier for \a aUnit for symbols with units.
*/
wxString GetUnitReference( int aUnit ) override;
/**
* Return true if the given unit \a aUnit has a display name defined
*/
bool HasUnitDisplayName( int aUnit ) override;
bool HasUnitDisplayName( int aUnit ) const;
wxString GetUnitName( int aUnit ) const override
{
return GetUnitDisplayName( aUnit, true );
}
/**
* Return the user-defined display name for \a aUnit for symbols with units.
*/
wxString GetUnitDisplayName( int aUnit ) override;
wxString GetUnitDisplayName( int aUnit, bool aLabel ) const override;
wxString GetBodyStyleDescription( int aBodyStyle, bool aLabel ) const override;
/**
* Copy all unit display names into the given map \a aTarget
@@ -585,7 +587,7 @@ public:
*/
bool IsMulti() const override { return m_unitCount > 1; }
static wxString LetterSubReference( int aUnit, int aFirstId );
static wxString LetterSubReference( int aUnit, wxChar aInitialLetter );
/**
* Set or clear the alternate body style (DeMorgan) for the symbol.
@@ -34,17 +34,15 @@
#include "netlist_exporter_allegro.h"
#include "netlist_exporter_xml.h"
#include <regex>
#include <fmt.h>
#include <fmt/ranges.h>
bool NETLIST_EXPORTER_ALLEGRO::WriteNetlist( const wxString& aOutFileName,
unsigned /* aNetlistOptions */,
REPORTER& aReporter )
{
m_f = nullptr;
wxString field;
wxString footprint;
int ret = 0; // zero now, OR in the sign bit on error
wxString netName;
bool success = true;
// Create the devices directory
m_exportPath = wxFileName( aOutFileName ).GetPath( wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR )
@@ -67,31 +65,41 @@ bool NETLIST_EXPORTER_ALLEGRO::WriteNetlist( const wxString& aOutFileName,
return false;
}
ret |= fprintf( m_f, "(Source: %s)\n", TO_UTF8( m_schematic->GetFileName() ) );
ret |= fprintf( m_f, "(Date: %s)\n", TO_UTF8( GetISO8601CurrentDateTime() ) );
try
{
fmt::print( m_f, "(NETLIST)\n" );
fmt::print( m_f, "(Source: {})\n", TO_UTF8( m_schematic->GetFileName() ) );
fmt::print( m_f, "(Date: {})\n", TO_UTF8( GetISO8601CurrentDateTime() ) );
m_packageProperties.clear();
m_componentGroups.clear();
m_orderedSymbolsSheetpath.clear();
m_netNameNodes.clear();
m_packageProperties.clear();
m_componentGroups.clear();
m_orderedSymbolsSheetpath.clear();
m_netNameNodes.clear();
extractComponentsInfo();
extractComponentsInfo();
// Start with package definitions, which we create from component groups.
toAllegroPackages();
// Start with package definitions, which we create from component groups.
toAllegroPackages();
// Write out nets
toAllegroNets();
// Write out package properties. NOTE: Allegro doesn't recognize much...
toAllegroPackageProperties();
// Write out package properties. NOTE: Allegro doesn't recognize much...
toAllegroPackageProperties();
// Write out nets
toAllegroNets();
fmt::print( m_f, "$END\n" );
}
catch (...)
{
success = false;
}
// Done with the netlist
fclose( m_f );
m_f = nullptr;
return ret >= 0;
return success;
}
@@ -437,8 +445,8 @@ void NETLIST_EXPORTER_ALLEGRO::toAllegroPackages()
}
}
fprintf( d, "PACKAGE '%s'\n", TO_UTF8( formatDevice( footprintText ) ) );
fprintf( d, "CLASS IC\n" );
fmt::print( d, "PACKAGE '{}'\n", TO_UTF8( formatDevice( footprintText ) ) );
fmt::print( d, "CLASS IC\n" );
std::vector<SCH_PIN*> pinList = sym->GetLibSymbolRef()->GetPins();
@@ -463,36 +471,26 @@ void NETLIST_EXPORTER_ALLEGRO::toAllegroPackages()
}
unsigned int pinCount = pinList.size();
fprintf( d, "PINCOUNT %u\n", pinCount );
fmt::print( d, "PINCOUNT {}\n", pinCount );
if( pinCount > 0 )
{
fprintf( d, "%s", TO_UTF8( formatFunction( "main", pinList ) ) );
fmt::print( d, "{}", TO_UTF8( formatFunction( "main", pinList ) ) );
}
if( !value.IsEmpty() )
{
fprintf( d, "PACKAGEPROP VALUE %s\n", TO_UTF8( value ) );
fmt::print( d, "PACKAGEPROP VALUE {}\n", TO_UTF8( value ) );
}
if( !tol.IsEmpty() )
{
fprintf( d, "PACKAGEPROP TOL %s\n", TO_UTF8( tol ) );
fmt::print( d, "PACKAGEPROP TOL {}\n", TO_UTF8( tol ) );
}
if( !footprintAlt.IsEmpty() )
{
fprintf( d, "PACKAGEPROP ALT_SYMBOLS '(" );
wxString footprintAltSymbolsText;
for( const wxString& fp : footprintAlt )
{
footprintAltSymbolsText += fp + wxString( "," );
}
footprintAltSymbolsText.Truncate( footprintAltSymbolsText.Length() - 1 );
fprintf( d, "%s)'\n", TO_UTF8( footprintAltSymbolsText ) );
fmt::print( d, "PACKAGEPROP ALT_SYMBOLS '({})'\n", fmt::join( footprintAlt, "," ) );
}
wxArrayString propArray;
@@ -503,7 +501,7 @@ void NETLIST_EXPORTER_ALLEGRO::toAllegroPackages()
if(!data.IsEmpty())
{
fprintf( d, "PACKAGEPROP %s %s\n", TO_UTF8( propArray[0] ), TO_UTF8( data ) );
fmt::print( d, "PACKAGEPROP {} {}\n", TO_UTF8( propArray[0] ), TO_UTF8( data ) );
}
propArray.clear();
@@ -512,14 +510,16 @@ void NETLIST_EXPORTER_ALLEGRO::toAllegroPackages()
if(!data.IsEmpty())
{
fprintf( d, "PACKAGEPROP %s %s\n", TO_UTF8( propArray[0] ), TO_UTF8( data ) );
fmt::print( d, "PACKAGEPROP {} {}\n", TO_UTF8( propArray[0] ), TO_UTF8( data ) );
}
fprintf( d, "END\n" );
fmt::print( d, "END\n" );
fclose( d );
}
fmt::print( m_f, "$PACKAGES\n" );
for( auto iter = compPackageMap.begin(); iter != compPackageMap.end(); iter++ )
{
wxString deviceType = iter->first;
@@ -528,25 +528,28 @@ void NETLIST_EXPORTER_ALLEGRO::toAllegroPackages()
if( value.IsEmpty() && tolerance.IsEmpty() )
{
fprintf( m_f, "!%s;", TO_UTF8( deviceType ) );
fmt::print( m_f, "! '{}' ; ", TO_UTF8( deviceType ) );
}
else if( tolerance.IsEmpty() )
{
fprintf( m_f, "!%s!%s;", TO_UTF8( deviceType ), TO_UTF8( value ) );
fmt::print( m_f, "! '{}' ! '{}' ; ", TO_UTF8( deviceType ), TO_UTF8( value ) );
}
else
{
fprintf( m_f, "!%s!%s!%s;", TO_UTF8( deviceType ), TO_UTF8( value ),
fmt::print( m_f, "! '{}' ! '{}' ! {} ; ", TO_UTF8( deviceType ), TO_UTF8( value ),
TO_UTF8( tolerance ) );
}
std::vector<std::pair<SCH_SYMBOL*, SCH_SHEET_PATH>> symbolSheetpaths =
iter->second.m_symbolSheetpaths;
std::vector<wxString> refTexts;
for( const auto& [ sym, sheetPath ] : symbolSheetpaths)
fprintf( m_f, ",\n\t%s", TO_UTF8( sym->GetRef( &sheetPath ) ) );
refTexts.push_back( sym->GetRef( &sheetPath ) );
fprintf( m_f, "\n" );
fmt::print( m_f, "{}", fmt::join( refTexts, ",\n\t" ) );
fmt::print( m_f, "\n" );
}
if( !deviceFileCreatingError.IsEmpty() )
@@ -680,15 +683,14 @@ wxString NETLIST_EXPORTER_ALLEGRO::formatDevice( wxString aString )
void NETLIST_EXPORTER_ALLEGRO::toAllegroPackageProperties()
{
fprintf( m_f, "%s\n", "$PACKAGES" );
fprintf( m_f, "%s\n", "$A_PROPERTIES" );
fmt::print( m_f, "$A_PROPERTIES\n" );
while( !m_packageProperties.empty() )
{
std::multimap<wxString, wxString>::iterator iter = m_packageProperties.begin();
wxString sheetPathText = iter->first;
fprintf( m_f, "ROOM %s;", TO_UTF8( formatText( sheetPathText ) ) );
fmt::print( m_f, "'ROOM' '{}' ; ", TO_UTF8( formatText( sheetPathText ) ) );
std::vector<wxString> refTexts;
@@ -705,17 +707,16 @@ void NETLIST_EXPORTER_ALLEGRO::toAllegroPackageProperties()
std::stable_sort( refTexts.begin(), refTexts.end(),
NETLIST_EXPORTER_ALLEGRO::CompareSymbolRef );
for( const wxString& ref : refTexts )
fprintf( m_f, ",\n\t%s", TO_UTF8( ref ) );
fmt::print( m_f, "{}", fmt::join( refTexts, ",\n\t" ) );
fprintf( m_f, "\n" );
fmt::print( m_f, "\n" );
}
}
void NETLIST_EXPORTER_ALLEGRO::toAllegroNets()
{
fprintf( m_f, "%s\n", "$NETS" );
fmt::print( m_f, "$NETS\n" );
while( !m_netNameNodes.empty() )
{
@@ -724,7 +725,7 @@ void NETLIST_EXPORTER_ALLEGRO::toAllegroNets()
wxString netName = iter->first;
fprintf( m_f, "%s;", TO_UTF8( formatText( netName ).MakeUpper() ) );
fmt::print( m_f, "{}; ", TO_UTF8( formatText( netName ).MakeUpper() ) );
auto pairIter = m_netNameNodes.equal_range( netName );
@@ -738,14 +739,17 @@ void NETLIST_EXPORTER_ALLEGRO::toAllegroNets()
std::stable_sort( netNodes.begin(), netNodes.end() );
std::vector<wxString> nets;
for( const NET_NODE& netNode : netNodes )
{
wxString refText = netNode.m_Pin->GetParentSymbol()->GetRef( &netNode.m_Sheet );
wxString pinText = netNode.m_Pin->GetShownNumber();
fprintf( m_f, ",\n\t%s.%s", TO_UTF8( refText ), TO_UTF8( pinText ) );
nets.push_back( refText + wxString( "." ) + pinText );
}
fprintf( m_f, "\n" );
fmt::print( m_f, "{}", fmt::join( nets, ",\n\t" ) );
fmt::print( m_f, "\n" );
}
}
+2 -2
View File
@@ -119,8 +119,8 @@ void SCH_EDIT_FRAME::SelectUnit( SCH_SYMBOL* aSymbol, int aUnit )
if( otherSymbolRef )
{
const wxString targetUnitName = symbol->GetUnitDisplayName( aUnit );
const wxString currUnitName = symbol->GetUnitDisplayName( currentUnit );
const wxString targetUnitName = symbol->GetUnitDisplayName( aUnit, false );
const wxString currUnitName = symbol->GetUnitDisplayName( currentUnit, false );
wxString otherSheetName = otherSymbolRef->GetSheetPath().PathHumanReadable( true, true );
if( otherSheetName.IsEmpty() )
+25 -30
View File
@@ -82,42 +82,37 @@ void InitTables()
{
// clang-format off
g_pinElectricalTypes = {
{ ELECTRICAL_PINTYPE::PT_INPUT, { _( "Input" ), BITMAPS::pintype_input } },
{ ELECTRICAL_PINTYPE::PT_OUTPUT, { _( "Output" ), BITMAPS::pintype_output } },
{ ELECTRICAL_PINTYPE::PT_BIDI, { _( "Bidirectional" ), BITMAPS::pintype_bidi } },
{ ELECTRICAL_PINTYPE::PT_TRISTATE, { _( "Tri-state" ), BITMAPS::pintype_3states } },
{ ELECTRICAL_PINTYPE::PT_PASSIVE, { _( "Passive" ), BITMAPS::pintype_passive } },
{ ELECTRICAL_PINTYPE::PT_NIC, { _( "Free" ), BITMAPS::pintype_nic } },
{ ELECTRICAL_PINTYPE::PT_UNSPECIFIED, { _( "Unspecified" ), BITMAPS::pintype_notspecif } },
{ ELECTRICAL_PINTYPE::PT_POWER_IN, { _( "Power input" ), BITMAPS::pintype_powerinput } },
{ ELECTRICAL_PINTYPE::PT_POWER_OUT, { _( "Power output" ), BITMAPS::pintype_poweroutput } },
{ ELECTRICAL_PINTYPE::PT_OPENCOLLECTOR, { _( "Open collector" ),
BITMAPS::pintype_opencoll } },
{ ELECTRICAL_PINTYPE::PT_OPENEMITTER, { _( "Open emitter" ), BITMAPS::pintype_openemit } },
{ ELECTRICAL_PINTYPE::PT_NC, { _( "Unconnected" ), BITMAPS::pintype_noconnect } },
{ ELECTRICAL_PINTYPE::PT_INPUT, { _( "Input" ), BITMAPS::pintype_input } },
{ ELECTRICAL_PINTYPE::PT_OUTPUT, { _( "Output" ), BITMAPS::pintype_output } },
{ ELECTRICAL_PINTYPE::PT_BIDI, { _( "Bidirectional" ), BITMAPS::pintype_bidi } },
{ ELECTRICAL_PINTYPE::PT_TRISTATE, { _( "Tri-state" ), BITMAPS::pintype_3states } },
{ ELECTRICAL_PINTYPE::PT_PASSIVE, { _( "Passive" ), BITMAPS::pintype_passive } },
{ ELECTRICAL_PINTYPE::PT_NIC, { _( "Free" ), BITMAPS::pintype_nic } },
{ ELECTRICAL_PINTYPE::PT_UNSPECIFIED, { _( "Unspecified" ), BITMAPS::pintype_notspecif } },
{ ELECTRICAL_PINTYPE::PT_POWER_IN, { _( "Power input" ), BITMAPS::pintype_powerinput } },
{ ELECTRICAL_PINTYPE::PT_POWER_OUT, { _( "Power output" ), BITMAPS::pintype_poweroutput } },
{ ELECTRICAL_PINTYPE::PT_OPENCOLLECTOR, { _( "Open collector" ), BITMAPS::pintype_opencoll } },
{ ELECTRICAL_PINTYPE::PT_OPENEMITTER, { _( "Open emitter" ), BITMAPS::pintype_openemit } },
{ ELECTRICAL_PINTYPE::PT_NC, { _( "Unconnected" ), BITMAPS::pintype_noconnect } },
};
g_pinShapes = {
{ GRAPHIC_PINSHAPE::LINE, { _( "Line" ), BITMAPS::pinshape_normal } },
{ GRAPHIC_PINSHAPE::INVERTED, { _( "Inverted" ), BITMAPS::pinshape_invert } },
{ GRAPHIC_PINSHAPE::CLOCK, { _( "Clock" ), BITMAPS::pinshape_clock_normal } },
{ GRAPHIC_PINSHAPE::INVERTED_CLOCK, { _( "Inverted clock" ),
BITMAPS::pinshape_clock_invert } },
{ GRAPHIC_PINSHAPE::INPUT_LOW, { _( "Input low" ), BITMAPS::pinshape_active_low_input } },
{ GRAPHIC_PINSHAPE::CLOCK_LOW, { _( "Clock low" ), BITMAPS::pinshape_clock_active_low } },
{ GRAPHIC_PINSHAPE::OUTPUT_LOW, { _( "Output low" ),
BITMAPS::pinshape_active_low_output } },
{ GRAPHIC_PINSHAPE::FALLING_EDGE_CLOCK, { _( "Falling edge clock" ),
BITMAPS::pinshape_clock_fall } },
{ GRAPHIC_PINSHAPE::NONLOGIC, { _( "NonLogic" ),
BITMAPS::pinshape_nonlogic } },
{ GRAPHIC_PINSHAPE::LINE, { _( "Line" ), BITMAPS::pinshape_normal } },
{ GRAPHIC_PINSHAPE::INVERTED, { _( "Inverted" ), BITMAPS::pinshape_invert } },
{ GRAPHIC_PINSHAPE::CLOCK, { _( "Clock" ), BITMAPS::pinshape_clock_normal } },
{ GRAPHIC_PINSHAPE::INVERTED_CLOCK, { _( "Inverted clock" ), BITMAPS::pinshape_clock_invert } },
{ GRAPHIC_PINSHAPE::INPUT_LOW, { _( "Input low" ), BITMAPS::pinshape_active_low_input } },
{ GRAPHIC_PINSHAPE::CLOCK_LOW, { _( "Clock low" ), BITMAPS::pinshape_clock_active_low } },
{ GRAPHIC_PINSHAPE::OUTPUT_LOW, { _( "Output low" ), BITMAPS::pinshape_active_low_output } },
{ GRAPHIC_PINSHAPE::FALLING_EDGE_CLOCK, { _( "Falling edge clock" ), BITMAPS::pinshape_clock_fall } },
{ GRAPHIC_PINSHAPE::NONLOGIC, { _( "NonLogic" ), BITMAPS::pinshape_nonlogic } },
};
g_pinOrientations = {
{ PIN_ORIENTATION::PIN_RIGHT, { _( "Right" ), BITMAPS::pinorient_right } },
{ PIN_ORIENTATION::PIN_LEFT, { _( "Left" ), BITMAPS::pinorient_left } },
{ PIN_ORIENTATION::PIN_UP, { _( "Up" ), BITMAPS::pinorient_up } },
{ PIN_ORIENTATION::PIN_DOWN, { _( "Down" ), BITMAPS::pinorient_down } },
{ PIN_ORIENTATION::PIN_RIGHT, { _( "Right" ), BITMAPS::pinorient_right } },
{ PIN_ORIENTATION::PIN_LEFT, { _( "Left" ), BITMAPS::pinorient_left } },
{ PIN_ORIENTATION::PIN_UP, { _( "Up" ), BITMAPS::pinorient_up } },
{ PIN_ORIENTATION::PIN_DOWN, { _( "Down" ), BITMAPS::pinorient_down } },
};
// clang-format on
+3 -1
View File
@@ -1614,7 +1614,9 @@ void SCH_EDIT_FRAME::RefreshOperatingPointDisplay()
{
std::vector<EMBEDDED_FILES*> embeddedFilesStack;
embeddedFilesStack.push_back( m_schematic->GetEmbeddedFiles() );
embeddedFilesStack.push_back( symbol->GetEmbeddedFiles() );
if( EMBEDDED_FILES* symbolEmbeddedFiles = symbol->GetEmbeddedFiles() )
embeddedFilesStack.push_back( symbolEmbeddedFiles );
simLibMgr.SetFilesStack( embeddedFilesStack );
+17 -1
View File
@@ -47,6 +47,20 @@
static const std::vector<KICAD_T> labelTypes = { SCH_LABEL_LOCATE_ANY_T };
SCH_FIELD::SCH_FIELD() :
SCH_ITEM( nullptr, SCH_FIELD_T ),
EDA_TEXT( schIUScale, wxEmptyString ),
m_id( MANDATORY_FIELD_T::INVALID_FIELD ),
m_showName( false ),
m_allowAutoPlace( true ),
m_isGeneratedField( false ),
m_autoAdded( false ),
m_showInChooser( true ),
m_renderCacheValid( false ),
m_lastResolvedColor( COLOR4D::UNSPECIFIED )
{
}
SCH_FIELD::SCH_FIELD( const VECTOR2I& aPos, int aFieldId, SCH_ITEM* aParent,
const wxString& aName ) :
SCH_ITEM( aParent, SCH_FIELD_T ),
@@ -937,7 +951,9 @@ void SCH_FIELD::OnScintillaCharAdded( SCINTILLA_TRICKS* aScintillaTricks,
std::vector<EMBEDDED_FILES*> embeddedFilesStack;
embeddedFilesStack.push_back( schematic->GetEmbeddedFiles() );
embeddedFilesStack.push_back( symbol->GetEmbeddedFiles() );
if( EMBEDDED_FILES* symbolEmbeddedFiles = symbol->GetEmbeddedFiles() )
embeddedFilesStack.push_back( symbolEmbeddedFiles );
mgr.SetFilesStack( embeddedFilesStack );
+2
View File
@@ -52,6 +52,8 @@ class SCH_TEXT;
class SCH_FIELD : public SCH_ITEM, public EDA_TEXT
{
public:
SCH_FIELD(); // For std::map::operator[]
SCH_FIELD( const VECTOR2I& aPos, int aFieldId, SCH_ITEM* aParent,
const wxString& aName = wxEmptyString );
+1 -2
View File
@@ -4894,8 +4894,7 @@ void SCH_IO_ALTIUM::doEnumerateSymbolLib( const wxString& aLibraryPath,
{
ensureLoadedLibrary( aLibraryPath, aProperties );
bool powerSymbolsOnly = ( aProperties &&
aProperties->find( SYMBOL_LIB_TABLE::PropPowerSymsOnly ) != aProperties->end() );
bool powerSymbolsOnly = ( aProperties && aProperties->contains( SYMBOL_LIB_TABLE::PropPowerSymsOnly ) );
auto it = m_libCache.find( aLibraryPath );
+5 -9
View File
@@ -73,9 +73,7 @@ void SCH_IO_DATABASE::EnumerateSymbolLib( std::vector<LIB_SYMBOL*>& aSymbolList,
if( !m_conn )
THROW_IO_ERROR( m_lastError );
bool powerSymbolsOnly = ( aProperties &&
aProperties->find( SYMBOL_LIB_TABLE::PropPowerSymsOnly ) !=
aProperties->end() );
bool powerSymbolsOnly = ( aProperties && aProperties->contains( SYMBOL_LIB_TABLE::PropPowerSymsOnly ) );
for( auto const& pair : m_nameToSymbolcache )
{
@@ -465,13 +463,13 @@ std::unique_ptr<LIB_SYMBOL> SCH_IO_DATABASE::loadSymbolFromRow( const wxString&
LIB_ID libId = symbol->GetLibId();
libId.SetSubLibraryName( aTable.name );;
symbol->SetLibId( libId );
wxArrayString footprintsList;
if( aRow.count( aTable.footprints_col ) )
{
std::string footprints = std::any_cast<std::string>( aRow.at( aTable.footprints_col ) );
wxString footprintsStr = wxString( footprints.c_str(), wxConvUTF8 );
wxArrayString footprintsList;
wxStringTokenizer tokenizer( footprintsStr, ';' );
while( tokenizer.HasMoreTokens() )
@@ -479,8 +477,6 @@ std::unique_ptr<LIB_SYMBOL> SCH_IO_DATABASE::loadSymbolFromRow( const wxString&
if( footprintsList.size() > 0 )
symbol->GetFootprintField().SetText( footprintsList[0] );
symbol->SetFPFilters( footprintsList );
}
else
{
@@ -509,11 +505,11 @@ std::unique_ptr<LIB_SYMBOL> SCH_IO_DATABASE::loadSymbolFromRow( const wxString&
wxString value( std::any_cast<std::string>( aRow.at( aTable.properties.footprint_filters ) )
.c_str(),
wxConvUTF8 );
wxArrayString filters;
filters.push_back( value );
symbol->SetFPFilters( filters );
footprintsList.push_back( value );
}
symbol->SetFPFilters( footprintsList );
if( !aTable.properties.exclude_from_sim.empty()
&& aRow.count( aTable.properties.exclude_from_sim ) )
{
+55 -62
View File
@@ -34,13 +34,7 @@ SCH_IO_HTTP_LIB::SCH_IO_HTTP_LIB() : SCH_IO( wxS( "HTTP library" ) ), m_libTable
}
SCH_IO_HTTP_LIB::~SCH_IO_HTTP_LIB()
{
}
void SCH_IO_HTTP_LIB::EnumerateSymbolLib( wxArrayString& aSymbolNameList,
const wxString& aLibraryPath,
void SCH_IO_HTTP_LIB::EnumerateSymbolLib( wxArrayString& aSymbolNameList, const wxString& aLibraryPath,
const std::map<std::string, UTF8>* aProperties )
{
std::vector<LIB_SYMBOL*> symbols;
@@ -51,23 +45,17 @@ void SCH_IO_HTTP_LIB::EnumerateSymbolLib( wxArrayString& aSymbolNameList
}
void SCH_IO_HTTP_LIB::EnumerateSymbolLib( std::vector<LIB_SYMBOL*>& aSymbolList,
const wxString& aLibraryPath,
const std::map<std::string, UTF8>* aProperties )
void SCH_IO_HTTP_LIB::EnumerateSymbolLib( std::vector<LIB_SYMBOL*>& aSymbolList, const wxString& aLibraryPath,
const std::map<std::string, UTF8>* aProperties )
{
wxCHECK_RET( m_libTable, _( "httplib plugin missing library table handle!" ) );
ensureSettings( aLibraryPath );
ensureConnection();
if( !m_conn )
{
THROW_IO_ERROR( m_lastError );
return;
}
bool powerSymbolsOnly =
( aProperties
&& aProperties->find( SYMBOL_LIB_TABLE::PropPowerSymsOnly ) != aProperties->end() );
bool powerSymbolsOnly = ( aProperties && aProperties->contains( SYMBOL_LIB_TABLE::PropPowerSymsOnly ) );
for( const HTTP_LIB_CATEGORY& category : m_conn->getCategories() )
{
@@ -121,12 +109,10 @@ LIB_SYMBOL* SCH_IO_HTTP_LIB::LoadSymbol( const wxString& aLibraryPath, const wxS
std::vector<HTTP_LIB_CATEGORY> categories = m_conn->getCategories();
if( m_conn->getCachedParts().empty() )
{
if( m_conn->GetCachedParts().empty() )
syncCache();
}
std::tuple relations = m_conn->getCachedParts()[partName];
std::tuple relations = m_conn->GetCachedParts()[partName];
std::string associatedCatID = std::get<1>( relations );
// get the matching category
@@ -158,13 +144,12 @@ LIB_SYMBOL* SCH_IO_HTTP_LIB::LoadSymbol( const wxString& aLibraryPath, const wxS
if( m_conn->SelectOne( part_id, result ) )
{
wxLogTrace( traceHTTPLib, wxT( "loadSymbol: SelectOne (%s) found in %s" ), part_id,
foundCategory->name );
wxLogTrace( traceHTTPLib, wxT( "LoadSymbol: SelectOne (%s) found in %s" ), part_id, foundCategory->name );
}
else
{
wxLogTrace( traceHTTPLib, wxT( "loadSymbol: SelectOne (%s) failed for category %s" ),
part_id, foundCategory->name );
wxLogTrace( traceHTTPLib, wxT( "LoadSymbol: SelectOne (%s) failed for category %s" ), part_id,
foundCategory->name );
THROW_IO_ERROR( m_lastError );
}
@@ -193,11 +178,13 @@ void SCH_IO_HTTP_LIB::GetSubLibraryNames( std::vector<wxString>& aNames )
}
}
wxString SCH_IO_HTTP_LIB::GetSubLibraryDescription( const wxString& aName )
{
return m_conn->getCategoryDescription( std::string( aName.mb_str() ) );
}
void SCH_IO_HTTP_LIB::GetAvailableSymbolFields( std::vector<wxString>& aNames )
{
// TODO: Implement this sometime; This is currently broken...
@@ -207,8 +194,7 @@ void SCH_IO_HTTP_LIB::GetAvailableSymbolFields( std::vector<wxString>& aNames )
void SCH_IO_HTTP_LIB::GetDefaultSymbolFields( std::vector<wxString>& aNames )
{
std::copy( m_defaultShownFields.begin(), m_defaultShownFields.end(),
std::back_inserter( aNames ) );
std::copy( m_defaultShownFields.begin(), m_defaultShownFields.end(), std::back_inserter( aNames ) );
}
@@ -330,14 +316,14 @@ void SCH_IO_HTTP_LIB::connect()
}
}
void SCH_IO_HTTP_LIB::syncCache()
{
for( const HTTP_LIB_CATEGORY& category : m_conn->getCategories() )
{
syncCache( category );
}
}
void SCH_IO_HTTP_LIB::syncCache( const HTTP_LIB_CATEGORY& category )
{
std::vector<HTTP_LIB_PART> found_parts;
@@ -363,9 +349,9 @@ void SCH_IO_HTTP_LIB::syncCache( const HTTP_LIB_CATEGORY& category )
}
LIB_SYMBOL* SCH_IO_HTTP_LIB::loadSymbolFromPart( const wxString& aSymbolName,
LIB_SYMBOL* SCH_IO_HTTP_LIB::loadSymbolFromPart( const wxString& aSymbolName,
const HTTP_LIB_CATEGORY& aCategory,
const HTTP_LIB_PART& aPart )
const HTTP_LIB_PART& aPart )
{
LIB_SYMBOL* symbol = nullptr;
LIB_SYMBOL* originalSymbol = nullptr;
@@ -379,14 +365,11 @@ LIB_SYMBOL* SCH_IO_HTTP_LIB::loadSymbolFromPart( const wxString& aSymbo
symbolId.Parse( symbolIdStr );
if( symbolId.IsValid() )
{
originalSymbol = m_libTable->LoadSymbol( symbolId );
}
if( originalSymbol )
{
wxLogTrace( traceHTTPLib, wxT( "loadSymbolFromPart: found original symbol '%s'" ),
symbolIdStr );
wxLogTrace( traceHTTPLib, wxT( "loadSymbolFromPart: found original symbol '%s'" ), symbolIdStr );
symbol = originalSymbol->Duplicate();
symbol->SetSourceLibId( symbolId );
@@ -397,17 +380,13 @@ LIB_SYMBOL* SCH_IO_HTTP_LIB::loadSymbolFromPart( const wxString& aSymbo
}
else if( !symbolId.IsValid() )
{
wxLogTrace( traceHTTPLib,
wxT( "loadSymbolFromPart: source symbol id '%s' is invalid, "
"will create empty symbol" ),
symbolIdStr );
wxLogTrace( traceHTTPLib, wxT( "loadSymbolFromPart: source symbol id '%s' is invalid, "
"will create empty symbol" ), symbolIdStr );
}
else
{
wxLogTrace( traceHTTPLib,
wxT( "loadSymbolFromPart: source symbol '%s' not found, "
"will create empty symbol" ),
symbolIdStr );
wxLogTrace( traceHTTPLib, wxT( "loadSymbolFromPart: source symbol '%s' not found, "
"will create empty symbol" ), symbolIdStr );
}
}
@@ -426,44 +405,50 @@ LIB_SYMBOL* SCH_IO_HTTP_LIB::loadSymbolFromPart( const wxString& aSymbo
symbol->SetExcludedFromBoard( aPart.exclude_from_board );
symbol->SetExcludedFromSim( aPart.exclude_from_sim );
SCH_FIELD* field;
wxArrayString fp_filters;
for( auto& _field : aPart.fields )
for( auto& [fieldName, fieldProperties] : aPart.fields )
{
wxString fieldName = wxString( _field.first );
std::tuple fieldProperties = _field.second;
wxString lowerFieldName = wxString( fieldName ).Lower();
if( fieldName.Lower() == footprint_field )
if( lowerFieldName == footprint_field )
{
field = &symbol->GetFootprintField();
SCH_FIELD* field = &symbol->GetFootprintField();
wxStringTokenizer tokenizer( std::get<0>( fieldProperties ), ';' );
while( tokenizer.HasMoreTokens() )
fp_filters.Add( tokenizer.GetNextToken() );
if( fp_filters.size() > 0 )
field->SetText( fp_filters[0] );
field->SetVisible( std::get<1>( fieldProperties ) );
}
else if( lowerFieldName == description_field )
{
SCH_FIELD* field = &symbol->GetDescriptionField();
field->SetText( std::get<0>( fieldProperties ) );
field->SetVisible( std::get<1>( fieldProperties ) );
}
else if( fieldName.Lower() == description_field )
else if( lowerFieldName == value_field )
{
field = &symbol->GetDescriptionField();
SCH_FIELD* field = &symbol->GetValueField();
field->SetText( std::get<0>( fieldProperties ) );
field->SetVisible( std::get<1>( fieldProperties ) );
}
else if( fieldName.Lower() == value_field )
else if( lowerFieldName == datasheet_field )
{
field = &symbol->GetValueField();
SCH_FIELD* field = &symbol->GetDatasheetField();
field->SetText( std::get<0>( fieldProperties ) );
field->SetVisible( std::get<1>( fieldProperties ) );
}
else if( fieldName.Lower() == datasheet_field )
else if( lowerFieldName == reference_field )
{
field = &symbol->GetDatasheetField();
SCH_FIELD* field = &symbol->GetReferenceField();
field->SetText( std::get<0>( fieldProperties ) );
field->SetVisible( std::get<1>( fieldProperties ) );
}
else if( fieldName.Lower() == reference_field )
{
field = &symbol->GetReferenceField();
field->SetText( std::get<0>( fieldProperties ) );
field->SetVisible( std::get<1>( fieldProperties ) );
}
else if( fieldName.Lower() == keywords_field )
else if( lowerFieldName == keywords_field )
{
symbol->SetKeyWords( std::get<0>( fieldProperties ) );
}
@@ -474,7 +459,7 @@ LIB_SYMBOL* SCH_IO_HTTP_LIB::loadSymbolFromPart( const wxString& aSymbo
// This proves useful in situations where, for instance, an individual requires a particular value, such as
// the material type showcased at a specific position for a capacitor. Subsequently, this value could be defined
// in the symbol itself and then, potentially, be modified by the HTTP library as necessary.
field = symbol->FindField( fieldName );
SCH_FIELD* field = symbol->FindField( fieldName );
if( field != nullptr )
{
@@ -497,6 +482,14 @@ LIB_SYMBOL* SCH_IO_HTTP_LIB::loadSymbolFromPart( const wxString& aSymbo
}
}
symbol->SetDescription( aPart.desc );
symbol->SetKeyWords( aPart.keywords );
for( const std::string& filter : aPart.fp_filters )
fp_filters.push_back( filter );
symbol->SetFPFilters( fp_filters );
return symbol;
}
+9 -17
View File
@@ -18,9 +18,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SCH_IO_HTTP_LIB_H
#define SCH_IO_HTTP_LIB_H
#pragma once
#include "http_lib/http_lib_settings.h"
#include <http_lib/http_lib_connection.h>
@@ -40,12 +38,11 @@ class SCH_IO_HTTP_LIB : public SCH_IO
{
public:
SCH_IO_HTTP_LIB();
virtual ~SCH_IO_HTTP_LIB();
~SCH_IO_HTTP_LIB() override = default;
const IO_BASE::IO_FILE_DESC GetLibraryDesc() const override
{
return IO_BASE::IO_FILE_DESC( _HKI( "KiCad HTTP library files" ),
{ FILEEXT::HTTPLibraryFileExtension } );
return IO_BASE::IO_FILE_DESC( _HKI( "KiCad HTTP library files" ), { FILEEXT::HTTPLibraryFileExtension } );
}
int GetModifyHash() const override { return 0; }
@@ -94,18 +91,15 @@ private:
LIB_SYMBOL* loadSymbolFromPart( const wxString& aSymbolName, const HTTP_LIB_CATEGORY& aCategory,
const HTTP_LIB_PART& aPart );
SYMBOL_LIB_TABLE* m_libTable;
private:
SYMBOL_LIB_TABLE* m_libTable;
/// Generally will be null if no valid connection is established
std::unique_ptr<HTTP_LIB_CONNECTION> m_conn;
std::unique_ptr<HTTP_LIB_SETTINGS> m_settings;
std::set<wxString> m_customFields;
std::set<wxString> m_defaultShownFields;
wxString m_lastError;
std::unique_ptr<HTTP_LIB_SETTINGS> m_settings;
std::set<wxString> m_customFields;
std::set<wxString> m_defaultShownFields;
wxString m_lastError;
wxString symbol_field = "symbol";
wxString footprint_field = "footprint";
@@ -118,5 +112,3 @@ private:
// category.id category
std::map<std::string, HTTP_LIB_CATEGORY> m_cachedCategories;
};
#endif // SCH_IO_HTTP_LIB_H_
@@ -2170,8 +2170,8 @@ void SCH_IO_KICAD_LEGACY::EnumerateSymbolLib( wxArrayString& aSymbolNameList,
void SCH_IO_KICAD_LEGACY::EnumerateSymbolLib( std::vector<LIB_SYMBOL*>& aSymbolList,
const wxString& aLibraryPath,
const std::map<std::string, UTF8>* aProperties )
const wxString& aLibraryPath,
const std::map<std::string, UTF8>* aProperties )
{
LOCALE_IO toggle; // toggles on, then off, the C locale.
@@ -514,7 +514,6 @@ void SCH_IO_KICAD_SEXPR::Format( SCH_SELECTION* aSelection, SCH_SHEET_PATH* aSel
m_schematic = &aSchematic;
m_out = aFormatter;
size_t i;
std::map<wxString, LIB_SYMBOL*> libSymbols;
SCH_SCREEN* screen = aSelection->GetScreen();
std::set<SCH_TABLE*> promotedTables;
@@ -249,7 +249,7 @@ void SCH_IO_KICAD_SEXPR_LIB_CACHE::SaveSymbol( LIB_SYMBOL* aSymbol, OUTPUTFORMAT
// if the unit has a display name, write that
if( aSymbol->HasUnitDisplayName( unit.m_unit ) )
{
name = aSymbol->GetUnitDisplayName( unit.m_unit );
name = aSymbol->GetUnitDisplayName( unit.m_unit, false );
aFormatter.Print( "(unit_name %s)", aFormatter.Quotes( name ).c_str() );
}
+85 -49
View File
@@ -50,28 +50,6 @@
#define BITMAP_FONT_SIZE_THRESHOLD 3
wxString SCH_ITEM::GetUnitDescription( int aUnit )
{
if( aUnit == 0 )
return _( "All" );
else
return LIB_SYMBOL::LetterSubReference( aUnit, 'A' );
}
wxString SCH_ITEM::GetBodyStyleDescription( int aBodyStyle )
{
if( aBodyStyle == 0 )
return _( "All" );
else if( aBodyStyle == BODY_STYLE::DEMORGAN )
return _( "Alternate" );
else if( aBodyStyle == BODY_STYLE::BASE )
return _( "Standard" );
else
return wxT( "?" );
}
/* Constructor and destructor for SCH_ITEM */
/* They are not inline because this creates problems with gcc at linking time in debug mode */
@@ -148,25 +126,52 @@ SCH_ITEM* SCH_ITEM::Duplicate( bool doClone ) const
}
void SCH_ITEM::SetUnitProp( int aUnit )
wxString SCH_ITEM::GetUnitDisplayName( int aUnit, bool aLabel ) const
{
if( GetParentSymbol() )
aUnit = std::min( aUnit, GetParentSymbol()->GetUnitCount() );
if( aUnit == 0 )
return aLabel ? _( "All units" ) : wxString( _HKI( "All units" ) );
else if( const SYMBOL* symbol = GetParentSymbol() )
return symbol->GetUnitDisplayName( aUnit, aLabel );
aUnit = std::max( aUnit, 0 );
m_unit = aUnit;
return wxEmptyString;
}
void SCH_ITEM::SetBodyStyleProp( int aBodyStyle )
wxString SCH_ITEM::GetBodyStyleDescription( int aBodyStyle, bool aLabel ) const
{
if( GetParentSymbol() && GetParentSymbol()->HasAlternateBodyStyle() )
aBodyStyle = std::min( aBodyStyle, (int) BODY_STYLE::DEMORGAN );
if( aBodyStyle == 0 )
return aLabel ? _( "All body styles" ) : wxString( _HKI( "All body styles" ) );
else if( const SYMBOL* symbol = GetParentSymbol() )
return symbol->GetBodyStyleDescription( aBodyStyle, aLabel );
aBodyStyle = std::max( aBodyStyle, 0 );
return wxEmptyString;
}
m_bodyStyle = aBodyStyle;
void SCH_ITEM::SetBodyStyleProp( const wxString& aBodyStyle )
{
if( aBodyStyle == _HKI( "All body styles" ) )
{
m_bodyStyle = 0;
return;
}
if( SYMBOL* symbol = GetParentSymbol() )
{
for( int bodyStyle : { BODY_STYLE::BASE, BODY_STYLE::DEMORGAN } )
{
if( symbol->GetBodyStyleDescription( bodyStyle, false ) == aBodyStyle )
{
m_bodyStyle = bodyStyle;
return;
}
}
}
}
wxString SCH_ITEM::GetBodyStyleProp() const
{
return GetBodyStyleDescription( m_bodyStyle, false );
}
@@ -535,23 +540,21 @@ bool SCH_ITEM::RenderAsBitmap( double aWorldScale ) const
}
void SCH_ITEM::getSymbolEditorMsgPanelInfo( EDA_DRAW_FRAME* aFrame,
std::vector<MSG_PANEL_ITEM>& aList )
void SCH_ITEM::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
{
wxString msg;
SYMBOL* symbol = GetParentSymbol();
aList.emplace_back( _( "Type" ), GetFriendlyName() );
if( !symbol )
return;
if( const SYMBOL* parent = GetParentSymbol() )
{
if( parent->GetUnitCount() )
aList.emplace_back( _( "Unit" ), GetUnitDescription( m_unit ) );
if( symbol->GetUnitCount() )
aList.emplace_back( _( "Unit" ), GetUnitDisplayName( GetUnit(), false ) );
if( parent->HasAlternateBodyStyle() )
aList.emplace_back( _( "Body Style" ), GetBodyStyleDescription( m_bodyStyle ) );
}
if( symbol->HasAlternateBodyStyle() )
aList.emplace_back( _( "Body Style" ), GetBodyStyleDescription( GetBodyStyle(), true ) );
if( IsPrivate() )
if( dynamic_cast<LIB_SYMBOL*>( symbol ) && IsPrivate() )
aList.emplace_back( _( "Private" ), wxEmptyString );
}
@@ -595,14 +598,47 @@ static struct SCH_ITEM_DESC
};
propMgr.AddProperty( new PROPERTY<SCH_ITEM, int>( _HKI( "Unit" ),
&SCH_ITEM::SetUnitProp, &SCH_ITEM::GetUnit ) )
&SCH_ITEM::SetUnit, &SCH_ITEM::GetUnit ) )
.SetAvailableFunc( multiUnit )
.SetIsHiddenFromDesignEditors();
.SetIsHiddenFromDesignEditors()
.SetChoicesFunc( []( INSPECTABLE* aItem )
{
wxPGChoices choices;
choices.Add( _HKI( "All units" ), 0 );
propMgr.AddProperty( new PROPERTY<SCH_ITEM, int>( _HKI( "Body Style" ),
&SCH_ITEM::SetBodyStyle, &SCH_ITEM::GetBodyStyle ) )
if( SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( aItem ) )
{
if( SYMBOL* symbol = item->GetParentSymbol() )
{
for( int ii = 1; ii <= symbol->GetUnitCount(); ii++ )
choices.Add( symbol->GetUnitDisplayName( ii, false ), ii );
}
}
return choices;
} );
propMgr.AddProperty( new PROPERTY<SCH_ITEM, wxString>( _HKI( "Body Style" ),
&SCH_ITEM::SetBodyStyleProp, &SCH_ITEM::GetBodyStyleProp ) )
.SetAvailableFunc( multiBodyStyle )
.SetIsHiddenFromDesignEditors();
.SetIsHiddenFromDesignEditors()
.SetChoicesFunc( []( INSPECTABLE* aItem )
{
wxPGChoices choices;
choices.Add( _HKI( "All body styles" ) );
if( SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( aItem ) )
{
if( SYMBOL* symbol = item->GetParentSymbol() )
{
for( int ii : { BODY_STYLE::BASE, BODY_STYLE::DEMORGAN } )
choices.Add( symbol->GetBodyStyleDescription( ii, false ) );
}
}
return choices;
} );
propMgr.AddProperty( new PROPERTY<SCH_ITEM, bool>( _HKI( "Private" ),
&SCH_ITEM::SetPrivate, &SCH_ITEM::IsPrivate ) )
+8 -7
View File
@@ -226,16 +226,17 @@ public:
*/
SCH_ITEM* Duplicate( bool doClone = false ) const;
static wxString GetUnitDescription( int aUnit );
static wxString GetBodyStyleDescription( int aBodyStyle );
virtual void SetUnit( int aUnit ) { m_unit = aUnit; }
int GetUnit() const { return m_unit; }
void SetUnitProp( int aUnit );
virtual wxString GetUnitDisplayName( int aUnit, bool aLabel ) const;
virtual wxString GetBodyStyleDescription( int aBodyStyle, bool aLabel ) const;
virtual void SetBodyStyle( int aBodyStyle ) { m_bodyStyle = aBodyStyle; }
int GetBodyStyle() const { return m_bodyStyle; }
void SetBodyStyleProp( int aBodyStyle );
virtual void SetBodyStyleProp( const wxString& aBodyStyle );
virtual wxString GetBodyStyleProp() const;
void SetPrivate( bool aPrivate ) { m_private = aPrivate; }
bool IsPrivate() const { return m_private; }
@@ -593,6 +594,8 @@ public:
virtual void SetStroke( const STROKE_PARAMS& aStroke ) { wxCHECK( false, /* void */ ); }
void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
/**
* Print an item.
*
@@ -688,8 +691,6 @@ protected:
bool operator()( const SCH_ITEM* aFirst, const SCH_ITEM* aSecond ) const;
};
void getSymbolEditorMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList );
/**
* Provide the draw object specific comparison called by the == and < operators.
*
+1 -1
View File
@@ -2274,7 +2274,7 @@ static struct SCH_LABEL_DESC
[]( INSPECTABLE* aItem ) -> bool
{
if( SCH_LABEL_BASE* label = dynamic_cast<SCH_LABEL_BASE*>( aItem ) )
return label->IsType( { SCH_GLOBAL_LABEL_T, SCH_HIER_LABEL_T } );
return label->IsType( { SCH_GLOBAL_LABEL_T, SCH_HIER_LABEL_T, SCH_SHEET_PIN_T } );
return false;
};
+5 -2
View File
@@ -191,8 +191,11 @@ void SCH_LINE::Show( int nestLevel, std::ostream& os ) const
std::vector<int> SCH_LINE::ViewGetLayers() const
{
return { LAYER_DANGLING, m_layer, LAYER_SELECTION_SHADOWS, LAYER_NET_COLOR_HIGHLIGHT,
LAYER_OP_VOLTAGES };
if( IsWire() || IsBus() )
return { LAYER_DANGLING, m_layer, LAYER_SELECTION_SHADOWS, LAYER_NET_COLOR_HIGHLIGHT,
LAYER_OP_VOLTAGES };
return { LAYER_DANGLING, m_layer, LAYER_SELECTION_SHADOWS, LAYER_OP_VOLTAGES };
}
+3
View File
@@ -1291,6 +1291,9 @@ void SCH_PAINTER::draw( const SCH_LINE* aLine, int aLayer )
if( !highlightNetclassColors && drawingNetColorHighlights )
return;
if( drawingNetColorHighlights && !( aLine->IsWire() || aLine->IsBus() ) )
return;
if( m_schSettings.m_OverrideItemColors && drawingNetColorHighlights )
return;
+16 -69
View File
@@ -43,32 +43,6 @@
// small margin in internal units between the pin text and the pin line
#define PIN_TEXT_MARGIN 4
wxString SCH_PIN::GetCanonicalElectricalTypeName( ELECTRICAL_PINTYPE aType )
{
// These strings are the canonical name of the electrictal type
// Not translated, no space in name, only ASCII chars.
// to use when the string name must be known and well defined
// must have same order than enum ELECTRICAL_PINTYPE (see sch_pin.h)
static const wxChar* msgPinElectricType[] =
{
wxT( "input" ),
wxT( "output" ),
wxT( "bidirectional" ),
wxT( "tri_state" ),
wxT( "passive" ),
wxT( "free" ),
wxT( "unspecified" ),
wxT( "power_in" ),
wxT( "power_out" ),
wxT( "open_collector" ),
wxT( "open_emitter" ),
wxT( "no_connect" )
};
return msgPinElectricType[static_cast<int>( aType )];
}
/// Utility for getting the size of the 'internal' pin decorators (as a radius)
/// i.e. the clock symbols (falling clock is actually external but is of
/// the same kind)
@@ -334,29 +308,25 @@ void SCH_PIN::SetType( ELECTRICAL_PINTYPE aType )
wxString SCH_PIN::GetCanonicalElectricalTypeName() const
{
if( m_type == ELECTRICAL_PINTYPE::PT_INHERIT )
{
if( !m_libPin )
return GetCanonicalElectricalTypeName( ELECTRICAL_PINTYPE::PT_UNSPECIFIED );
if( m_type != ELECTRICAL_PINTYPE::PT_INHERIT )
return ::GetCanonicalElectricalTypeName( m_type );
return m_libPin->GetCanonicalElectricalTypeName();
}
if( !m_libPin )
return ::GetCanonicalElectricalTypeName( ELECTRICAL_PINTYPE::PT_UNSPECIFIED );
return GetCanonicalElectricalTypeName( m_type );
return m_libPin->GetCanonicalElectricalTypeName();
}
wxString SCH_PIN::GetElectricalTypeName() const
{
if( m_type == ELECTRICAL_PINTYPE::PT_INHERIT )
{
if( !m_libPin )
return ElectricalPinTypeGetText( ELECTRICAL_PINTYPE::PT_UNSPECIFIED );
if( m_type != ELECTRICAL_PINTYPE::PT_INHERIT )
return ElectricalPinTypeGetText( m_type );
return m_libPin->GetElectricalTypeName();
}
if( !m_libPin )
return ElectricalPinTypeGetText( ELECTRICAL_PINTYPE::PT_UNSPECIFIED );
return ElectricalPinTypeGetText( m_type );
return m_libPin->GetElectricalTypeName();
}
@@ -1472,10 +1442,10 @@ void SCH_PIN::ChangeLength( int aLength )
offsetX = -1 * lengthChange;
break;
case PIN_ORIENTATION::PIN_UP:
offsetY = lengthChange;
offsetY = -1 * lengthChange;
break;
case PIN_ORIENTATION::PIN_DOWN:
offsetY = -1 * lengthChange;
offsetY = lengthChange;
break;
}
@@ -1594,28 +1564,9 @@ void SCH_PIN::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITE
wxString msg;
SYMBOL* symbol = GetParentSymbol();
if( dynamic_cast<LIB_SYMBOL*>( symbol ) )
{
getSymbolEditorMsgPanelInfo( aFrame, aList );
}
else
{
aList.emplace_back( _( "Type" ), _( "Pin" ) );
aList.emplace_back( _( "Type" ), _( "Pin" ) );
if( symbol->GetUnitCount() )
{
msg = m_libPin ? GetUnitDescription( m_libPin->GetUnit() ) :
wxString( "Undefined library pin." );
aList.emplace_back( _( "Unit" ), msg );
}
if( symbol->HasAlternateBodyStyle() )
{
msg = m_libPin ? GetBodyStyleDescription( m_libPin->GetBodyStyle() ) :
wxString( "Undefined library pin." );
aList.emplace_back( _( "Body Style" ), msg );
}
}
SCH_ITEM::GetMsgPanelInfo( aFrame, aList );
aList.emplace_back( _( "Name" ), UnescapeString( GetShownName() ) );
aList.emplace_back( _( "Number" ), GetShownNumber() );
@@ -1828,11 +1779,7 @@ bool SCH_PIN::HasConnectivityChanges( const SCH_ITEM* aItem,
bool SCH_PIN::ConnectionPropagatesTo( const EDA_ITEM* aItem ) const
{
if( !m_libPin )
return false;
// Reciprocal checking is done in CONNECTION_GRAPH anyway
return m_libPin->GetType() != ELECTRICAL_PINTYPE::PT_NC;
return GetType() != ELECTRICAL_PINTYPE::PT_NC;
}
@@ -2207,7 +2154,7 @@ static struct SCH_PIN_DESC
.SetWriteableFunc( isSymbolEditor );
propMgr.AddProperty( new PROPERTY<SCH_PIN, int>( _HKI( "Length" ),
&SCH_PIN::SetLength, &SCH_PIN::GetLength,
&SCH_PIN::ChangeLength, &SCH_PIN::GetLength,
PROPERTY_DISPLAY::PT_SIZE ) )
.SetWriteableFunc( isSymbolEditor );
+1 -4
View File
@@ -523,10 +523,7 @@ void SCH_SHAPE::Print( const SCH_RENDER_SETTINGS* aSettings, int aUnit, int aBod
void SCH_SHAPE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
{
if( m_layer == LAYER_DEVICE )
getSymbolEditorMsgPanelInfo( aFrame, aList );
else
SCH_ITEM::GetMsgPanelInfo( aFrame, aList );
SCH_ITEM::GetMsgPanelInfo( aFrame, aList );
ShapeGetMsgPanelInfo( aFrame, aList );
}
+17 -1
View File
@@ -45,6 +45,8 @@
#include <settings/color_settings.h>
#include <settings/settings_manager.h>
#include <trace_helpers.h>
#include <validators.h>
#include <properties/property_validators.h>
#include <pgm_base.h>
#include <wx/log.h>
@@ -1729,7 +1731,21 @@ static struct SCH_SHEET_DESC
propMgr.InheritsAfter( TYPE_HASH( SCH_SHEET ), TYPE_HASH( SCH_ITEM ) );
propMgr.AddProperty( new PROPERTY<SCH_SHEET, wxString>( _HKI( "Sheet Name" ),
&SCH_SHEET::SetName, &SCH_SHEET::GetName ) );
&SCH_SHEET::SetName, &SCH_SHEET::GetName ) )
.SetValidator( []( const wxAny&& aValue, EDA_ITEM* ) -> VALIDATOR_RESULT
{
wxString value;
if( !aValue.GetAs( &value ) )
return {};
wxString msg = GetFieldValidationErrorMessage( SHEETNAME_V, value );
if( msg.empty() )
return {};
return std::make_unique<VALIDATION_ERROR_MSG>( msg );
} );
propMgr.AddProperty( new PROPERTY<SCH_SHEET, int>( _HKI( "Border Width" ),
&SCH_SHEET::SetBorderWidth, &SCH_SHEET::GetBorderWidth,
+60 -27
View File
@@ -330,6 +330,8 @@ void SCH_SYMBOL::UpdatePins()
ii->second.erase( it );
pin->SetLibPin( libPin );
pin->SetPosition( libPin->GetPosition() );
pin->SetUnit( libPin->GetUnit() );
pin->SetBodyStyle( libPin->GetBodyStyle() );
unassignedSchPins.erase( pin );
@@ -362,6 +364,8 @@ void SCH_SYMBOL::UpdatePins()
m_pinMap[ libPin ] = pin;
pin->SetLibPin( libPin );
pin->SetPosition( libPin->GetPosition() );
pin->SetUnit( libPin->GetUnit() );
pin->SetBodyStyle( libPin->GetBodyStyle() );
pin->SetNumber( libPin->GetNumber() );
auto iii = altPinMap.find( libPin->GetNumber() );
@@ -440,19 +444,27 @@ int SCH_SYMBOL::GetUnitCount() const
}
wxString SCH_SYMBOL::GetUnitDisplayName( int aUnit ) const
wxString SCH_SYMBOL::GetUnitDisplayName( int aUnit, bool aLabel ) const
{
wxCHECK( m_part, ( wxString::Format( _( "Unit %s" ), SubReference( aUnit ) ) ) );
return m_part->GetUnitDisplayName( aUnit );
if( m_part )
return m_part->GetUnitDisplayName( aUnit, aLabel );
else if( aLabel )
return wxString::Format( _( "Unit %s" ), SubReference( aUnit ) );
else
return SubReference( aUnit );
}
bool SCH_SYMBOL::HasUnitDisplayName( int aUnit ) const
wxString SCH_SYMBOL::GetBodyStyleDescription( int aBodyStyle, bool aLabel ) const
{
wxCHECK( m_part, false );
return m_part->HasUnitDisplayName( aUnit );
if( m_part )
return m_part->GetBodyStyleDescription( aBodyStyle, aLabel );
else if( aBodyStyle == BODY_STYLE::DEMORGAN )
return aLabel ? _( "Alternate" ) : wxString( _HKI( "Alternate" ) );
else if( aBodyStyle == BODY_STYLE::BASE )
return aLabel ? _( "Standard" ) : wxString( _HKI( "Standard" ) );
else
return wxT( "?" );
}
@@ -550,8 +562,8 @@ void SCH_SYMBOL::Print( const SCH_RENDER_SETTINGS* aSettings, int aUnit, int aBo
}
bool SCH_SYMBOL::GetInstance( SCH_SYMBOL_INSTANCE& aInstance,
const KIID_PATH& aSheetPath, bool aTestFromEnd ) const
bool SCH_SYMBOL::GetInstance( SCH_SYMBOL_INSTANCE& aInstance, const KIID_PATH& aSheetPath,
bool aTestFromEnd ) const
{
for( const SCH_SYMBOL_INSTANCE& instance : m_instanceReferences )
{
@@ -1224,15 +1236,12 @@ std::vector<SCH_PIN*> SCH_SYMBOL::GetPins( const SCH_SHEET_PATH* aSheet ) const
if( aSheet )
unit = GetUnitSelection( aSheet );
for( const std::unique_ptr<SCH_PIN>& p : m_pins )
for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
{
if( unit && p->GetLibPin() && p->GetLibPin()->GetUnit()
&& ( p->GetLibPin()->GetUnit() != unit ) )
{
if( unit && pin->GetUnit() && pin->GetUnit() != unit )
continue;
}
pins.push_back( p.get() );
pins.push_back( pin.get() );
}
return pins;
@@ -2084,6 +2093,11 @@ BITMAPS SCH_SYMBOL::GetMenuImage() const
EMBEDDED_FILES* SCH_SYMBOL::GetEmbeddedFiles()
{
std::unique_ptr<LIB_SYMBOL>& libSymbolRef = GetLibSymbolRef();
if( !libSymbolRef )
return nullptr;
return GetLibSymbolRef()->GetEmbeddedFiles();
}
@@ -2525,15 +2539,10 @@ bool SCH_SYMBOL::doIsConnected( const VECTOR2I& aPosition ) const
// Collect only pins attached to the current unit and convert.
// others are not associated to this symbol instance
int pin_unit = pin->GetLibPin() ? pin->GetLibPin()->GetUnit()
: GetUnit();
int pin_bodyStyle = pin->GetLibPin() ? pin->GetLibPin()->GetBodyStyle()
: GetBodyStyle();
if( pin_unit > 0 && pin_unit != GetUnit() )
if( pin->GetUnit() > 0 && pin->GetUnit() != GetUnit() )
continue;
if( pin_bodyStyle > 0 && pin_bodyStyle != GetBodyStyle() )
if( pin->GetBodyStyle() > 0 && pin->GetBodyStyle() != GetBodyStyle() )
continue;
if( pin->GetLocalPosition() == new_pos )
@@ -2981,13 +2990,37 @@ static struct SCH_SYMBOL_DESC
return false;
};
propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, wxString>( _HKI( "Unit" ),
propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, int>( _HKI( "Unit" ),
&SCH_SYMBOL::SetUnitProp, &SCH_SYMBOL::GetUnitProp ) )
.SetAvailableFunc( multiUnit );
.SetAvailableFunc( multiUnit )
.SetChoicesFunc( []( INSPECTABLE* aItem )
{
wxPGChoices choices;
propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, int>( _HKI( "Body Style" ),
if( SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( aItem ) )
{
for( int ii = 1; ii <= symbol->GetUnitCount(); ii++ )
choices.Add( symbol->GetUnitDisplayName( ii, false ), ii );
}
return choices;
} );
propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, wxString>( _HKI( "Body Style" ),
&SCH_SYMBOL::SetBodyStyleProp, &SCH_SYMBOL::GetBodyStyleProp ) )
.SetAvailableFunc( multiBodyStyle );
.SetAvailableFunc( multiBodyStyle )
.SetChoicesFunc( []( INSPECTABLE* aItem )
{
wxPGChoices choices;
if( SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( aItem ) )
{
for( int ii : { BODY_STYLE::BASE, BODY_STYLE::DEMORGAN } )
choices.Add( symbol->GetBodyStyleDescription( ii, false ) );
}
return choices;
} );
const wxString groupAttributes = _HKI( "Attributes" );
+21 -40
View File
@@ -221,19 +221,14 @@ public:
*/
void UpdatePins();
/**
* Return true if the given unit \a aUnit has a display name set.
*
* @return true if the display name of a unit is set, otherwise false.
*/
bool HasUnitDisplayName( int aUnit ) const;
/**
* Return the display name for a given unit \a aUnit.
*
* @return the display name of a unit if set, or the ordinal name of the unit otherwise.
*/
wxString GetUnitDisplayName( int aUnit ) const;
wxString GetUnitDisplayName( int aUnit, bool aLabel ) const override;
wxString GetBodyStyleDescription( int aBodyStyle, bool aLabel ) const override;
void SetBodyStyle( int aBodyStyle ) override;
@@ -510,6 +505,7 @@ public:
}
void SetRefProp( const wxString& aRef );
wxString GetValueProp() const
{
return GetValue( false, &Schematic()->CurrentSheet(), false );
@@ -520,47 +516,32 @@ public:
SetValueFieldText( aRef );
}
wxString GetUnitProp() const
int GetUnitProp() const
{
int unit = GetUnitSelection( &Schematic()->CurrentSheet() );
if( HasUnitDisplayName( unit ) )
return GetUnitDisplayName( unit );
else
return SubReference( unit, false );
return GetUnitSelection( &Schematic()->CurrentSheet() );
}
void SetUnitProp( const wxString& aUnit )
void SetUnitProp( int aUnit )
{
for( int unit = 1; unit <= GetUnitCount(); unit++ )
SetUnitSelection( &Schematic()->CurrentSheet(), aUnit );
SetUnit( aUnit );
}
wxString GetBodyStyleProp() const override
{
return GetBodyStyleDescription( GetBodyStyle(), false );
}
void SetBodyStyleProp( const wxString& aBodyStyle ) override
{
for( int bodyStyle : { BODY_STYLE::BASE, BODY_STYLE::DEMORGAN } )
{
if( HasUnitDisplayName( unit ) && GetUnitDisplayName( unit ) == aUnit )
if( GetBodyStyleDescription( bodyStyle, false ) == aBodyStyle )
{
SetUnitSelection( &Schematic()->CurrentSheet(), unit );
SetUnit( unit );
SetBodyStyle( bodyStyle );
return;
}
}
for( int unit = 1; unit <= GetUnitCount(); unit++ )
{
if( SubReference( unit, false ) == aUnit )
{
SetUnitSelection( &Schematic()->CurrentSheet(), unit );
SetUnit( unit );
return;
}
}
}
int GetBodyStyleProp() const
{
return GetBodyStyle();
}
void SetBodyStyleProp( int aBodyStyle )
{
SetBodyStyle( aBodyStyle );
}
/**
+2
View File
@@ -580,6 +580,8 @@ void SCH_TABLE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_I
{
// Don't use GetShownText() here; we want to show the user the variable references
aList.emplace_back( _( "Table" ), wxString::Format( _( "%d Columns" ), m_colCount ) );
SCH_ITEM::GetMsgPanelInfo( aFrame, aList );
}
+2
View File
@@ -636,6 +636,8 @@ void SCH_TEXT::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_IT
// Don't use GetShownText() here; we want to show the user the variable references
aList.emplace_back( _( "Text" ), KIUI::EllipsizeStatusText( aFrame, GetText() ) );
SCH_ITEM::GetMsgPanelInfo( aFrame, aList );
if( m_excludedFromSim )
aList.emplace_back( _( "Exclude from" ), _( "Simulation" ) );
+2
View File
@@ -531,6 +531,8 @@ void SCH_TEXTBOX::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL
// Don't use GetShownText() here; we want to show the user the variable references
aList.emplace_back( _( "Text Box" ), KIUI::EllipsizeStatusText( aFrame, GetText() ) );
SCH_ITEM::GetMsgPanelInfo( aFrame, aList );
if( m_excludedFromSim )
aList.emplace_back( _( "Exclude from" ), _( "Simulation" ) );
+13
View File
@@ -913,6 +913,18 @@ const EMBEDDED_FILES* SCHEMATIC::GetEmbeddedFiles() const
}
void SCHEMATIC::RunOnNestedEmbeddedFiles( const std::function<void( EMBEDDED_FILES* )>& aFunction )
{
SCH_SCREENS screens( Root() );
for( SCH_SCREEN* screen = screens.GetFirst(); screen; screen = screens.GetNext() )
{
for( auto& [name, libSym] : screen->GetLibSymbols() )
aFunction( libSym->GetEmbeddedFiles() );
}
}
std::set<KIFONT::OUTLINE_FONT*> SCHEMATIC::GetFonts() const
{
std::set<KIFONT::OUTLINE_FONT*> fonts;
@@ -1277,6 +1289,7 @@ void SCHEMATIC::RecalculateConnections( SCH_COMMIT* aCommit, SCH_CLEANUP_FLAGS a
PICKED_ITEMS_LIST* aLastChangeList )
{
SCHEMATIC_SETTINGS& settings = Settings();
RefreshHierarchy();
SCH_SHEET_LIST list = Hierarchy();
SCH_COMMIT localCommit( aToolManager );
+2
View File
@@ -376,6 +376,8 @@ public:
*/
void RemoveAllListeners();
void RunOnNestedEmbeddedFiles( const std::function<void( EMBEDDED_FILES* )>& aFunction ) override;
/**
* Embed fonts in the schematic.
*/
+2 -1
View File
@@ -1756,7 +1756,8 @@ void SIM_MODEL::MigrateSimModel( T& aSymbol, const PROJECT* aProject )
embeddedFilesStack.push_back( symbol->Schematic()->GetEmbeddedFiles() );
}
embeddedFilesStack.push_back( aSymbol.GetEmbeddedFiles() );
if( EMBEDDED_FILES* symbolEmbeddedFiles = aSymbol.GetEmbeddedFiles() )
embeddedFilesStack.push_back( symbolEmbeddedFiles );
libMgr.SetFilesStack( embeddedFilesStack );
+5 -1
View File
@@ -1016,6 +1016,7 @@ void SIMULATOR_FRAME_UI::OnFilterText( wxCommandEvent& aEvent )
void SIMULATOR_FRAME_UI::OnFilterMouseMoved( wxMouseEvent& aEvent )
{
#if defined( __WXOSX__ ) || wxCHECK_VERSION( 3, 3, 0 ) // Doesn't work properly on other ports
wxPoint pos = aEvent.GetPosition();
wxRect ctrlRect = m_filter->GetScreenRect();
int buttonWidth = ctrlRect.GetHeight(); // Presume buttons are square
@@ -1026,6 +1027,7 @@ void SIMULATOR_FRAME_UI::OnFilterMouseMoved( wxMouseEvent& aEvent )
SetCursor( wxCURSOR_ARROW );
else
SetCursor( wxCURSOR_IBEAM );
#endif
}
@@ -1483,7 +1485,9 @@ void SIMULATOR_FRAME_UI::UpdateTunerValue( const SCH_SHEET_PATH& aSheetPath, con
std::vector<EMBEDDED_FILES*> embeddedFilesStack;
embeddedFilesStack.push_back( m_schematicFrame->Schematic().GetEmbeddedFiles() );
embeddedFilesStack.push_back( symbol->GetEmbeddedFiles() );
if( EMBEDDED_FILES* symbolEmbeddedFiles = symbol->GetEmbeddedFiles() )
embeddedFilesStack.push_back( symbolEmbeddedFiles );
mgr.SetFilesStack( embeddedFilesStack );
+10 -10
View File
@@ -86,7 +86,7 @@ void CheckDuplicatePins( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
pin->GetName(),
aUnitsProvider->MessageTextFromValue( pin->GetPosition().x ),
aUnitsProvider->MessageTextFromValue( -pin->GetPosition().y ),
SCH_ITEM::GetBodyStyleDescription( pin->GetBodyStyle() ).Lower() );
aSymbol->GetBodyStyleDescription( pin->GetBodyStyle(), true ).Lower() );
}
else
{
@@ -101,9 +101,9 @@ void CheckDuplicatePins( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
pinName,
aUnitsProvider->MessageTextFromValue( pin->GetPosition().x ),
aUnitsProvider->MessageTextFromValue( -pin->GetPosition().y ),
aSymbol->GetUnitReference( next->GetUnit() ),
aSymbol->GetUnitReference( pin->GetUnit() ),
SCH_ITEM::GetBodyStyleDescription( pin->GetBodyStyle() ).Lower() );
aSymbol->GetUnitDisplayName( next->GetUnit(), false ),
aSymbol->GetUnitDisplayName( pin->GetUnit(), false ),
aSymbol->GetBodyStyleDescription( pin->GetBodyStyle(), true ).Lower() );
}
}
else
@@ -134,8 +134,8 @@ void CheckDuplicatePins( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
pinName,
aUnitsProvider->MessageTextFromValue( pin->GetPosition().x ),
aUnitsProvider->MessageTextFromValue( -pin->GetPosition().y ),
aSymbol->GetUnitReference( next->GetUnit() ),
aSymbol->GetUnitReference( pin->GetUnit() ) );
aSymbol->GetUnitDisplayName( next->GetUnit(), false ),
aSymbol->GetUnitDisplayName( pin->GetUnit(), false ) );
}
}
@@ -272,7 +272,7 @@ void CheckLibSymbol( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
pinName,
aUnitsProvider->MessageTextFromValue( pin->GetPosition().x ),
aUnitsProvider->MessageTextFromValue( -pin->GetPosition().y ),
SCH_ITEM::GetBodyStyleDescription( pin->GetBodyStyle() ).Lower() );
aSymbol->GetBodyStyleDescription( pin->GetBodyStyle(), true ).Lower() );
}
else
{
@@ -283,7 +283,7 @@ void CheckLibSymbol( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
aUnitsProvider->MessageTextFromValue( pin->GetPosition().x ),
aUnitsProvider->MessageTextFromValue( -pin->GetPosition().y ),
'A' + pin->GetUnit() - 1,
SCH_ITEM::GetBodyStyleDescription( pin->GetBodyStyle() ).Lower() );
aSymbol->GetBodyStyleDescription( pin->GetBodyStyle(), true ).Lower() );
}
}
else
@@ -331,7 +331,7 @@ void CheckLibSymbol( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
pinName,
aUnitsProvider->MessageTextFromValue( pin->GetPosition().x ),
aUnitsProvider->MessageTextFromValue( -pin->GetPosition().y ),
SCH_ITEM::GetBodyStyleDescription( pin->GetBodyStyle() ).Lower() );
aSymbol->GetBodyStyleDescription( pin->GetBodyStyle(), true ).Lower() );
}
else
{
@@ -342,7 +342,7 @@ void CheckLibSymbol( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
aUnitsProvider->MessageTextFromValue( pin->GetPosition().x ),
aUnitsProvider->MessageTextFromValue( -pin->GetPosition().y ),
'A' + pin->GetUnit() - 1,
SCH_ITEM::GetBodyStyleDescription( pin->GetBodyStyle() ).Lower() );
aSymbol->GetBodyStyleDescription( pin->GetBodyStyle(), true ).Lower() );
}
}
else
+3 -3
View File
@@ -314,7 +314,7 @@ SYMBOL_EDIT_FRAME::~SYMBOL_EDIT_FRAME()
void SYMBOL_EDIT_FRAME::LoadSettings( APP_SETTINGS_BASE* aCfg )
{
wxCHECK_RET( m_settings, "Call to SYMBOL_EDIT_FRAME::LoadSettings with null m_boardAdapter" );
wxCHECK_RET( m_settings, "Call to SYMBOL_EDIT_FRAME::LoadSettings with null m_settings" );
SCH_BASE_FRAME::LoadSettings( GetSettings() );
@@ -328,7 +328,7 @@ void SYMBOL_EDIT_FRAME::LoadSettings( APP_SETTINGS_BASE* aCfg )
void SYMBOL_EDIT_FRAME::SaveSettings( APP_SETTINGS_BASE* aCfg )
{
wxCHECK_RET( m_settings, "Call to SYMBOL_EDIT_FRAME::LoadSettings with null m_boardAdapter" );
wxCHECK_RET( m_settings, "Call to SYMBOL_EDIT_FRAME:SaveSettings with null m_settings" );
GetGalDisplayOptions().m_axesEnabled = true;
@@ -715,7 +715,7 @@ void SYMBOL_EDIT_FRAME::RebuildSymbolUnitsList()
{
for( int i = 0; i < m_symbol->GetUnitCount(); i++ )
{
wxString unitDisplayName = m_symbol->GetUnitDisplayName( i + 1 );
wxString unitDisplayName = m_symbol->GetUnitDisplayName( i + 1, true );
m_unitSelectBox->Append( unitDisplayName );
}
}
+1 -1
View File
@@ -502,7 +502,7 @@ void SYMBOL_VIEWER_FRAME::onUpdateUnitChoice( wxUpdateUIEvent& aEvent )
for( int ii = 0; ii < unit_count; ii++ )
{
wxString unit = symbol->GetUnitDisplayName( ii + 1 );
wxString unit = symbol->GetUnitDisplayName( ii + 1, true );
m_unitChoice->Append( unit );
}
+1 -1
View File
@@ -71,7 +71,7 @@ bool BACK_ANNOTATE::BackAnnotateSymbols( const std::string& aNetlist )
m_changesCount = 0;
if( !m_matchByReference && !m_processValues && !m_processFootprints && !m_processReferences
&& !m_processNetNames && !m_processAttributes )
&& !m_processNetNames && !m_processAttributes && !m_processOtherFields )
{
m_reporter.ReportTail( _( "Select at least one property to back annotate." ),
RPT_SEVERITY_ERROR );
+4 -2
View File
@@ -834,8 +834,10 @@ TOOL_ACTION SCH_ACTIONS::toLabel( TOOL_ACTION_ARGS()
.Flags( AF_NONE )
.Parameter( SCH_LABEL_T ) );
TOOL_ACTION SCH_ACTIONS::toCLabel( TOOL_ACTION_ARGS()
.Name( "eeschema.InteractiveEdit.toCLabel" )
TOOL_ACTION SCH_ACTIONS::toDLabel(TOOL_ACTION_ARGS()
.Name( "eeschema.InteractiveEdit.toCLabel" ) // Old name based on netClass label.
// There's no sense losing hotkey assignments, so we
// leave it as-is)
.Scope( AS_GLOBAL )
.FriendlyName( _( "Change to Directive Label" ) )
.Tooltip( _( "Change existing item to a directive label" ) )
+1 -1
View File
@@ -142,7 +142,7 @@ public:
static TOOL_ACTION showDeMorganAlternate;
static TOOL_ACTION editSymbolUnit;
static TOOL_ACTION toLabel;
static TOOL_ACTION toCLabel;
static TOOL_ACTION toDLabel;
static TOOL_ACTION toHLabel;
static TOOL_ACTION toGLabel;
static TOOL_ACTION toText;

Some files were not shown because too many files have changed in this diff Show More