mirror of https://github.com/KLayout/klayout.git
Fixing issue #1864 (Copy & paste allows creating a recursive hierarchy)
This commit is contained in:
parent
ff708186ec
commit
5ece4d74ae
|
|
@ -156,6 +156,11 @@ ClipboardData::add (const db::Layout &layout, const db::Cell &cell, unsigned int
|
|||
std::vector<unsigned int>
|
||||
ClipboardData::do_insert (db::Layout &layout, const db::ICplxTrans *trans, db::Cell *cell, std::vector<db::cell_index_type> *new_tops, ClipboardDataInsertReceiver *insert_receiver) const
|
||||
{
|
||||
// identify the cells our target is eventually called from, including itself
|
||||
std::set<db::cell_index_type> callers;
|
||||
cell->collect_caller_cells (callers);
|
||||
callers.insert (cell->cell_index ());
|
||||
|
||||
std::vector <unsigned int> new_layers;
|
||||
PropertyMapper prop_id_map (&layout, &m_layout);
|
||||
|
||||
|
|
@ -279,14 +284,21 @@ ClipboardData::do_insert (db::Layout &layout, const db::ICplxTrans *trans, db::C
|
|||
|
||||
for (db::Cell::const_iterator inst = c->begin (); ! inst.at_end (); ++inst) {
|
||||
|
||||
tl::const_map<db::cell_index_type> im (cell_map.find (inst->cell_index ())->second);
|
||||
db::Instance new_inst = t.insert (*inst, im, prop_id_map);
|
||||
if (trans) {
|
||||
new_inst = t.transform (new_inst, *trans);
|
||||
}
|
||||
db::cell_index_type inst_cell = cell_map.find (inst->cell_index ())->second;
|
||||
if (callers.find (inst_cell) == callers.end ()) {
|
||||
|
||||
if (insert_receiver) {
|
||||
insert_receiver->instance_inserted (cp->second, new_inst);
|
||||
tl::const_map<db::cell_index_type> im (inst_cell);
|
||||
db::Instance new_inst = t.insert (*inst, im, prop_id_map);
|
||||
if (trans) {
|
||||
new_inst = t.transform (new_inst, *trans);
|
||||
}
|
||||
|
||||
if (insert_receiver) {
|
||||
insert_receiver->instance_inserted (cp->second, new_inst);
|
||||
}
|
||||
|
||||
} else {
|
||||
tl::warn << tl::sprintf (tl::to_string (tr ("Refusing to paste an instance for cell %s, as this would create a recursive hierarchy")), layout.cell_name (inst_cell));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2667,8 +2667,22 @@ MainService::paste ()
|
|||
{
|
||||
if (view ()->is_editable ()) {
|
||||
|
||||
// skip, if there is nothing to insert
|
||||
bool any = false;
|
||||
for (db::Clipboard::iterator c = db::Clipboard::instance ().begin (); c != db::Clipboard::instance ().end () && ! any; ++c) {
|
||||
const db::ClipboardValue<edt::ClipboardData> *value = dynamic_cast<const db::ClipboardValue<edt::ClipboardData> *> (*c);
|
||||
any = (value != 0);
|
||||
}
|
||||
if (! any) {
|
||||
return;
|
||||
}
|
||||
|
||||
int cv_index = view ()->active_cellview_index ();
|
||||
|
||||
const lay::CellView &cv = view ()->cellview (cv_index);
|
||||
if (! cv.is_valid ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("No cell selected to paste something into")));
|
||||
}
|
||||
|
||||
NewObjectsSelection insert_notification (cv_index, cv.cell_index (), view ());
|
||||
|
||||
|
|
@ -2678,14 +2692,8 @@ MainService::paste ()
|
|||
for (db::Clipboard::iterator c = db::Clipboard::instance ().begin (); c != db::Clipboard::instance ().end (); ++c) {
|
||||
const db::ClipboardValue<edt::ClipboardData> *value = dynamic_cast<const db::ClipboardValue<edt::ClipboardData> *> (*c);
|
||||
if (value) {
|
||||
|
||||
if (! cv.is_valid ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("No cell selected to paste something into")));
|
||||
}
|
||||
|
||||
std::vector<unsigned int> nl = value->get ().insert (cv->layout (), cv.context_trans ().inverted (), &cv->layout ().cell (cv.cell_index ()), 0 /*new_tops*/, &insert_notification);
|
||||
new_layers.insert (new_layers.end (), nl.begin (), nl.end ());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue