Merge branch 'master' into wip2

This commit is contained in:
Matthias Koefferlein 2023-05-14 18:34:17 +02:00
commit b30837411e
24 changed files with 666 additions and 139 deletions

View File

@ -62,15 +62,56 @@ DECL
end
# --------------------------------------------------------------
# Provides the definitions for QObject::findChild
# Provides the definitions for QObject::findChild and QObject::findChildren
def add_native_impl_QObject_findChild()
# alternative implementation for QObject::findChild using QObject for T
add_native_impl("QObject", <<'CODE', <<'DECL')
QObject *find_child_impl (QObject *object, const QString &name) { return object->findChild<QObject *> (name); }
#if QT_VERSION < 0x50000
#include <QRegExp>
QObject *find_child_impl (QObject *object, const QString &name)
{
return object->findChild<QObject *> (name);
}
QList<QObject *> find_children_impl (QObject *object, const QString &name)
{
return object->findChildren<QObject *> (name);
}
QList<QObject *> find_children_impl2 (QObject *object, const QRegExp &re)
{
return object->findChildren<QObject *> (re);
}
#else
#include <QRegularExpression>
QObject *find_child_impl (QObject *object, const QString &name, Qt::FindChildOptions options)
{
return object->findChild<QObject *> (name, options);
}
QList<QObject *> find_children_impl (QObject *object, const QString &name, Qt::FindChildOptions options)
{
return object->findChildren<QObject *> (name, options);
}
QList<QObject *> find_children_impl2 (QObject *object, const QRegularExpression &re, Qt::FindChildOptions options)
{
return object->findChildren<QObject *> (re, options);
}
#endif
CODE
gsi::method_ext("findChild", &find_child_impl, "@brief Specialisation for findChild (uses QObject as T).")
#if QT_VERSION < 0x50000
gsi::method_ext("findChild", &find_child_impl, gsi::arg("name", QString(), "null"), "@brief Specialisation for findChild (uses QObject as T).") +
gsi::method_ext("findChildren", &find_children_impl, gsi::arg("name", QString(), "null"), "@brief Specialisation for findChildren (uses QObject as T).") +
gsi::method_ext("findChildren", &find_children_impl2, gsi::arg("re"), "@brief Specialisation for findChildren (uses QObject as T).")
#else
gsi::method_ext("findChild", &find_child_impl, gsi::arg("name", QString(), "null"), gsi::arg("options", Qt::FindChildrenRecursively, "Qt::FindChildrenRecursively"), "@brief Specialisation for findChild (uses QObject as T).") +
gsi::method_ext("findChildren", &find_children_impl, gsi::arg("name", QString(), "null"), gsi::arg("options", Qt::FindChildrenRecursively, "Qt::FindChildrenRecursively"), "@brief Specialisation for findChildren (uses QObject as T).") +
gsi::method_ext("findChildren", &find_children_impl2, gsi::arg("re"), gsi::arg("options", Qt::FindChildrenRecursively, "Qt::FindChildrenRecursively"), "@brief Specialisation for findChildren (uses QObject as T).")
#endif
DECL
end

View File

