WIP: library browser - PCell variants as children of PCells

This commit is contained in:
Matthias Koefferlein 2019-08-01 22:52:20 +02:00
parent 0c18171e63
commit 4428ef808b
5 changed files with 97 additions and 31 deletions

View File

@ -51,6 +51,7 @@ class DB_PUBLIC PCellHeader
{
public:
typedef std::map<const pcell_parameters_type *, db::PCellVariant *, PCellParametersCompareFunc> variant_map_t;
typedef variant_map_t::const_iterator variant_iterator;
/**
* @brief The default constructor
@ -112,6 +113,22 @@ public:
*/
void register_variant (PCellVariant *variant);
/**
* @brief Iterates the variants (begin)
*/
variant_iterator begin () const
{
return m_variant_map.begin ();
}
/**
* @brief Iterates the variants (end)
*/
variant_iterator end () const
{
return m_variant_map.end ();
}
/**
* @brief Get the PCell Id for this variant
*/

View File

@ -1248,6 +1248,7 @@ MainWindow::close_all ()
mp_views.pop_back ();
mp_lp_stack->removeWidget (mp_views.size ());
mp_hp_stack->removeWidget (mp_views.size ());
mp_libs_stack->removeWidget (mp_views.size ());
mp_view_stack->removeWidget (mp_views.size ());
delete view;
@ -3299,6 +3300,7 @@ MainWindow::select_view (int index)
mp_view_stack->raiseWidget (index);
mp_hp_stack->raiseWidget (index);
mp_lp_stack->raiseWidget (index);
mp_libs_stack->raiseWidget (index);
mp_setup_form->setup ();
}
@ -3970,6 +3972,7 @@ MainWindow::close_view (int index)
mp_view_stack->removeWidget (index);
mp_lp_stack->removeWidget (index);
mp_hp_stack->removeWidget (index);
mp_libs_stack->removeWidget (index);
view_closed_event (int (index));

View File

