1 #include "core_schematic.hpp"
2 #include "core_properties.hpp"
3 #include "pool/part.hpp"
4 #include "util/util.hpp"
5 #include <algorithm>
6 #include "nlohmann/json.hpp"
7 #include <giomm/file.h>
8 #include <glibmm/fileutils.h>
9 #include "pool/ipool.hpp"
10 #include "util/str_util.hpp"
11 #include "util/picture_load.hpp"
12
13 namespace horizon {
CoreSchematic(const std::string & schematic_filename,const std::string & block_filename,const std::string & pictures_dir,IPool & pool,IPool & pool_caching)14 CoreSchematic::CoreSchematic(const std::string &schematic_filename, const std::string &block_filename,
15 const std::string &pictures_dir, IPool &pool, IPool &pool_caching)
16 : Core(pool, &pool_caching), block(Block::new_from_file(block_filename, pool_caching)),
17 project_meta_loaded_from_block(block->project_meta.size()),
18 sch(Schematic::new_from_file(schematic_filename, *block, pool_caching)), rules(sch->rules),
19 bom_export_settings(block->bom_export_settings), pdf_export_settings(sch->pdf_export_settings),
20 m_schematic_filename(schematic_filename), m_block_filename(block_filename), m_pictures_dir(pictures_dir)
21 {
22 auto x = std::find_if(sch->sheets.cbegin(), sch->sheets.cend(), [](const auto &a) { return a.second.index == 1; });
23 assert(x != sch->sheets.cend());
24 sheet_uuid = x->first;
25 sch->load_pictures(m_pictures_dir);
26 rebuild();
27 }
28
get_junction(const UUID & uu)29 Junction *CoreSchematic::get_junction(const UUID &uu)
30 {
31 auto &sheet = sch->sheets.at(sheet_uuid);
32 return &sheet.junctions.at(uu);
33 }
get_schematic_symbol(const UUID & uu)34 SchematicSymbol *CoreSchematic::get_schematic_symbol(const UUID &uu)
35 {
36 auto &sheet = sch->sheets.at(sheet_uuid);
37 return &sheet.symbols.at(uu);
38 }
get_text(const UUID & uu)39 Text *CoreSchematic::get_text(const UUID &uu)
40 {
41 auto &sheet = sch->sheets.at(sheet_uuid);
42 return &sheet.texts.at(uu);
43 }
get_schematic()44 Schematic *CoreSchematic::get_schematic()
45 {
46 return &*sch;
47 }
48
get_block()49 Block *CoreSchematic::get_block()
50 {
51 return get_schematic()->block;
52 }
53
get_layer_provider()54 LayerProvider &CoreSchematic::get_layer_provider()
55 {
56 return *get_sheet();
57 }
58
get_sheet()59 Sheet *CoreSchematic::get_sheet()
60 {
61 return &sch->sheets.at(sheet_uuid);
62 }
63
get_sheet() const64 const Sheet *CoreSchematic::get_sheet() const
65 {
66 return &sch->sheets.at(sheet_uuid);
67 }
68
get_line(const UUID & uu)69 Line *CoreSchematic::get_line(const UUID &uu)
70 {
71 auto &sheet = sch->sheets.at(sheet_uuid);
72 return &sheet.lines.at(uu);
73 }
get_arc(const UUID & uu)74 Arc *CoreSchematic::get_arc(const UUID &uu)
75 {
76 auto &sheet = sch->sheets.at(sheet_uuid);
77 return &sheet.arcs.at(uu);
78 }
79
insert_junction(const UUID & uu)80 Junction *CoreSchematic::insert_junction(const UUID &uu)
81 {
82 auto &sheet = sch->sheets.at(sheet_uuid);
83 auto x = sheet.junctions.emplace(std::make_pair(uu, uu));
84 return &(x.first->second);
85 }
86
insert_line_net(const UUID & uu)87 LineNet *CoreSchematic::insert_line_net(const UUID &uu)
88 {
89 auto &sheet = sch->sheets.at(sheet_uuid);
90 auto x = sheet.net_lines.emplace(std::make_pair(uu, uu));
91 return &(x.first->second);
92 }
93
delete_junction(const UUID & uu)94 void CoreSchematic::delete_junction(const UUID &uu)
95 {
96 auto &sheet = sch->sheets.at(sheet_uuid);
97 sheet.junctions.erase(uu);
98 }
delete_line_net(const UUID & uu)99 void CoreSchematic::delete_line_net(const UUID &uu)
100 {
101 auto &sheet = sch->sheets.at(sheet_uuid);
102 sheet.net_lines.erase(uu);
103 }
delete_schematic_symbol(const UUID & uu)104 void CoreSchematic::delete_schematic_symbol(const UUID &uu)
105 {
106 auto &sheet = sch->sheets.at(sheet_uuid);
107 sheet.symbols.erase(uu);
108 }
insert_schematic_symbol(const UUID & uu,const Symbol * sym)109 SchematicSymbol *CoreSchematic::insert_schematic_symbol(const UUID &uu, const Symbol *sym)
110 {
111 auto &sheet = sch->sheets.at(sheet_uuid);
112 auto x = sheet.symbols.emplace(std::make_pair(uu, SchematicSymbol{uu, sym}));
113 return &(x.first->second);
114 return nullptr;
115 }
116
insert_line(const UUID & uu)117 Line *CoreSchematic::insert_line(const UUID &uu)
118 {
119 auto &sheet = sch->sheets.at(sheet_uuid);
120 auto x = sheet.lines.emplace(std::make_pair(uu, uu));
121 return &(x.first->second);
122 }
delete_line(const UUID & uu)123 void CoreSchematic::delete_line(const UUID &uu)
124 {
125 auto &sheet = sch->sheets.at(sheet_uuid);
126 sheet.lines.erase(uu);
127 }
128
insert_arc(const UUID & uu)129 Arc *CoreSchematic::insert_arc(const UUID &uu)
130 {
131 auto &sheet = sch->sheets.at(sheet_uuid);
132 auto x = sheet.arcs.emplace(std::make_pair(uu, uu));
133 return &(x.first->second);
134 }
delete_arc(const UUID & uu)135 void CoreSchematic::delete_arc(const UUID &uu)
136 {
137 auto &sheet = sch->sheets.at(sheet_uuid);
138 sheet.arcs.erase(uu);
139 }
140
get_net_lines()141 std::vector<LineNet *> CoreSchematic::get_net_lines()
142 {
143 auto &sheet = sch->sheets.at(sheet_uuid);
144 std::vector<LineNet *> r;
145 for (auto &it : sheet.net_lines) {
146 r.push_back(&it.second);
147 }
148 return r;
149 }
get_net_labels()150 std::vector<NetLabel *> CoreSchematic::get_net_labels()
151 {
152 auto &sheet = sch->sheets.at(sheet_uuid);
153 std::vector<NetLabel *> r;
154 for (auto &it : sheet.net_labels) {
155 r.push_back(&it.second);
156 }
157 return r;
158 }
159
get_lines()160 std::vector<Line *> CoreSchematic::get_lines()
161 {
162 auto &sheet = sch->sheets.at(sheet_uuid);
163 std::vector<Line *> r;
164 for (auto &it : sheet.lines) {
165 r.push_back(&it.second);
166 }
167 return r;
168 }
169
get_arcs()170 std::vector<Arc *> CoreSchematic::get_arcs()
171 {
172 auto &sheet = sch->sheets.at(sheet_uuid);
173 std::vector<Arc *> r;
174 for (auto &it : sheet.arcs) {
175 r.push_back(&it.second);
176 }
177 return r;
178 }
179
delete_text(const UUID & uu)180 void CoreSchematic::delete_text(const UUID &uu)
181 {
182 auto &sheet = sch->sheets.at(sheet_uuid);
183 sheet.texts.erase(uu);
184 }
insert_text(const UUID & uu)185 Text *CoreSchematic::insert_text(const UUID &uu)
186 {
187 auto &sheet = sch->sheets.at(sheet_uuid);
188 auto x = sheet.texts.emplace(std::make_pair(uu, uu));
189 return &(x.first->second);
190 }
191
get_picture(const UUID & uu)192 Picture *CoreSchematic::get_picture(const UUID &uu)
193 {
194 auto &sheet = sch->sheets.at(sheet_uuid);
195 return &sheet.pictures.at(uu);
196 }
delete_picture(const UUID & uu)197 void CoreSchematic::delete_picture(const UUID &uu)
198 {
199 auto &sheet = sch->sheets.at(sheet_uuid);
200 sheet.pictures.erase(uu);
201 }
insert_picture(const UUID & uu)202 Picture *CoreSchematic::insert_picture(const UUID &uu)
203 {
204 auto &sheet = sch->sheets.at(sheet_uuid);
205 auto x = sheet.pictures.emplace(std::make_pair(uu, uu));
206 return &(x.first->second);
207 }
208
has_object_type(ObjectType ty) const209 bool CoreSchematic::has_object_type(ObjectType ty) const
210 {
211 switch (ty) {
212 case ObjectType::JUNCTION:
213 case ObjectType::SCHEMATIC_SYMBOL:
214 case ObjectType::BUS_LABEL:
215 case ObjectType::BUS_RIPPER:
216 case ObjectType::NET_LABEL:
217 case ObjectType::LINE_NET:
218 case ObjectType::POWER_SYMBOL:
219 case ObjectType::TEXT:
220 case ObjectType::LINE:
221 case ObjectType::ARC:
222 case ObjectType::PICTURE:
223 return true;
224 break;
225 default:;
226 }
227
228 return false;
229 }
230
get_rules()231 Rules *CoreSchematic::get_rules()
232 {
233 return &rules;
234 }
235
get_property(ObjectType type,const UUID & uu,ObjectProperty::ID property,PropertyValue & value)236 bool CoreSchematic::get_property(ObjectType type, const UUID &uu, ObjectProperty::ID property, PropertyValue &value)
237 {
238 if (Core::get_property(type, uu, property, value))
239 return true;
240 auto &sheet = sch->sheets.at(sheet_uuid);
241 switch (type) {
242 case ObjectType::NET: {
243 auto net = &block->nets.at(uu);
244 switch (property) {
245 case ObjectProperty::ID::NAME:
246 dynamic_cast<PropertyValueString &>(value).value = net->name;
247 return true;
248
249 case ObjectProperty::ID::NET_CLASS:
250 dynamic_cast<PropertyValueUUID &>(value).value = net->net_class->uuid;
251 return true;
252
253 case ObjectProperty::ID::DIFFPAIR: {
254 std::string s;
255 if (net->diffpair) {
256 s = (net->diffpair_master ? "Master: " : "Slave: ") + net->diffpair->name;
257 }
258 else {
259 s = "None";
260 }
261 dynamic_cast<PropertyValueString &>(value).value = s;
262 return true;
263 }
264
265 case ObjectProperty::ID::IS_POWER:
266 dynamic_cast<PropertyValueBool &>(value).value = net->is_power;
267 return true;
268
269 default:
270 return false;
271 }
272 } break;
273
274 case ObjectType::NET_LABEL: {
275 auto label = &sheet.net_labels.at(uu);
276 switch (property) {
277 case ObjectProperty::ID::NAME:
278 if (label->junction->net)
279 dynamic_cast<PropertyValueString &>(value).value = label->junction->net->name;
280 else
281 dynamic_cast<PropertyValueString &>(value).value = "<no net>";
282 return true;
283
284 case ObjectProperty::ID::OFFSHEET_REFS:
285 dynamic_cast<PropertyValueBool &>(value).value = label->offsheet_refs;
286 return true;
287
288 case ObjectProperty::ID::SIZE:
289 dynamic_cast<PropertyValueInt &>(value).value = label->size;
290 return true;
291
292 default:
293 return false;
294 }
295 } break;
296
297 case ObjectType::COMPONENT: {
298 auto comp = &block->components.at(uu);
299 switch (property) {
300 case ObjectProperty::ID::REFDES:
301 dynamic_cast<PropertyValueString &>(value).value = comp->refdes;
302 return true;
303
304 case ObjectProperty::ID::VALUE:
305 if (block->components.at(uu).part)
306 dynamic_cast<PropertyValueString &>(value).value = comp->part->get_value();
307 else
308 dynamic_cast<PropertyValueString &>(value).value = comp->value;
309 return true;
310
311 case ObjectProperty::ID::MPN:
312 if (block->components.at(uu).part)
313 dynamic_cast<PropertyValueString &>(value).value = comp->part->get_MPN();
314 else
315 dynamic_cast<PropertyValueString &>(value).value = "<no part>";
316 return true;
317
318 case ObjectProperty::ID::NOPOPULATE:
319 if (block->components.at(uu).part)
320 dynamic_cast<PropertyValueBool &>(value).value = comp->nopopulate;
321 else
322 dynamic_cast<PropertyValueBool &>(value).value = false;
323 return true;
324
325 default:
326 return false;
327 }
328 } break;
329
330 case ObjectType::SCHEMATIC_SYMBOL: {
331 auto sym = &sheet.symbols.at(uu);
332 switch (property) {
333 case ObjectProperty::ID::DISPLAY_DIRECTIONS:
334 dynamic_cast<PropertyValueBool &>(value).value = sym->display_directions;
335 return true;
336
337 case ObjectProperty::ID::DISPLAY_ALL_PADS:
338 dynamic_cast<PropertyValueBool &>(value).value = sym->display_all_pads;
339 return true;
340
341 case ObjectProperty::ID::PIN_NAME_DISPLAY:
342 dynamic_cast<PropertyValueInt &>(value).value = static_cast<int>(sym->pin_display_mode);
343 return true;
344
345 case ObjectProperty::ID::EXPAND:
346 dynamic_cast<PropertyValueInt &>(value).value = static_cast<int>(sym->expand);
347 return true;
348
349 case ObjectProperty::ID::REFDES:
350 dynamic_cast<PropertyValueString &>(value).value = sym->component->refdes + sym->gate->suffix;
351 return true;
352
353 case ObjectProperty::ID::VALUE:
354 dynamic_cast<PropertyValueString &>(value).value = sym->custom_value;
355 return true;
356
357 default:
358 return false;
359 }
360 } break;
361
362 default:
363 return false;
364 }
365 }
366
set_property(ObjectType type,const UUID & uu,ObjectProperty::ID property,const PropertyValue & value)367 bool CoreSchematic::set_property(ObjectType type, const UUID &uu, ObjectProperty::ID property,
368 const PropertyValue &value)
369 {
370 if (Core::set_property(type, uu, property, value))
371 return true;
372 auto &sheet = sch->sheets.at(sheet_uuid);
373 switch (type) {
374 case ObjectType::COMPONENT: {
375 auto comp = &block->components.at(uu);
376 switch (property) {
377 case ObjectProperty::ID::REFDES:
378 comp->refdes = dynamic_cast<const PropertyValueString &>(value).value;
379 break;
380
381 case ObjectProperty::ID::VALUE:
382 if (comp->part)
383 return false;
384 comp->value = dynamic_cast<const PropertyValueString &>(value).value;
385 break;
386
387 case ObjectProperty::ID::NOPOPULATE:
388 comp->nopopulate = dynamic_cast<const PropertyValueBool &>(value).value;
389 break;
390
391 default:
392 return false;
393 }
394 } break;
395
396 case ObjectType::NET: {
397 auto net = &block->nets.at(uu);
398 switch (property) {
399 case ObjectProperty::ID::NAME:
400 net->name = dynamic_cast<const PropertyValueString &>(value).value;
401 break;
402
403 case ObjectProperty::ID::NET_CLASS: {
404 net->net_class = &block->net_classes.at(dynamic_cast<const PropertyValueUUID &>(value).value);
405 } break;
406
407 case ObjectProperty::ID::IS_POWER:
408 if (block->nets.at(uu).is_power_forced)
409 return false;
410 block->nets.at(uu).is_power = dynamic_cast<const PropertyValueBool &>(value).value;
411 break;
412
413 default:
414 return false;
415 }
416 } break;
417
418 case ObjectType::SCHEMATIC_SYMBOL: {
419 auto sym = &sheet.symbols.at(uu);
420 switch (property) {
421 case ObjectProperty::ID::DISPLAY_DIRECTIONS:
422 sym->display_directions = dynamic_cast<const PropertyValueBool &>(value).value;
423 break;
424
425 case ObjectProperty::ID::DISPLAY_ALL_PADS:
426 sym->display_all_pads = dynamic_cast<const PropertyValueBool &>(value).value;
427 break;
428
429 case ObjectProperty::ID::PIN_NAME_DISPLAY:
430 sym->pin_display_mode =
431 static_cast<SchematicSymbol::PinDisplayMode>(dynamic_cast<const PropertyValueInt &>(value).value);
432 break;
433
434 case ObjectProperty::ID::EXPAND:
435 sym->expand = dynamic_cast<const PropertyValueInt &>(value).value;
436 sym->apply_expand();
437 break;
438
439 case ObjectProperty::ID::VALUE:
440 sym->custom_value = dynamic_cast<const PropertyValueString &>(value).value;
441 trim(sym->custom_value);
442 break;
443
444 default:
445 return false;
446 }
447 } break;
448
449 case ObjectType::NET_LABEL: {
450 auto label = &sheet.net_labels.at(uu);
451 switch (property) {
452 case ObjectProperty::ID::OFFSHEET_REFS:
453 label->offsheet_refs = dynamic_cast<const PropertyValueBool &>(value).value;
454 break;
455
456 case ObjectProperty::ID::SIZE:
457 label->size = dynamic_cast<const PropertyValueInt &>(value).value;
458 break;
459
460 default:
461 return false;
462 }
463 } break;
464
465 default:
466 return false;
467 }
468 if (!property_transaction) {
469 rebuild(false);
470 set_needs_save(true);
471 }
472 return true;
473 }
474
get_property_meta(ObjectType type,const UUID & uu,ObjectProperty::ID property,PropertyMeta & meta)475 bool CoreSchematic::get_property_meta(ObjectType type, const UUID &uu, ObjectProperty::ID property, PropertyMeta &meta)
476 {
477 if (Core::get_property_meta(type, uu, property, meta))
478 return true;
479 auto &sheet = sch->sheets.at(sheet_uuid);
480 switch (type) {
481 case ObjectType::NET:
482 switch (property) {
483 case ObjectProperty::ID::IS_POWER:
484 meta.is_settable = !block->nets.at(uu).is_power_forced;
485 return true;
486
487 case ObjectProperty::ID::NET_CLASS: {
488 PropertyMetaNetClasses &m = dynamic_cast<PropertyMetaNetClasses &>(meta);
489 m.net_classes.clear();
490 for (const auto &it : block->net_classes) {
491 m.net_classes.emplace(it.first, it.second.name);
492 }
493 return true;
494 }
495
496 default:
497 return false;
498 }
499 break;
500
501 case ObjectType::COMPONENT:
502 switch (property) {
503 case ObjectProperty::ID::VALUE:
504 meta.is_settable = block->components.at(uu).part == nullptr;
505 return true;
506
507 default:
508 return false;
509 }
510 break;
511
512 case ObjectType::SCHEMATIC_SYMBOL:
513 switch (property) {
514 case ObjectProperty::ID::EXPAND:
515 meta.is_settable = sheet.symbols.at(uu).pool_symbol->can_expand;
516 return true;
517
518 default:
519 return false;
520 }
521 break;
522
523 case ObjectType::TEXT:
524 switch (property) {
525 case ObjectProperty::ID::ALLOW_UPSIDE_DOWN:
526 meta.is_visible = false;
527 return true;
528 default:
529 return false;
530 }
531 break;
532
533 default:
534 return false;
535 }
536 return false;
537 }
538
get_display_name(ObjectType type,const UUID & uu)539 std::string CoreSchematic::get_display_name(ObjectType type, const UUID &uu)
540 {
541 return get_display_name(type, uu, sheet_uuid);
542 }
543
get_display_name(ObjectType type,const UUID & uu,const UUID & sh)544 std::string CoreSchematic::get_display_name(ObjectType type, const UUID &uu, const UUID &sh)
545 {
546 auto &sheet = sch->sheets.at(sh);
547 switch (type) {
548 case ObjectType::NET:
549 return block->nets.at(uu).name;
550
551 case ObjectType::LINE_NET: {
552 const auto &li = sheet.net_lines.at(uu);
553 return li.net ? li.net->name : "";
554 }
555
556 case ObjectType::JUNCTION: {
557 const auto &ju = sheet.junctions.at(uu);
558 return ju.net ? ju.net->name : "";
559 }
560
561 case ObjectType::NET_LABEL: {
562 const auto &la = sheet.net_labels.at(uu);
563 return la.junction->net ? la.junction->net->name : "";
564 }
565
566 case ObjectType::SCHEMATIC_SYMBOL:
567 return sheet.symbols.at(uu).component->refdes + sheet.symbols.at(uu).gate->suffix;
568
569 case ObjectType::COMPONENT:
570 return block->components.at(uu).refdes;
571
572 case ObjectType::POWER_SYMBOL:
573 return sheet.power_symbols.at(uu).net->name;
574
575 case ObjectType::BUS_RIPPER:
576 return sheet.bus_rippers.at(uu).bus_member->net->name;
577
578 case ObjectType::TEXT:
579 return sheet.texts.at(uu).text;
580
581 default:
582 return Core::get_display_name(type, uu);
583 }
584 }
585
add_sheet()586 void CoreSchematic::add_sheet()
587 {
588 auto uu = UUID::random();
589 auto sheet_max = std::max_element(sch->sheets.begin(), sch->sheets.end(),
590 [](const auto &p1, const auto &p2) { return p1.second.index < p2.second.index; });
591 auto *sheet = &sch->sheets.emplace(uu, uu).first->second;
592 sheet->index = sheet_max->second.index + 1;
593 sheet->name = "sheet " + std::to_string(sheet->index);
594 sheet->pool_frame = sch->sheets.at(sheet_uuid).pool_frame;
595 rebuild();
596 }
597
delete_sheet(const UUID & uu)598 void CoreSchematic::delete_sheet(const UUID &uu)
599 {
600 if (sch->sheets.size() <= 1)
601 return;
602 if (sch->sheets.at(uu).symbols.size() > 0) // only delete empty sheets
603 return;
604 auto deleted_index = sch->sheets.at(uu).index;
605 sch->sheets.erase(uu);
606 for (auto &it : sch->sheets) {
607 if (it.second.index > deleted_index) {
608 it.second.index--;
609 }
610 }
611 if (sheet_uuid == uu) { // deleted current sheet
612 auto x = std::find_if(sch->sheets.begin(), sch->sheets.end(), [](auto e) { return e.second.index == 1; });
613 sheet_uuid = x->first;
614 }
615 rebuild();
616 }
617
set_sheet(const UUID & uu)618 void CoreSchematic::set_sheet(const UUID &uu)
619 {
620 if (tool_is_active())
621 return;
622 if (sch->sheets.count(uu) == 0)
623 return;
624 sheet_uuid = uu;
625 }
626
rebuild(bool from_undo)627 void CoreSchematic::rebuild(bool from_undo)
628 {
629 clock_t begin = clock();
630 sch->expand();
631 Core::rebuild(from_undo);
632 clock_t end = clock();
633 double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
634 std::cout << "rebuild took " << elapsed_secs << std::endl;
635 }
636
get_canvas_data()637 const Sheet &CoreSchematic::get_canvas_data()
638 {
639 return sch->sheets.at(sheet_uuid);
640 }
641
history_push()642 void CoreSchematic::history_push()
643 {
644 history.push_back(std::make_unique<CoreSchematic::HistoryItem>(*block, *sch));
645 auto x = dynamic_cast<CoreSchematic::HistoryItem *>(history.back().get());
646 x->sch.block = &x->block;
647 x->sch.update_refs();
648 }
649
history_load(unsigned int i)650 void CoreSchematic::history_load(unsigned int i)
651 {
652 const auto &x = dynamic_cast<CoreSchematic::HistoryItem &>(*history.at(history_current));
653 sch.emplace(x.sch);
654 block.emplace(x.block);
655 sch->block = &*block;
656 sch->update_refs();
657 s_signal_rebuilt.emit();
658 }
659
reload_pool()660 void CoreSchematic::reload_pool()
661 {
662 PictureKeeper keeper;
663 for (const auto &[uu_sheet, sheet] : sch->sheets) {
664 keeper.save(sheet.pictures);
665 }
666 const auto sch_j = sch->serialize();
667 const auto block_j = block->serialize();
668 m_pool.clear();
669 m_pool_caching.clear();
670 block.emplace(block->uuid, block_j, m_pool_caching);
671 sch.emplace(sch->uuid, sch_j, *block, m_pool_caching);
672 for (auto &[uu_sheet, sheet] : sch->sheets) {
673 keeper.restore(sheet.pictures);
674 }
675 bom_export_settings.update_refs(m_pool_caching);
676 history_clear();
677 rebuild();
678 }
679
get_bbox()680 std::pair<Coordi, Coordi> CoreSchematic::get_bbox()
681 {
682 return get_sheet()->frame.get_bbox();
683 }
684
get_filename() const685 const std::string &CoreSchematic::get_filename() const
686 {
687 return m_schematic_filename;
688 }
689
save(const std::string & suffix)690 void CoreSchematic::save(const std::string &suffix)
691 {
692 sch->rules = rules;
693 block->bom_export_settings = bom_export_settings;
694 sch->pdf_export_settings = pdf_export_settings;
695 save_json_to_file(m_schematic_filename + suffix, sch->serialize());
696 save_json_to_file(m_block_filename + suffix, block->serialize());
697 sch->save_pictures(m_pictures_dir);
698 }
699
700
delete_autosave()701 void CoreSchematic::delete_autosave()
702 {
703 if (Glib::file_test(m_schematic_filename + autosave_suffix, Glib::FILE_TEST_IS_REGULAR))
704 Gio::File::create_for_path(m_schematic_filename + autosave_suffix)->remove();
705 if (Glib::file_test(m_block_filename + autosave_suffix, Glib::FILE_TEST_IS_REGULAR))
706 Gio::File::create_for_path(m_block_filename + autosave_suffix)->remove();
707 }
708
709 } // namespace horizon
710