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
+
+
+
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 ();