/* KLayout Layout Viewer Copyright (C) 2006-2017 Matthias Koefferlein This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include "layCellSelectionForm.h" #include "dbCellInst.h" #include "dbLibrary.h" #include "dbLibraryManager.h" #include "tlException.h" #include "tlAlgorithm.h" #include "tlAssert.h" #include "layCellTreeModel.h" #include "layLayoutView.h" #include "tlExceptions.h" #include namespace lay { // ------------------------------------------------------------ CellSelectionForm::CellSelectionForm (QWidget *parent, lay::LayoutView *view, const char *name, bool simple_mode) : QDialog (parent), Ui::CellSelectionForm (), mp_view (view), m_current_cv (-1), m_name_cb_enabled (true), m_cells_cb_enabled (true), m_children_cb_enabled (true), m_parents_cb_enabled (true), m_update_all_dm (this, &CellSelectionForm::update_all), m_simple_mode (simple_mode) { setObjectName (QString::fromUtf8 (name)); Ui::CellSelectionForm::setupUi (this); // signals and slots connections connect (cancel_button, SIGNAL(clicked()), this, SLOT(reject())); connect (cb_views, SIGNAL(activated(int)), this, SLOT(view_changed(int))); connect (tb_set_parent, SIGNAL(clicked()), this, SLOT(set_parent())); connect (tb_set_child, SIGNAL(clicked()), this, SLOT(set_child())); connect (pb_hide, SIGNAL(clicked()), this, SLOT(hide_cell())); connect (pb_show, SIGNAL(clicked()), this, SLOT(show_cell())); connect (le_cell_name, SIGNAL(textChanged(const QString&)), this, SLOT(name_changed(const QString&))); connect (ok_button, SIGNAL(clicked()), this, SLOT(accept())); connect (apply_button, SIGNAL(clicked()), this, SLOT(apply_clicked())); connect (find_next, SIGNAL(clicked()), this, SLOT(find_next_clicked())); connect (lv_parents, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(parent_changed(const QModelIndex &))); connect (lv_children, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(child_changed(const QModelIndex &))); m_cellviews.reserve (mp_view->cellviews ()); for (unsigned int i = 0; i < mp_view->cellviews (); ++i) { m_cellviews.push_back (mp_view->cellview (i)); } if (simple_mode) { apply_button->hide (); tools_frame->hide (); } else { apply_button->show (); tools_frame->show (); } if (! m_cellviews.empty ()) { m_current_cv = view->active_cellview_index (); int cvi = 0; for (std::vector::const_iterator cv = m_cellviews.begin (); cv != m_cellviews.end (); ++cv, ++cvi) { cb_views->addItem (tl::to_qstring ((*cv)->name () + " (@" + tl::to_string (cvi + 1) + ")")); } cb_views->setCurrentIndex (m_current_cv); if (m_cellviews.size () == 1) { cb_views->hide (); layout_lbl->hide (); } else { cb_views->show (); layout_lbl->show (); } lv_cells->header ()->hide (); lv_cells->setRootIsDecorated (false); lv_children->header ()->hide (); lv_children->setRootIsDecorated (false); lv_parents->header ()->hide (); lv_parents->setRootIsDecorated (false); update_cell_list (); } } void CellSelectionForm::update_cell_list () { if (m_current_cv < 0 || m_current_cv >= int (m_cellviews.size ())) { return; } if (lv_cells->model ()) { delete lv_cells->model (); } lay::CellTreeModel *model = new lay::CellTreeModel (lv_cells, mp_view, m_current_cv, lay::CellTreeModel::Flat); lv_cells->setModel (model); // connect can only happen after setModel() connect (lv_cells->selectionModel (), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(cell_changed(const QModelIndex &, const QModelIndex &))); lay::CellView::unspecific_cell_path_type path (m_cellviews [m_current_cv].combined_unspecific_path ()); if (! path.empty ()) { select_entry (path.back ()); } } void CellSelectionForm::update_parents_list () { m_parents_cb_enabled = false; if (m_current_cv >= 0 && m_current_cv < int (m_cellviews.size ())) { lay::CellTreeModel *model = dynamic_cast (lv_cells->model ()); if (model) { if (lv_parents->model ()) { delete lv_parents->model (); } lv_parents->setModel (new lay::CellTreeModel (lv_parents, mp_view, m_current_cv, lay::CellTreeModel::Flat | lay::CellTreeModel::Parents, model->cell (lv_cells->selectionModel ()->currentIndex ()))); } } m_parents_cb_enabled = true; } void CellSelectionForm::update_children_list () { m_children_cb_enabled = false; if (m_current_cv >= 0 && m_current_cv < int (m_cellviews.size ())) { lay::CellTreeModel *model = dynamic_cast (lv_cells->model ()); if (model) { if (lv_children->model ()) { delete lv_children->model (); } lv_children->setModel (new lay::CellTreeModel (lv_children, mp_view, m_current_cv, lay::CellTreeModel::Flat | lay::CellTreeModel::Children, model->cell (lv_cells->selectionModel ()->currentIndex ()))); } } m_children_cb_enabled = true; } int CellSelectionForm::selected_cellview_index () const { return m_current_cv; } const lay::CellView & CellSelectionForm::selected_cellview () const { tl_assert (m_current_cv >= 0 && m_current_cv < int (m_cellviews.size ())); return m_cellviews [m_current_cv]; } void CellSelectionForm::commit_cv () { // update the cell view if (m_current_cv >= 0 && m_current_cv < int (m_cellviews.size ())) { lay::CellTreeModel *model = dynamic_cast (lv_cells->model ()); if (! model) { return; } const db::Cell *cell = model->cell (lv_cells->selectionModel ()->currentIndex ()); if (cell) { m_cellviews [m_current_cv].set_cell (cell->cell_index ()); } } } void CellSelectionForm::view_changed (int cv) { commit_cv (); m_current_cv = cv; update_cell_list (); } void CellSelectionForm::accept () { commit_cv (); QDialog::accept (); } void CellSelectionForm::apply_clicked() { // select the current cell but don't make it the new top. if (m_current_cv >= 0 && m_current_cv < int (m_cellviews.size ())) { lay::CellTreeModel *model = dynamic_cast (lv_cells->model ()); if (! model) { return; } const db::Cell *cell = model->cell (lv_cells->selectionModel ()->currentIndex ()); lay::CellView cv (m_cellviews [m_current_cv]); cv.set_cell (cell->cell_index ()); mp_view->set_current_cell_path(m_current_cv, cv.combined_unspecific_path ()); } } void CellSelectionForm::cell_changed (const QModelIndex ¤t, const QModelIndex &) { if (m_cells_cb_enabled) { m_name_cb_enabled = false; lay::CellTreeModel *model = dynamic_cast (lv_cells->model ()); if (model) { le_cell_name->setText (tl::to_qstring (model->cell_name (current))); model->clear_locate (); } m_name_cb_enabled = true; update_children_list (); update_parents_list (); } } void CellSelectionForm::set_child () { child_changed (lv_children->selectionModel ()->currentIndex ()); } void CellSelectionForm::child_changed(const QModelIndex ¤t) { if (m_children_cb_enabled && current.isValid ()) { if (m_current_cv >= 0 && m_current_cv < int (m_cellviews.size ())) { lay::CellTreeModel *model = dynamic_cast (lv_children->model ()); if (model) { select_entry (model->cell_index (lv_children->selectionModel ()->currentIndex ())); } } } } void CellSelectionForm::set_parent () { parent_changed (lv_parents->selectionModel ()->currentIndex ()); } void CellSelectionForm::parent_changed(const QModelIndex ¤t) { if (m_parents_cb_enabled && current.isValid ()) { if (m_current_cv >= 0 && m_current_cv < int (m_cellviews.size ())) { lay::CellTreeModel *model = dynamic_cast (lv_parents->model ()); if (model) { select_entry (model->cell_index (lv_parents->selectionModel ()->currentIndex ())); } } } } void CellSelectionForm::select_entry (lay::CellView::cell_index_type ci) { m_cells_cb_enabled = false; lay::CellTreeModel *model = dynamic_cast (lv_cells->model ()); if (! model) { return; } // select the current entry QModelIndex mi; for (int c = 0; c < model->toplevel_items (); ++c) { lay::CellTreeItem *item = model->toplevel_item (c); if (item->cell_index () == ci) { mi = model->model_index (item); break; } } if (mi.isValid ()) { m_cells_cb_enabled = false; lv_cells->selectionModel ()->setCurrentIndex (mi, QItemSelectionModel::Clear | QItemSelectionModel::SelectCurrent); lv_cells->scrollTo (mi); m_cells_cb_enabled = true; m_name_cb_enabled = false; le_cell_name->setText (tl::to_qstring (model->cell_name (mi))); model->clear_locate (); m_name_cb_enabled = true; // do child list updates in a user event handler. Otherwise changing the models // immediately interferes with Qt's internal logic. So we do an deferred update. m_update_all_dm (); } m_cells_cb_enabled = true; } void CellSelectionForm::update_all () { update_children_list (); update_parents_list (); } void CellSelectionForm::find_next_clicked () { lay::CellTreeModel *model = dynamic_cast (lv_cells->model ()); if (! model) { return; } QModelIndex mi = model->locate_next (); if (mi.isValid ()) { m_cells_cb_enabled = false; lv_cells->selectionModel ()->setCurrentIndex (mi, QItemSelectionModel::SelectCurrent); lv_cells->scrollTo (mi); update_children_list (); update_parents_list (); m_cells_cb_enabled = true; } } void CellSelectionForm::name_changed (const QString &s) { if (m_name_cb_enabled) { lay::CellTreeModel *model = dynamic_cast (lv_cells->model ()); if (! model) { return; } QModelIndex mi = model->locate (tl::to_string (s).c_str (), true); if (mi.isValid ()) { m_cells_cb_enabled = false; lv_cells->selectionModel ()->setCurrentIndex (mi, QItemSelectionModel::SelectCurrent); lv_cells->scrollTo (mi); update_children_list (); update_parents_list (); m_cells_cb_enabled = true; } } } void CellSelectionForm::show_cell () { lay::CellTreeModel *model = dynamic_cast (lv_cells->model ()); if (! model) { return; } if (m_current_cv < 0 || m_current_cv >= int (m_cellviews.size ())) { return; } QModelIndexList sel = lv_cells->selectionModel ()->selectedIndexes (); for (QModelIndexList::const_iterator s = sel.begin (); s != sel.end (); ++s) { db::cell_index_type ci = model->cell (*s)->cell_index (); mp_view->manager ()->transaction (tl::to_string (QObject::tr ("Show cells"))); mp_view->show_cell (ci, m_current_cv); mp_view->manager ()->commit (); } model->signal_data_changed (); } void CellSelectionForm::hide_cell () { lay::CellTreeModel *model = dynamic_cast (lv_cells->model ()); if (! model) { return; } if (m_current_cv < 0 || m_current_cv >= int (m_cellviews.size ())) { return; } QModelIndexList sel = lv_cells->selectionModel ()->selectedIndexes (); for (QModelIndexList::const_iterator s = sel.begin (); s != sel.end (); ++s) { db::cell_index_type ci = model->cell (*s)->cell_index (); mp_view->manager ()->transaction (tl::to_string (QObject::tr ("Hide cells"))); mp_view->hide_cell (ci, m_current_cv); mp_view->manager ()->commit (); } model->signal_data_changed (); } // ------------------------------------------------------------ SimpleCellSelectionForm::SimpleCellSelectionForm (QWidget *parent, db::Layout *layout, const char *name) : QDialog (parent), Ui::SimpleCellSelectionForm (), mp_layout (layout), m_name_cb_enabled (true), m_cells_cb_enabled (true), m_children_cb_enabled (true), m_parents_cb_enabled (true), m_update_all_dm (this, &SimpleCellSelectionForm::update_all), m_cell_index (-1) { setObjectName (QString::fromUtf8 (name)); Ui::SimpleCellSelectionForm::setupUi (this); // signals and slots connections connect (cancel_button, SIGNAL(clicked()), this, SLOT(reject())); connect (tb_set_parent, SIGNAL(clicked()), this, SLOT(set_parent())); connect (tb_set_child, SIGNAL(clicked()), this, SLOT(set_child())); connect (le_cell_name, SIGNAL(textChanged(const QString&)), this, SLOT(name_changed(const QString&))); connect (ok_button, SIGNAL(clicked()), this, SLOT(accept())); connect (find_next, SIGNAL(clicked()), this, SLOT(find_next_clicked())); connect (lv_parents, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(parent_changed(const QModelIndex &))); connect (lv_children, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(child_changed(const QModelIndex &))); lv_cells->header ()->hide (); lv_cells->setRootIsDecorated (false); lv_children->header ()->hide (); lv_children->setRootIsDecorated (false); lv_parents->header ()->hide (); lv_parents->setRootIsDecorated (false); ok_button->setText (QObject::tr ("Ok")); cancel_button->setText (QObject::tr ("Cancel")); update_cell_list (); } void SimpleCellSelectionForm::set_selected_cell_index (db::cell_index_type ci) { if (ci != m_cell_index) { m_cell_index = ci; select_entry (m_cell_index); } } void SimpleCellSelectionForm::update_cell_list () { if (lv_cells->model ()) { delete lv_cells->model (); } lay::CellTreeModel *model = new lay::CellTreeModel (lv_cells, mp_layout, lay::CellTreeModel::Flat); lv_cells->setModel (model); // connect can only happen after setModel() connect (lv_cells->selectionModel (), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(cell_changed(const QModelIndex &, const QModelIndex &))); select_entry (m_cell_index); } void SimpleCellSelectionForm::update_parents_list () { m_parents_cb_enabled = false; if (lv_parents->model ()) { delete lv_parents->model (); } if (mp_layout->is_valid_cell_index (m_cell_index)) { lv_parents->setModel (new lay::CellTreeModel (lv_parents, mp_layout, lay::CellTreeModel::Flat | lay::CellTreeModel::Parents, &mp_layout->cell (m_cell_index))); } m_parents_cb_enabled = true; } void SimpleCellSelectionForm::update_children_list () { m_children_cb_enabled = false; if (lv_children->model ()) { delete lv_children->model (); } if (mp_layout->is_valid_cell_index (m_cell_index)) { lv_children->setModel (new lay::CellTreeModel (lv_children, mp_layout, lay::CellTreeModel::Flat | lay::CellTreeModel::Children, &mp_layout->cell (m_cell_index))); } m_children_cb_enabled = true; } void SimpleCellSelectionForm::cell_changed (const QModelIndex ¤t, const QModelIndex &) { if (m_cells_cb_enabled) { m_name_cb_enabled = false; lay::CellTreeModel *model = dynamic_cast (lv_cells->model ()); if (model) { le_cell_name->setText (tl::to_qstring (model->cell_name (current))); m_cell_index = model->cell_index (current); model->clear_locate (); } else { m_cell_index = -1; } m_name_cb_enabled = true; update_children_list (); update_parents_list (); } } void SimpleCellSelectionForm::set_child () { child_changed (lv_children->selectionModel ()->currentIndex ()); } void SimpleCellSelectionForm::child_changed(const QModelIndex ¤t) { if (m_children_cb_enabled && current.isValid ()) { lay::CellTreeModel *model = dynamic_cast (lv_children->model ()); if (model) { select_entry (model->cell_index (lv_children->selectionModel ()->currentIndex ())); } } } void SimpleCellSelectionForm::set_parent () { parent_changed (lv_parents->selectionModel ()->currentIndex ()); } void SimpleCellSelectionForm::parent_changed(const QModelIndex ¤t) { if (m_parents_cb_enabled && current.isValid ()) { lay::CellTreeModel *model = dynamic_cast (lv_parents->model ()); if (model) { select_entry (model->cell_index (lv_parents->selectionModel ()->currentIndex ())); } } } void SimpleCellSelectionForm::select_entry (lay::CellView::cell_index_type ci) { m_cells_cb_enabled = false; m_cell_index = ci; lay::CellTreeModel *model = dynamic_cast (lv_cells->model ()); if (! model) { return; } // select the current entry QModelIndex mi; for (int c = 0; c < model->toplevel_items (); ++c) { lay::CellTreeItem *item = model->toplevel_item (c); if (item->cell_index () == ci) { mi = model->model_index (item); break; } } if (mi.isValid ()) { m_cells_cb_enabled = false; lv_cells->selectionModel ()->setCurrentIndex (mi, QItemSelectionModel::Clear | QItemSelectionModel::SelectCurrent); lv_cells->scrollTo (mi); m_cells_cb_enabled = true; m_name_cb_enabled = false; le_cell_name->setText (tl::to_qstring (model->cell_name (mi))); model->clear_locate (); m_name_cb_enabled = true; // do child list updates in a user event handler. Otherwise changing the models // immediately interferes with Qt's internal logic. So we do an deferred update. m_update_all_dm (); } m_cells_cb_enabled = true; } void SimpleCellSelectionForm::update_all () { update_children_list (); update_parents_list (); } void SimpleCellSelectionForm::find_next_clicked () { lay::CellTreeModel *model = dynamic_cast (lv_cells->model ()); if (! model) { return; } QModelIndex mi = model->locate_next (); if (mi.isValid ()) { m_cells_cb_enabled = false; lv_cells->selectionModel ()->setCurrentIndex (mi, QItemSelectionModel::SelectCurrent); lv_cells->scrollTo (mi); m_cell_index = model->cell_index (mi); update_children_list (); update_parents_list (); m_cells_cb_enabled = true; } else { m_cell_index = -1; } } void SimpleCellSelectionForm::name_changed (const QString &s) { if (m_name_cb_enabled) { lay::CellTreeModel *model = dynamic_cast (lv_cells->model ()); if (! model) { return; } QModelIndex mi = model->locate (tl::to_string (s).c_str (), true); if (mi.isValid ()) { m_cells_cb_enabled = false; lv_cells->selectionModel ()->setCurrentIndex (mi, QItemSelectionModel::SelectCurrent); lv_cells->scrollTo (mi); m_cell_index = model->cell_index (mi); update_children_list (); update_parents_list (); m_cells_cb_enabled = true; } else { m_cell_index = -1; } } } // ------------------------------------------------------------ LibraryCellSelectionForm::LibraryCellSelectionForm (QWidget *parent, db::Layout *layout, const char *name, bool all_cells) : QDialog (parent), Ui::LibraryCellSelectionForm (), mp_lib (0), mp_layout (layout), m_name_cb_enabled (true), m_cells_cb_enabled (true), m_cell_index (-1), m_pcell_id (-1), m_is_pcell (false), m_all_cells (all_cells) { setObjectName (QString::fromUtf8 (name)); Ui::LibraryCellSelectionForm::setupUi (this); // no library selection lib_label->hide (); lib_cb->hide (); // signals and slots connections connect (cancel_button, SIGNAL(clicked()), this, SLOT(reject())); connect (ok_button, SIGNAL(clicked()), this, SLOT(accept())); connect (le_cell_name, SIGNAL(textChanged(const QString&)), this, SLOT(name_changed(const QString&))); connect (find_next, SIGNAL(clicked()), this, SLOT(find_next_clicked())); connect (cb_show_all_cells, SIGNAL(clicked()), this, SLOT(show_all_changed())); lv_cells->header ()->hide (); lv_cells->setRootIsDecorated (false); ok_button->setText (QObject::tr ("Ok")); cancel_button->setText (QObject::tr ("Cancel")); update_cell_list (); } LibraryCellSelectionForm::LibraryCellSelectionForm (QWidget *parent, const char *name, bool all_cells) : QDialog (parent), Ui::LibraryCellSelectionForm (), mp_lib (0), mp_layout (0), m_name_cb_enabled (true), m_cells_cb_enabled (true), m_cell_index (-1), m_pcell_id (-1), m_is_pcell (false), m_all_cells (all_cells) { mp_lib = db::LibraryManager::instance ().lib_ptr_by_name ("Basic"); mp_layout = &mp_lib->layout (); setObjectName (QString::fromUtf8 (name)); Ui::LibraryCellSelectionForm::setupUi (this); lib_cb->set_current_library (mp_lib); // signals and slots connections connect (cancel_button, SIGNAL(clicked()), this, SLOT(reject())); connect (ok_button, SIGNAL(clicked()), this, SLOT(accept())); connect (le_cell_name, SIGNAL(textChanged(const QString&)), this, SLOT(name_changed(const QString&))); connect (find_next, SIGNAL(clicked()), this, SLOT(find_next_clicked())); connect (lib_cb, SIGNAL(currentIndexChanged(int)), this, SLOT(lib_changed())); connect (cb_show_all_cells, SIGNAL(clicked()), this, SLOT(show_all_changed())); lv_cells->header ()->hide (); lv_cells->setRootIsDecorated (false); ok_button->setText (QObject::tr ("Ok")); cancel_button->setText (QObject::tr ("Cancel")); update_cell_list (); } void LibraryCellSelectionForm::show_all_changed () { m_all_cells = cb_show_all_cells->isChecked (); update_cell_list (); } void LibraryCellSelectionForm::lib_changed () { mp_lib = lib_cb->current_library (); mp_layout = mp_lib ? &mp_lib->layout () : 0; update_cell_list (); } void LibraryCellSelectionForm::set_current_library (db::Library *lib) { mp_lib = lib; mp_layout = mp_lib ? &mp_lib->layout () : 0; update_cell_list (); } void LibraryCellSelectionForm::set_selected_cell_index (db::cell_index_type ci) { if (ci != m_cell_index || selected_cell_is_pcell ()) { m_cell_index = ci; m_pcell_id = 0; m_is_pcell = false; select_entry (m_cell_index); } } void LibraryCellSelectionForm::set_selected_pcell_id (db::pcell_id_type pci) { if (pci != m_pcell_id || ! selected_cell_is_pcell ()) { m_cell_index = 0; m_pcell_id = pci; m_is_pcell = true; select_pcell_entry (m_pcell_id); } } void LibraryCellSelectionForm::accept () { BEGIN_PROTECTED if (! mp_layout) { throw tl::Exception (tl::to_string (QObject::tr ("No library selected"))); } if (! m_is_pcell && ! mp_layout->is_valid_cell_index (m_cell_index)) { throw tl::Exception (tl::to_string (QObject::tr ("No cell selected"))); } QDialog::accept (); END_PROTECTED } void LibraryCellSelectionForm::update_cell_list () { if (lv_cells->model ()) { delete lv_cells->model (); } cb_show_all_cells->setChecked (m_all_cells); if (mp_layout) { // TODO: get rid of that const_cast lay::CellTreeModel *model = new lay::CellTreeModel (lv_cells, const_cast (mp_layout), lay::CellTreeModel::Flat | (m_all_cells ? 0 : (lay::CellTreeModel::TopCells | lay::CellTreeModel::BasicCells))); lv_cells->setModel (model); // connect can only happen after setModel() connect (lv_cells->selectionModel (), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(cell_changed(const QModelIndex &, const QModelIndex &))); select_entry (std::numeric_limits::max ()); } } void LibraryCellSelectionForm::cell_changed (const QModelIndex ¤t, const QModelIndex &) { if (m_cells_cb_enabled) { m_name_cb_enabled = false; lay::CellTreeModel *model = dynamic_cast (lv_cells->model ()); if (model) { m_is_pcell = model->is_pcell (current); if (m_is_pcell) { m_pcell_id = model->pcell_id (current); } else { m_cell_index = model->cell_index (current); } le_cell_name->setText (tl::to_qstring (model->cell_name (current))); model->clear_locate (); } else { m_cell_index = -1; m_pcell_id = -1; m_is_pcell = false; } m_name_cb_enabled = true; } } void LibraryCellSelectionForm::select_pcell_entry (db::pcell_id_type pci) { m_cells_cb_enabled = false; m_pcell_id = pci; m_is_pcell = true; lay::CellTreeModel *model = dynamic_cast (lv_cells->model ()); if (! model) { return; } // select the current entry QModelIndex mi; for (int c = 0; c < model->toplevel_items (); ++c) { lay::CellTreeItem *item = model->toplevel_item (c); if (item->is_pcell () && item->cell_index () == pci) { mi = model->model_index (item); break; } } if (mi.isValid ()) { m_cells_cb_enabled = false; lv_cells->selectionModel ()->setCurrentIndex (mi, QItemSelectionModel::Clear | QItemSelectionModel::SelectCurrent); lv_cells->scrollTo (mi); m_cells_cb_enabled = true; m_name_cb_enabled = false; le_cell_name->setText (tl::to_qstring (model->cell_name (mi))); model->clear_locate (); m_name_cb_enabled = true; } m_cells_cb_enabled = true; } void LibraryCellSelectionForm::select_entry (lay::CellView::cell_index_type ci) { m_cells_cb_enabled = false; m_cell_index = ci; m_is_pcell = false; lay::CellTreeModel *model = dynamic_cast (lv_cells->model ()); if (! model) { return; } // select the current entry QModelIndex mi; for (int c = 0; c < model->toplevel_items (); ++c) { lay::CellTreeItem *item = model->toplevel_item (c); if (item->cell_index () == ci) { mi = model->model_index (item); break; } } if (mi.isValid ()) { m_cells_cb_enabled = false; lv_cells->selectionModel ()->setCurrentIndex (mi, QItemSelectionModel::Clear | QItemSelectionModel::SelectCurrent); lv_cells->scrollTo (mi); m_cells_cb_enabled = true; m_name_cb_enabled = false; le_cell_name->setText (tl::to_qstring (model->cell_name (mi))); model->clear_locate (); m_name_cb_enabled = true; } m_cells_cb_enabled = true; } void LibraryCellSelectionForm::find_next_clicked () { lay::CellTreeModel *model = dynamic_cast (lv_cells->model ()); if (! model) { return; } QModelIndex mi = model->locate_next (); if (mi.isValid ()) { m_cells_cb_enabled = false; lv_cells->selectionModel ()->setCurrentIndex (mi, QItemSelectionModel::SelectCurrent); lv_cells->scrollTo (mi); m_is_pcell = model->is_pcell (mi); if (m_is_pcell) { m_pcell_id = model->pcell_id (mi); } else { m_cell_index = model->cell_index (mi); } m_cells_cb_enabled = true; } else { m_cell_index = -1; m_pcell_id = -1; m_is_pcell = false; } } void LibraryCellSelectionForm::name_changed (const QString &s) { if (m_name_cb_enabled) { lay::CellTreeModel *model = dynamic_cast (lv_cells->model ()); if (! model) { return; } QModelIndex mi = model->locate (tl::to_string (s).c_str (), true); if (mi.isValid ()) { m_cells_cb_enabled = false; lv_cells->selectionModel ()->setCurrentIndex (mi, QItemSelectionModel::SelectCurrent); lv_cells->scrollTo (mi); m_is_pcell = model->is_pcell (mi); if (m_is_pcell) { m_pcell_id = model->pcell_id (mi); } else { m_cell_index = model->cell_index (mi); } m_cells_cb_enabled = true; } else { m_cell_index = -1; m_pcell_id = -1; m_is_pcell = false; } } } }