KiCad PCB EDA Suite
Loading...
Searching...
No Matches
kicad_clipboard.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.TXT for contributors.
5 * @author Kristoffer Ödmark
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21#include <wx/clipbrd.h>
22#include <wx/log.h>
23
24#include <board.h>
25#include <build_version.h>
26#include <core/ignore.h>
27#include <footprint.h>
28#include <font/fontconfig.h>
29#include <pad.h>
30#include <pcb_group.h>
33#include <pcb_generator.h>
34#include <pcb_text.h>
35#include <pcb_table.h>
36#include <zone.h>
37#include <locale_io.h>
40#include <kicad_clipboard.h>
41#include <kidialog.h>
43
52
53
57
58
60{
61 m_board = aBoard;
62}
63
64
65void CLIPBOARD_IO::clipboardWriter( const wxString& aData )
66{
67 wxLogNull doNotLog; // disable logging of failed clipboard actions
68 auto clipboard = wxTheClipboard;
69 wxClipboardLocker clipboardLock( clipboard );
70
71 if( !clipboardLock || !clipboard->IsOpened() )
72 return;
73
74 clipboard->SetData( new wxTextDataObject( aData ) );
75
76 clipboard->Flush();
77
78#ifndef __WXOSX__
79 // This section exists to return the clipboard data, ensuring it has fully
80 // been processed by the system clipboard. This appears to be needed for
81 // extremely large clipboard copies on asynchronous linux clipboard managers
82 // such as KDE's Klipper. However, a read back of the data on OSX before the
83 // clipboard is closed seems to cause an ASAN error (heap-buffer-overflow)
84 // since it uses the cached version of the clipboard data and not the system
85 // clipboard data.
86 if( clipboard->IsSupported( wxDF_TEXT ) || clipboard->IsSupported( wxDF_UNICODETEXT ) )
87 {
88 wxTextDataObject data;
89 clipboard->GetData( data );
90 ignore_unused( data.GetText() );
91 }
92#endif
93}
94
95
97{
98 wxLogNull doNotLog; // disable logging of failed clipboard actions
99
100 auto clipboard = wxTheClipboard;
101 wxClipboardLocker clipboardLock( clipboard );
102
103 if( !clipboardLock )
104 return wxEmptyString;
105
106 if( clipboard->IsSupported( wxDF_TEXT ) || clipboard->IsSupported( wxDF_UNICODETEXT ) )
107 {
108 wxTextDataObject data;
109 clipboard->GetData( data );
110 return data.GetText();
111 }
112
113 return wxEmptyString;
114}
115
116
117void CLIPBOARD_IO::SaveSelection( const PCB_SELECTION& aSelected, bool isFootprintEditor )
118{
119 VECTOR2I refPoint( 0, 0 );
120
121 // dont even start if the selection is empty
122 if( aSelected.Empty() )
123 return;
124
125 if( aSelected.HasReferencePoint() )
126 refPoint = aSelected.GetReferencePoint();
127
128 auto deleteUnselectedCells =
129 []( PCB_TABLE* aTable )
130 {
131 int minCol = aTable->GetColCount();
132 int maxCol = -1;
133 int minRow = aTable->GetRowCount();
134 int maxRow = -1;
135
136 for( int row = 0; row < aTable->GetRowCount(); ++row )
137 {
138 for( int col = 0; col < aTable->GetColCount(); ++col )
139 {
140 PCB_TABLECELL* cell = aTable->GetCell( row, col );
141
142 if( cell->IsSelected() )
143 {
144 minRow = std::min( minRow, row );
145 maxRow = std::max( maxRow, row );
146 minCol = std::min( minCol, col );
147 maxCol = std::max( maxCol, col );
148 }
149 else
150 {
151 cell->SetFlags( STRUCT_DELETED );
152 }
153 }
154 }
155
156 wxCHECK_MSG( maxCol >= minCol && maxRow >= minRow, /*void*/,
157 wxT( "No selected cells!" ) );
158
159 // aTable is always a clone in the clipboard case
160 int destRow = 0;
161
162 for( int row = minRow; row <= maxRow; row++ )
163 aTable->SetRowHeight( destRow++, aTable->GetRowHeight( row ) );
164
165 int destCol = 0;
166
167 for( int col = minCol; col <= maxCol; col++ )
168 aTable->SetColWidth( destCol++, aTable->GetColWidth( col ) );
169
170 aTable->DeleteMarkedCells();
171 aTable->SetColCount( ( maxCol - minCol ) + 1 );
172 aTable->Normalize();
173 };
174
175 std::set<PCB_TABLE*> promotedTables;
176
177 auto parentIsPromoted =
178 [&]( PCB_TABLECELL* cell ) -> bool
179 {
180 for( PCB_TABLE* table : promotedTables )
181 {
182 if( table->m_Uuid == cell->GetParent()->m_Uuid )
183 return true;
184 }
185
186 return false;
187 };
188
189 if( aSelected.Size() == 1 && aSelected.Front()->Type() == PCB_FOOTPRINT_T )
190 {
191 // make the footprint safe to transfer to other pcbs
192 const FOOTPRINT* footprint = static_cast<FOOTPRINT*>( aSelected.Front() );
193 // Do not modify existing board
194 FOOTPRINT newFootprint( *footprint );
195
196 for( PAD* pad : newFootprint.Pads() )
197 pad->SetNetCode( 0 );
198
199 // locked means "locked in place"; copied items therefore can't be locked
200 newFootprint.SetLocked( false );
201
202 // locate the reference point at (0, 0) in the copied items
203 newFootprint.Move( VECTOR2I( -refPoint.x, -refPoint.y ) );
204
205 Format( static_cast<BOARD_ITEM*>( &newFootprint ) );
206
207 newFootprint.SetParent( nullptr );
208 newFootprint.SetParentGroup( nullptr );
209 }
210 else if( isFootprintEditor )
211 {
212 FOOTPRINT partialFootprint( m_board );
213
214 // Useful to copy the selection to the board editor (if any), and provides
215 // a dummy lib id.
216 // Perhaps not a good Id, but better than a empty id
217 KIID dummy;
218 LIB_ID id( "clipboard", dummy.AsString() );
219 partialFootprint.SetFPID( id );
220
221 for( EDA_ITEM* item : aSelected )
222 {
223 if( !item->IsBOARD_ITEM() )
224 continue;
225
226 BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( item );
227 BOARD_ITEM* copy = nullptr;
228
229 if( PCB_FIELD* field = dynamic_cast<PCB_FIELD*>( item ) )
230 {
231 if( field->IsMandatory() )
232 continue;
233 }
234
235 if( boardItem->Type() == PCB_GROUP_T )
236 {
237 copy = static_cast<PCB_GROUP*>( boardItem )->DeepClone();
238 }
239 else if( boardItem->Type() == PCB_GENERATOR_T )
240 {
241 copy = static_cast<PCB_GENERATOR*>( boardItem )->DeepClone();
242 }
243 else if( item->Type() == PCB_TABLECELL_T )
244 {
245 if( parentIsPromoted( static_cast<PCB_TABLECELL*>( item ) ) )
246 continue;
247
248 copy = static_cast<BOARD_ITEM*>( item->GetParent()->Clone() );
249 promotedTables.insert( static_cast<PCB_TABLE*>( copy ) );
250 }
251 else
252 {
253 copy = static_cast<BOARD_ITEM*>( boardItem->Clone() );
254 }
255
256 // If it is only a footprint, clear the nets from the pads
257 if( PAD* pad = dynamic_cast<PAD*>( copy ) )
258 pad->SetNetCode( 0 );
259
260 // Don't copy group membership information for the 1st level objects being copied
261 // since the group they belong to isn't being copied.
262 copy->SetParentGroup( nullptr );
263
264 // Add the pad to the new footprint before moving to ensure the local coords are
265 // correct
266 partialFootprint.Add( copy );
267
268 // A list of not added items, when adding items to the footprint
269 // some PCB_TEXT (reference and value) cannot be added to the footprint
270 std::vector<BOARD_ITEM*> skipped_items;
271
272 // Will catch at least PCB_GROUP_T and PCB_GENERATOR_T
273 if( PCB_GROUP* group = dynamic_cast<PCB_GROUP*>( copy ) )
274 {
275 group->RunOnChildren(
276 [&]( BOARD_ITEM* descendant )
277 {
278 // One cannot add an additional mandatory field to a given footprint:
279 // only one is allowed. So add only non-mandatory fields.
280 bool can_add = true;
281
282 if( const PCB_FIELD* field = dynamic_cast<const PCB_FIELD*>( item ) )
283 {
284 if( field->IsMandatory() )
285 can_add = false;
286 }
287
288 if( can_add )
289 partialFootprint.Add( descendant );
290 else
291 skipped_items.push_back( descendant );
292 },
294 }
295
296 // locate the reference point at (0, 0) in the copied items
297 copy->Move( -refPoint );
298
299 // Now delete items, duplicated but not added:
300 for( BOARD_ITEM* skipped_item : skipped_items )
301 {
302 static_cast<PCB_GROUP*>( copy )->RemoveItem( skipped_item );
303 skipped_item->SetParentGroup( nullptr );
304 delete skipped_item;
305 }
306 }
307
308 // Set the new relative internal local coordinates of copied items
309 FOOTPRINT* editedFootprint = m_board->Footprints().front();
310 VECTOR2I moveVector = partialFootprint.GetPosition() + editedFootprint->GetPosition();
311
312 partialFootprint.MoveAnchorPosition( moveVector );
313
314 // Carry footprint constraints whose members were all copied, like the board branch below;
315 // the paste path remaps the member KIIDs to the pasted copies.
316 std::set<KIID> selectedIds = CollectConstraintScopeIds( aSelected );
317
318 for( PCB_CONSTRAINT* constraint : editedFootprint->Constraints() )
319 {
320 if( ConstraintFullySelected( constraint, selectedIds ) )
321 partialFootprint.Add( static_cast<PCB_CONSTRAINT*>( constraint->Clone() ) );
322 }
323
324 for( PCB_TABLE* table : promotedTables )
325 deleteUnselectedCells( table );
326
327 Format( &partialFootprint );
328
329 partialFootprint.SetParent( nullptr );
330 }
331 else
332 {
333 // we will fake being a .kicad_pcb to get the full parser kicking
334 // This means we also need layers and nets
335 LOCALE_IO io;
336
337 m_formatter.Print( "(kicad_pcb (version %d) (generator \"pcbnew\") (generator_version %s)",
339 m_formatter.Quotew( GetMajorMinorVersion() ).c_str() );
340
342
343 for( EDA_ITEM* item : aSelected )
344 {
345 if( !item->IsBOARD_ITEM() )
346 continue;
347
348 BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( item );
349 BOARD_ITEM* copy = nullptr;
350
351 wxCHECK2( boardItem, continue );
352
353 if( boardItem->Type() == PCB_FIELD_T )
354 {
355 PCB_FIELD* field = static_cast<PCB_FIELD*>( boardItem );
356 copy = new PCB_TEXT( m_board );
357
358 PCB_TEXT* textItem = static_cast<PCB_TEXT*>( copy );
359 textItem->SetPosition( field->GetPosition() );
360 textItem->SetLayer( field->GetLayer() );
361 textItem->SetHyperlink( field->GetHyperlink() );
362 textItem->SetText( field->GetText() );
363 textItem->SetAttributes( field->GetAttributes() );
364 textItem->SetTextAngle( field->GetDrawRotation() );
365
366 if ( textItem->GetText() == wxT( "${VALUE}" ) )
367 textItem->SetText( boardItem->GetParentFootprint()->GetValue() );
368 else if ( textItem->GetText() == wxT( "${REFERENCE}" ) )
369 textItem->SetText( boardItem->GetParentFootprint()->GetReference() );
370
371 }
372 else if( boardItem->Type() == PCB_TEXT_T )
373 {
374 copy = static_cast<BOARD_ITEM*>( boardItem->Clone() );
375
376 PCB_TEXT* textItem = static_cast<PCB_TEXT*>( copy );
377
378 if( textItem->GetText() == wxT( "${VALUE}" ) )
379 textItem->SetText( boardItem->GetParentFootprint()->GetValue() );
380 else if( textItem->GetText() == wxT( "${REFERENCE}" ) )
381 textItem->SetText( boardItem->GetParentFootprint()->GetReference() );
382 }
383 else if( boardItem->Type() == PCB_GROUP_T )
384 {
385 copy = static_cast<PCB_GROUP*>( boardItem )->DeepClone();
386 }
387 else if( boardItem->Type() == PCB_GENERATOR_T )
388 {
389 copy = static_cast<PCB_GENERATOR*>( boardItem )->DeepClone();
390 }
391 else if( item->Type() == PCB_TABLECELL_T )
392 {
393 if( parentIsPromoted( static_cast<PCB_TABLECELL*>( item ) ) )
394 continue;
395
396 copy = static_cast<BOARD_ITEM*>( item->GetParent()->Clone() );
397 promotedTables.insert( static_cast<PCB_TABLE*>( copy ) );
398 }
399 else
400 {
401 copy = static_cast<BOARD_ITEM*>( boardItem->Clone() );
402 }
403
404 if( copy )
405 {
406 if( copy->Type() == PCB_FIELD_T || copy->Type() == PCB_PAD_T )
407 {
408 // Create a parent footprint to own the copied item
409 FOOTPRINT* footprint = new FOOTPRINT( m_board );
410
411 footprint->SetPosition( copy->GetPosition() );
412 footprint->Add( copy );
413
414 // Convert any mandatory fields to user fields. The destination footprint
415 // will already have its own mandatory fields.
416 if( PCB_FIELD* field = dynamic_cast<PCB_FIELD*>( copy ) )
417 {
418 if( field->IsMandatory() )
419 field->SetOrdinal( footprint->GetNextFieldOrdinal() );
420 }
421
422 copy = footprint;
423 }
424
425 copy->SetLocked( false );
426 copy->SetParent( m_board );
427 copy->SetParentGroup( nullptr );
428
429 // locate the reference point at (0, 0) in the copied items
430 copy->Move( -refPoint );
431
432 if( copy->Type() == PCB_TABLE_T )
433 {
434 PCB_TABLE* table = static_cast<PCB_TABLE*>( copy );
435
436 if( promotedTables.count( table ) )
437 deleteUnselectedCells( table );
438 }
439
440 Format( copy );
441
442 if( copy->Type() == PCB_GROUP_T || copy->Type() == PCB_GENERATOR_T )
443 {
444 copy->RunOnChildren(
445 [&]( BOARD_ITEM* descendant )
446 {
447 descendant->SetLocked( false );
448 Format( descendant );
449 },
451 }
452
453 delete copy;
454 }
455 }
456
457 // Copy a constraint along with its objects when every participant is in the selection
458 // (Zulip "Geometry Constraint Solver", 2026-06-18). Member KIIDs are preserved; the
459 // paste/append parser remaps them to the pasted copies.
460 std::set<KIID> selectedIds = CollectConstraintScopeIds( aSelected );
461
462 for( PCB_CONSTRAINT* constraint : m_board->Constraints() )
463 {
464 if( ConstraintFullySelected( constraint, selectedIds ) )
465 {
466 std::unique_ptr<PCB_CONSTRAINT> copy(
467 static_cast<PCB_CONSTRAINT*>( constraint->Clone() ) );
468 Format( copy.get() );
469 }
470 }
471
472 m_formatter.Print( ")" );
473 }
474
475 std::string prettyData = m_formatter.GetString();
476 KICAD_FORMAT::Prettify( prettyData, KICAD_FORMAT::FORMAT_MODE::COMPACT_TEXT_PROPERTIES );
477
478 // These are placed at the end to minimize the open time of the clipboard
479 m_writer( wxString( prettyData.c_str(), wxConvUTF8 ) );
480}
481
482
484{
485 BOARD_ITEM* item;
486 wxString result = m_reader();
487
488 try
489 {
491 }
492 catch (...)
493 {
494 item = nullptr;
495 }
496
497 return item;
498}
499
500
501void CLIPBOARD_IO::SaveBoard( const wxString& aFileName, BOARD* aBoard,
502 const std::map<std::string, UTF8>* aProperties )
503{
504 init( aProperties );
505
506 m_board = aBoard; // after init()
507
508 m_formatter.Print( "(kicad_pcb (version %d) (generator \"pcbnew\") (generator_version %s)",
510 m_formatter.Quotew( GetMajorMinorVersion() ).c_str() );
511
512 Format( aBoard );
513
514 m_formatter.Print( ")" );
515
516 std::string prettyData = m_formatter.GetString();
517 KICAD_FORMAT::Prettify( prettyData, KICAD_FORMAT::FORMAT_MODE::COMPACT_TEXT_PROPERTIES );
518
519 m_writer( wxString( prettyData.c_str(), wxConvUTF8 ) );
520}
521
522
523BOARD* CLIPBOARD_IO::LoadBoard( const wxString& aFileName, BOARD* aAppendToMe,
524 const std::map<std::string, UTF8>* aProperties, PROJECT* aProject )
525{
526 std::string result( m_reader().mb_str() );
527
528 std::function<bool( wxString, int, wxString, wxString )> queryUser =
529 [&]( wxString aTitle, int aIcon, wxString aMessage, wxString aAction ) -> bool
530 {
531 KIDIALOG dlg( nullptr, aMessage, aTitle, wxOK | wxCANCEL | aIcon );
532
533 if( !aAction.IsEmpty() )
534 dlg.SetOKLabel( aAction );
535
536 dlg.DoNotShowCheckbox( aMessage, 0 );
537
538 return dlg.ShowModal() == wxID_OK;
539 };
540
541 STRING_LINE_READER reader( result, wxT( "clipboard" ) );
542 PCB_IO_KICAD_SEXPR_PARSER parser( &reader, aAppendToMe, queryUser );
543
544 init( aProperties );
545
546 BOARD_ITEM* item;
547 BOARD* board;
548
549 try
550 {
551 item = parser.Parse();
552 }
553 catch( const FUTURE_FORMAT_ERROR& )
554 {
555 // Don't wrap a FUTURE_FORMAT_ERROR in another
556 throw;
557 }
558 catch( const PARSE_ERROR& parse_error )
559 {
560 if( parser.IsTooRecent() )
561 throw FUTURE_FORMAT_ERROR( parse_error, parser.GetRequiredVersion() );
562 else
563 throw;
564 }
565
566 if( item->Type() != PCB_T )
567 {
568 // The parser loaded something that was valid, but wasn't a board.
569 THROW_PARSE_ERROR( _( "Clipboard content is not KiCad compatible" ), parser.CurSource(),
570 parser.CurLine(), parser.CurLineNumber(), parser.CurOffset() );
571 }
572 else
573 {
574 board = dynamic_cast<BOARD*>( item );
575 }
576
577 // Give the filename to the board if it's new
578 if( board && !aAppendToMe )
579 board->SetFileName( aFileName );
580
581 return board;
582}
wxString GetMajorMinorVersion()
Get only the major and minor version in a string major.minor.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:83
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition board_item.h:295
void SetLocked(bool aLocked) override
Definition board_item.h:386
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition board_item.h:343
FOOTPRINT * GetParentFootprint() const
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:373
void SetFileName(const wxString &aFileName)
Definition board.h:408
void SaveSelection(const PCB_SELECTION &selected, bool isFootprintEditor)
STRING_FORMATTER m_formatter
BOARD_ITEM * Parse()
void SaveBoard(const wxString &aFileName, BOARD *aBoard, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Write aBoard to a storage file in a format that this PCB_IO implementation knows about or it can be u...
static void clipboardWriter(const wxString &aData)
static wxString clipboardReader()
void SetBoard(BOARD *aBoard)
std::function< wxString()> m_reader
BOARD * LoadBoard(const wxString &aFileName, BOARD *aAppendToMe, const std::map< std::string, UTF8 > *aProperties=nullptr, PROJECT *aProject=nullptr) override
Load information from some input file format that this PCB_IO implementation knows about into either ...
std::function< void(const wxString &)> m_writer
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:96
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition eda_item.h:152
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:108
virtual void SetParentGroup(EDA_GROUP *aGroup)
Definition eda_item.h:113
bool IsSelected() const
Definition eda_item.h:132
virtual EDA_ITEM * Clone() const
Create a duplicate of this item with linked list members set to NULL.
Definition eda_item.cpp:143
virtual void SetParent(EDA_ITEM *aParent)
Definition eda_item.cpp:89
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition eda_text.h:110
void SetAttributes(const EDA_TEXT &aSrc, bool aSetPosition=true)
Set the text attributes from another instance.
Definition eda_text.cpp:428
wxString GetHyperlink() const
Definition eda_text.h:424
const TEXT_ATTRIBUTES & GetAttributes() const
Definition eda_text.h:252
void SetHyperlink(wxString aLink)
Definition eda_text.h:425
virtual void SetText(const wxString &aText)
Definition eda_text.cpp:265
void SetPosition(const VECTOR2I &aPos) override
void SetFPID(const LIB_ID &aFPID)
Definition footprint.h:445
void SetLocked(bool isLocked) override
Set the #MODULE_is_LOCKED bit in the m_ModuleStatus.
Definition footprint.h:660
int GetNextFieldOrdinal() const
Return the next ordinal for a user field for this footprint.
void MoveAnchorPosition(const VECTOR2I &aMoveVector)
Move the reference point of the footprint.
CONSTRAINTS & Constraints()
Definition footprint.h:387
std::deque< PAD * > & Pads()
Definition footprint.h:375
void Move(const VECTOR2I &aMoveVector) override
Move this object.
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
const wxString & GetValue() const
Definition footprint.h:879
const wxString & GetReference() const
Definition footprint.h:857
VECTOR2I GetPosition() const override
Definition footprint.h:406
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition kidialog.h:38
void DoNotShowCheckbox(wxString file, int line)
Shows the 'do not show again' checkbox.
Definition kidialog.cpp:51
int ShowModal() override
Definition kidialog.cpp:89
Definition kiid.h:46
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:45
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition locale_io.h:37
Definition pad.h:61
A geometric constraint between board items (issue #2329).
A set of BOARD_ITEMs (i.e., without duplicates).
Definition pcb_group.h:51
Read a Pcbnew s-expression formatted LINE_READER object and returns the appropriate BOARD_ITEM object...
bool IsTooRecent()
Return whether a version number, if any was parsed, was too recent.
wxString GetRequiredVersion()
Return a string representing the version of KiCad required to open this file.
void formatBoardLayers(const BOARD *aBoard) const
formats the board layer information
BOARD_ITEM * Parse(const wxString &aClipboardSourceInput)
void init(const std::map< std::string, UTF8 > *aProperties)
void Format(const BOARD_ITEM *aItem) const
Output aItem to aFormatter in s-expression format.
PCB_IO_KICAD_SEXPR(int aControlFlags=CTL_FOR_BOARD)
OUTPUTFORMATTER * m_out
output any Format()s to this, no ownership
BOARD * m_board
The board BOARD being worked on, no ownership here.
Definition pcb_io.h:349
virtual VECTOR2I GetPosition() const override
Definition pcb_text.h:93
virtual void SetPosition(const VECTOR2I &aPos) override
Definition pcb_text.h:95
EDA_ANGLE GetDrawRotation() const override
Definition pcb_text.cpp:204
void SetTextAngle(const EDA_ANGLE &aAngle) override
Definition pcb_text.cpp:553
Container for project specific data.
Definition project.h:63
VECTOR2I GetReferencePoint() const
EDA_ITEM * Front() const
Definition selection.h:176
int Size() const
Returns the number of selected parts.
Definition selection.h:120
bool Empty() const
Checks if there is anything selected.
Definition selection.h:114
bool HasReferencePoint() const
Definition selection.h:215
Is a LINE_READER that reads from a multiline 8 bit wide std::string.
Definition richio.h:222
std::set< KIID > CollectConstraintScopeIds(const PCB_SELECTION &aSelection)
Shared logic deciding which constraints follow items through copy paste or duplicate.
bool ConstraintFullySelected(const PCB_CONSTRAINT *aConstraint, const std::set< KIID > &aScopeIds)
True when aConstraint has members and every one of them is present in aScopeIds, so the whole relatio...
#define _(s)
@ RECURSE
Definition eda_item.h:49
#define STRUCT_DELETED
flag indication structures to be erased
void ignore_unused(const T &)
Definition ignore.h:20
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
void Prettify(std::string &aSource, FORMAT_MODE aMode)
Pretty-prints s-expression text according to KiCad format rules.
Class to handle a set of BOARD_ITEMs.
#define CTL_FOR_CLIPBOARD
Format output for the clipboard instead of footprint library or BOARD.
#define SEXPR_BOARD_FILE_VERSION
Current s-expression file format version. 2 was the last legacy format version.
Pcbnew s-expression file format parser definition.
std::vector< FAB_LAYER_COLOR > dummy
Variant of PARSE_ERROR indicating that a syntax or related error was likely caused by a file generate...
A filename or source description, a problem input line, a line number, a byte offset,...
wxString result
Test unit parsing edge cases and error handling.
@ PCB_T
Definition typeinfo.h:75
@ PCB_GENERATOR_T
class PCB_GENERATOR, generator on a layer
Definition typeinfo.h:84
@ PCB_GROUP_T
class PCB_GROUP, a set of BOARD_ITEMs
Definition typeinfo.h:104
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition typeinfo.h:85
@ PCB_FIELD_T
class PCB_FIELD, text associated with a footprint property
Definition typeinfo.h:83
@ PCB_TABLECELL_T
class PCB_TABLECELL, PCB_TEXTBOX for use in tables
Definition typeinfo.h:88
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
Definition typeinfo.h:79
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition typeinfo.h:80
@ PCB_TABLE_T
class PCB_TABLE, table of PCB_TABLECELLs
Definition typeinfo.h:87
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683