Implemented solution for #2306

First of all, NetlistBrowserDialog#current_path now has a setter.
Changing the selection will navigate to the location of the
selected object, but not issue an "on_selection_changed" event.

In addition, the following features have been added:
* NetlistBrowserDialog#db_index
* NetlistBrowserDialog#view
This commit is contained in:
Matthias Koefferlein 2026-03-21 20:32:32 +01:00
parent 415650bb3a
commit c211925d2a
7 changed files with 108 additions and 31 deletions

View File

@ -169,6 +169,20 @@ static lay::NetlistObjectPath current_path_second (lay::NetlistBrowserDialog *di
return dialog->current_path ().second ();
}
static void set_current_path (lay::NetlistBrowserDialog *dialog, const lay::NetlistObjectsPath *path)
{
if (! path) {
dialog->set_current_path (lay::NetlistObjectsPath ());
} else {
dialog->set_current_path (*path);
}
}
static lay::LayoutViewBase *get_view (lay::NetlistBrowserDialog *dialog)
{
return dialog->view ();
}
Class<lay::NetlistBrowserDialog> decl_NetlistBrowserDialog ("lay", "NetlistBrowserDialog",
gsi::event ("on_current_db_changed", &lay::NetlistBrowserDialog::current_db_changed_event,
"@brief This event is triggered when the current database is changed.\n"
@ -187,6 +201,16 @@ Class<lay::NetlistBrowserDialog> decl_NetlistBrowserDialog ("lay", "NetlistBrows
gsi::method ("db", &lay::NetlistBrowserDialog::db,
"@brief Gets the database the browser is connected to.\n"
) +
gsi::method ("db_index", &lay::NetlistBrowserDialog::l2n_index,
"@brief Gets the database index inside the view the browser is connected to.\n"
"\n"
"This attribute has been introduced in version 0.30.8.\n"
) +
gsi::method_ext ("view", &get_view,
"@brief Gets the view the browser is connected to.\n"
"\n"
"This attribute has been introduced in version 0.30.8.\n"
) +
gsi::method_ext ("current_path_first", &current_path_first,
"@brief Gets the path of the current object on the first (layout in case of LVS database) side.\n"
) +
@ -196,6 +220,14 @@ Class<lay::NetlistBrowserDialog> decl_NetlistBrowserDialog ("lay", "NetlistBrows
gsi::method ("current_path", &lay::NetlistBrowserDialog::current_path,
"@brief Gets the path of the current object as a path pair (combines layout and schematic object paths in case of a LVS database view).\n"
) +
gsi::method_ext ("current_path=", &set_current_path,
"@brief Sets the current path.\n"
"This is the setter corresponding to the 'current_path' getter. Passing nil clears the selection.\n"
"Changing the selection will update the highlights and navigate to the location depending on the "
"settings. An \\on_selection_changed signal is not emitted.\n"
"\n"
"This setter has been introduced in version 0.30.8.\n"
) +
gsi::method ("selected_paths", &lay::NetlistBrowserDialog::selected_paths,
"@brief Gets the nets currently selected objects (paths) in the netlist database browser.\n"
"The result is an array of path pairs. See \\NetlistObjectsPath for details about these pairs."

View File

@ -306,28 +306,28 @@ SingleIndexedNetlistModel::parent_of (const subcircuit_pair &subcircuits) const
return std::make_pair (subcircuits.first ? subcircuits.first->circuit () : 0, (const db::Circuit *) 0);
}
std::pair<IndexedNetlistModel::circuit_pair, std::pair<IndexedNetlistModel::Status, std::string> > SingleIndexedNetlistModel::top_circuit_from_index(size_t index) const
std::pair<IndexedNetlistModel::circuit_pair, std::pair<IndexedNetlistModel::Status, std::string> > SingleIndexedNetlistModel::top_circuit_from_index (size_t index) const
{
db::Netlist::const_top_down_circuit_iterator none;
return std::make_pair (attr_by_object_and_index (std::make_pair ((const db::Circuit *) 0, (const db::Circuit *) 0), index, mp_netlist->begin_top_down (), mp_netlist->begin_top_down () + mp_netlist->top_circuit_count (), none, none, m_child_circuit_by_circuit_and_index, sort_by_name<db::Circuit> ()), std::make_pair (db::NetlistCrossReference::None, std::string ()));
}
std::pair<IndexedNetlistModel::circuit_pair, std::pair<IndexedNetlistModel::Status, std::string> > SingleIndexedNetlistModel::child_circuit_from_index(const circuit_pair &circuits, size_t index) const
std::pair<IndexedNetlistModel::circuit_pair, std::pair<IndexedNetlistModel::Status, std::string> > SingleIndexedNetlistModel::child_circuit_from_index (const circuit_pair &circuits, size_t index) const
{
db::Circuit::const_child_circuit_iterator none;
return std::make_pair (attr_by_object_and_index (circuits, index, circuits.first->begin_children (), circuits.first->end_children (), none, none, m_child_circuit_by_circuit_and_index, sort_by_name<db::Circuit> ()), std::make_pair (db::NetlistCrossReference::None, std::string ()));
}
std::pair<IndexedNetlistModel::circuit_pair, std::pair<IndexedNetlistModel::Status, std::string> > SingleIndexedNetlistModel::circuit_from_index(size_t index) const
std::pair<IndexedNetlistModel::circuit_pair, std::pair<IndexedNetlistModel::Status, std::string> > SingleIndexedNetlistModel::circuit_from_index (size_t index) const
{
db::Netlist::const_circuit_iterator none;
return std::make_pair (attr_by_object_and_index (std::make_pair (mp_netlist, (const db::Netlist *) 0), index, mp_netlist->begin_circuits (), mp_netlist->end_circuits (), none, none, m_circuit_by_index, sort_by_name<db::Circuit> ()), std::make_pair (db::NetlistCrossReference::None, std::string ()));
}
std::pair<IndexedNetlistModel::net_pair, std::pair<IndexedNetlistModel::Status, std::string> > SingleIndexedNetlistModel::net_from_index(const circuit_pair &circuits, size_t index) const
std::pair<IndexedNetlistModel::net_pair, std::pair<IndexedNetlistModel::Status, std::string> > SingleIndexedNetlistModel::net_from_index (const circuit_pair &circuits, size_t index) const
{
db::Circuit::const_net_iterator none;
return std::make_pair (attr_by_object_and_index (circuits, index, circuits.first->begin_nets (), circuits.first->end_nets (), none, none, m_net_by_circuit_and_index, sort_by_expanded_name<db::Net> ()), std::make_pair (db::NetlistCrossReference::None, std::string ()));
return std::make_pair (attr_by_object_and_index (std::make_pair (circuits.first, (const db::Circuit *) 0), index, circuits.first->begin_nets (), circuits.first->end_nets (), none, none, m_net_by_circuit_and_index, sort_by_expanded_name<db::Net> ()), std::make_pair (db::NetlistCrossReference::None, std::string ()));
}
const db::Net *
@ -346,12 +346,15 @@ IndexedNetlistModel::net_subcircuit_pin_pair
SingleIndexedNetlistModel::net_subcircuit_pinref_from_index (const net_pair &nets, size_t index) const
{
db::Net::const_subcircuit_pin_iterator none;
return attr_by_object_and_index (nets, index, nets.first->begin_subcircuit_pins (), nets.first->end_subcircuit_pins (), none, none, m_subcircuit_pinref_by_net_and_index, sort_by_pin_name<db::NetSubcircuitPinRef> ());
return attr_by_object_and_index (std::make_pair (nets.first, (const db::Net *) 0), index, nets.first->begin_subcircuit_pins (), nets.first->end_subcircuit_pins (), none, none, m_subcircuit_pinref_by_net_and_index, sort_by_pin_name<db::NetSubcircuitPinRef> ());
}
IndexedNetlistModel::net_subcircuit_pin_pair
SingleIndexedNetlistModel::subcircuit_pinref_from_index (const subcircuit_pair &subcircuits, size_t index) const
SingleIndexedNetlistModel::subcircuit_pinref_from_index (const subcircuit_pair &subcircuits_in, size_t index) const
{
subcircuit_pair subcircuits = subcircuits_in;
subcircuits.second = 0;
if (! subcircuits.first) {
return IndexedNetlistModel::net_subcircuit_pin_pair ((const db::NetSubcircuitPinRef *) 0, (const db::NetSubcircuitPinRef *) 0);
}
@ -381,62 +384,68 @@ IndexedNetlistModel::net_terminal_pair
SingleIndexedNetlistModel::net_terminalref_from_index (const net_pair &nets, size_t index) const
{
db::Net::const_terminal_iterator none;
return attr_by_object_and_index (nets, index, nets.first->begin_terminals (), nets.first->end_terminals (), none, none, m_terminalref_by_net_and_index, sort_by_terminal_id<db::NetTerminalRef> ());
return attr_by_object_and_index (std::make_pair (nets.first, (const db::Net *) 0), index, nets.first->begin_terminals (), nets.first->end_terminals (), none, none, m_terminalref_by_net_and_index, sort_by_terminal_id<db::NetTerminalRef> ());
}
IndexedNetlistModel::net_pin_pair
SingleIndexedNetlistModel::net_pinref_from_index (const net_pair &nets, size_t index) const
{
db::Net::const_pin_iterator none;
return attr_by_object_and_index (nets, index, nets.first->begin_pins (), nets.first->end_pins (), none, none, m_pinref_by_net_and_index, sort_by_pin_name<db::NetPinRef> ());
return attr_by_object_and_index (std::make_pair (nets.first, (const db::Net *) 0), index, nets.first->begin_pins (), nets.first->end_pins (), none, none, m_pinref_by_net_and_index, sort_by_pin_name<db::NetPinRef> ());
}
std::pair<IndexedNetlistModel::device_pair, std::pair<IndexedNetlistModel::Status, std::string> > SingleIndexedNetlistModel::device_from_index(const circuit_pair &circuits, size_t index) const
std::pair<IndexedNetlistModel::device_pair, std::pair<IndexedNetlistModel::Status, std::string> > SingleIndexedNetlistModel::device_from_index (const circuit_pair &circuits, size_t index) const
{
db::Circuit::const_device_iterator none;
return std::make_pair (attr_by_object_and_index (circuits, index, circuits.first->begin_devices (), circuits.first->end_devices (), none, none, m_device_by_circuit_and_index, sort_by_expanded_name<db::Device> ()), std::make_pair (db::NetlistCrossReference::None, std::string ()));
return std::make_pair (attr_by_object_and_index (std::make_pair (circuits.first, (const db::Circuit *) 0), index, circuits.first->begin_devices (), circuits.first->end_devices (), none, none, m_device_by_circuit_and_index, sort_by_expanded_name<db::Device> ()), std::make_pair (db::NetlistCrossReference::None, std::string ()));
}
std::pair<IndexedNetlistModel::pin_pair, std::pair<IndexedNetlistModel::Status, std::string> > SingleIndexedNetlistModel::pin_from_index(const circuit_pair &circuits, size_t index) const
std::pair<IndexedNetlistModel::pin_pair, std::pair<IndexedNetlistModel::Status, std::string> > SingleIndexedNetlistModel::pin_from_index (const circuit_pair &circuits, size_t index) const
{
db::Circuit::const_pin_iterator none;
return std::make_pair (attr_by_object_and_index (circuits, index, circuits.first->begin_pins (), circuits.first->end_pins (), none, none, m_pin_by_circuit_and_index, Unsorted ()), std::make_pair (db::NetlistCrossReference::None, std::string ()));
return std::make_pair (attr_by_object_and_index (std::make_pair (circuits.first, (const db::Circuit *) 0), index, circuits.first->begin_pins (), circuits.first->end_pins (), none, none, m_pin_by_circuit_and_index, Unsorted ()), std::make_pair (db::NetlistCrossReference::None, std::string ()));
}
std::pair<IndexedNetlistModel::subcircuit_pair, std::pair<IndexedNetlistModel::Status, std::string> > SingleIndexedNetlistModel::subcircuit_from_index(const circuit_pair &circuits, size_t index) const
std::pair<IndexedNetlistModel::subcircuit_pair, std::pair<IndexedNetlistModel::Status, std::string> > SingleIndexedNetlistModel::subcircuit_from_index (const circuit_pair &circuits, size_t index) const
{
db::Circuit::const_subcircuit_iterator none;
return std::make_pair (attr_by_object_and_index (circuits, index, circuits.first->begin_subcircuits (), circuits.first->end_subcircuits (), none, none, m_subcircuit_by_circuit_and_index, sort_by_expanded_name<db::SubCircuit> ()), std::make_pair (db::NetlistCrossReference::None, std::string ()));
return std::make_pair (attr_by_object_and_index (std::make_pair (circuits.first, (const db::Circuit *) 0), index, circuits.first->begin_subcircuits (), circuits.first->end_subcircuits (), none, none, m_subcircuit_by_circuit_and_index, sort_by_expanded_name<db::SubCircuit> ()), std::make_pair (db::NetlistCrossReference::None, std::string ()));
}
size_t
SingleIndexedNetlistModel::circuit_index (const circuit_pair &circuits) const
{
db::Netlist::const_circuit_iterator none;
return index_from_attr (circuits, mp_netlist->begin_circuits (), mp_netlist->end_circuits (), none, none, m_circuit_index_by_object, sort_by_name<db::Circuit> ());
return index_from_attr (std::make_pair (circuits.first, (const db::Circuit *) 0), mp_netlist->begin_circuits (), mp_netlist->end_circuits (), none, none, m_circuit_index_by_object, sort_by_name<db::Circuit> ());
}
size_t
SingleIndexedNetlistModel::net_index (const net_pair &nets) const
SingleIndexedNetlistModel::net_index (const net_pair &nets_in) const
{
db::Circuit::const_net_iterator none;
net_pair nets = nets_in;
nets.second = 0;
circuit_pair circuits = parent_of (nets);
return index_from_attr (nets,
circuits.first ? circuits.first->begin_nets () : none, circuits.first ? circuits.first->end_nets () : none,
circuits.second ? circuits.second->begin_nets () : none, circuits.second ? circuits.second->end_nets () : none,
none, none,
m_net_index_by_object, sort_by_expanded_name<db::Net> ());
}
size_t
SingleIndexedNetlistModel::device_index (const device_pair &devices) const
SingleIndexedNetlistModel::device_index (const device_pair &devices_in) const
{
db::Circuit::const_device_iterator none;
device_pair devices = devices_in;
devices.second = 0;
circuit_pair circuits = parent_of (devices);
return index_from_attr (devices,
circuits.first ? circuits.first->begin_devices () : none, circuits.first ? circuits.first->end_devices () : none,
circuits.second ? circuits.second->begin_devices () : none, circuits.second ? circuits.second->end_devices () : none,
none, none,
m_device_index_by_object, sort_by_expanded_name<db::Device> ());
}
@ -445,21 +454,24 @@ SingleIndexedNetlistModel::pin_index (const pin_pair &pins, const circuit_pair &
{
db::Circuit::const_pin_iterator none;
return index_from_attr (pins,
return index_from_attr (std::make_pair (pins.first, (const db::Pin *) 0),
circuits.first ? circuits.first->begin_pins () : none, circuits.first ? circuits.first->end_pins () : none,
circuits.second ? circuits.second->begin_pins () : none, circuits.second ? circuits.second->end_pins () : none,
none, none,
m_pin_index_by_object, sort_by_expanded_name<db::Pin> ());
}
size_t
SingleIndexedNetlistModel::subcircuit_index (const subcircuit_pair &subcircuits) const
SingleIndexedNetlistModel::subcircuit_index (const subcircuit_pair &subcircuits_in) const
{
db::Circuit::const_subcircuit_iterator none;
subcircuit_pair subcircuits = subcircuits_in;
subcircuits.second = 0;
circuit_pair circuits = parent_of (subcircuits);
return index_from_attr (subcircuits,
circuits.first ? circuits.first->begin_subcircuits () : none, circuits.first ? circuits.first->end_subcircuits () : none,
circuits.second ? circuits.second->begin_subcircuits () : none, circuits.second ? circuits.second->end_subcircuits () : none,
none, none,
m_subcircuit_index_by_object, sort_by_expanded_name<db::SubCircuit> ());
}

View File

@ -141,6 +141,12 @@ NetlistBrowserDialog::db ()
return mp_ui->browser_page->db ();
}
int
NetlistBrowserDialog::l2n_index ()
{
return m_l2n_index;
}
const lay::NetlistObjectsPath &
NetlistBrowserDialog::current_path () const
{
@ -152,6 +158,14 @@ NetlistBrowserDialog::current_path () const
}
}
void
NetlistBrowserDialog::set_current_path (const lay::NetlistObjectsPath &path)
{
if (mp_ui->browser_page) {
mp_ui->browser_page->select_path (path);
}
}
const std::vector<lay::NetlistObjectsPath> &
NetlistBrowserDialog::selected_paths () const
{

View File

@ -77,11 +77,26 @@ public:
*/
db::LayoutToNetlist *db ();
/**
* @brief Gets the index of the currently selected database in the view
*/
int l2n_index ();
/**
* @brief Gets the current object's path
*/
const lay::NetlistObjectsPath &current_path () const;
/**
* @brief Sets the current object's path
*
* This will make the given netlist object the current one and change the
* selection to this one.
*
* Passing a null path will clear the selection.
*/
void set_current_path (const lay::NetlistObjectsPath &path);
/**
* @brief Gets the selected nets
*/

View File

@ -3025,9 +3025,9 @@ NetlistBrowserModel::index_from_subcircuit (const std::pair<const db::SubCircuit
}
QModelIndex
NetlistBrowserModel::index_from_circuit (const db::Circuit *net) const
NetlistBrowserModel::index_from_circuit (const db::Circuit *circuit) const
{
return index_from_circuit (std::make_pair (net, mp_indexer->second_circuit_for (net)));
return index_from_circuit (std::make_pair (circuit, mp_indexer->second_circuit_for (circuit)));
}
std::pair<const db::Circuit *, const db::Circuit *>

View File

@ -502,9 +502,9 @@ NetlistBrowserPage::select_path (const lay::NetlistObjectsPath &path)
{
if (path.is_null ()) {
nl_directory_tree->clearSelection ();
sch_directory_tree->clearSelection ();
xref_directory_tree->clearSelection ();
nl_directory_tree->setCurrentIndex (QModelIndex ());
sch_directory_tree->setCurrentIndex (QModelIndex ());
xref_directory_tree->setCurrentIndex (QModelIndex ());
} else {
@ -1315,7 +1315,7 @@ NetlistBrowserPage::clear_highlights ()
void
NetlistBrowserPage::highlight (const NetlistObjectsPath &current_path, const std::vector<NetlistObjectsPath> &selected_paths)
{
if (current_path != m_current_path && selected_paths != m_selected_paths) {
if (current_path != m_current_path || selected_paths != m_selected_paths) {
m_current_path = current_path;
m_selected_paths = selected_paths;

View File

@ -169,6 +169,11 @@ public:
*/
void update_highlights ();
/**
* @brief Adjusts the view depending on the current settings
*/
void adjust_view ();
/**
* @brief Gets the current object's path
*/
@ -255,7 +260,6 @@ private:
void setup_trees ();
void add_to_history (const QModelIndex &index, bool fwd);
void navigate_to (const QModelIndex &index, bool forward = true);
void adjust_view ();
void clear_markers ();
void highlight (const NetlistObjectsPath &current_path, const std::vector<NetlistObjectsPath> &selected_paths);
void clear_highlights ();