Netlist browser: find text feature.

This commit is contained in:
Matthias Koefferlein 2019-04-28 19:22:39 +02:00
parent bfea3fdc2f
commit d68c61394a
3 changed files with 465 additions and 179 deletions

View File

@ -47,7 +47,10 @@
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QGridLayout">
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
@ -60,174 +63,7 @@
<property name="bottomMargin">
<number>0</number>
</property>
<property name="spacing">
<number>6</number>
</property>
<item row="3" column="0" colspan="9">
<widget class="QFrame" name="frame_3">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QToolButton" name="dir_down_pb">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../lay/lay/layResources.qrc">
<normaloff>:/down.png</normaloff>:/down.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="dir_up_pb">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../lay/lay/layResources.qrc">
<normaloff>:/up.png</normaloff>:/up.png</iconset>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_4">
<property name="toolTip">
<string>Configure filters</string>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="../../lay/lay/layResources.qrc">:/find.png</pixmap>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="filter">
<property name="sizePolicy">
<sizepolicy hsizetype="Ignored" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="0" colspan="9">
<widget class="QTreeView" name="directory_tree">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="baseSize">
<size>
<width>0</width>
<height>4</height>
</size>
</property>
<property name="contextMenuPolicy">
<enum>Qt::ActionsContextMenu</enum>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="uniformRowHeights">
<bool>true</bool>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<property name="allColumnsShowFocus">
<bool>true</bool>
</property>
<attribute name="headerVisible">
<bool>true</bool>
</attribute>
</widget>
</item>
<item row="4" column="5" colspan="4">
<widget class="QFrame" name="frame_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
</layout>
</widget>
</item>
<item row="1" column="0" colspan="9">
<item>
<widget class="QFrame" name="frame_4">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
@ -283,6 +119,182 @@
</property>
</widget>
</item>
<item>
<widget class="lay::DecoratedLineEdit" name="find_text">
<property name="sizePolicy">
<sizepolicy hsizetype="Ignored" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>250</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="find_button">
<property name="toolTip">
<string>Find in netlist</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../lay/lay/layResources.qrc">
<normaloff>:/find.png</normaloff>:/find.png</iconset>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>6</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QTreeView" name="directory_tree">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="baseSize">
<size>
<width>0</width>
<height>4</height>
</size>
</property>
<property name="contextMenuPolicy">
<enum>Qt::ActionsContextMenu</enum>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="uniformRowHeights">
<bool>true</bool>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<property name="allColumnsShowFocus">
<bool>true</bool>
</property>
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_3">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="info_label">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="info_button">
<property name="toolTip">
<string>Show more information about nets</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../lay/lay/layResources.qrc">
<normaloff>:/info_16.png</normaloff>:/info_16.png</iconset>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
</layout>
</widget>
</item>
@ -301,7 +313,30 @@
<string>Expand All</string>
</property>
</action>
<action name="actionUseRegularExpressions">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Use Regular Expressions</string>
</property>
</action>
<action name="actionCaseSensitive">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Case Sensitive</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>
<class>lay::DecoratedLineEdit</class>
<extends>QLineEdit</extends>
<header>layWidgets.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>directory_tree</tabstop>
</tabstops>

View File

@ -32,6 +32,7 @@
#include <QUrl>
#include <QPainter>
#include <QColorDialog>
#include <QRegExp>
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<MarkerBrowserTreeViewModel *> (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<QModelIndex> parent_stack;
std::vector<std::pair<int, int> > 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 ());
}
}

View File

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