@ -118,6 +118,7 @@ GenericReaderOptions::GenericReaderOptions ()
m_lefdef_read_lef_with_def = load_options.get_option_by_name ("lefdef_config.read_lef_with_def").to_bool ();
m_lefdef_separate_groups = load_options.get_option_by_name ("lefdef_config.separate_groups").to_bool ();
m_lefdef_joined_paths = load_options.get_option_by_name ("lefdef_config.joined_paths").to_bool ();
m_lefdef_map_file = load_options.get_option_by_name ("lefdef_config.map_file").to_string ();
m_lefdef_macro_resolution_mode = load_options.get_option_by_name ("lefdef_config.macro_resolution_mode").to_int ();
}
@ -441,6 +442,11 @@ GenericReaderOptions::add_options (tl::CommandLineOptions &cmd)
"This option is used together with '--" + m_long_prefix + "lefdef-produce-regions'. If given, the region polygons will be put "
"into a cell hierarchy where the cells indicate the region groups.\n"
)
<< tl::arg (group +
"#--" + m_long_prefix + "lefdef-joined-paths", &m_lefdef_joined_paths, "Specifies to produce joined paths for wires",
"If given, multi-segment paths are created for wires if possible (this will fail for 45 degree segments for example). "
"By default, individual straight segments will be produced."
)
<< tl::arg (group +
"#!--" + m_long_prefix + "lefdef-dont-produce-via-geometry", &m_lefdef_produce_via_geometry, "Skips vias when producing geometry",
"If this option is given, no via geometry will be produced."
@ -793,6 +799,7 @@ GenericReaderOptions::configure (db::LoadLayoutOptions &load_options)
load_options.set_option_by_name ("lefdef_config.lef_files", tl::Variant (m_lefdef_lef_files.begin (), m_lefdef_lef_files.end ()));
load_options.set_option_by_name ("lefdef_config.read_lef_with_def", m_lefdef_read_lef_with_def);
load_options.set_option_by_name ("lefdef_config.separate_groups", m_lefdef_separate_groups);
load_options.set_option_by_name ("lefdef_config.joined_paths", m_lefdef_joined_paths);
load_options.set_option_by_name ("lefdef_config.map_file", m_lefdef_map_file);
load_options.set_option_by_name ("lefdef_config.macro_resolution_mode", m_lefdef_macro_resolution_mode);
load_options.set_option_by_name ("lefdef_config.macro_resolution_mode", m_lefdef_macro_resolution_mode);

View File

@ -185,6 +185,7 @@ private:
std::vector<std::string> m_lefdef_lef_files;
bool m_lefdef_read_lef_with_def;
bool m_lefdef_separate_groups;
bool m_lefdef_joined_paths;
std::string m_lefdef_map_file;
int m_lefdef_macro_resolution_mode;
std::vector<std::string> m_lefdef_lef_layout_files;

View File

@ -51,7 +51,40 @@ static void _call_smo (const qt_gsi::GenericStaticMethod *, gsi::SerialArgs &, g
ret.write<const QMetaObject &> (QObject::staticMetaObject);
}
QObject *find_child_impl (QObject *object, const QString &name) { return object->findChild<QObject *> (name); }
#if QT_VERSION < 0x50000
#include <QRegExp>
QObject *find_child_impl (QObject *object, const QString &name)
{
return object->findChild<QObject *> (name);
}
QList<QObject *> find_children_impl (QObject *object, const QString &name)
{
return object->findChildren<QObject *> (name);
}
QList<QObject *> find_children_impl2 (QObject *object, const QRegExp &re)
{
return object->findChildren<QObject *> (re);
}
#else
#include <QRegularExpression>
QObject *find_child_impl (QObject *object, const QString &name, Qt::FindChildOptions options)
{
return object->findChild<QObject *> (name, options);
}
QList<QObject *> find_children_impl (QObject *object, const QString &name, Qt::FindChildOptions options)
{
return object->findChildren<QObject *> (name, options);
}
QList<QObject *> find_children_impl2 (QObject *object, const QRegularExpression &re, Qt::FindChildOptions options)
{
return object->findChildren<QObject *> (re, options);
}
#endif
// bool QObject::blockSignals(bool b)
@ -757,7 +790,15 @@ static gsi::Methods methods_QObject () {
}
qt_gsi::QtNativeClass<QObject> decl_QObject ("QtCore", "QObject_Native",
gsi::method_ext("findChild", &find_child_impl, "@brief Specialisation for findChild (uses QObject as T).")
#if QT_VERSION < 0x50000
gsi::method_ext("findChild", &find_child_impl, gsi::arg("name", QString(), "null"), "@brief Specialisation for findChild (uses QObject as T).") +
gsi::method_ext("findChildren", &find_children_impl, gsi::arg("name", QString(), "null"), "@brief Specialisation for findChildren (uses QObject as T).") +
gsi::method_ext("findChildren", &find_children_impl2, gsi::arg("re"), "@brief Specialisation for findChildren (uses QObject as T).")
#else
gsi::method_ext("findChild", &find_child_impl, gsi::arg("name", QString(), "null"), gsi::arg("options", Qt::FindChildrenRecursively, "Qt::FindChildrenRecursively"), "@brief Specialisation for findChild (uses QObject as T).") +
gsi::method_ext("findChildren", &find_children_impl, gsi::arg("name", QString(), "null"), gsi::arg("options", Qt::FindChildrenRecursively, "Qt::FindChildrenRecursively"), "@brief Specialisation for findChildren (uses QObject as T).") +
gsi::method_ext("findChildren", &find_children_impl2, gsi::arg("re"), gsi::arg("options", Qt::FindChildrenRecursively, "Qt::FindChildrenRecursively"), "@brief Specialisation for findChildren (uses QObject as T).")
#endif
+
methods_QObject (),
"@hide\n@alias QObject");

View File

@ -52,7 +52,40 @@ static void _call_smo (const qt_gsi::GenericStaticMethod *, gsi::SerialArgs &, g
ret.write<const QMetaObject &> (QObject::staticMetaObject);
}
QObject *find_child_impl (QObject *object, const QString &name) { return object->findChild<QObject *> (name); }
#if QT_VERSION < 0x50000
#include <QRegExp>
QObject *find_child_impl (QObject *object, const QString &name)
{
return object->findChild<QObject *> (name);
}
QList<QObject *> find_children_impl (QObject *object, const QString &name)
{
return object->findChildren<QObject *> (name);
}
QList<QObject *> find_children_impl2 (QObject *object, const QRegExp &re)
{
return object->findChildren<QObject *> (re);
}
#else
#include <QRegularExpression>
QObject *find_child_impl (QObject *object, const QString &name, Qt::FindChildOptions options)
{
return object->findChild<QObject *> (name, options);
}
QList<QObject *> find_children_impl (QObject *object, const QString &name, Qt::FindChildOptions options)
{
return object->findChildren<QObject *> (name, options);
}
QList<QObject *> find_children_impl2 (QObject *object, const QRegularExpression &re, Qt::FindChildOptions options)
{
return object->findChildren<QObject *> (re, options);
}
#endif
// bool QObject::blockSignals(bool b)
@ -813,7 +846,15 @@ static gsi::Methods methods_QObject () {
}
qt_gsi::QtNativeClass<QObject> decl_QObject ("QtCore", "QObject_Native",
gsi::method_ext("findChild", &find_child_impl, "@brief Specialisation for findChild (uses QObject as T).")
#if QT_VERSION < 0x50000
gsi::method_ext("findChild", &find_child_impl, gsi::arg("name", QString(), "null"), "@brief Specialisation for findChild (uses QObject as T).") +
gsi::method_ext("findChildren", &find_children_impl, gsi::arg("name", QString(), "null"), "@brief Specialisation for findChildren (uses QObject as T).") +
gsi::method_ext("findChildren", &find_children_impl2, gsi::arg("re"), "@brief Specialisation for findChildren (uses QObject as T).")
#else
gsi::method_ext("findChild", &find_child_impl, gsi::arg("name", QString(), "null"), gsi::arg("options", Qt::FindChildrenRecursively, "Qt::FindChildrenRecursively"), "@brief Specialisation for findChild (uses QObject as T).") +
gsi::method_ext("findChildren", &find_children_impl, gsi::arg("name", QString(), "null"), gsi::arg("options", Qt::FindChildrenRecursively, "Qt::FindChildrenRecursively"), "@brief Specialisation for findChildren (uses QObject as T).") +
gsi::method_ext("findChildren", &find_children_impl2, gsi::arg("re"), gsi::arg("options", Qt::FindChildrenRecursively, "Qt::FindChildrenRecursively"), "@brief Specialisation for findChildren (uses QObject as T).")
#endif
+
methods_QObject (),
"@hide\n@alias QObject");

View File

@ -52,7 +52,40 @@ static void _call_smo (const qt_gsi::GenericStaticMethod *, gsi::SerialArgs &, g
ret.write<const QMetaObject &> (QObject::staticMetaObject);
}
QObject *find_child_impl (QObject *object, const QString &name) { return object->findChild<QObject *> (name); }
#if QT_VERSION < 0x50000
#include <QRegExp>
QObject *find_child_impl (QObject *object, const QString &name)
{
return object->findChild<QObject *> (name);
}
QList<QObject *> find_children_impl (QObject *object, const QString &name)
{
return object->findChildren<QObject *> (name);
}
QList<QObject *> find_children_impl2 (QObject *object, const QRegExp &re)
{
return object->findChildren<QObject *> (re);
}
#else
#include <QRegularExpression>
QObject *find_child_impl (QObject *object, const QString &name, Qt::FindChildOptions options)
{
return object->findChild<QObject *> (name, options);
}
QList<QObject *> find_children_impl (QObject *object, const QString &name, Qt::FindChildOptions options)
{
return object->findChildren<QObject *> (name, options);
}
QList<QObject *> find_children_impl2 (QObject *object, const QRegularExpression &re, Qt::FindChildOptions options)
{
return object->findChildren<QObject *> (re, options);
}
#endif
// bool QObject::blockSignals(bool b)
@ -771,7 +804,15 @@ static gsi::Methods methods_QObject () {
}
qt_gsi::QtNativeClass<QObject> decl_QObject ("QtCore", "QObject_Native",
gsi::method_ext("findChild", &find_child_impl, "@brief Specialisation for findChild (uses QObject as T).")
#if QT_VERSION < 0x50000
gsi::method_ext("findChild", &find_child_impl, gsi::arg("name", QString(), "null"), "@brief Specialisation for findChild (uses QObject as T).") +
gsi::method_ext("findChildren", &find_children_impl, gsi::arg("name", QString(), "null"), "@brief Specialisation for findChildren (uses QObject as T).") +
gsi::method_ext("findChildren", &find_children_impl2, gsi::arg("re"), "@brief Specialisation for findChildren (uses QObject as T).")
#else
gsi::method_ext("findChild", &find_child_impl, gsi::arg("name", QString(), "null"), gsi::arg("options", Qt::FindChildrenRecursively, "Qt::FindChildrenRecursively"), "@brief Specialisation for findChild (uses QObject as T).") +
gsi::method_ext("findChildren", &find_children_impl, gsi::arg("name", QString(), "null"), gsi::arg("options", Qt::FindChildrenRecursively, "Qt::FindChildrenRecursively"), "@brief Specialisation for findChildren (uses QObject as T).") +
gsi::method_ext("findChildren", &find_children_impl2, gsi::arg("re"), gsi::arg("options", Qt::FindChildrenRecursively, "Qt::FindChildrenRecursively"), "@brief Specialisation for findChildren (uses QObject as T).")
#endif
+
methods_QObject (),
"@hide\n@alias QObject");

View File

@ -399,6 +399,7 @@ MacroEditorDialog::MacroEditorDialog (lay::Dispatcher *pr, lym::MacroCollection
replaceText->setPlaceholderText (tr ("Replace text ..."));
#endif
connect (closeButton, SIGNAL (clicked ()), this, SLOT (close_button_clicked ()));
connect (forwardButton, SIGNAL (clicked ()), this, SLOT (forward ()));
connect (backwardButton, SIGNAL (clicked ()), this, SLOT (backward ()));
@ -2362,7 +2363,7 @@ END_PROTECTED
void
MacroEditorDialog::tab_close_requested (int index)
{
if (m_in_exec) {
if (m_in_exec || index < 0) {
return;
}
@ -3736,8 +3737,12 @@ MacroEditorDialog::run (int stop_stack_depth, lym::Macro *macro)
set_run_macro (macro);
try {
write_str (tl::sprintf (tl::to_string (tr ("Running macro %s\n")), macro->path ()).c_str (), OS_echo);
macro->run ();
m_stop_stack_depth = -1;
} catch (tl::ExitException &) {
m_stop_stack_depth = -1;
// .. ignore exit exceptions ..

View File

@ -590,12 +590,7 @@ MainWindow::file_changed_timer ()
}
// Prevent recursive signals
m_file_changed_timer.blockSignals (true);
std::set<QString> reloaded_files;
BEGIN_PROTECTED
std::set<QString> notified_files;
// Make the names unique
std::sort (m_changed_files.begin (), m_changed_files.end ());
@ -605,68 +600,38 @@ BEGIN_PROTECTED
return;
}
QString msg;
if (m_changed_files.size () == 1) {
msg = QObject::tr ("The following file has been changed on disk:\n\n");
for (std::vector<QString>::const_iterator f = m_changed_files.begin (); f != m_changed_files.end (); ++f) {
msg += QString::fromUtf8 (" %1\n").arg (*f);
}
msg += tr ("\nReload this file?");
} else {
msg = QObject::tr ("The following files have been changed on disk:\n\n");
for (std::vector<QString>::const_iterator f = m_changed_files.begin (); f != m_changed_files.end (); ++f) {
msg += QString::fromUtf8 (" %1\n").arg (*f);
}
msg += tr ("\nReload these files?");
}
// adds a notification to the involved views that the file has changed
std::vector<QString> changed_files;
changed_files.swap (m_changed_files);
if (QMessageBox::question (this, tr ("Reload Files"), msg, QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
std::map<QString, std::vector<std::pair<lay::LayoutViewWidget *, int> > > views_per_file;
m_file_changed_timer.blockSignals (false);
std::map<QString, std::pair<lay::LayoutViewWidget *, int> > views_per_file;
for (std::vector<lay::LayoutViewWidget *>::iterator v = mp_views.begin (); v != mp_views.end (); ++v) {
for (int cv = 0; cv < int ((*v)->view ()->cellviews ()); ++cv) {
views_per_file [tl::to_qstring ((*v)->view ()->cellview (cv)->filename ())] = std::make_pair (*v, cv);
}
for (auto v = mp_views.begin (); v != mp_views.end (); ++v) {
for (int cv = 0; cv < int ((*v)->view ()->cellviews ()); ++cv) {
views_per_file [tl::to_qstring ((*v)->view ()->cellview (cv)->filename ())].push_back (std::make_pair (*v, cv));
}
for (std::vector<QString>::const_iterator f = changed_files.begin (); f != changed_files.end (); ++f) {
std::map<QString, std::pair<lay::LayoutViewWidget *, int> >::const_iterator v = views_per_file.find (*f);
if (v != views_per_file.end ()) {
v->second.first->view ()->reload_layout (v->second.second);
reloaded_files.insert (*f);
}
}
}
END_PROTECTED
for (auto f = changed_files.begin (); f != changed_files.end (); ++f) {
m_file_changed_timer.blockSignals (false);
auto v = views_per_file.find (*f);
if (v != views_per_file.end ()) {
// While the message box was open, new request might have collected - remove
// the ones we just reloaded and restart the timer
if (! m_changed_files.empty ()) {
for (auto w = v->second.begin (); w != v->second.end (); ++w) {
std::string title;
if (w->first->view ()->cellviews () > 1) {
title = tl::sprintf (tl::to_string (tr ("Layout file @%d (%s) has changed on disk")), w->second + 1, tl::filename (tl::to_string (*f)));
} else {
title = tl::sprintf (tl::to_string (tr ("Layout file (%s) has changed on disk")), tl::filename (tl::to_string (*f)));
}
lay::LayoutViewNotification n ("reload", title, tl::Variant (tl::to_string (*f)));
n.add_action ("reload", tl::to_string (tr ("Reload")));
w->first->add_notification (n);
std::vector<QString> changed_files;
changed_files.swap (m_changed_files);
for (std::vector<QString>::const_iterator f = changed_files.begin (); f != changed_files.end (); ++f) {
if (reloaded_files.find (*f) == reloaded_files.end ()) {
m_changed_files.push_back (*f);
}
}
if (! m_changed_files.empty ()) {
// Wait a little to let more to allow for more reload requests to collect
m_file_changed_timer.setInterval (300);
m_file_changed_timer.start ();
}

View File

@ -1752,8 +1752,21 @@ set_hidden_flags_rec (LayerTreeModel *model, QTreeView *tree_view, const QModelI
}
} else {
tree_view->setRowHidden (r, parent, false);
set_hidden_flags_rec (model, tree_view, index);
// hide a group entry if all children are hidden
bool hide = true;
int rrows = model->rowCount (index);
for (int rr = 0; rr < rrows; ++rr) {
if (! tree_view->isRowHidden (rr, index)) {
hide = false;
}
}
tree_view->setRowHidden (r, parent, hide);
}
}

View File

@ -39,6 +39,8 @@
#include <QHBoxLayout>
#include <QMessageBox>
#include <QApplication>
#include <QPushButton>
#include <QToolButton>
#include "tlInternational.h"
#include "tlExpression.h"
@ -76,6 +78,7 @@
#include "layEditorOptionsPages.h"
#include "layUtils.h"
#include "layPropertiesDialog.h"
#include "layQtTools.h"
#include "dbClipboard.h"
#include "dbLayout.h"
#include "dbLayoutUtils.h"
@ -94,12 +97,70 @@
namespace lay
{
// -------------------------------------------------------------
// LayoutViewNotificationWidget implementation
LayoutViewNotificationWidget::LayoutViewNotificationWidget (LayoutViewWidget *parent, const LayoutViewNotification *notification)
: QFrame (parent), mp_parent (parent), mp_notification (notification)
{
setBackgroundRole (QPalette::ToolTipBase);
setAutoFillBackground (true);
QHBoxLayout *layout = new QHBoxLayout (this);
layout->setContentsMargins (4, 4, 4, 4);
QLabel *title_label = new QLabel (this);
layout->addWidget (title_label, 1);
title_label->setText (tl::to_qstring (notification->title ()));
title_label->setForegroundRole (QPalette::ToolTipText);
title_label->setWordWrap (true);
activate_help_links (title_label);
for (auto a = notification->actions ().begin (); a != notification->actions ().end (); ++a) {
QPushButton *pb = new QPushButton (this);
layout->addWidget (pb);
pb->setText (tl::to_qstring (a->second));
m_action_buttons.insert (std::make_pair (pb, a->first));
connect (pb, SIGNAL (clicked ()), this, SLOT (action_triggered ()));
}
QToolButton *close_button = new QToolButton ();
close_button->setIcon (QIcon (":clear_edit_16px.png"));
close_button->setAutoRaise (true);
layout->addWidget (close_button);
connect (close_button, SIGNAL (clicked ()), this, SLOT (close_triggered ()));
}
void
LayoutViewNotificationWidget::action_triggered ()
{
auto a = m_action_buttons.find (sender ());
if (a != m_action_buttons.end ()) {
mp_parent->notification_action (*mp_notification, a->second);
}
}
void
LayoutViewNotificationWidget::close_triggered ()
{
mp_parent->remove_notification (*mp_notification);
}
// -------------------------------------------------------------
// LayoutViewWidget implementation
LayoutViewWidget::LayoutViewWidget (db::Manager *mgr, bool editable, lay::Plugin *plugin_parent, QWidget *parent, unsigned int options)
: QFrame (parent), mp_view (0)
{
mp_layout = new QVBoxLayout (this);
mp_layout->setContentsMargins (0, 0, 0, 0);
mp_layout->setSpacing (0);
mp_layout->addStretch (1);
// NOTE: construction the LayoutView may trigger events (script code executed etc.) which must
// not meet an invalid mp_view pointer (e.g. in eventFilter). Hence, mp_view is 0 first, and set only
// after the LayoutView is successfully constructed.
@ -110,6 +171,11 @@ LayoutViewWidget::LayoutViewWidget (db::Manager *mgr, bool editable, lay::Plugin
LayoutViewWidget::LayoutViewWidget (lay::LayoutView *source, db::Manager *mgr, bool editable, lay::Plugin *plugin_parent, QWidget *parent, unsigned int options)
: QFrame (parent), mp_view (0)
{
mp_layout = new QVBoxLayout (this);
mp_layout->setContentsMargins (0, 0, 0, 0);
mp_layout->setSpacing (0);
mp_layout->addStretch (1);
// NOTE: construction the LayoutView may trigger events (script code executed etc.) which must
// not meet an invalid mp_view pointer (e.g. in eventFilter). Hence, mp_view is 0 first, and set only
// after the LayoutView is successfully constructed.
@ -124,6 +190,55 @@ LayoutViewWidget::~LayoutViewWidget ()
delete view;
}
void
LayoutViewWidget::add_notification (const LayoutViewNotification &notificaton)
{
if (m_notification_widgets.find (&notificaton) == m_notification_widgets.end ()) {
m_notifications.push_back (notificaton);
QWidget *w = new LayoutViewNotificationWidget (this, &m_notifications.back ());
m_notification_widgets.insert (std::make_pair (&m_notifications.back (), w));
mp_layout->insertWidget (0, w);
}
}
void
LayoutViewWidget::remove_notification (const LayoutViewNotification &notification)
{
auto nw = m_notification_widgets.find (&notification);
if (nw != m_notification_widgets.end ()) {
nw->second->deleteLater ();
m_notification_widgets.erase (nw);
for (auto n = m_notifications.begin (); n != m_notifications.end (); ++n) {
if (*n == notification) {
m_notifications.erase (n);
break;
}
}
}
}
void
LayoutViewWidget::notification_action (const LayoutViewNotification &notification, const std::string &action)
{
if (action == "reload") {
std::string fn = notification.parameter ().to_string ();
for (unsigned int cvi = 0; cvi < mp_view->cellviews (); ++cvi) {
const lay::CellView &cv = mp_view->cellview (cvi);
if (cv->filename () == fn) {
mp_view->reload_layout (cvi);
}
}
remove_notification (notification);
}
}
void
LayoutViewWidget::view_deleted (lay::LayoutView *view)
{
@ -135,6 +250,14 @@ LayoutViewWidget::view_deleted (lay::LayoutView *view)
mp_view = new LayoutView (view->manager (), view->is_editable (), view->plugin_parent (), this, view->options ());
}
void
LayoutViewWidget::resizeEvent (QResizeEvent *)
{
if (mp_view && mp_view->canvas ()) {
mp_view->canvas ()->resize (width (), height ());
}
}
QSize
LayoutViewWidget::sizeHint () const
{

View File

@ -57,6 +57,7 @@
#include <QImage>
#include <QPointer>
#include <QVBoxLayout>
class QSpinBox;
@ -683,6 +684,91 @@ private:
void activate_editor_option_pages ();
};
/**
* @brief Descriptor for a notification inside the layout view
*
* Notifications are popups added at the top of the view to indicate need for reloading for example.
* Notifications have a name, a title, optional actions (id, title) and a parameter (e.g. file path to reload).
* Actions are mapped to QPushButtons.
*/
class LAYVIEW_PUBLIC LayoutViewNotification
{
public:
LayoutViewNotification (const std::string &name, const std::string &title, const tl::Variant &parameter = tl::Variant ())
: m_name (name), m_title (title), m_parameter (parameter)
{
// .. nothing yet ..
}
void add_action (const std::string &name, const std::string &title)
{
m_actions.push_back (std::make_pair (name, title));
}
const std::vector<std::pair<std::string, std::string> > &actions () const
{
return m_actions;
}
const std::string &name () const
{
return m_name;
}
const std::string &title () const
{
return m_title;
}
const tl::Variant &parameter () const
{
return m_parameter;
}
bool operator<(const LayoutViewNotification &other) const
{
if (m_name != other.name ()) {
return m_name < other.name ();
}
return m_parameter < other.parameter ();
}
bool operator==(const LayoutViewNotification &other) const
{
if (m_name != other.name ()) {
return false;
}
return m_parameter == other.parameter ();
}
private:
std::string m_name;
std::string m_title;
tl::Variant m_parameter;
std::vector<std::pair<std::string, std::string> > m_actions;
};
/**
* @brief A widget representing a notification
*/
class LAYVIEW_PUBLIC LayoutViewNotificationWidget
: public QFrame
{
Q_OBJECT
public:
LayoutViewNotificationWidget (LayoutViewWidget *parent, const LayoutViewNotification *notification);
private slots:
void action_triggered ();
void close_triggered ();
private:
LayoutViewWidget *mp_parent;
const LayoutViewNotification *mp_notification;
std::map<QObject *, std::string> m_action_buttons;
};
/**
* @brief The layout view widget
*
@ -710,6 +796,16 @@ public:
*/
~LayoutViewWidget ();
/**
* @brief Adds a notification
*/
void add_notification (const LayoutViewNotification &notificaton);
/**
* @brief Removes a notification
*/
void remove_notification (const LayoutViewNotification &notificaton);
/**
* @brief Gets the LayoutView embedded into this widget
*/
@ -817,10 +913,25 @@ signals:
private:
friend class LayoutView;
friend class LayoutViewNotificationWidget;
void view_deleted (lay::LayoutView *view);
void notification_action (const LayoutViewNotification &notification, const std::string &action);
void resizeEvent (QResizeEvent *event);
struct CompareNotificationPointers
{
bool operator() (const LayoutViewNotification *a, const LayoutViewNotification *b) const
{
return *a < *b;
}
};
LayoutView *mp_view;
QVBoxLayout *mp_layout;
std::list<lay::LayoutViewNotification> m_notifications;
std::map<const LayoutViewNotification *, QWidget *, CompareNotificationPointers> m_notification_widgets;
};
/**

View File

@ -424,25 +424,25 @@ DEFImporter::produce_routing_geometry (db::Cell &design, const Polygon *style, u
}
}
#if 0
// single path
db::Path p (pt0, pt + 1, wxy, be, ee, false);
if (prop_id != 0) {
design.shapes (layer).insert (db::object_with_properties<db::Path> (p, prop_id));
} else {
design.shapes (layer).insert (p);
}
#else
// multipart paths
for (std::vector<db::Point>::const_iterator i = pt0; i != pt; ++i) {
db::Path p (i, i + 2, wxy, i == pt0 ? be : wxy / 2, i + 1 != pt ? wxy / 2 : ee, false);
if (options ().joined_paths ()) {
// single path
db::Path p (pt0, pt + 1, wxy, be, ee, false);
if (prop_id != 0) {
design.shapes (layer).insert (db::object_with_properties<db::Path> (p, prop_id));
} else {
design.shapes (layer).insert (p);
}
} else {
// multipart paths
for (std::vector<db::Point>::const_iterator i = pt0; i != pt; ++i) {
db::Path p (i, i + 2, wxy, i == pt0 ? be : wxy / 2, i + 1 != pt ? wxy / 2 : ee, false);
if (prop_id != 0) {
design.shapes (layer).insert (db::object_with_properties<db::Path> (p, prop_id));
} else {
design.shapes (layer).insert (p);
}
}
}
#endif
was_path_before = true;

View File

@ -515,6 +515,7 @@ LEFDEFReaderOptions::LEFDEFReaderOptions ()
m_special_routing_suffix (""),
m_special_routing_datatype (0),
m_separate_groups (false),
m_joined_paths (false),
m_map_file (),
m_macro_resolution_mode (0),
m_read_lef_with_def (true),
@ -592,6 +593,7 @@ LEFDEFReaderOptions &LEFDEFReaderOptions::operator= (const LEFDEFReaderOptions &
m_special_routing_datatype = d.m_special_routing_datatype;
m_special_routing_datatypes = d.m_special_routing_datatypes;
m_separate_groups = d.m_separate_groups;
m_joined_paths = d.m_joined_paths;
m_map_file = d.m_map_file;
m_macro_resolution_mode = d.m_macro_resolution_mode;
m_lef_files = d.m_lef_files;

View File

@ -874,6 +874,16 @@ public:
m_separate_groups = f;
}
bool joined_paths () const
{
return m_joined_paths;
}
void set_joined_paths (bool f)
{
m_joined_paths = f;
}
const std::string &map_file () const
{
return m_map_file;
@ -1009,6 +1019,7 @@ private:
std::map<unsigned int, std::string> m_special_routing_suffixes;
std::map<unsigned int, int> m_special_routing_datatypes;
bool m_separate_groups;
bool m_joined_paths;
std::string m_map_file;
unsigned int m_macro_resolution_mode;
bool m_read_lef_with_def;

View File

@ -424,6 +424,7 @@ class LEFDEFFormatDeclaration
tl::make_member (&LEFDEFReaderOptions::read_lef_with_def, &LEFDEFReaderOptions::set_read_lef_with_def, "read-lef-with-def") +
tl::make_member (&LEFDEFReaderOptions::macro_resolution_mode, &LEFDEFReaderOptions::set_macro_resolution_mode, "macro-resolution-mode", MacroResolutionModeConverter ()) +
tl::make_member (&LEFDEFReaderOptions::separate_groups, &LEFDEFReaderOptions::set_separate_groups, "separate-groups") +
tl::make_member (&LEFDEFReaderOptions::joined_paths, &LEFDEFReaderOptions::set_joined_paths, "joined-paths") +
tl::make_member (&LEFDEFReaderOptions::map_file, &LEFDEFReaderOptions::set_map_file, "map-file")
);
}

View File

@ -880,6 +880,20 @@ gsi::Class<db::LEFDEFReaderOptions> decl_lefdef_config ("db", "LEFDEFReaderConfi
"\n"
"This property has been added in version 0.27.\n"
) +
gsi::method ("joined_paths", &db::LEFDEFReaderOptions::joined_paths,
"@brief Gets a value indicating whether to create joined paths for wires.\n"
"If this property is set to true, wires are represented by multi-segment paths as far as possible "
"(this will fail for 45 degree path segments for example). By defauls, wires are represented "
"by multiple straight segments.\n"
"\n"
"This property has been added in version 0.28.8.\n"
) +
gsi::method ("joined_paths=", &db::LEFDEFReaderOptions::set_joined_paths, gsi::arg ("flag"),
"@brief Sets a value indicating whether to create joined paths for wires.\n"
"See \\joined_paths for details about this property.\n"
"\n"
"This property has been added in version 0.28.8.\n"
) +
gsi::method ("map_file", &db::LEFDEFReaderOptions::map_file,
"@brief Gets the layer map file to use.\n"
"If a layer map file is given, the reader will pull the layer mapping from this file. The layer mapping rules "

View File

@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>638</width>
<width>664</width>
<height>868</height>
</rect>
</property>
@ -35,7 +35,7 @@
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>2</number>
<number>0</number>
</property>
<widget class="QWidget" name="tab_3">
<attribute name="title">
@ -425,34 +425,21 @@
<property name="bottomMargin">
<number>0</number>
</property>
<item row="2" column="0">
<item row="3" column="0">
<widget class="QLabel" name="label_21">
<property name="text">
<string>Via cell name prefix</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_5">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item row="1" column="1" colspan="2">
<widget class="QCheckBox" name="separate_groups">
<property name="text">
<string>µm</string>
<string>Produce a parent cell per group</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_22">
<property name="text">
<string>Groups</string>
</property>
</widget>
</item>
<item row="0" column="3" rowspan="3">
<item row="0" column="3" rowspan="4">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
@ -465,41 +452,7 @@
</property>
</spacer>
</item>
<item row="1" column="1" colspan="2">
<widget class="QCheckBox" name="separate_groups">
<property name="text">
<string>Produce a parent cell per group</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Layout DBU</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="prefix_via_cellname">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="dbu">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="3" column="1" colspan="3">
<item row="4" column="1" colspan="3">
<widget class="QFrame" name="frame_3">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
@ -523,6 +476,67 @@
</layout>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_5">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>µm</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="dbu">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Layout DBU</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_22">
<property name="text">
<string>Groups</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_33">
<property name="text">
<string>Join paths</string>
</property>
</widget>
</item>
<item row="2" column="1" colspan="2">
<widget class="QCheckBox" name="joined_paths">
<property name="text">
<string>Produce multi-segment wire paths</string>
</property>
</widget>
</item>
<item row="3" column="1" colspan="2">
<widget class="QLineEdit" name="prefix_via_cellname">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</widget>
</item>
@ -598,7 +612,6 @@
<widget class="QCheckBox" name="produce_net_names">
<property name="font">
<font>
<weight>50</weight>
<italic>false</italic>
<bold>false</bold>
</font>
@ -773,7 +786,6 @@
<widget class="QLabel" name="label_2">
<property name="font">
<font>
<weight>50</weight>
<italic>false</italic>
<bold>false</bold>
<underline>false</underline>
@ -1011,8 +1023,8 @@ Otherwise it's looked up relative to the LEF or DEF file.
<rect>
<x>0</x>
<y>0</y>
<width>609</width>
<height>591</height>
<width>679</width>
<height>582</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
@ -1595,6 +1607,7 @@ type ...</string>
<tabstop>move_lef_files_down</tabstop>
<tabstop>dbu</tabstop>
<tabstop>separate_groups</tabstop>
<tabstop>joined_paths</tabstop>
<tabstop>prefix_via_cellname</tabstop>
<tabstop>produce_net_names</tabstop>
<tabstop>net_prop_name</tabstop>

View File

@ -521,6 +521,7 @@ LEFDEFReaderOptionsEditor::commit (db::FormatSpecificReaderOptions *options, con
data->set_lef_labels_suffix (tl::to_string (suffix_lef_labels->text ()));
data->set_lef_labels_datatype (datatype_lef_labels->text ().toInt ());
data->set_separate_groups (separate_groups->isChecked ());
data->set_joined_paths (joined_paths->isChecked ());
data->set_read_lef_with_def (read_lef_with_def->isChecked ());
data->set_map_file (tl::to_string (mapfile_path->text ()));
data->set_macro_resolution_mode (macro_resolution_mode->currentIndex ());
@ -595,6 +596,7 @@ LEFDEFReaderOptionsEditor::setup (const db::FormatSpecificReaderOptions *options
suffix_lef_labels->setText (tl::to_qstring (data->lef_labels_suffix ()));
datatype_lef_labels->setText (QString::number (data->lef_labels_datatype ()));
separate_groups->setChecked (data->separate_groups ());
joined_paths->setChecked (data->joined_paths ());
read_lef_with_def->setChecked (data->read_lef_with_def ());
mapfile_path->setText (tl::to_qstring (data->map_file ()));
layer_map_mode->setCurrentIndex (data->map_file ().empty () ? 1 : 0);

View File

@ -976,3 +976,13 @@ TEST(206_lef_spacing)
run_test (_this, "issue-1282", "read:a.lef", 0, default_options (), false);
}
// issue-1345
TEST(207_joined_paths)
{
db::LEFDEFReaderOptions lefdef_opt = default_options ();
lefdef_opt.set_joined_paths (true);
run_test (_this, "issue-1345", "lef:in.lef+def:in.def", "au.oas.gz", lefdef_opt, false);
run_test (_this, "issue-1345", "lef:in.lef+def:in.def", "au-nojoin.oas.gz", default_options (), false);
}

Binary file not shown.

BIN
testdata/lefdef/issue-1345/au.oas.gz vendored Normal file

Binary file not shown.

16
testdata/lefdef/issue-1345/in.def vendored Normal file
View File

@ -0,0 +1,16 @@
VERSION 5.6 ;
NAMESCASESENSITIVE ON ;
DIVIDERCHAR "/" ;
BUSBITCHARS "<>" ;
DESIGN SMALL ;
UNITS DISTANCE MICRONS 100 ;
DIEAREA ( -30 -30 ) ( 1030 1030 ) ;
NETS 1 ;
- TOP
+ ROUTED M1 ( 0 0 ) ( 1000 * ) ( * 1000 ) M2_M1
NEW M2 ( 1000 1000 ) ( 0 * ) ( 0 0 ) ;
END NETS
END DESIGN

40
testdata/lefdef/issue-1345/in.lef vendored Normal file
View File

@ -0,0 +1,40 @@
VERSION 5.7 ;
NAMESCASESENSITIVE ON ;
BUSBITCHARS "[]" ;
DIVIDERCHAR "/" ;
UNITS
DATABASE MICRONS 1000 ;
END UNITS
USEMINSPACING OBS ON ;
USEMINSPACING PIN OFF ;
CLEARANCEMEASURE EUCLIDEAN ;
MANUFACTURINGGRID 0.05 ;
LAYER M1
TYPE ROUTING ;
DIRECTION HORIZONTAL ;
WIDTH 0.2 ;
END M1
LAYER V2
TYPE CUT ;
END V2
LAYER M2
TYPE ROUTING ;
DIRECTION VERTICAL ;
WIDTH 0.2 ;
END M2
VIA M2_M1 DEFAULT
LAYER M1 ;
RECT -0.300 -0.300 0.300 0.300 ;
LAYER V2 ;
RECT -0.200 -0.200 0.200 0.200 ;
LAYER M2 ;
RECT -0.300 -0.300 0.300 0.300 ;
END M2_M1
END LIBRARY

View File

@ -767,6 +767,35 @@ class QtBinding_TestClass < TestBase
end
def test_60
# findChild, findChildren
w = RBA::QWidget::new
w.objectName = "w"
w1 = RBA::QWidget::new(w)
w1.objectName = "w1"
w2 = RBA::QWidget::new(w1)
w2.objectName = "w2"
assert_equal(w.findChild.objectName, "w1")
assert_equal(w.findChild("w2").objectName, "w2")
assert_equal(w.findChildren().collect { |c| c.objectName }.join(","), "w1,w2")
assert_equal(w.findChildren("w2").collect { |c| c.objectName }.join(","), "w2")
begin
# Qt5++
re_cls = RBA::QRegularExpression
rescue => ex
# Qt4
re_cls = RBA::QRegExp
end
assert_equal(w.findChildren(re_cls::new("^.2$")).collect { |c| c.objectName }.join(","), "w2")
assert_equal(w.findChildren(re_cls::new("^w.$")).collect { |c| c.objectName }.join(","), "w1,w2")
end
end
load("test_epilogue.rb")