@ -25,6 +25,7 @@
#include "layLayoutView.h"
#include "tlGlobPattern.h"
#include "dbPCellHeader.h"
#include "dbPCellVariant.h"
#include <QTreeView>
#include <QPalette>
@ -82,8 +83,8 @@ struct cmp_cell_tree_item_vs_name_f
// --------------------------------------------------------------------
// CellTreeItem implementation
CellTreeItem::CellTreeItem (const db::Layout *layout, CellTreeItem *parent, bool is_pcell, size_t cell_or_pcell_index, bool flat, CellTreeModel::Sorting s)
: mp_layout (layout), mp_parent (parent), m_sorting (s), m_is_pcell (is_pcell), m_index (0), m_children (), m_cell_or_pcell_index (cell_or_pcell_index)
CellTreeItem::CellTreeItem (const db::Layout *layout, bool is_pcell, size_t cell_or_pcell_index, bool flat, CellTreeModel::Sorting s)
: mp_layout (layout), mp_parent (0), m_sorting (s), m_is_pcell (is_pcell), m_index (0), m_children (), m_cell_or_pcell_index (cell_or_pcell_index)
{
if (! flat && ! is_pcell) {
m_child_count = int (mp_layout->cell (cell_index ()).child_cells ());
@ -100,6 +101,12 @@ CellTreeItem::~CellTreeItem ()
m_children.clear ();
}
bool
CellTreeItem::is_valid () const
{
return m_is_pcell || mp_layout->is_valid_cell_index (cell_index ());
}
std::string
CellTreeItem::display_text () const
{
@ -130,21 +137,38 @@ CellTreeItem::child (int index)
m_children.reserve (m_child_count);
for (db::Cell::child_cell_iterator child = cell->begin_child_cells (); ! child.at_end (); ++child) {
CellTreeItem *child_item = new CellTreeItem (mp_layout, this, false, *child, false, m_sorting);
m_children.push_back (child_item);
add_child (new CellTreeItem (mp_layout, false, *child, false, m_sorting));
}
std::sort (m_children.begin (), m_children.end (), cmp_cell_tree_items_f (m_sorting));
for (size_t i = 0; i < m_children.size (); ++i) {
m_children [i]->set_index (i);
}
finish_children ();
}
return m_children [index];
}
void
CellTreeItem::add_child (CellTreeItem *item)
{
// explicitly added
if (size_t (m_child_count) == m_children.size ()) {
++m_child_count;
}
item->mp_parent = this;
m_children.push_back (item);
}
void
CellTreeItem::finish_children ()
{
std::sort (m_children.begin (), m_children.end (), cmp_cell_tree_items_f (m_sorting));
for (size_t i = 0; i < m_children.size (); ++i) {
m_children [i]->set_index (i);
}
}
db::cell_index_type
CellTreeItem::cell_index () const
{
@ -452,7 +476,7 @@ CellTreeModel::build_top_level ()
if (mp_base) {
m_toplevel.reserve (mp_base->child_cells ());
for (db::Cell::child_cell_iterator child = mp_base->begin_child_cells (); ! child.at_end (); ++child) {
CellTreeItem *item = new CellTreeItem (mp_layout, 0, false, *child, true, m_sorting);
CellTreeItem *item = new CellTreeItem (mp_layout, false, *child, true, m_sorting);
m_toplevel.push_back (item);
}
}
@ -464,7 +488,7 @@ CellTreeModel::build_top_level ()
if (mp_base) {
m_toplevel.reserve (mp_base->parent_cells ());
for (db::Cell::parent_cell_iterator parent = mp_base->begin_parent_cells (); parent != mp_base->end_parent_cells (); ++parent) {
CellTreeItem *item = new CellTreeItem (mp_layout, 0, false, *parent, true, m_sorting);
CellTreeItem *item = new CellTreeItem (mp_layout, false, *parent, true, m_sorting);
m_toplevel.push_back (item);
}
}
@ -479,11 +503,11 @@ CellTreeModel::build_top_level ()
while (top != mp_layout->end_top_down ()) {
if (m_flat) {
CellTreeItem *item = new CellTreeItem (mp_layout, 0, false, *top, true, m_sorting);
CellTreeItem *item = new CellTreeItem (mp_layout, false, *top, true, m_sorting);
m_toplevel.push_back (item);
} else if (mp_layout->cell (*top).is_top ()) {
if ((m_flags & BasicCells) == 0 || ! mp_layout->cell (*top).is_proxy ()) {
CellTreeItem *item = new CellTreeItem (mp_layout, 0, false, *top, (m_flags & TopCells) != 0, m_sorting);
CellTreeItem *item = new CellTreeItem (mp_layout, false, *top, (m_flags & TopCells) != 0, m_sorting);
m_toplevel.push_back (item);
}
} else {
@ -495,10 +519,25 @@ CellTreeModel::build_top_level ()
}
if ((m_flags & BasicCells) != 0) {
for (db::Layout::pcell_iterator pc = mp_layout->begin_pcells (); pc != mp_layout->end_pcells (); ++pc) {
CellTreeItem *item = new CellTreeItem (mp_layout, 0, true, pc->second, true, m_sorting);
CellTreeItem *item = new CellTreeItem (mp_layout, true, pc->second, true, m_sorting);
m_toplevel.push_back (item);
if ((m_flags & WithVariants) != 0) {
const db::PCellHeader *pcell_header = mp_layout->pcell_header (pc->second);
for (db::PCellHeader::variant_iterator v = pcell_header->begin (); v != pcell_header->end (); ++v) {
item->add_child (new CellTreeItem (mp_layout, false, v->second->cell_index (), true, m_sorting));
}
item->finish_children ();
}
}
}
}
@ -699,7 +738,7 @@ CellTreeModel::rowCount (const QModelIndex &parent) const
CellTreeItem *item = (CellTreeItem *) parent.internalPointer ();
if (! item) {
return 0;
} else if (! mp_layout->is_valid_cell_index (item->cell_index ())) {
} else if (! item->is_valid ()) {
// for safety we return 0 children for invalid cells
return 0;
} else {
@ -719,7 +758,7 @@ CellTreeModel::index (int row, int column, const QModelIndex &parent) const
CellTreeItem *item = (CellTreeItem *) parent.internalPointer ();
if (! item) {
return QModelIndex ();
} else if (! mp_layout->is_valid_cell_index (item->cell_index ())) {
} else if (! item->is_valid ()) {
// for safety we don't return valid child indexes for invalid cells
return QModelIndex ();
} else {

View File

@ -56,18 +56,19 @@ class CellTreeModel
{
public:
enum Flags {
Flat = 1, // flat list (rather than hierarchy)
Children = 2, // direct children of cell "base"
Parents = 4, // direct parents of cell "base"
TopCells = 8, // show top cells only
BasicCells = 16, // show basic cells (PCells included, no proxies)
NoPadding = 32 // enable padding of display string with a blank at the beginning and end
Flat = 1, // flat list (rather than hierarchy)
Children = 2, // direct children of cell "base"
Parents = 4, // direct parents of cell "base"
TopCells = 8, // show top cells only
BasicCells = 16, // show basic cells (PCells included, no proxies)
WithVariants = 32, // show PCell variants below PCells
NoPadding = 64 // disable padding of display string with a blank at the beginning and end
};
enum Sorting {
ByName, // sort by name
ByArea, // sort by cell area (small to large)
ByAreaReverse // sort by cell area (large to small)
ByName, // sort by name
ByArea, // sort by cell area (small to large)
ByAreaReverse // sort by cell area (large to small)
};
/**
@ -247,7 +248,7 @@ private:
class CellTreeItem
{
public:
CellTreeItem (const db::Layout *layout, CellTreeItem *parent, bool is_pcell, size_t cell_or_pcell_index, bool flat, CellTreeModel::Sorting sorting);
CellTreeItem (const db::Layout *layout, bool is_pcell, size_t cell_or_pcell_index, bool flat, CellTreeModel::Sorting sorting);
~CellTreeItem ();
int children () const;
@ -261,6 +262,9 @@ public:
bool name_equals (const char *name) const;
bool name_matches (const tl::GlobPattern &p) const;
std::string display_text () const;
void add_child (CellTreeItem *item);
void finish_children ();
bool is_valid () const;
bool is_pcell () const
{

View File

@ -333,8 +333,6 @@ LibrariesView::LibrariesView (lay::LayoutView *view, QWidget *parent, const char
sp.setVerticalStretch (0);
setSizePolicy (sp);
db::LibraryManager::instance ().changed_event.add (this, &LibrariesView::update_required);
do_update_content ();
}
@ -714,9 +712,14 @@ LibrariesView::do_update_content (int lib_index)
size_t imin = (lib_index < 0 ? 0 : (size_t) lib_index);
size_t imax = (lib_index < 0 ? std::numeric_limits <size_t>::max () : (size_t) lib_index);
// rebuild all events
detach_from_all_events ();
db::LibraryManager::instance ().changed_event.add (this, &LibrariesView::update_required);
std::vector<db::Library *> libraries;
for (db::LibraryManager::iterator lib = db::LibraryManager::instance ().begin (); lib != db::LibraryManager::instance ().end (); ++lib) {
libraries.push_back (db::LibraryManager::instance ().lib (lib->second));
libraries.back ()->layout ().hier_changed_event.add (this, &LibrariesView::update_required);
}
for (size_t i = imin; i < libraries.size () && i <= imax; ++i) {
@ -791,7 +794,7 @@ LibrariesView::do_update_content (int lib_index)
LibraryTreeWidget *cell_list = new LibraryTreeWidget (cl_frame, "tree", mp_view->view_object_widget ());
cl_ly->addWidget (cell_list);
cell_list->setModel (new CellTreeModel (cell_list, &m_libraries [i]->layout (), CellTreeModel::Flat | CellTreeModel::TopCells | CellTreeModel::BasicCells, 0));
cell_list->setModel (new CellTreeModel (cell_list, &m_libraries [i]->layout (), CellTreeModel::Flat | CellTreeModel::TopCells | CellTreeModel::BasicCells | CellTreeModel::WithVariants, 0));
cell_list->setUniformRowHeights (true);
pl = cell_list->palette ();
@ -805,7 +808,7 @@ LibrariesView::do_update_content (int lib_index)
cell_list->header ()->hide ();
cell_list->setSelectionMode (QTreeView::ExtendedSelection);
cell_list->setRootIsDecorated (false);
cell_list->setRootIsDecorated (true);
cell_list->setContextMenuPolicy (Qt::CustomContextMenu);
connect (cell_list, SIGNAL (customContextMenuRequested (const QPoint &)), this, SLOT (context_menu (const QPoint &)));
@ -866,7 +869,7 @@ LibrariesView::do_update_content (int lib_index)
CellTreeModel *model = dynamic_cast <CellTreeModel *> (mp_cell_lists [i]->model ());
if (model) {
model->configure (& m_libraries [i]->layout (), CellTreeModel::Flat | CellTreeModel::TopCells | CellTreeModel::BasicCells, 0);
model->configure (& m_libraries [i]->layout (), CellTreeModel::Flat | CellTreeModel::TopCells | CellTreeModel::BasicCells | CellTreeModel::WithVariants, 0);
}
}