diff --git a/src/laybasic/laybasic/NetlistBrowserPage.ui b/src/laybasic/laybasic/NetlistBrowserPage.ui index 24516eb09..988e57d28 100644 --- a/src/laybasic/laybasic/NetlistBrowserPage.ui +++ b/src/laybasic/laybasic/NetlistBrowserPage.ui @@ -47,7 +47,10 @@ QFrame::Raised - + + + 0 + 0 @@ -60,174 +63,7 @@ 0 - - 6 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - ... - - - - :/down.png:/down.png - - - - - - - ... - - - - :/up.png:/up.png - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 10 - 20 - - - - - - - - Configure filters - - - - - - :/find.png - - - - - - - - 1 - 0 - - - - - 0 - 0 - - - - - - - - - - - - 0 - 0 - - - - - 0 - 4 - - - - Qt::ActionsContextMenu - - - QAbstractItemView::ExtendedSelection - - - QAbstractItemView::SelectRows - - - true - - - true - - - true - - - true - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - + QFrame::NoFrame @@ -283,6 +119,182 @@ + + + + + 1 + 0 + + + + + 0 + 0 + + + + + 250 + 16777215 + + + + + + + + Find in netlist + + + ... + + + + :/find.png:/find.png + + + true + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 6 + + + + + + + + + 0 + 0 + + + + + 0 + 4 + + + + Qt::ActionsContextMenu + + + QAbstractItemView::ExtendedSelection + + + QAbstractItemView::SelectRows + + + true + + + true + + + true + + + false + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + TextLabel + + + + + + + Show more information about nets + + + ... + + + + :/info_16.png:/info_16.png + + + true + + + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + @@ -301,7 +313,30 @@ Expand All + + + true + + + Use Regular Expressions + + + + + true + + + Case Sensitive + + + + + lay::DecoratedLineEdit + QLineEdit +
layWidgets.h
+
+
directory_tree diff --git a/src/laybasic/laybasic/layNetlistBrowserPage.cc b/src/laybasic/laybasic/layNetlistBrowserPage.cc index 452708079..687a0b5ce 100644 --- a/src/laybasic/laybasic/layNetlistBrowserPage.cc +++ b/src/laybasic/laybasic/layNetlistBrowserPage.cc @@ -32,6 +32,7 @@ #include #include #include +#include namespace lay { @@ -578,6 +579,8 @@ NetlistBrowserModel::data (const QModelIndex &index, int role) const return QVariant (icon (index)); } else if (role == Qt::DisplayRole) { return QVariant (text (index)); + } else if (role == Qt::UserRole) { + return QVariant (search_text (index)); } else { return QVariant (); } @@ -848,6 +851,155 @@ NetlistBrowserModel::text (const QModelIndex &index) const return QString (); } +QString +NetlistBrowserModel::search_text (const QModelIndex &index) const +{ + void *id = index.internalPointer (); + + if (is_id_circuit (id)) { + + const db::Circuit *circuit = circuit_from_id (id); + if (circuit) { + return tl::to_qstring (circuit->name ()); + } + // TODO: in case of compare, use circuit_name(a)|circuit_name(b) + + } else if (is_id_circuit_pin (id)) { + + const db::Pin *pin = pin_from_id (id); + if (pin) { + return tl::to_qstring (pin->expanded_name ()); + } + // TODO: in case of compare, use pin_name(a)|pin_name(b) + + } else if (is_id_circuit_pin_net (id)) { + + const db::Circuit *circuit = circuit_from_id (id); + const db::Pin *pin = pin_from_id (id); + if (pin) { + const db::Net *net = circuit->net_for_pin (pin->id ()); + if (net) { + return tl::to_qstring (net->expanded_name ()); + } + } + // TODO: in case of compare, use net_name(a)|net_name(b) + + } else if (is_id_circuit_device (id)) { + + const db::Device *device = device_from_id (id); + if (device && device->device_class ()) { + return tl::to_qstring (device->device_class ()->name () + "|" + device->expanded_name ()); + } + // TODO: in case of compare, use class(a)|device_name(a)|class(b)|device_name(b) + + } else if (is_id_circuit_device_terminal (id)) { + + const db::Device *device = device_from_id (id); + if (device && device->device_class ()) { + size_t terminal = circuit_device_terminal_index_from_id (id); + if (device->device_class ()->terminal_definitions ().size () > terminal) { + const db::DeviceTerminalDefinition &td = device->device_class ()->terminal_definitions () [terminal]; + const db::Net *net = device->net_for_terminal (td.id ()); + if (net) { + return tl::to_qstring (td.name () + "|" + net->expanded_name ()); + } + } + } + // TODO: in case of compare, use terminal_name(a)|net_name(a)|terminal_name(b)|net_name(b) + + } else if (is_id_circuit_subcircuit (id)) { + + const db::SubCircuit *subcircuit = subcircuit_from_id (id); + if (subcircuit && subcircuit->circuit_ref ()) { + return tl::to_qstring (subcircuit->circuit_ref ()->name () + "|" + subcircuit->expanded_name ()); + } + // TODO: in case of compare, use circuit_name(a)|subcircuit_name(a)|circuit_name(b)|subcircuit_name(b) + + } else if (is_id_circuit_subcircuit_pin (id)) { + + const db::SubCircuit *subcircuit = subcircuit_from_id (id); + if (subcircuit && subcircuit->circuit () && subcircuit->circuit_ref ()) { + const db::Pin *pin = pin_from_id (id); + if (pin) { + const db::Net *net = subcircuit->net_for_pin (pin->id ()); + if (net) { + return tl::to_qstring (pin->name () + "|" + net->expanded_name ()); + } + } + } + // TODO: in case of compare, use pin_name(a)|net_name(a)|pin_name(b)|net_name(b) + + } else if (is_id_circuit_net (id)) { + + const db::Net *net = net_from_id (id); + if (net) { + return tl::to_qstring (net->expanded_name ()); + } + // TODO: in case of compare, use name(a)|name(b) + + } else if (is_id_circuit_net_pin (id)) { + + const db::NetPinRef *ref = net_pinref_from_id (id); + if (ref && ref->pin ()) { + return tl::to_qstring (ref->pin ()->name ()); + } + // TODO: in case of compare, use pin_name(a)|pin_name(b) + + } else if (is_id_circuit_net_subcircuit_pin (id)) { + + const db::NetSubcircuitPinRef *ref = net_subcircuit_pinref_from_id (id); + if (ref && ref->pin () && ref->subcircuit ()) { + const db::Circuit *circuit = ref->subcircuit ()->circuit_ref (); + if (circuit) { + return tl::to_qstring (ref->pin ()->name () + "|" + circuit->name () + "|" + ref->subcircuit ()->name ()); + } + } + // TODO: in case of compare, use pin_name(a)|circuit_name(a)|subcircuit_name(a)|pin_name(b)|circuit_name(b)|subcircuit_name(b) + + } else if (is_id_circuit_net_subcircuit_pin_others (id)) { + + const db::NetSubcircuitPinRef *ref = net_subcircuit_pinref_from_id (id); + size_t other_index = circuit_net_subcircuit_pin_other_index_from_id (id); + + if (ref && ref->pin () && ref->subcircuit ()) { + const db::Circuit *circuit = ref->subcircuit ()->circuit_ref (); + if (circuit && circuit->pin_by_id (other_index)) { + const db::Pin *pin = circuit->pin_by_id (other_index); + const db::Net *net = ref->subcircuit ()->net_for_pin (pin->id ()); + if (net) { + return tl::to_qstring (pin->name () + "|" + net->expanded_name ()); + } + } + } + // TODO: in case of compare, use pin_name(a)|net_name(a)|pin_name(b)|net_name(b) + + } else if (is_id_circuit_net_device_terminal (id)) { + + const db::NetTerminalRef *ref = net_terminalref_from_id (id); + if (ref && ref->terminal_def () && ref->device () && ref->device ()->device_class ()) { + return tl::to_qstring (ref->terminal_def ()->name () + "|" + ref->device ()->device_class ()->name () + "|" + ref->device ()->expanded_name ()); + } + // TODO: in case of compare, use terminal_name(a)|device_class(a)|device_name(a)|terminal_name(b)|device_class(b)|device_name(b) + + } else if (is_id_circuit_net_device_terminal_others (id)) { + + const db::NetTerminalRef *ref = net_terminalref_from_id (id); + size_t other_index = circuit_net_device_terminal_other_index_from_id (id); + + if (ref && ref->device_class () && ref->device_class ()->terminal_definitions ().size () > other_index) { + const db::DeviceTerminalDefinition &def = ref->device_class ()->terminal_definitions ()[other_index]; + const db::Net *net = ref->device ()->net_for_terminal (def.id ()); + if (net) { + return tl::to_qstring (def.name () + "|" + net->expanded_name ()); + } + } + // TODO: in case of compare, use terminal_name(a)|net_name(a)|terminal_name(b)|net_name(b) + + } + + return QString (); +} + static QIcon icon_for_net () { QIcon icon; @@ -1553,8 +1705,20 @@ NetlistBrowserPage::NetlistBrowserPage (QWidget * /*parent*/) connect (delegate, SIGNAL (anchor_clicked (const QString &)), this, SLOT (anchor_clicked (const QString &))); directory_tree->setItemDelegateForColumn (0, delegate); + QMenu *find_edit_menu = new QMenu (find_text); + find_edit_menu->addAction (actionUseRegularExpressions); + find_edit_menu->addAction (actionCaseSensitive); + + find_text->set_clear_button_enabled (true); + find_text->set_options_button_enabled (true); + find_text->set_options_menu (find_edit_menu); +#if QT_VERSION >= 0x40700 + find_text->setPlaceholderText (tr ("Find text ...")); +#endif + connect (m_show_all_action, SIGNAL (triggered ()), this, SLOT (show_all_clicked ())); - connect (filter, SIGNAL (textEdited (const QString &)), this, SLOT (filter_changed ())); + connect (info_button, SIGNAL (pressed ()), this, SLOT (info_button_pressed ())); + connect (find_button, SIGNAL (pressed ()), this, SLOT (find_button_pressed ())); connect (forward, SIGNAL (clicked ()), this, SLOT (navigate_forward ())); connect (backward, SIGNAL (clicked ()), this, SLOT (navigate_back ())); @@ -1761,15 +1925,100 @@ NetlistBrowserPage::navigate_forward () } void -NetlistBrowserPage::filter_changed () +NetlistBrowserPage::info_button_pressed () { -#if 0 // @@@ - MarkerBrowserTreeViewModel *tree_model = dynamic_cast (directory_tree->model ()); - if (tree_model) { - set_hidden_rec (tree_model, directory_tree, QModelIndex (), m_show_all, cat_filter->text (), cell_filter->text ()); + // @@@ +} + +static QModelIndex find_next (QAbstractItemModel *model, const QRegExp &to_find, const QModelIndex &from) +{ + if (! from.isValid ()) { + return from; + } + + std::vector parent_stack; + std::vector > rows_stack; + + QModelIndex index = from; + + while (index.isValid ()) { + + parent_stack.push_back (model->parent (index)); + rows_stack.push_back (std::make_pair (index.row (), model->rowCount (parent_stack.back ()))); + + index = parent_stack.back (); + + } + + std::reverse (parent_stack.begin (), parent_stack.end ()); + std::reverse (rows_stack.begin (), rows_stack.end ()); + + QModelIndex current = from; + + do { + + bool has_next = false; + + if (model->hasChildren (current)) { + + int row_count = model->rowCount (current); + if (row_count > 0) { + + parent_stack.push_back (current); + rows_stack.push_back (std::make_pair (0, row_count)); + + current = model->index (0, 0, current); + has_next = true; + + } + + } + + while (! has_next && ! rows_stack.empty ()) { + + ++rows_stack.back ().first; + + if (rows_stack.back ().first == rows_stack.back ().second) { + + // up + current = parent_stack.back (); + rows_stack.pop_back (); + parent_stack.pop_back (); + + } else { + + current = model->index (rows_stack.back ().first, 0, parent_stack.back ()); + has_next = true; + + } + + } + + if (has_next) { + + QString text = model->data (current, Qt::UserRole).toString (); + if (text.indexOf (to_find) >= 0) { + return current; + } + + } + + } while (current != from); + + return QModelIndex (); +} + +void +NetlistBrowserPage::find_button_pressed () +{ + QRegExp re (find_text->text (), + actionCaseSensitive->isChecked () ? Qt::CaseSensitive : Qt::CaseInsensitive, + actionUseRegularExpressions->isChecked () ? QRegExp::RegExp : QRegExp::FixedString); + + QModelIndex next = find_next (directory_tree->model (), re, directory_tree->currentIndex ()); + if (next.isValid ()) { + navigate_to (next.internalPointer ()); } - update_highlights (2 /*select all*/); -#endif } void @@ -1821,7 +2070,7 @@ NetlistBrowserPage::set_l2ndb (db::LayoutToNetlist *database) directory_tree->header ()->setSortIndicatorShown (true); - filter->setText (QString ()); + find_text->setText (QString ()); } } diff --git a/src/laybasic/laybasic/layNetlistBrowserPage.h b/src/laybasic/laybasic/layNetlistBrowserPage.h index b5b7b8c03..ca2553a3d 100644 --- a/src/laybasic/laybasic/layNetlistBrowserPage.h +++ b/src/laybasic/laybasic/layNetlistBrowserPage.h @@ -174,6 +174,7 @@ private: const db::Pin *pin_from_id (void *id) const; const db::SubCircuit *subcircuit_from_id (void *id) const; QString text (const QModelIndex &index) const; + QString search_text (const QModelIndex &index) const; QIcon icon (const QModelIndex &index) const; size_t circuit_index (const db::Circuit *circuit) const; size_t net_index (const db::Net *net) const; @@ -298,7 +299,8 @@ public: private slots: void show_all_clicked (); - void filter_changed (); + void info_button_pressed (); + void find_button_pressed (); void anchor_clicked (const QString &url); void navigate_back (); void navigate_forward ();