diff --git a/src/db/db/dbStream.cc b/src/db/db/dbStream.cc index 3d7cf935d..878198943 100644 --- a/src/db/db/dbStream.cc +++ b/src/db/db/dbStream.cc @@ -30,6 +30,42 @@ namespace db { +// ------------------------------------------------------------------ +// Implementation of StreamFormatDeclaration + +std::string StreamFormatDeclaration::all_formats_string () +{ + std::string fmts = tl::to_string (tr ("All layout files (")); + + for (tl::Registrar::iterator rdr = tl::Registrar::begin (); rdr != tl::Registrar::end (); ++rdr) { + if (rdr != tl::Registrar::begin ()) { + fmts += " "; + } + std::string f = rdr->file_format (); + if (!f.empty ()) { + const char *fp = f.c_str (); + while (*fp && *fp != '(') { + ++fp; + } + if (*fp) { + ++fp; + } + while (*fp && *fp != ')') { + fmts += *fp++; + } + } + } + fmts += ")"; + for (tl::Registrar::iterator rdr = tl::Registrar::begin (); rdr != tl::Registrar::end (); ++rdr) { + if (!rdr->file_format ().empty ()) { + fmts += ";;"; + fmts += rdr->file_format (); + } + } + + return fmts; +} + // ------------------------------------------------------------------ // Implementation of load_options_xml_element_list diff --git a/src/db/db/dbStream.h b/src/db/db/dbStream.h index 06ce1755d..97dfee6ef 100644 --- a/src/db/db/dbStream.h +++ b/src/db/db/dbStream.h @@ -136,6 +136,11 @@ public: { return 0; } + + /** + * @brief Returns a string for the file dialogs that describes all formats + */ + static std::string all_formats_string (); }; /** diff --git a/src/lay/lay/layMainWindow.cc b/src/lay/lay/layMainWindow.cc index 0eb2eb397..bda513a58 100644 --- a/src/lay/lay/layMainWindow.cc +++ b/src/lay/lay/layMainWindow.cc @@ -498,34 +498,9 @@ MainWindow::~MainWindow () std::string MainWindow::all_layout_file_formats () const { - std::string fmts = tl::to_string (QObject::tr ("All layout files (")); - for (tl::Registrar::iterator rdr = tl::Registrar::begin (); rdr != tl::Registrar::end (); ++rdr) { - if (rdr != tl::Registrar::begin ()) { - fmts += " "; - } - std::string f = rdr->file_format (); - if (!f.empty ()) { - const char *fp = f.c_str (); - while (*fp && *fp != '(') { - ++fp; - } - if (*fp) { - ++fp; - } - while (*fp && *fp != ')') { - fmts += *fp++; - } - } - } - fmts += ");;"; - for (tl::Registrar::iterator rdr = tl::Registrar::begin (); rdr != tl::Registrar::end (); ++rdr) { - if (!rdr->file_format ().empty ()) { - fmts += rdr->file_format (); - fmts += ";;"; - } - } - fmts += tl::to_string (QObject::tr ("All files (*)")); - + std::string fmts = db::StreamFormatDeclaration::all_formats_string (); + fmts += ";;"; + fmts += tl::to_string (tr ("All files (*)")); return fmts; } diff --git a/src/layui/layui/rdbMarkerBrowserDialog.cc b/src/layui/layui/rdbMarkerBrowserDialog.cc index 459803767..7502734ad 100644 --- a/src/layui/layui/rdbMarkerBrowserDialog.cc +++ b/src/layui/layui/rdbMarkerBrowserDialog.cc @@ -35,6 +35,7 @@ #include "layConfigurationDialog.h" #include "dbLayoutUtils.h" #include "dbRecursiveShapeIterator.h" +#include "dbStream.h" #include "ui_MarkerBrowserDialog.h" @@ -412,6 +413,26 @@ BEGIN_PROTECTED END_PROTECTED } +void +MarkerBrowserDialog::read_db_from_layout (rdb::Database *db, const std::string &filename) +{ + // try reading a layout file + db::Layout layout; + tl::InputStream is (m_open_filename); + db::Reader reader (is); + + reader.read (layout); + + std::vector > layers; + for (auto l = layout.begin_layers (); l != layout.end_layers (); ++l) { + layers.push_back (std::make_pair ((*l).first, std::string ())); + } + + if (layout.begin_top_down () != layout.end_top_down ()) { + scan_layout (db, layout, *layout.begin_top_down (), layers, false /*hierarchical*/); + } +} + void MarkerBrowserDialog::open_clicked () { @@ -420,15 +441,34 @@ BEGIN_PROTECTED // collect the formats available ... std::string fmts = tl::to_string (QObject::tr ("All files (*)")); for (tl::Registrar::iterator rdr = tl::Registrar::begin (); rdr != tl::Registrar::end (); ++rdr) { - fmts += ";;" + rdr->file_format (); + fmts += ";;"; + fmts += rdr->file_format (); } + // also provide the stream formats + fmts += ";;"; + fmts += db::StreamFormatDeclaration::all_formats_string (); + // prepare and open the file dialog lay::FileDialog open_dialog (this, tl::to_string (QObject::tr ("Load Marker Database File")), fmts); + if (open_dialog.get_open (m_open_filename)) { std::unique_ptr db (new rdb::Database ()); - db->load (m_open_filename); + + bool ok = false; + try { + // try reading a stream file + read_db_from_layout (db.get (), m_open_filename); + ok = true; + } catch (tl::Exception &ex) { + // continue + } + + if (! ok) { + // try reading database directly. + db->load (m_open_filename); + } int rdb_index = view ()->add_rdb (db.release ()); mp_ui->rdb_cb->setCurrentIndex (rdb_index); @@ -731,111 +771,17 @@ MarkerBrowserDialog::deactivated () void MarkerBrowserDialog::scan_layer () { - std::vector layers = view ()->selected_layers (); - if (layers.empty ()) { - throw tl::Exception (tl::to_string (QObject::tr ("No layer selected to get shapes from"))); - } - - int cv_index = -1; - for (std::vector::const_iterator l = layers.begin (); l != layers.end (); ++l) { - if (!(*l)->has_children ()) { - if (cv_index < 0) { - cv_index = (*l)->cellview_index (); - } else if ((*l)->cellview_index () >= 0) { - if (cv_index != (*l)->cellview_index ()) { - throw tl::Exception (tl::to_string (QObject::tr ("All layers must originate from the same layout"))); - } - } - } - } - - if (cv_index < 0) { - throw tl::Exception (tl::to_string (QObject::tr ("No valid layer selected"))); - } - - tl::AbsoluteProgress progress (tl::to_string (QObject::tr ("Shapes To Markers")), 10000); - progress.set_format (tl::to_string (QObject::tr ("%.0f0000 markers"))); - progress.set_unit (10000); - - const lay::CellView &cv = view ()->cellview (cv_index); - const db::Layout &layout = cv->layout (); - - std::unique_ptr rdb (new rdb::Database ()); - rdb->set_name ("Shapes"); - rdb->set_top_cell_name (layout.cell_name (cv.cell_index ())); - rdb::Cell *rdb_top_cell = rdb->create_cell (rdb->top_cell_name ()); - - std::string desc; - for (std::vector::const_iterator l = layers.begin (); l != layers.end (); ++l) { - if (!(*l)->has_children () && (*l)->cellview_index () == cv_index && layout.is_valid_layer ((*l)->layer_index ())) { - if (! desc.empty ()) { - desc += ", "; - } - desc += layout.get_properties ((*l)->layer_index ()).to_string (); - } - } - desc = tl::to_string (tr ("Hierarchical shapes of layer(s) ")) + desc; - desc += " "; - desc += tl::to_string (tr ("from cell ")); - desc += cv->layout ().cell_name (cv.cell_index ()); - rdb->set_description (desc); - - std::set called_cells; - called_cells.insert (cv.cell_index ()); - cv->layout ().cell (cv.cell_index ()).collect_called_cells (called_cells); - - for (std::vector::const_iterator l = layers.begin (); l != layers.end (); ++l) { - - if (!(*l)->has_children () && (*l)->cellview_index () == cv_index && layout.is_valid_layer ((*l)->layer_index ())) { - - rdb::Category *cat = rdb->create_category (layout.get_properties ((*l)->layer_index ()).to_string ()); - - for (db::Layout::const_iterator cid = layout.begin (); cid != layout.end (); ++cid) { - - if (called_cells.find (cid->cell_index ()) == called_cells.end ()) { - continue; - } - - const db::Cell &cell = *cid; - if (cell.shapes ((*l)->layer_index ()).size () > 0) { - - std::string cn = layout.cell_name (cell.cell_index ()); - const rdb::Cell *rdb_cell = rdb->cell_by_qname (cn); - if (! rdb_cell) { - - rdb::Cell *rdb_cell_nc = rdb->create_cell (cn); - rdb_cell = rdb_cell_nc; - - std::pair ctx = db::find_layout_context (layout, cell.cell_index (), cv.cell_index ()); - if (ctx.first) { - db::DCplxTrans t = db::DCplxTrans (layout.dbu ()) * db::DCplxTrans (ctx.second) * db::DCplxTrans (1.0 / layout.dbu ()); - rdb_cell_nc->references ().insert (Reference (t, rdb_top_cell->id ())); - } - - } - - for (db::ShapeIterator shape = cell.shapes ((*l)->layer_index ()).begin (db::ShapeIterator::All); ! shape.at_end (); ++shape) { - - rdb::create_item_from_shape (rdb.get (), rdb_cell->id (), cat->id (), db::CplxTrans (layout.dbu ()), *shape); - - ++progress; - - } - - } - - } - - } - - } - - unsigned int rdb_index = view ()->add_rdb (rdb.release ()); - view ()->open_rdb_browser (rdb_index, cv_index); + scan_layer_flat_or_hierarchical (false); } -void +void MarkerBrowserDialog::scan_layer_flat () +{ + scan_layer_flat_or_hierarchical (true); +} + +void +MarkerBrowserDialog::scan_layer_flat_or_hierarchical (bool flat) { std::vector layers = view ()->selected_layers (); if (layers.empty ()) { @@ -859,43 +805,87 @@ MarkerBrowserDialog::scan_layer_flat () throw tl::Exception (tl::to_string (QObject::tr ("No valid layer selected"))); } + const lay::CellView &cv = view ()->cellview (cv_index); + const db::Layout &layout = cv->layout (); + + std::vector > layer_indexes; + for (std::vector::const_iterator l = layers.begin (); l != layers.end (); ++l) { + if (!(*l)->has_children () && (*l)->cellview_index () == cv_index && layout.is_valid_layer ((*l)->layer_index ())) { + layer_indexes.push_back (std::make_pair ((*l)->layer_index (), (*l)->name ())); + } + } + + std::unique_ptr rdb (new rdb::Database ()); + + scan_layout (rdb.get (), layout, cv.cell_index (), layer_indexes, flat); + + unsigned int rdb_index = view ()->add_rdb (rdb.release ()); + view ()->open_rdb_browser (rdb_index, cv_index); +} + +void +MarkerBrowserDialog::scan_layout (rdb::Database *rdb, const db::Layout &layout, db::cell_index_type cell_index, const std::vector > &layers_and_descriptions, bool flat) +{ tl::AbsoluteProgress progress (tl::to_string (QObject::tr ("Shapes To Markers")), 10000); progress.set_format (tl::to_string (QObject::tr ("%.0f0000 markers"))); progress.set_unit (10000); - const lay::CellView &cv = view ()->cellview (cv_index); - const db::Layout &layout = cv->layout (); - - std::unique_ptr rdb (new rdb::Database ()); rdb->set_name ("Shapes"); - rdb->set_top_cell_name (layout.cell_name (cv.cell_index ())); + rdb->set_top_cell_name (layout.cell_name (cell_index)); rdb::Cell *rdb_top_cell = rdb->create_cell (rdb->top_cell_name ()); std::string desc; - for (std::vector::const_iterator l = layers.begin (); l != layers.end (); ++l) { - if (!(*l)->has_children () && (*l)->cellview_index () == cv_index && layout.is_valid_layer ((*l)->layer_index ())) { - if (! desc.empty ()) { - desc += ", "; - } - desc += layout.get_properties ((*l)->layer_index ()).to_string (); + + if (layers_and_descriptions.size () == 1) { + + if (flat) { + desc = tl::to_string (tr ("Flat shapes of layer ")); + } else { + desc = tl::to_string (tr ("Hierarchical shapes of layer ")); } + + desc += layout.get_properties (layers_and_descriptions.front ().first).to_string (); + + } else if (layers_and_descriptions.size () < 4 && layers_and_descriptions.size () > 0) { + + if (flat) { + desc = tl::to_string (tr ("Flat shapes of layers ")); + } else { + desc = tl::to_string (tr ("Hierarchical shapes of layers ")); + } + + for (auto l = layers_and_descriptions.begin (); l != layers_and_descriptions.end (); ++l) { + if (l != layers_and_descriptions.begin ()) { + desc += ","; + } + desc += layout.get_properties (l->first).to_string (); + } + + } else { + + if (flat) { + desc = tl::sprintf (tl::to_string (tr ("Flat shapes of %d layers")), int (layers_and_descriptions.size ())); + } else { + desc = tl::sprintf (tl::to_string (tr ("Hierarchical shapes of %d layers")), int (layers_and_descriptions.size ())); + } + } - desc = tl::to_string (tr ("Flat shapes of layer(s) ")) + desc; + desc += " "; desc += tl::to_string (tr ("from cell ")); - desc += cv->layout ().cell_name (cv.cell_index ()); + desc += layout.cell_name (cell_index); rdb->set_description (desc); - for (std::vector::const_iterator l = layers.begin (); l != layers.end (); ++l) { + if (flat) { - if (!(*l)->has_children () && (*l)->cellview_index () == cv_index && layout.is_valid_layer ((*l)->layer_index ())) { + for (auto l = layers_and_descriptions.begin (); l != layers_and_descriptions.end (); ++l) { - rdb::Category *cat = rdb->create_category (layout.get_properties ((*l)->layer_index ()).to_string ()); + rdb::Category *cat = rdb->create_category (l->second.empty () ? layout.get_properties (l->first).to_string () : l->second); - db::RecursiveShapeIterator shape (layout, *cv.cell (), (*l)->layer_index ()); + db::RecursiveShapeIterator shape (layout, layout.cell (cell_index), l->first); while (! shape.at_end ()) { - rdb::create_item_from_shape (rdb.get (), rdb_top_cell->id (), cat->id (), db::CplxTrans (layout.dbu ()) * shape.trans (), *shape); + rdb::create_item_from_shape (rdb, rdb_top_cell->id (), cat->id (), db::CplxTrans (layout.dbu ()) * shape.trans (), *shape); ++progress; ++shape; @@ -904,10 +894,55 @@ MarkerBrowserDialog::scan_layer_flat () } - } + } else { - unsigned int rdb_index = view ()->add_rdb (rdb.release ()); - view ()->open_rdb_browser (rdb_index, cv_index); + std::set called_cells; + called_cells.insert (cell_index); + layout.cell (cell_index).collect_called_cells (called_cells); + + for (auto l = layers_and_descriptions.begin (); l != layers_and_descriptions.end (); ++l) { + + rdb::Category *cat = rdb->create_category (l->second.empty () ? layout.get_properties (l->first).to_string () : l->second); + + for (db::Layout::const_iterator cid = layout.begin (); cid != layout.end (); ++cid) { + + if (called_cells.find (cid->cell_index ()) == called_cells.end ()) { + continue; + } + + const db::Cell &cell = *cid; + if (! cell.shapes (l->first).empty ()) { + + std::string cn = layout.cell_name (cell.cell_index ()); + const rdb::Cell *rdb_cell = rdb->cell_by_qname (cn); + if (! rdb_cell) { + + rdb::Cell *rdb_cell_nc = rdb->create_cell (cn); + rdb_cell = rdb_cell_nc; + + std::pair ctx = db::find_layout_context (layout, cell.cell_index (), cell_index); + if (ctx.first) { + db::DCplxTrans t = db::DCplxTrans (layout.dbu ()) * db::DCplxTrans (ctx.second) * db::DCplxTrans (1.0 / layout.dbu ()); + rdb_cell_nc->references ().insert (Reference (t, rdb_top_cell->id ())); + } + + } + + for (db::ShapeIterator shape = cell.shapes (l->first).begin (db::ShapeIterator::All); ! shape.at_end (); ++shape) { + + rdb::create_item_from_shape (rdb, rdb_cell->id (), cat->id (), db::CplxTrans (layout.dbu ()), *shape); + + ++progress; + + } + + } + + } + + } + + } } void diff --git a/src/layui/layui/rdbMarkerBrowserDialog.h b/src/layui/layui/rdbMarkerBrowserDialog.h index 7988d6070..3b50f1fa7 100644 --- a/src/layui/layui/rdbMarkerBrowserDialog.h +++ b/src/layui/layui/rdbMarkerBrowserDialog.h @@ -36,9 +36,16 @@ namespace Ui class MarkerBrowserDialog; } +namespace db +{ + class Layout; +} + namespace rdb { +class Database; + class LAYUI_PUBLIC MarkerBrowserDialog : public lay::Browser { @@ -101,6 +108,9 @@ private: void update_content (); void scan_layer (); void scan_layer_flat (); + void scan_layer_flat_or_hierarchical (bool flat); + void scan_layout (rdb::Database *db, const db::Layout &layout, db::cell_index_type cell_index, const std::vector > &layers_and_descriptions, bool flat); + void read_db_from_layout (rdb::Database *db, const std::string &filename); }; }