mirror of https://github.com/KLayout/klayout.git
Merge pull request #336 from KLayout/multiple-files-on-import
Stream import: support multiple files
This commit is contained in:
commit
fde4fd42f9
|
|
@ -101,3 +101,6 @@ plugins.depends += lib rdb db
|
|||
|
||||
unit_tests.depends += plugins $$MAIN_DEPENDS
|
||||
|
||||
RESOURCES += \
|
||||
plugins/tools/import/lay_plugin/layResources.qrc
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -61,7 +61,7 @@ public:
|
|||
virtual void get_menu_entries (std::vector<lay::MenuEntry> &menu_entries) const
|
||||
{
|
||||
lay::PluginDeclaration::get_menu_entries (menu_entries);
|
||||
menu_entries.push_back (lay::MenuEntry ("lay::import_stream", "import_stream:edit", "file_menu.import_menu.end", tl::to_string (QObject::tr ("Other File Into Current"))));
|
||||
menu_entries.push_back (lay::MenuEntry ("lay::import_stream", "import_stream:edit", "file_menu.import_menu.end", tl::to_string (QObject::tr ("Other Files Into Current"))));
|
||||
}
|
||||
|
||||
virtual bool configure (const std::string &name, const std::string &value)
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ StreamImportData::setup_importer (StreamImporter *importer)
|
|||
importer->set_reference_points (reference_points);
|
||||
importer->set_cell_mapping (mode);
|
||||
importer->set_layer_mapping (layer_mode);
|
||||
importer->set_file (file);
|
||||
importer->set_files (files);
|
||||
importer->set_topcell (topcell);
|
||||
importer->set_layer_offset (layer_offset);
|
||||
importer->set_reader_options (options);
|
||||
|
|
@ -136,9 +136,12 @@ static tl::XMLElementList xml_elements ()
|
|||
{
|
||||
typedef std::pair <db::DPoint, db::DPoint> ref_point;
|
||||
typedef std::vector<ref_point> ref_point_v;
|
||||
typedef std::vector<std::string> string_v;
|
||||
|
||||
return
|
||||
tl::make_member (&StreamImportData::file, "file") +
|
||||
tl::make_element (&StreamImportData::files, "files",
|
||||
tl::make_member<std::string, string_v::const_iterator, string_v> (&string_v::begin, &string_v::end, &string_v::push_back, "file")
|
||||
) +
|
||||
tl::make_member (&StreamImportData::topcell, "cell-name") +
|
||||
tl::make_member (&StreamImportData::layer_offset, "layer-offset") +
|
||||
tl::make_member (&StreamImportData::layer_mode, "layer-mode", LayerModeConverter ()) +
|
||||
|
|
@ -217,10 +220,14 @@ StreamImportDialog::reset_options ()
|
|||
void
|
||||
StreamImportDialog::browse_filename ()
|
||||
{
|
||||
QString file = mp_ui->file_le->text ();
|
||||
file = QFileDialog::getOpenFileName (this, QObject::tr ("File To Import"), file, QObject::tr ("All files (*)"));
|
||||
if (! file.isNull ()) {
|
||||
mp_ui->file_le->setText (file);
|
||||
QStringList files = mp_ui->files_te->toPlainText ().split (QString::fromUtf8 ("\n"));
|
||||
QString file;
|
||||
if (! files.isEmpty ()) {
|
||||
file = files.front ();
|
||||
}
|
||||
files = QFileDialog::getOpenFileNames (this, QObject::tr ("File To Import"), file, QObject::tr ("All files (*)"));
|
||||
if (! files.isEmpty ()) {
|
||||
mp_ui->files_te->setPlainText (files.join (QString::fromUtf8 ("\n")));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -319,7 +326,7 @@ StreamImportDialog::commit_page ()
|
|||
if (page == 0) {
|
||||
|
||||
// --- General page
|
||||
mp_data->file = tl::to_string (mp_ui->file_le->text ());
|
||||
mp_data->files = tl::split (tl::to_string (mp_ui->files_te->toPlainText ()), "\n");
|
||||
mp_data->topcell = tl::to_string (mp_ui->topcell_le->text ());
|
||||
if (mp_ui->import_simple_rb->isChecked ()) {
|
||||
mp_data->mode = StreamImportData::Simple;
|
||||
|
|
@ -426,7 +433,7 @@ StreamImportDialog::update ()
|
|||
mp_ui->section_header_lbl->setText (tl::to_qstring (section_headers [page]));
|
||||
|
||||
// --- General page
|
||||
mp_ui->file_le->setText (tl::to_qstring (mp_data->file));
|
||||
mp_ui->files_te->setPlainText (tl::to_qstring (tl::join (mp_data->files, "\n")));
|
||||
mp_ui->topcell_le->setText (tl::to_qstring (mp_data->topcell));
|
||||
mp_ui->import_simple_rb->setChecked (mp_data->mode == StreamImportData::Simple);
|
||||
mp_ui->import_extra_rb->setChecked (mp_data->mode == StreamImportData::Extra);
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ public:
|
|||
enum layer_mode_type { Original = 0, Offset = 1 };
|
||||
|
||||
mode_type mode;
|
||||
std::string file;
|
||||
std::vector<std::string> files;
|
||||
std::string topcell;
|
||||
std::vector <std::pair <db::DPoint, db::DPoint> > reference_points;
|
||||
db::DCplxTrans explicit_trans;
|
||||
|
|
|
|||
|
|
@ -126,61 +126,6 @@ StreamImporter::read (db::Layout &target, db::cell_index_type target_cell_index,
|
|||
|
||||
}
|
||||
|
||||
// Prepare the layout to read
|
||||
db::Layout source;
|
||||
|
||||
// Load the layout
|
||||
{
|
||||
tl::InputStream stream (m_file);
|
||||
db::Reader reader (stream);
|
||||
|
||||
tl::log << tl::to_string (QObject::tr ("Loading file: ")) << m_file;
|
||||
tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (QObject::tr ("Loading")));
|
||||
reader.read (source, m_options);
|
||||
}
|
||||
|
||||
// Locate the top cell in the source file
|
||||
db::cell_index_type source_topcell;
|
||||
std::vector <db::cell_index_type> source_cells;
|
||||
|
||||
if (m_cell_mapping != StreamImportData::Extra || !m_topcell.empty ()) {
|
||||
|
||||
if (m_topcell.empty ()) {
|
||||
|
||||
db::Layout::top_down_const_iterator t = source.begin_top_down ();
|
||||
if (t == source.end_top_down ()) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Source layout does not have a top cell")));
|
||||
}
|
||||
|
||||
source_topcell = *t;
|
||||
|
||||
++t;
|
||||
if (t != source.end_top_cells ()) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Source layout does not have a unique top cell - specify one explicitly")));
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
std::pair<bool, db::cell_index_type> t = source.cell_by_name (m_topcell.c_str ());
|
||||
if (! t.first) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Source layout does not have a cell named '%s'")), m_topcell);
|
||||
}
|
||||
|
||||
source_topcell = t.second;
|
||||
|
||||
}
|
||||
|
||||
source_cells.push_back (source_topcell);
|
||||
|
||||
} else {
|
||||
|
||||
// collect source cells
|
||||
for (db::Layout::top_down_const_iterator t = source.begin_top_down (); t != source.end_top_cells (); ++t) {
|
||||
source_cells.push_back (*t);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Issue a warning, if the transformation is not ortho etc.
|
||||
if (fabs (global_trans.mag () - floor (global_trans.mag () + 0.5)) > 1e-6 || ! global_trans.is_ortho ()) {
|
||||
|
||||
|
|
@ -193,76 +138,141 @@ StreamImporter::read (db::Layout &target, db::cell_index_type target_cell_index,
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
// Create a layer map
|
||||
std::map <unsigned int, unsigned int> layer_map;
|
||||
for (db::Layout::layer_iterator l = source.begin_layers (); l != source.end_layers (); ++l) {
|
||||
|
||||
db::LayerProperties lp (*(*l).second);
|
||||
if (m_layer_mapping == StreamImportData::Offset) {
|
||||
lp = m_layer_offset.apply (lp);
|
||||
|
||||
// TODO: Currently no merging is provided for non-unity transformations
|
||||
if (m_cell_mapping == StreamImportData::Merge && ! global_trans.equal (db::DCplxTrans ())) {
|
||||
|
||||
if (QMessageBox::warning (QApplication::activeWindow (),
|
||||
QObject::tr ("Merge Mode Is Not Available"),
|
||||
tl::to_qstring (tl::sprintf (tl::to_string (QObject::tr ("Merge mode is not supported for the specified transformation (%s).\nSimple mode will be used instead.\nPress 'Ok' to continue.")), global_trans.to_string ())),
|
||||
QMessageBox::Ok | QMessageBox::Cancel,
|
||||
QMessageBox::Ok) != QMessageBox::Ok) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool layer_found = false;
|
||||
for (db::Layout::layer_iterator ll = target.begin_layers (); ll != target.end_layers () && ! layer_found; ++ll) {
|
||||
if ((*ll).second->log_equal (lp)) {
|
||||
layer_map.insert (std::make_pair ((*l).first, (*ll).first));
|
||||
layer_found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (! layer_found) {
|
||||
unsigned int new_layer = target.insert_layer (lp);
|
||||
layer_map.insert (std::make_pair ((*l).first, new_layer));
|
||||
new_layers.push_back (new_layer);
|
||||
}
|
||||
m_cell_mapping = StreamImportData::Simple;
|
||||
|
||||
}
|
||||
|
||||
// Create a cell map
|
||||
std::map <db::cell_index_type, db::cell_index_type> cell_map;
|
||||
for (size_t file_index = 0; file_index < m_files.size (); ++file_index) {
|
||||
|
||||
if (m_cell_mapping == StreamImportData::Simple) {
|
||||
std::string file = m_files [file_index];
|
||||
|
||||
cell_map.insert (std::make_pair (source_topcell, target_cell_index));
|
||||
// Prepare the layout to read
|
||||
db::Layout source;
|
||||
|
||||
} else if (m_cell_mapping == StreamImportData::Extra) {
|
||||
// Load the layout
|
||||
{
|
||||
tl::InputStream stream (file);
|
||||
db::Reader reader (stream);
|
||||
|
||||
// create new top cells for each source top cell
|
||||
for (std::vector<db::cell_index_type>::const_iterator t = source_cells.begin (); t != source_cells.end (); ++t) {
|
||||
db::cell_index_type new_top = target.add_cell (source.cell_name (*t));
|
||||
cell_map.insert (std::make_pair (*t, new_top));
|
||||
tl::log << tl::to_string (QObject::tr ("Loading file: ")) << file;
|
||||
tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (QObject::tr ("Loading file: ")) + file);
|
||||
reader.read (source, m_options);
|
||||
}
|
||||
|
||||
} else if (m_cell_mapping == StreamImportData::Instantiate) {
|
||||
// Locate the top cell in the source file
|
||||
db::cell_index_type source_topcell;
|
||||
std::vector <db::cell_index_type> source_cells;
|
||||
|
||||
// Create a new top cell for importing into and use the cell reference to produce the first part of the transformation
|
||||
if (m_cell_mapping != StreamImportData::Extra || !m_topcell.empty ()) {
|
||||
|
||||
db::cell_index_type new_top = target.add_cell (source.cell_name (source_topcell));
|
||||
cell_map.insert (std::make_pair (source_topcell, new_top));
|
||||
if (m_topcell.empty ()) {
|
||||
|
||||
db::ICplxTrans gt_dbu = db::VCplxTrans (1.0 / target.dbu ()) * global_trans * db::CplxTrans (source.dbu ());
|
||||
target.cell (target_cell_index).insert (db::CellInstArray (new_top, gt_dbu * db::ICplxTrans (1.0 / global_trans.mag ())));
|
||||
db::Layout::top_down_const_iterator t = source.begin_top_down ();
|
||||
if (t == source.end_top_down ()) {
|
||||
throw tl::Exception (tl::sprintf (tl::to_string (QObject::tr ("Source layout '%s' does not have a top cell")), file));
|
||||
}
|
||||
|
||||
global_trans = db::DCplxTrans (global_trans.mag ());
|
||||
source_topcell = *t;
|
||||
|
||||
} else if (m_cell_mapping == StreamImportData::Merge) {
|
||||
++t;
|
||||
if (t != source.end_top_cells ()) {
|
||||
throw tl::Exception (tl::sprintf (tl::to_string (QObject::tr ("Source layout '%s' does not have a unique top cell - specify one explicitly")), file));
|
||||
}
|
||||
|
||||
// Create the cell mapping
|
||||
// TODO: Currently no merging is provided for non-unity transformations
|
||||
if (! global_trans.equal (db::DCplxTrans ())) {
|
||||
} else {
|
||||
|
||||
std::pair<bool, db::cell_index_type> t = source.cell_by_name (m_topcell.c_str ());
|
||||
if (! t.first) {
|
||||
throw tl::Exception (tl::sprintf (tl::to_string (QObject::tr ("Source layout '%s' does not have a cell named '%s'")), file, m_topcell));
|
||||
}
|
||||
|
||||
source_topcell = t.second;
|
||||
|
||||
if (QMessageBox::warning (QApplication::activeWindow (),
|
||||
QObject::tr ("Merge Mode Is Not Available"),
|
||||
tl::to_qstring (tl::sprintf (tl::to_string (QObject::tr ("Merge mode is not supported for the specified transformation (%s).\nSimple mode will be used instead.\nPress 'Ok' to continue.")), global_trans.to_string ())),
|
||||
QMessageBox::Ok | QMessageBox::Cancel,
|
||||
QMessageBox::Ok) != QMessageBox::Ok) {
|
||||
return;
|
||||
}
|
||||
|
||||
source_cells.push_back (source_topcell);
|
||||
|
||||
} else {
|
||||
|
||||
// collect source cells
|
||||
for (db::Layout::top_down_const_iterator t = source.begin_top_down (); t != source.end_top_cells (); ++t) {
|
||||
source_cells.push_back (*t);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Create a layer map
|
||||
std::map <unsigned int, unsigned int> layer_map;
|
||||
for (db::Layout::layer_iterator l = source.begin_layers (); l != source.end_layers (); ++l) {
|
||||
|
||||
db::LayerProperties lp (*(*l).second);
|
||||
if (m_layer_mapping == StreamImportData::Offset) {
|
||||
lp = m_layer_offset.apply (lp);
|
||||
}
|
||||
|
||||
bool layer_found = false;
|
||||
for (db::Layout::layer_iterator ll = target.begin_layers (); ll != target.end_layers () && ! layer_found; ++ll) {
|
||||
if ((*ll).second->log_equal (lp)) {
|
||||
layer_map.insert (std::make_pair ((*l).first, (*ll).first));
|
||||
layer_found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (! layer_found) {
|
||||
unsigned int new_layer = target.insert_layer (lp);
|
||||
layer_map.insert (std::make_pair ((*l).first, new_layer));
|
||||
new_layers.push_back (new_layer);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Computes the final global transformation
|
||||
db::DCplxTrans gt = global_trans;
|
||||
|
||||
// Create a cell map
|
||||
std::map <db::cell_index_type, db::cell_index_type> cell_map;
|
||||
|
||||
if (m_cell_mapping == StreamImportData::Simple) {
|
||||
|
||||
cell_map.insert (std::make_pair (source_topcell, target_cell_index));
|
||||
|
||||
} else {
|
||||
} else if (m_cell_mapping == StreamImportData::Extra) {
|
||||
|
||||
// create new top cells for each source top cell
|
||||
for (std::vector<db::cell_index_type>::const_iterator t = source_cells.begin (); t != source_cells.end (); ++t) {
|
||||
db::cell_index_type new_top = target.add_cell (source.cell_name (*t));
|
||||
cell_map.insert (std::make_pair (*t, new_top));
|
||||
}
|
||||
|
||||
} else if (m_cell_mapping == StreamImportData::Instantiate) {
|
||||
|
||||
// Create a new top cell for importing into and use the cell reference to produce the first part of the transformation
|
||||
|
||||
db::cell_index_type new_top = target.add_cell (source.cell_name (source_topcell));
|
||||
cell_map.insert (std::make_pair (source_topcell, new_top));
|
||||
|
||||
db::ICplxTrans gt_dbu = db::VCplxTrans (1.0 / target.dbu ()) * gt * db::CplxTrans (source.dbu ());
|
||||
target.cell (target_cell_index).insert (db::CellInstArray (new_top, gt_dbu * db::ICplxTrans (1.0 / gt.mag ())));
|
||||
|
||||
gt = db::DCplxTrans (gt.mag ());
|
||||
|
||||
} else if (m_cell_mapping == StreamImportData::Merge) {
|
||||
|
||||
// Create the cell mapping
|
||||
// TODO: Currently no merging is provided for non-unity transformations
|
||||
tl_assert (gt.equal (db::DCplxTrans ()));
|
||||
|
||||
db::CellMapping cm;
|
||||
cm.create_from_geometry (target, target_cell_index, source, source_topcell);
|
||||
|
|
@ -270,11 +280,10 @@ StreamImporter::read (db::Layout &target, db::cell_index_type target_cell_index,
|
|||
|
||||
}
|
||||
|
||||
// And actually merge
|
||||
db::merge_layouts (target, source, db::VCplxTrans (1.0 / target.dbu ()) * gt * db::CplxTrans (source.dbu ()), source_cells, cell_map, layer_map);
|
||||
|
||||
}
|
||||
|
||||
// And actually merge
|
||||
db::merge_layouts (target, source, db::VCplxTrans (1.0 / target.dbu ()) * global_trans * db::CplxTrans (source.dbu ()), source_cells, cell_map, layer_map);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,19 +93,19 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Set file which is read.
|
||||
* @brief Set files which are read.
|
||||
*/
|
||||
void set_file (const std::string &file)
|
||||
void set_files (const std::vector<std::string> &files)
|
||||
{
|
||||
m_file = file;
|
||||
m_files = files;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the file which is read
|
||||
*/
|
||||
const std::string &file () const
|
||||
const std::vector<std::string> &files () const
|
||||
{
|
||||
return m_file;
|
||||
return m_files;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -192,7 +192,7 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
std::string m_file;
|
||||
std::vector<std::string> m_files;
|
||||
std::string m_topcell;
|
||||
db::DCplxTrans m_global_trans;
|
||||
std::vector <std::pair <db::DPoint, db::DPoint> > m_reference_points;
|
||||
|
|
|
|||
Loading…
Reference in New Issue