mirror of https://github.com/KLayout/klayout.git
Merge branch 'master' of https://github.com/KLayout/klayout
This commit is contained in:
commit
15e5af8171
|
|
@ -36,6 +36,7 @@
|
|||
build-*
|
||||
bin-*
|
||||
mkqtdecl.tmp
|
||||
mkqtdecl5.tmp
|
||||
testtmp
|
||||
*build.macos*
|
||||
*bin.macos*
|
||||
|
|
|
|||
47
build.sh
47
build.sh
|
|
@ -26,6 +26,14 @@ IS_WINDOWS="no"
|
|||
IS_LINUX="no"
|
||||
|
||||
HAVE_QTBINDINGS=1
|
||||
HAVE_QT_UITOOLS=1
|
||||
HAVE_QT_NETWORK=1
|
||||
HAVE_QT_SQL=1
|
||||
HAVE_QT_SVG=1
|
||||
HAVE_QT_PRINTSUPPORT=1
|
||||
HAVE_QT_MULTIMEDIA=1
|
||||
HAVE_QT_DESIGNER=1
|
||||
HAVE_QT_XML=1
|
||||
HAVE_64BIT_COORD=0
|
||||
HAVE_QT=1
|
||||
HAVE_QT5="" # not set
|
||||
|
|
@ -83,15 +91,39 @@ while [ "$*" != "" ]; do
|
|||
shift
|
||||
|
||||
case $a in
|
||||
-with-qtbinding)
|
||||
HAVE_QTBINDINGS=1
|
||||
;;
|
||||
-without-qt)
|
||||
HAVE_QT=0
|
||||
;;
|
||||
-with-qtbinding)
|
||||
HAVE_QTBINDINGS=1
|
||||
;;
|
||||
-without-qtbinding)
|
||||
HAVE_QTBINDINGS=0
|
||||
;;
|
||||
-without-qt-uitools)
|
||||
HAVE_QT_UITOOLS=0
|
||||
;;
|
||||
-without-qt-network)
|
||||
HAVE_QT_NETWORK=0
|
||||
;;
|
||||
-without-qt-sql)
|
||||
HAVE_QT_SQL=0
|
||||
;;
|
||||
-without-qt-svg)
|
||||
HAVE_QT_SVG=0
|
||||
;;
|
||||
-without-qt-printsupport)
|
||||
HAVE_QT_PRINTSUPPORT=0
|
||||
;;
|
||||
-without-qt-multimedia)
|
||||
HAVE_QT_MULTIMEDIA=0
|
||||
;;
|
||||
-without-qt-designer)
|
||||
HAVE_QT_DESIGNER=0
|
||||
;;
|
||||
-without-qt-xml)
|
||||
HAVE_QT_XML=0
|
||||
;;
|
||||
-with-64bit-coord)
|
||||
HAVE_64BIT_COORD=1
|
||||
;;
|
||||
|
|
@ -207,6 +239,7 @@ while [ "$*" != "" ]; do
|
|||
echo ""
|
||||
echo " -with-qtbinding Create Qt bindings for ruby scripts [default]"
|
||||
echo " -without-qtbinding Don't create Qt bindings for ruby scripts"
|
||||
echo " -without-qt-uitools Don't include uitools in Qt binding"
|
||||
echo " -with-64bit-coord Use long (64bit) coordinates - EXPERIMENTAL FEATURE"
|
||||
echo " (only available for gcc>=4.4 for 64bit build)"
|
||||
echo " -without-64bit-coord Don't use long (64bit) coordinates [default]"
|
||||
|
|
@ -604,6 +637,14 @@ qmake_options=(
|
|||
PYTHONEXTSUFFIX="$PYTHONEXTSUFFIX"
|
||||
HAVE_PYTHON="$HAVE_PYTHON"
|
||||
HAVE_QTBINDINGS="$HAVE_QTBINDINGS"
|
||||
HAVE_QT_UITOOLS="$HAVE_QT_UITOOLS"
|
||||
HAVE_QT_NETWORK="$HAVE_QT_NETWORK"
|
||||
HAVE_QT_SQL="$HAVE_QT_SQL"
|
||||
HAVE_QT_SVG="$HAVE_QT_SVG"
|
||||
HAVE_QT_PRINTSUPPORT="$HAVE_QT_PRINTSUPPORT"
|
||||
HAVE_QT_MULTIMEDIA="$HAVE_QT_MULTIMEDIA"
|
||||
HAVE_QT_DESIGNER="$HAVE_QT_DESIGNER"
|
||||
HAVE_QT_XML="$HAVE_QT_XML"
|
||||
HAVE_64BIT_COORD="$HAVE_64BIT_COORD"
|
||||
HAVE_QT="$HAVE_QT"
|
||||
HAVE_QT5="$HAVE_QT5"
|
||||
|
|
|
|||
|
|
@ -49,8 +49,8 @@ inst_dir5=`pwd`/scripts/mkqtdecl5
|
|||
src_dir=`pwd`/src
|
||||
src_name4=gsiqt/qt4
|
||||
src_name5=gsiqt/qt5
|
||||
qt_mods4="QtCore QtGui QtDesigner QtNetwork QtSql QtXml"
|
||||
qt_mods5="QtCore QtGui QtWidgets QtDesigner QtNetwork QtPrintSupport QtSql QtSvg QtXml QtXmlPatterns QtMultimedia"
|
||||
qt_mods4="QtCore QtGui QtDesigner QtNetwork QtSql QtXml QtUiTools"
|
||||
qt_mods5="QtCore QtGui QtWidgets QtDesigner QtNetwork QtPrintSupport QtSql QtSvg QtXml QtXmlPatterns QtMultimedia QtUiTools"
|
||||
|
||||
src_name=$src_name4
|
||||
inst_dir=$inst_dir4
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
#include "QtUiTools/QUiLoader"
|
||||
|
|
@ -302,6 +302,13 @@ rename "QProcess", /QProcess::finished\(int[\s\w]*\)/, "finished_int" # disambig
|
|||
drop_method "QCoreApplication", /QCoreApplication::QCoreApplication/
|
||||
add_native_qapp_ctor_impl("QCoreApplication")
|
||||
|
||||
# Reasoning: "notify" is hardly needed (use postEvent or sendEvent instead). Reimplementing remains as a use case.
|
||||
# Reimplementing this method however is questionable: providing an reimplementation hook has severe consequences as even
|
||||
# Qt object constructors will route over this slot and invoke interpreter calls. This will for example lead to preliminary
|
||||
# binding of Qt objects to Python objects, hence spoil their object identity.
|
||||
drop_method "QCoreApplication", /QCoreApplication::notify/
|
||||
drop_method "QApplication", /QApplication::notify/
|
||||
|
||||
# alternative implementation for QObject::findChild
|
||||
add_native_impl_QObject_findChild
|
||||
|
||||
|
|
@ -886,6 +893,11 @@ no_copy_ctor "QFormLayout"
|
|||
no_copy_ctor "QXmlParseException"
|
||||
no_copy_ctor "QNetworkAccessManager"
|
||||
|
||||
# --------------------------------------------------------------
|
||||
# QtUiTools
|
||||
|
||||
include "QUiLoader", [ "<QUiLoader>", "<QDir>", "<QAction>", "<QActionGroup>", "<QLayout>", "<QWidget>", "<QChildEvent>", "<QEvent>", "<QTimerEvent>" ]
|
||||
|
||||
# --------------------------------------------------------------
|
||||
# events and properties
|
||||
# NOTE: to generate these files use scripts/mkqtdecl/mkqtdecl_extract_props.rb
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
#include "QtUiTools/QUiLoader"
|
||||
|
|
@ -375,6 +375,14 @@ rename "QProcess", /QProcess::finished\(int[\s\w]*\)/, "finished_int" # disambig
|
|||
drop_method "QCoreApplication", /QCoreApplication::QCoreApplication/
|
||||
add_native_qapp_ctor_impl("QCoreApplication")
|
||||
|
||||
# Reasoning: "notify" is hardly needed (use postEvent or sendEvent instead). Reimplementing remains as a use case.
|
||||
# Reimplementing this method however is questionable: providing an reimplementation hook has severe consequences as even
|
||||
# Qt object constructors will route over this slot and invoke interpreter calls. This will for example lead to preliminary
|
||||
# binding of Qt objects to Python objects, hence spoil their object identity.
|
||||
drop_method "QCoreApplication", /QCoreApplication::notify/
|
||||
drop_method "QApplication", /QApplication::notify/
|
||||
drop_method "QGuiApplication", /QGuiApplication::notify/
|
||||
|
||||
# alternative implementation for QObject::findChild
|
||||
add_native_impl_QObject_findChild
|
||||
|
||||
|
|
@ -1210,6 +1218,11 @@ rename "QNetworkSession", /QNetworkSession::error\(QNetworkSession::/, "error_si
|
|||
rename "QSqlDriver", /QSqlDriver::notification\(const\s+QString\s*\&\s*\w*\s*\)/, "notification" # disambiguator
|
||||
rename "QSqlDriver", /QSqlDriver::notification\(const\s+QString\s*\&\s*\w*\s*,/, "notification_withData" # disambiguator
|
||||
|
||||
# --------------------------------------------------------------
|
||||
# QtUiTools
|
||||
|
||||
include "QUiLoader", [ "<QUiLoader>", "<QDir>", "<QAction>", "<QActionGroup>", "<QLayout>", "<QWidget>", "<QChildEvent>", "<QEvent>", "<QTimerEvent>" ]
|
||||
|
||||
# --------------------------------------------------------------
|
||||
# events and properties
|
||||
# NOTE: to generate these files use scripts/mkqtdecl/mkqtdecl_extract_props.rb
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ PropertiesPage::get_points (db::DPoint &p1, db::DPoint &p2)
|
|||
|
||||
try {
|
||||
tl::from_string (tl::to_string (x1->text ()), dx1);
|
||||
lay::indicate_error (x1, 0);
|
||||
lay::indicate_error (x1, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (x1, &ex);
|
||||
has_error = true;
|
||||
|
|
@ -142,7 +142,7 @@ PropertiesPage::get_points (db::DPoint &p1, db::DPoint &p2)
|
|||
|
||||
try {
|
||||
tl::from_string (tl::to_string (x2->text ()), dx2);
|
||||
lay::indicate_error (x2, 0);
|
||||
lay::indicate_error (x2, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (x2, &ex);
|
||||
has_error = true;
|
||||
|
|
@ -150,7 +150,7 @@ PropertiesPage::get_points (db::DPoint &p1, db::DPoint &p2)
|
|||
|
||||
try {
|
||||
tl::from_string (tl::to_string (y1->text ()), dy1);
|
||||
lay::indicate_error (y1, 0);
|
||||
lay::indicate_error (y1, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (y1, &ex);
|
||||
has_error = true;
|
||||
|
|
@ -158,7 +158,7 @@ PropertiesPage::get_points (db::DPoint &p1, db::DPoint &p2)
|
|||
|
||||
try {
|
||||
tl::from_string (tl::to_string (y2->text ()), dy2);
|
||||
lay::indicate_error (y2, 0);
|
||||
lay::indicate_error (y2, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (y2, &ex);
|
||||
has_error = true;
|
||||
|
|
|
|||
|
|
@ -71,13 +71,10 @@ public:
|
|||
ProgressAdaptor (int verbosity);
|
||||
virtual ~ProgressAdaptor ();
|
||||
|
||||
virtual void register_object (tl::Progress *progress);
|
||||
virtual void unregister_object (tl::Progress *progress);
|
||||
virtual void trigger (tl::Progress *progress);
|
||||
virtual void yield (tl::Progress *progress);
|
||||
|
||||
private:
|
||||
std::list<tl::Progress *> mp_objects;
|
||||
int m_verbosity;
|
||||
std::string m_progress_text, m_progress_value;
|
||||
};
|
||||
|
|
@ -93,36 +90,19 @@ ProgressAdaptor::~ProgressAdaptor ()
|
|||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void
|
||||
ProgressAdaptor::register_object (tl::Progress *progress)
|
||||
{
|
||||
mp_objects.push_back (progress); // this keeps the outmost one visible. push_front would make the latest one visible.
|
||||
}
|
||||
|
||||
void
|
||||
ProgressAdaptor::unregister_object (tl::Progress *progress)
|
||||
{
|
||||
for (std::list<tl::Progress *>::iterator k = mp_objects.begin (); k != mp_objects.end (); ++k) {
|
||||
if (*k == progress) {
|
||||
mp_objects.erase (k);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ProgressAdaptor::trigger (tl::Progress *progress)
|
||||
{
|
||||
if (! mp_objects.empty () && mp_objects.front () == progress && tl::verbosity () >= m_verbosity) {
|
||||
if (progress && first () == progress && tl::verbosity () >= m_verbosity) {
|
||||
|
||||
std::string text = mp_objects.front ()->desc ();
|
||||
std::string text = progress->desc ();
|
||||
|
||||
if (m_progress_text != text) {
|
||||
tl::info << text << " ..";
|
||||
m_progress_text = text;
|
||||
}
|
||||
|
||||
std::string value = mp_objects.front ()->formatted_value ();
|
||||
std::string value = progress->formatted_value ();
|
||||
if (m_progress_value != value) {
|
||||
tl::info << ".. " << value;
|
||||
m_progress_value = value;
|
||||
|
|
|
|||
|
|
@ -97,6 +97,9 @@ GenericReaderOptions::GenericReaderOptions ()
|
|||
m_lefdef_produce_lef_pins = load_options.get_option_by_name ("lefdef_config.produce_lef_pins").to_bool ();
|
||||
m_lefdef_lef_pins_suffix = load_options.get_option_by_name ("lefdef_config.lef_pins_suffix_str").to_string ();
|
||||
m_lefdef_lef_pins_datatype = load_options.get_option_by_name ("lefdef_config.lef_pins_datatype_str").to_string ();
|
||||
m_lefdef_produce_fills = load_options.get_option_by_name ("lefdef_config.produce_fills").to_bool ();
|
||||
m_lefdef_fills_suffix = load_options.get_option_by_name ("lefdef_config.fills_suffix_str").to_string ();
|
||||
m_lefdef_fills_datatype = load_options.get_option_by_name ("lefdef_config.fills_datatype_str").to_string ();
|
||||
m_lefdef_produce_obstructions = load_options.get_option_by_name ("lefdef_config.produce_obstructions").to_bool ();
|
||||
m_lefdef_obstruction_suffix = load_options.get_option_by_name ("lefdef_config.obstructions_suffix").to_string ();
|
||||
m_lefdef_obstruction_datatype = load_options.get_option_by_name ("lefdef_config.obstructions_datatype").to_int ();
|
||||
|
|
@ -500,6 +503,20 @@ GenericReaderOptions::add_options (tl::CommandLineOptions &cmd)
|
|||
"The LEF pin geometry generation and layer mapping is designed in the same way than via geometry mapping. "
|
||||
"See '--" + m_long_prefix + "lefdef-produce-via-geometry' for a description of the mapping scheme.\n"
|
||||
)
|
||||
<< tl::arg (group +
|
||||
"#!--" + m_long_prefix + "lefdef-dont-produce-fills", &m_lefdef_produce_fills, "Skips fills when producing geometry",
|
||||
"If this option is given, no fill geometry will be produced."
|
||||
)
|
||||
<< tl::arg (group +
|
||||
"#--" + m_long_prefix + "lefdef-fills-suffix", &m_lefdef_fills_suffix, "Specifies the fill geometry layer suffix in pattern-based mode",
|
||||
"The fill geometry generation and layer mapfillg is designed in the same way than via geometry mapfillg. "
|
||||
"See '--" + m_long_prefix + "lefdef-via-geometry-suffix' for a description of the mapfillg scheme.\n"
|
||||
)
|
||||
<< tl::arg (group +
|
||||
"#--" + m_long_prefix + "lefdef-fills-datatype", &m_lefdef_fills_datatype, "Specifies the fill geometry layer datatype in pattern-based mode",
|
||||
"The fill geometry generation and layer mapfillg is designed in the same way than via geometry mapfillg. "
|
||||
"See '--" + m_long_prefix + "lefdef-produce-via-geometry' for a description of the mapfillg scheme.\n"
|
||||
)
|
||||
<< tl::arg (group +
|
||||
"#!--" + m_long_prefix + "lefdef-dont-produce-routing", &m_lefdef_produce_routing, "Skips routing when producing geometry",
|
||||
"If this option is given, no routing geometry will be produced."
|
||||
|
|
@ -724,6 +741,9 @@ GenericReaderOptions::configure (db::LoadLayoutOptions &load_options) const
|
|||
load_options.set_option_by_name ("lefdef_config.produce_lef_pins", m_lefdef_produce_lef_pins);
|
||||
load_options.set_option_by_name ("lefdef_config.lef_pins_suffix_str", m_lefdef_lef_pins_suffix);
|
||||
load_options.set_option_by_name ("lefdef_config.lef_pins_datatype_str", m_lefdef_lef_pins_datatype);
|
||||
load_options.set_option_by_name ("lefdef_config.produce_fills", m_lefdef_produce_fills);
|
||||
load_options.set_option_by_name ("lefdef_config.fills_suffix_str", m_lefdef_fills_suffix);
|
||||
load_options.set_option_by_name ("lefdef_config.fills_datatype_str", m_lefdef_fills_datatype);
|
||||
load_options.set_option_by_name ("lefdef_config.produce_obstructions", m_lefdef_produce_obstructions);
|
||||
load_options.set_option_by_name ("lefdef_config.obstructions_suffix", m_lefdef_obstruction_suffix);
|
||||
load_options.set_option_by_name ("lefdef_config.obstructions_datatype", m_lefdef_obstruction_datatype);
|
||||
|
|
|
|||
|
|
@ -161,6 +161,9 @@ private:
|
|||
bool m_lefdef_produce_lef_pins;
|
||||
std::string m_lefdef_lef_pins_suffix;
|
||||
std::string m_lefdef_lef_pins_datatype;
|
||||
bool m_lefdef_produce_fills;
|
||||
std::string m_lefdef_fills_suffix;
|
||||
std::string m_lefdef_fills_datatype;
|
||||
bool m_lefdef_produce_obstructions;
|
||||
std::string m_lefdef_obstruction_suffix;
|
||||
int m_lefdef_obstruction_datatype;
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
// Testing the converter main implementation (CIF)
|
||||
TEST(1)
|
||||
{
|
||||
#if defined(HAVE_PYTHON)
|
||||
std::string fp (tl::testsrc ());
|
||||
fp += "/testdata/bd/strmrun.py";
|
||||
|
||||
|
|
@ -51,5 +52,6 @@ TEST(1)
|
|||
tl::info << data;
|
||||
|
||||
EXPECT_EQ (data, "Hello, world (0,-42;42,0)!\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ SOURCES = \
|
|||
dbPolygonGenerators.cc \
|
||||
dbPropertiesRepository.cc \
|
||||
dbReader.cc \
|
||||
dbRecursiveInstanceIterator.cc \
|
||||
dbRecursiveShapeIterator.cc \
|
||||
dbRegion.cc \
|
||||
dbRegionLocalOperations.cc \
|
||||
|
|
@ -114,6 +115,7 @@ SOURCES = \
|
|||
gsiDeclDbPoint.cc \
|
||||
gsiDeclDbPolygon.cc \
|
||||
gsiDeclDbReader.cc \
|
||||
gsiDeclDbRecursiveInstanceIterator.cc \
|
||||
gsiDeclDbRecursiveShapeIterator.cc \
|
||||
gsiDeclDbRegion.cc \
|
||||
gsiDeclDbShape.cc \
|
||||
|
|
@ -269,6 +271,7 @@ HEADERS = \
|
|||
dbPolygonGenerators.h \
|
||||
dbPropertiesRepository.h \
|
||||
dbReader.h \
|
||||
dbRecursiveInstanceIterator.h \
|
||||
dbRecursiveShapeIterator.h \
|
||||
dbRegion.h \
|
||||
dbRegionLocalOperations.h \
|
||||
|
|
|
|||
|
|
@ -403,6 +403,8 @@ AsIfFlatRegion::selected_interacting_generic (const Edges &other, bool inverse,
|
|||
|
||||
db::local_processor<db::Polygon, db::Edge, db::Polygon> proc;
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_description (progress_desc ());
|
||||
proc.set_report_progress (report_progress ());
|
||||
|
||||
std::vector<generic_shape_iterator<db::Edge> > others;
|
||||
others.push_back (counting ? other.begin_merged () : other.begin ());
|
||||
|
|
@ -479,6 +481,8 @@ AsIfFlatRegion::selected_interacting_generic (const Texts &other, bool inverse,
|
|||
|
||||
db::local_processor<db::Polygon, db::Text, db::Polygon> proc;
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_description (progress_desc ());
|
||||
proc.set_report_progress (report_progress ());
|
||||
|
||||
std::vector<generic_shape_iterator<db::Text> > others;
|
||||
others.push_back (other.begin ());
|
||||
|
|
@ -564,6 +568,8 @@ AsIfFlatRegion::selected_interacting_generic (const Region &other, int mode, boo
|
|||
|
||||
db::local_processor<db::Polygon, db::Polygon, db::Polygon> proc;
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_description (progress_desc ());
|
||||
proc.set_report_progress (report_progress ());
|
||||
|
||||
std::vector<generic_shape_iterator<db::Polygon> > others;
|
||||
others.push_back ((mode < 0 || counting) ? other.begin_merged () : other.begin ());
|
||||
|
|
@ -702,6 +708,8 @@ AsIfFlatRegion::pull_generic (const Edges &other) const
|
|||
|
||||
db::local_processor<db::Polygon, db::Edge, db::Edge> proc;
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_description (progress_desc ());
|
||||
proc.set_report_progress (report_progress ());
|
||||
|
||||
std::vector<generic_shape_iterator<db::Edge> > others;
|
||||
others.push_back (other.begin_merged ());
|
||||
|
|
@ -752,6 +760,8 @@ AsIfFlatRegion::pull_generic (const Texts &other) const
|
|||
|
||||
db::local_processor<db::Polygon, db::Text, db::Text> proc;
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_description (progress_desc ());
|
||||
proc.set_report_progress (report_progress ());
|
||||
|
||||
std::vector<generic_shape_iterator<db::Text> > others;
|
||||
others.push_back (other.begin ());
|
||||
|
|
@ -807,6 +817,8 @@ AsIfFlatRegion::pull_generic (const Region &other, int mode, bool touching) cons
|
|||
|
||||
db::local_processor<db::Polygon, db::Polygon, db::Polygon> proc;
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_description (progress_desc ());
|
||||
proc.set_report_progress (report_progress ());
|
||||
|
||||
std::vector<generic_shape_iterator<db::Polygon> > others;
|
||||
others.push_back (other.begin_merged ());
|
||||
|
|
@ -1170,6 +1182,8 @@ AsIfFlatRegion::run_check (db::edge_relation_type rel, bool different_polygons,
|
|||
|
||||
db::local_processor<db::Polygon, db::Polygon, db::EdgePair> proc;
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_description (progress_desc ());
|
||||
proc.set_report_progress (report_progress ());
|
||||
|
||||
std::vector<generic_shape_iterator<db::Polygon> > others;
|
||||
std::vector<bool> foreign;
|
||||
|
|
|
|||
|
|
@ -601,6 +601,8 @@ DeepRegion::and_or_not_with (const DeepRegion *other, bool and_op) const
|
|||
|
||||
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&deep_layer ().layout ()), const_cast<db::Cell *> (&deep_layer ().initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell (), deep_layer ().breakout_cells (), other->deep_layer ().breakout_cells ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_description (progress_desc ());
|
||||
proc.set_report_progress (report_progress ());
|
||||
proc.set_threads (deep_layer ().store ()->threads ());
|
||||
proc.set_area_ratio (deep_layer ().store ()->max_area_ratio ());
|
||||
proc.set_max_vertex_count (deep_layer ().store ()->max_vertex_count ());
|
||||
|
|
@ -620,6 +622,8 @@ DeepRegion::and_and_not_with (const DeepRegion *other) const
|
|||
|
||||
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&deep_layer ().layout ()), const_cast<db::Cell *> (&deep_layer ().initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell (), deep_layer ().breakout_cells (), other->deep_layer ().breakout_cells ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_description (progress_desc ());
|
||||
proc.set_report_progress (report_progress ());
|
||||
proc.set_threads (deep_layer ().store ()->threads ());
|
||||
proc.set_area_ratio (deep_layer ().store ()->max_area_ratio ());
|
||||
proc.set_max_vertex_count (deep_layer ().store ()->max_vertex_count ());
|
||||
|
|
@ -1359,6 +1363,8 @@ Output *region_cop_impl (DeepRegion *region, db::CompoundRegionOperationNode &no
|
|||
const_cast<db::Cell *> (®ion->deep_layer ().initial_cell ()),
|
||||
region->deep_layer ().breakout_cells ());
|
||||
|
||||
proc.set_description (region->progress_desc ());
|
||||
proc.set_report_progress (region->report_progress ());
|
||||
proc.set_base_verbosity (region->base_verbosity ());
|
||||
proc.set_threads (region->deep_layer ().store ()->threads ());
|
||||
|
||||
|
|
@ -1464,6 +1470,8 @@ DeepRegion::run_check (db::edge_relation_type rel, bool different_polygons, cons
|
|||
deep_layer ().breakout_cells (),
|
||||
other_deep ? other_deep->deep_layer ().breakout_cells () : 0);
|
||||
|
||||
proc.set_description (progress_desc ());
|
||||
proc.set_report_progress (report_progress ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_threads (polygons.store ()->threads ());
|
||||
|
||||
|
|
@ -1536,6 +1544,8 @@ DeepRegion::selected_interacting_generic (const Region &other, int mode, bool to
|
|||
db::InteractingLocalOperation op (mode, touching, inverse, min_count, max_count, true);
|
||||
|
||||
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_polygons.layout (), &other_polygons.initial_cell (), polygons.breakout_cells (), other_polygons.breakout_cells ());
|
||||
proc.set_description (progress_desc ());
|
||||
proc.set_report_progress (report_progress ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_threads (polygons.store ()->threads ());
|
||||
if (split_after) {
|
||||
|
|
@ -1575,6 +1585,8 @@ DeepRegion::selected_interacting_generic (const Edges &other, bool inverse, size
|
|||
db::InteractingWithEdgeLocalOperation op (inverse, min_count, max_count, true);
|
||||
|
||||
db::local_processor<db::PolygonRef, db::Edge, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell (), polygons.breakout_cells (), other_deep->deep_layer ().breakout_cells ());
|
||||
proc.set_description (progress_desc ());
|
||||
proc.set_report_progress (report_progress ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_threads (polygons.store ()->threads ());
|
||||
if (split_after) {
|
||||
|
|
@ -1614,6 +1626,8 @@ DeepRegion::pull_generic (const Region &other, int mode, bool touching) const
|
|||
db::PullLocalOperation op (mode, touching);
|
||||
|
||||
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_polygons.layout (), &other_polygons.initial_cell (), polygons.breakout_cells (), other_polygons.breakout_cells ());
|
||||
proc.set_description (progress_desc ());
|
||||
proc.set_report_progress (report_progress ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_threads (polygons.store ()->threads ());
|
||||
if (split_after) {
|
||||
|
|
@ -1650,6 +1664,8 @@ DeepRegion::pull_generic (const Edges &other) const
|
|||
db::PullWithEdgeLocalOperation op;
|
||||
|
||||
db::local_processor<db::PolygonRef, db::Edge, db::Edge> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_edges.layout (), &other_edges.initial_cell (), polygons.breakout_cells (), other_edges.breakout_cells ());
|
||||
proc.set_description (progress_desc ());
|
||||
proc.set_report_progress (report_progress ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_threads (polygons.store ()->threads ());
|
||||
proc.run (&op, polygons.layer (), other_edges.layer (), dl_out.layer ());
|
||||
|
|
@ -1679,6 +1695,8 @@ DeepRegion::pull_generic (const Texts &other) const
|
|||
db::PullWithTextLocalOperation op;
|
||||
|
||||
db::local_processor<db::PolygonRef, db::TextRef, db::TextRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_texts.layout (), &other_texts.initial_cell (), polygons.breakout_cells (), other_texts.breakout_cells ());
|
||||
proc.set_description (progress_desc ());
|
||||
proc.set_report_progress (report_progress ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_threads (polygons.store ()->threads ());
|
||||
proc.run (&op, polygons.layer (), other_texts.layer (), dl_out.layer ());
|
||||
|
|
@ -1709,6 +1727,8 @@ DeepRegion::selected_interacting_generic (const Texts &other, bool inverse, size
|
|||
db::InteractingWithTextLocalOperation op (inverse, min_count, max_count);
|
||||
|
||||
db::local_processor<db::PolygonRef, db::TextRef, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell (), polygons.breakout_cells (), other_deep->deep_layer ().breakout_cells ());
|
||||
proc.set_description (progress_desc ());
|
||||
proc.set_report_progress (report_progress ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_threads (polygons.store ()->threads ());
|
||||
if (split_after) {
|
||||
|
|
|
|||
|
|
@ -395,7 +395,7 @@ void NetlistSpiceReader::push_stream (const std::string &path)
|
|||
istream = new tl::InputStream (tl::combine_path (tl::dirname (mp_stream->source ()), path));
|
||||
}
|
||||
} else {
|
||||
istream = new tl::InputStream (current_uri.resolved (new_uri).to_string ());
|
||||
istream = new tl::InputStream (current_uri.resolved (new_uri).to_abstract_path ());
|
||||
}
|
||||
|
||||
m_streams.push_back (std::make_pair (istream, mp_stream.release ()));
|
||||
|
|
|
|||
|
|
@ -725,7 +725,7 @@ template DB_PUBLIC void split_polygon<> (const db::DSimplePolygon &polygon, std:
|
|||
// Smoothing tools
|
||||
|
||||
void
|
||||
smooth_contour (db::Polygon::polygon_contour_iterator from, db::Polygon::polygon_contour_iterator to, std::vector <db::Point> &points, db::Coord d)
|
||||
smooth_contour (db::Polygon::polygon_contour_iterator from, db::Polygon::polygon_contour_iterator to, std::vector <db::Point> &points, db::Coord d, bool keep_hv)
|
||||
{
|
||||
points.clear ();
|
||||
points.reserve (std::distance (from, to));
|
||||
|
|
@ -781,7 +781,9 @@ smooth_contour (db::Polygon::polygon_contour_iterator from, db::Polygon::polygon
|
|||
|
||||
bool can_drop = false;
|
||||
|
||||
if (db::Coord (p1.distance(p0)) <= d && db::sprod_sign (p2 - p1, p0 - pm1) > 0 && std::abs (db::vprod (p2 - p1, p0 - pm1)) < 0.8 * p2.distance (p1) * p0.distance (pm1)) {
|
||||
if (keep_hv && (p1.x () == p0.x () || p1.y () == p0.y () || p2.x () == p1.x () || p2.y () == p1.y ())) {
|
||||
// keep points which participate in either a vertical or horizontal edge
|
||||
} else if (db::Coord (p1.distance(p0)) <= d && db::sprod_sign (p2 - p1, p0 - pm1) > 0 && std::abs (db::vprod (p2 - p1, p0 - pm1)) < 0.8 * p2.distance (p1) * p0.distance (pm1)) {
|
||||
// jog configurations with small edges are candidates
|
||||
can_drop = true;
|
||||
} else if (db::vprod_sign (p2 - p1, p1 - p0) < 0) {
|
||||
|
|
@ -839,19 +841,19 @@ smooth_contour (db::Polygon::polygon_contour_iterator from, db::Polygon::polygon
|
|||
}
|
||||
|
||||
db::Polygon
|
||||
smooth (const db::Polygon &polygon, db::Coord d)
|
||||
smooth (const db::Polygon &polygon, db::Coord d, bool keep_hv)
|
||||
{
|
||||
db::Polygon new_poly;
|
||||
std::vector <db::Point> new_pts;
|
||||
|
||||
smooth_contour (polygon.begin_hull (), polygon.end_hull (), new_pts, d);
|
||||
smooth_contour (polygon.begin_hull (), polygon.end_hull (), new_pts, d, keep_hv);
|
||||
if (new_pts.size () >= 3) {
|
||||
|
||||
new_poly.assign_hull (new_pts.begin (), new_pts.end (), false /*don't compress*/);
|
||||
|
||||
for (unsigned int h = 0; h < polygon.holes (); ++h) {
|
||||
new_pts.clear ();
|
||||
smooth_contour (polygon.begin_hole (h), polygon.end_hole (h), new_pts, d);
|
||||
smooth_contour (polygon.begin_hole (h), polygon.end_hole (h), new_pts, d, keep_hv);
|
||||
if (new_pts.size () >= 3) {
|
||||
new_poly.insert_hole (new_pts.begin (), new_pts.end (), false /*don't compress*/);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -449,6 +449,8 @@ db::Polygon DB_PUBLIC compute_rounded (const db::Polygon &poly, double rinner, d
|
|||
*/
|
||||
db::DPolygon DB_PUBLIC compute_rounded (const db::DPolygon &poly, double rinner, double router, unsigned int n);
|
||||
|
||||
#define KLAYOUT_SMOOTH_HAS_KEEP_HV 1
|
||||
|
||||
/**
|
||||
* @brief Smooth a contour
|
||||
*
|
||||
|
|
@ -458,13 +460,14 @@ db::DPolygon DB_PUBLIC compute_rounded (const db::DPolygon &poly, double rinner,
|
|||
* @param to The end of the contour
|
||||
* @param new_pts The points that make up the new contour
|
||||
* @param d The distance that determines the smoothing "roughness"
|
||||
* @param keep_hv If true, vertical and horizontal edges are maintained
|
||||
*/
|
||||
void DB_PUBLIC smooth_contour (db::Polygon::polygon_contour_iterator from, db::Polygon::polygon_contour_iterator to, std::vector <db::Point> &new_pts, db::Coord d);
|
||||
void DB_PUBLIC smooth_contour (db::Polygon::polygon_contour_iterator from, db::Polygon::polygon_contour_iterator to, std::vector <db::Point> &new_pts, db::Coord d, bool keep_hv);
|
||||
|
||||
/**
|
||||
* @brief Smooth a polygon (apply smoothing to the whole polygon)
|
||||
*/
|
||||
db::Polygon DB_PUBLIC smooth (const db::Polygon &poly, db::Coord d);
|
||||
db::Polygon DB_PUBLIC smooth (const db::Polygon &poly, db::Coord d, bool keep_hv);
|
||||
|
||||
/**
|
||||
* @brief Returns a value indicating whether the polygon is an "strange polygon"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,755 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2021 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include "dbRecursiveInstanceIterator.h"
|
||||
#include "dbRegion.h"
|
||||
#include "dbEdgeProcessor.h"
|
||||
#include "tlProgress.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Recursive shape iterator implementation
|
||||
|
||||
RecursiveInstanceIterator::RecursiveInstanceIterator (const RecursiveInstanceIterator &d)
|
||||
{
|
||||
operator= (d);
|
||||
}
|
||||
|
||||
RecursiveInstanceIterator &RecursiveInstanceIterator::operator= (const RecursiveInstanceIterator &d)
|
||||
{
|
||||
if (&d != this) {
|
||||
|
||||
m_all_targets = d.m_all_targets;
|
||||
m_targets = d.m_targets;
|
||||
|
||||
m_max_depth = d.m_max_depth;
|
||||
m_min_depth = d.m_min_depth;
|
||||
m_overlapping = d.m_overlapping;
|
||||
m_start = d.m_start;
|
||||
m_stop = d.m_stop;
|
||||
|
||||
mp_layout = d.mp_layout;
|
||||
mp_top_cell = d.mp_top_cell;
|
||||
|
||||
m_region = d.m_region;
|
||||
if (d.mp_complex_region.get () != 0) {
|
||||
mp_complex_region.reset (new region_type (*d.mp_complex_region.get ()));
|
||||
} else {
|
||||
mp_complex_region.reset (0);
|
||||
}
|
||||
|
||||
m_box_convert = d.m_box_convert;
|
||||
|
||||
m_inst = d.m_inst;
|
||||
m_inst_array = d.m_inst_array;
|
||||
m_empty_cells_cache = d.m_empty_cells_cache;
|
||||
mp_cell = d.mp_cell;
|
||||
m_trans = d.m_trans;
|
||||
m_trans_stack = d.m_trans_stack;
|
||||
m_inst_iterators = d.m_inst_iterators;
|
||||
m_inst_array_iterators = d.m_inst_array_iterators;
|
||||
m_cells = d.m_cells;
|
||||
m_local_complex_region_stack = d.m_local_complex_region_stack;
|
||||
m_local_region_stack = d.m_local_region_stack;
|
||||
m_needs_reinit = d.m_needs_reinit;
|
||||
m_inst_quad_id = d.m_inst_quad_id;
|
||||
m_inst_quad_id_stack = d.m_inst_quad_id_stack;
|
||||
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
RecursiveInstanceIterator::RecursiveInstanceIterator ()
|
||||
{
|
||||
// anything. Not necessary reasonable.
|
||||
mp_layout = 0;
|
||||
mp_top_cell = 0;
|
||||
mp_cell = 0;
|
||||
m_overlapping = false;
|
||||
m_max_depth = std::numeric_limits<int>::max (); // all
|
||||
m_min_depth = 0;
|
||||
m_needs_reinit = false;
|
||||
m_inst_quad_id = 0;
|
||||
m_all_targets = true;
|
||||
}
|
||||
|
||||
RecursiveInstanceIterator::RecursiveInstanceIterator (const layout_type &layout, const cell_type &cell, const box_type ®ion, bool overlapping)
|
||||
: m_box_convert (layout)
|
||||
{
|
||||
mp_layout = &layout;
|
||||
mp_top_cell = &cell;
|
||||
m_overlapping = overlapping;
|
||||
init ();
|
||||
init_region (region);
|
||||
}
|
||||
|
||||
RecursiveInstanceIterator::RecursiveInstanceIterator (const layout_type &layout, const cell_type &cell, const region_type ®ion, bool overlapping)
|
||||
: m_box_convert (layout)
|
||||
{
|
||||
mp_layout = &layout;
|
||||
mp_top_cell = &cell;
|
||||
m_overlapping = overlapping;
|
||||
init ();
|
||||
init_region (region);
|
||||
}
|
||||
|
||||
RecursiveInstanceIterator::RecursiveInstanceIterator (const layout_type &layout, const cell_type &cell)
|
||||
: m_box_convert (layout)
|
||||
{
|
||||
mp_layout = &layout;
|
||||
mp_top_cell = &cell;
|
||||
m_overlapping = false;
|
||||
init ();
|
||||
init_region (box_type::world ());
|
||||
}
|
||||
|
||||
RecursiveInstanceIterator::~RecursiveInstanceIterator ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
RecursiveInstanceIterator::init ()
|
||||
{
|
||||
m_needs_reinit = true;
|
||||
m_max_depth = std::numeric_limits<int>::max (); // all
|
||||
m_min_depth = 0; // from the beginning
|
||||
m_inst_quad_id = 0;
|
||||
mp_cell = 0;
|
||||
m_all_targets = true;
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveInstanceIterator::init_region (const RecursiveInstanceIterator::box_type ®ion)
|
||||
{
|
||||
m_region = region;
|
||||
mp_complex_region.reset (0);
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveInstanceIterator::init_region (const RecursiveInstanceIterator::region_type ®ion)
|
||||
{
|
||||
if (region.empty ()) {
|
||||
|
||||
m_region = box_type ();
|
||||
mp_complex_region.reset (0);
|
||||
|
||||
} else if (region.is_box ()) {
|
||||
|
||||
m_region = region.bbox ();
|
||||
mp_complex_region.reset (0);
|
||||
|
||||
} else {
|
||||
|
||||
mp_complex_region.reset (new region_type (region));
|
||||
m_region = region.bbox ();
|
||||
// A small optimization. We can do this since we merge and translate to trapezoids anyway.
|
||||
mp_complex_region->set_strict_handling (false);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveInstanceIterator::set_region (const box_type ®ion)
|
||||
{
|
||||
if (m_region != region || mp_complex_region.get () != 0) {
|
||||
init_region (region);
|
||||
m_needs_reinit = true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveInstanceIterator::set_region (const region_type ®ion)
|
||||
{
|
||||
init_region (region);
|
||||
m_needs_reinit = true;
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveInstanceIterator::confine_region (const box_type ®ion)
|
||||
{
|
||||
if (m_region.empty ()) {
|
||||
// no more confinement
|
||||
} else if (mp_complex_region.get ()) {
|
||||
init_region (*mp_complex_region & region_type (region));
|
||||
} else {
|
||||
init_region (m_region & region);
|
||||
}
|
||||
m_needs_reinit = true;
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveInstanceIterator::confine_region (const region_type ®ion)
|
||||
{
|
||||
if (m_region.empty ()) {
|
||||
// no more confinement
|
||||
} else if (mp_complex_region.get ()) {
|
||||
init_region (*mp_complex_region & region);
|
||||
} else {
|
||||
init_region (region & region_type (m_region));
|
||||
}
|
||||
m_needs_reinit = true;
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveInstanceIterator::enable_all_targets ()
|
||||
{
|
||||
if (! m_all_targets) {
|
||||
m_all_targets = true;
|
||||
m_targets.clear ();
|
||||
m_needs_reinit = true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveInstanceIterator::set_targets (const std::set<db::cell_index_type> &tgt)
|
||||
{
|
||||
if (m_all_targets || m_targets != tgt) {
|
||||
m_targets = tgt;
|
||||
m_all_targets = false;
|
||||
m_needs_reinit = true;
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
struct BoxTreePusher
|
||||
: public db::SimplePolygonSink
|
||||
{
|
||||
BoxTreePusher (RecursiveInstanceIterator::box_tree_type *bt)
|
||||
: mp_bt (bt)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void put (const db::SimplePolygon &sp)
|
||||
{
|
||||
mp_bt->insert (sp.box ());
|
||||
}
|
||||
|
||||
private:
|
||||
RecursiveInstanceIterator::box_tree_type *mp_bt;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveInstanceIterator::validate (RecursiveInstanceReceiver *receiver) const
|
||||
{
|
||||
if (! m_needs_reinit) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_needs_reinit = false;
|
||||
|
||||
// re-initialize
|
||||
mp_cell = mp_top_cell;
|
||||
m_trans_stack.clear ();
|
||||
m_inst_iterators.clear ();
|
||||
m_inst_quad_id_stack.clear ();
|
||||
m_inst_array_iterators.clear ();
|
||||
m_cells.clear ();
|
||||
m_trans = cplx_trans_type ();
|
||||
|
||||
m_local_region_stack.clear ();
|
||||
m_local_region_stack.push_back (m_region);
|
||||
|
||||
m_local_complex_region_stack.clear ();
|
||||
if (mp_complex_region.get ()) {
|
||||
|
||||
// prepare a local complex region
|
||||
m_local_complex_region_stack.push_back (box_tree_type ());
|
||||
|
||||
// Use a merge and the trapezoid generator to produce a decomposition that goes into the complex region
|
||||
|
||||
db::EdgeProcessor ep;
|
||||
size_t n = 0;
|
||||
for (region_type::const_iterator p = mp_complex_region->begin (); !p.at_end (); ++p, ++n) {
|
||||
ep.insert (*p, n);
|
||||
}
|
||||
|
||||
BoxTreePusher btp (&m_local_complex_region_stack.back ());
|
||||
db::TrapezoidGenerator tg (btp);
|
||||
|
||||
db::MergeOp op (0);
|
||||
ep.process (tg, op);
|
||||
|
||||
m_local_complex_region_stack.back ().sort (db::box_convert <db::Box> ());
|
||||
|
||||
}
|
||||
|
||||
if (mp_top_cell) {
|
||||
|
||||
if (! m_all_targets) {
|
||||
m_target_tree.clear ();
|
||||
mp_top_cell->collect_called_cells (m_target_tree);
|
||||
}
|
||||
|
||||
new_cell (receiver);
|
||||
next_instance (receiver);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveInstanceIterator::reset_selection ()
|
||||
{
|
||||
if (mp_layout) {
|
||||
|
||||
m_start.clear ();
|
||||
m_stop.clear ();
|
||||
|
||||
m_needs_reinit = true;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveInstanceIterator::unselect_cells (const std::set<db::cell_index_type> &cells)
|
||||
{
|
||||
if (mp_layout) {
|
||||
|
||||
for (std::set<db::cell_index_type>::const_iterator c = cells.begin (); c != cells.end (); ++c) {
|
||||
m_stop.insert (*c);
|
||||
m_start.erase (*c);
|
||||
}
|
||||
|
||||
m_needs_reinit = true;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveInstanceIterator::unselect_all_cells ()
|
||||
{
|
||||
if (mp_layout) {
|
||||
|
||||
m_start.clear ();
|
||||
for (db::Layout::const_iterator c = mp_layout->begin (); c != mp_layout->end (); ++c) {
|
||||
m_stop.insert (c->cell_index ());
|
||||
}
|
||||
|
||||
m_needs_reinit = true;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveInstanceIterator::select_cells (const std::set<db::cell_index_type> &cells)
|
||||
{
|
||||
if (mp_layout) {
|
||||
|
||||
for (std::set<db::cell_index_type>::const_iterator c = cells.begin (); c != cells.end (); ++c) {
|
||||
m_start.insert (*c);
|
||||
m_stop.erase (*c);
|
||||
}
|
||||
|
||||
m_needs_reinit = true;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveInstanceIterator::select_all_cells ()
|
||||
{
|
||||
if (mp_layout) {
|
||||
|
||||
m_stop.clear ();
|
||||
for (db::Layout::const_iterator c = mp_layout->begin (); c != mp_layout->end (); ++c) {
|
||||
m_start.insert (c->cell_index ());
|
||||
}
|
||||
|
||||
m_needs_reinit = true;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
const RecursiveInstanceIterator::instance_element_type *
|
||||
RecursiveInstanceIterator::operator-> () const
|
||||
{
|
||||
validate (0);
|
||||
m_combined_instance = db::InstElement (*m_inst, m_inst_array);
|
||||
return &m_combined_instance;
|
||||
}
|
||||
|
||||
bool
|
||||
RecursiveInstanceIterator::at_end () const
|
||||
{
|
||||
validate (0);
|
||||
return m_inst.at_end ();
|
||||
}
|
||||
|
||||
std::vector<db::InstElement>
|
||||
RecursiveInstanceIterator::path () const
|
||||
{
|
||||
std::vector<db::InstElement> elements;
|
||||
for (size_t i = 0; i < m_inst_array_iterators.size () && i < m_inst_iterators.size (); ++i) {
|
||||
elements.push_back (db::InstElement (*m_inst_iterators [i], m_inst_array_iterators [i]));
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveInstanceIterator::skip_inst_iter_for_complex_region () const
|
||||
{
|
||||
while (! m_inst.at_end ()) {
|
||||
|
||||
// skip inst quad if possible
|
||||
while (! m_inst.at_end ()) {
|
||||
if (is_outside_complex_region (m_inst.quad_box ())) {
|
||||
m_inst.skip_quad ();
|
||||
} else {
|
||||
m_inst_quad_id = m_inst.quad_id ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// skip insts outside the complex region
|
||||
if (! m_inst.at_end ()) {
|
||||
if (! is_outside_complex_region (m_inst->bbox ())) {
|
||||
break;
|
||||
} else {
|
||||
++m_inst;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveInstanceIterator::next (RecursiveInstanceReceiver *receiver)
|
||||
{
|
||||
if (! at_end ()) {
|
||||
++m_inst_array;
|
||||
if (! m_inst_array.at_end ()) {
|
||||
new_inst_member (receiver);
|
||||
} else {
|
||||
++m_inst;
|
||||
new_inst (receiver);
|
||||
next_instance (receiver);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
RecursiveInstanceIterator::needs_visit () const
|
||||
{
|
||||
return int (m_inst_iterators.size ()) >= m_min_depth && ! is_inactive () && (m_all_targets || m_targets.find (m_inst->cell_index ()) != m_targets.end ());
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveInstanceIterator::next_instance (RecursiveInstanceReceiver *receiver) const
|
||||
{
|
||||
while (true) {
|
||||
|
||||
if (! m_inst.at_end ()) {
|
||||
|
||||
if (int (m_inst_iterators.size ()) < m_max_depth && (m_all_targets || m_target_tree.find (m_inst->cell_index ()) != m_target_tree.end ())) {
|
||||
down (receiver);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (! m_inst_iterators.empty ()) {
|
||||
// no more instances: up and next instance
|
||||
up (receiver);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (! m_inst.at_end ()) {
|
||||
if (! needs_visit ()) {
|
||||
++m_inst_array;
|
||||
if (! m_inst_array.at_end ()) {
|
||||
new_inst_member (receiver);
|
||||
} else {
|
||||
++m_inst;
|
||||
new_inst (receiver);
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveInstanceIterator::down (RecursiveInstanceReceiver *receiver) const
|
||||
{
|
||||
m_trans_stack.push_back (m_trans);
|
||||
m_cells.push_back (mp_cell);
|
||||
|
||||
m_inst_iterators.push_back (m_inst);
|
||||
m_inst_array_iterators.push_back (m_inst_array);
|
||||
m_inst_quad_id_stack.push_back (m_inst_quad_id);
|
||||
|
||||
bool ia = is_inactive ();
|
||||
bool aoi = is_all_of_instance ();
|
||||
mp_cell = &mp_layout->cell (m_inst->cell_index ());
|
||||
set_inactive (ia);
|
||||
set_all_of_instance (aoi);
|
||||
|
||||
m_trans = m_trans * m_inst->complex_trans (*m_inst_array);
|
||||
|
||||
// don't transform the world region, since transformation of that region might not work properly
|
||||
box_type new_region = box_type::world ();
|
||||
|
||||
// compute the region inside the new cell
|
||||
if (new_region != m_local_region_stack.front ()) {
|
||||
new_region = m_trans.inverted () * m_local_region_stack.front ();
|
||||
new_region &= cell ()->bbox ();
|
||||
}
|
||||
m_local_region_stack.push_back (new_region);
|
||||
|
||||
if (! m_local_complex_region_stack.empty ()) {
|
||||
|
||||
m_local_complex_region_stack.push_back (box_tree_type ());
|
||||
const box_tree_type &pcl = m_local_complex_region_stack.end ()[-2];
|
||||
|
||||
if (! new_region.empty ()) {
|
||||
|
||||
// compute a new, reduced complex region for use inside the new cell
|
||||
|
||||
db::CellInstArray::complex_trans_type tinst = m_inst->complex_trans (*m_inst_array);
|
||||
db::CellInstArray::complex_trans_type tinst_inv = tinst.inverted ();
|
||||
|
||||
db::Box bb;
|
||||
|
||||
for (box_tree_type::touching_iterator b = pcl.begin_touching (correct_box_overlapping (new_region.transformed (tinst)), db::box_convert<db::Box> ()); ! b.at_end (); ++b) {
|
||||
db::Box lb = (b->transformed (tinst_inv) & new_region);
|
||||
if (! lb.empty ()) {
|
||||
m_local_complex_region_stack.back ().insert (lb);
|
||||
bb += lb;
|
||||
}
|
||||
}
|
||||
|
||||
m_local_complex_region_stack.back ().sort (db::box_convert<db::Box> ());
|
||||
|
||||
// re-adjust the new local region, so we take into account additional clipping by the complex region.
|
||||
// in the extreme case, this box is empty:
|
||||
m_local_region_stack.back () = bb;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (receiver) {
|
||||
receiver->enter_cell (this, cell (), m_local_region_stack.back (), m_local_complex_region_stack.empty () ? 0 : &m_local_complex_region_stack.back ());
|
||||
}
|
||||
|
||||
new_cell (receiver);
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveInstanceIterator::up (RecursiveInstanceReceiver *receiver) const
|
||||
{
|
||||
if (receiver) {
|
||||
receiver->leave_cell (this, cell ());
|
||||
}
|
||||
|
||||
m_inst = m_inst_iterators.back ();
|
||||
m_inst_array = m_inst_array_iterators.back ();
|
||||
m_inst_quad_id = m_inst_quad_id_stack.back ();
|
||||
m_inst_iterators.pop_back ();
|
||||
m_inst_array_iterators.pop_back ();
|
||||
m_inst_quad_id_stack.pop_back ();
|
||||
|
||||
m_trans = m_trans_stack.back ();
|
||||
m_trans_stack.pop_back ();
|
||||
mp_cell = m_cells.back ();
|
||||
m_cells.pop_back ();
|
||||
m_local_region_stack.pop_back ();
|
||||
if (! m_local_complex_region_stack.empty ()) {
|
||||
m_local_complex_region_stack.pop_back ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveInstanceIterator::new_cell (RecursiveInstanceReceiver *receiver) const
|
||||
{
|
||||
bool new_cell_inactive = is_child_inactive (cell_index ());
|
||||
if (is_inactive () != new_cell_inactive) {
|
||||
set_inactive (new_cell_inactive);
|
||||
}
|
||||
|
||||
m_inst = cell ()->begin_touching (correct_box_overlapping (m_local_region_stack.back ()));
|
||||
|
||||
m_inst_quad_id = 0;
|
||||
|
||||
// skip instance quad if possible
|
||||
if (! m_local_complex_region_stack.empty ()) {
|
||||
skip_inst_iter_for_complex_region ();
|
||||
}
|
||||
|
||||
new_inst (receiver);
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveInstanceIterator::new_inst (RecursiveInstanceReceiver *receiver) const
|
||||
{
|
||||
// look for the next instance with a non-empty array iterator. The array iterator can be empty because we
|
||||
// use a lookup region.
|
||||
while (! m_inst.at_end ()) {
|
||||
|
||||
// skip instance quad if possible
|
||||
if (! m_local_complex_region_stack.empty ()) {
|
||||
skip_inst_iter_for_complex_region ();
|
||||
if (m_inst.at_end ()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool all_of_instance = false;
|
||||
bool with_region = false;
|
||||
|
||||
if (m_local_region_stack.back () != box_type::world () && ! m_inst->cell_inst ().bbox (m_box_convert).inside (m_local_region_stack.back ())) {
|
||||
with_region = true;
|
||||
} else {
|
||||
// TODO: optimization potential: only report all_of_instance == false, if not entirely within the complex region
|
||||
all_of_instance = m_local_complex_region_stack.empty ();
|
||||
}
|
||||
|
||||
RecursiveInstanceReceiver::new_inst_mode ni = RecursiveInstanceReceiver::NI_all;
|
||||
if (receiver) {
|
||||
ni = receiver->new_inst (this, m_inst->cell_inst (), m_local_region_stack.back (), m_local_complex_region_stack.empty () ? 0 : &m_local_complex_region_stack.back (), all_of_instance);
|
||||
}
|
||||
|
||||
if (ni == RecursiveInstanceReceiver::NI_skip) {
|
||||
m_inst_array = inst_array_iterator ();
|
||||
} else if (ni == RecursiveInstanceReceiver::NI_single) {
|
||||
// a singular iterator
|
||||
m_inst_array = db::CellInstArray::iterator (m_inst->cell_inst ().front (), false);
|
||||
} else if (with_region) {
|
||||
m_inst_array = m_inst->cell_inst ().begin_touching (correct_box_overlapping (m_local_region_stack.back ()), m_box_convert);
|
||||
} else {
|
||||
m_inst_array = m_inst->cell_inst ().begin ();
|
||||
}
|
||||
|
||||
set_all_of_instance (all_of_instance);
|
||||
|
||||
new_inst_member (receiver);
|
||||
|
||||
if (! m_inst_array.at_end ()) {
|
||||
break;
|
||||
} else {
|
||||
++m_inst;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveInstanceIterator::new_inst_member (RecursiveInstanceReceiver *receiver) const
|
||||
{
|
||||
if (! m_local_complex_region_stack.empty ()) {
|
||||
|
||||
// skip instance array members not part of the complex region
|
||||
while (! m_inst_array.at_end ()) {
|
||||
db::Box ia_box = m_inst->complex_trans (*m_inst_array) * m_box_convert (m_inst->cell_inst ().object ());
|
||||
if (! is_outside_complex_region (ia_box)) {
|
||||
break;
|
||||
} else {
|
||||
++m_inst_array;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
while (! m_inst_array.at_end () && receiver) {
|
||||
if (receiver->new_inst_member (this, m_inst->cell_inst (), m_inst->complex_trans (*m_inst_array), m_local_region_stack.back (), m_local_complex_region_stack.empty () ? 0 : &m_local_complex_region_stack.back (), is_all_of_instance ())) {
|
||||
break;
|
||||
} else {
|
||||
++m_inst_array;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RecursiveInstanceIterator::box_type
|
||||
RecursiveInstanceIterator::correct_box_overlapping (const box_type &box) const
|
||||
{
|
||||
if (! m_overlapping) {
|
||||
return box;
|
||||
} else if (box.empty () || box == box_type::world ()) {
|
||||
return box;
|
||||
} else if (box.width () < 2 || box.height () < 2) {
|
||||
return box;
|
||||
} else {
|
||||
return box.enlarged (box_type::vector_type (-1, -1));
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
RecursiveInstanceIterator::is_outside_complex_region (const box_type &box) const
|
||||
{
|
||||
if (m_overlapping) {
|
||||
return m_local_complex_region_stack.back ().begin_overlapping (box, db::box_convert<box_type> ()).at_end ();
|
||||
} else {
|
||||
return m_local_complex_region_stack.back ().begin_touching (box, db::box_convert<box_type> ()).at_end ();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
RecursiveInstanceIterator::is_child_inactive (db::cell_index_type new_child) const
|
||||
{
|
||||
bool inactive = is_inactive ();
|
||||
if (! m_start.empty () && m_start.find (new_child) != m_start.end ()) {
|
||||
inactive = false;
|
||||
} else if (! m_stop.empty () && m_stop.find (new_child) != m_stop.end ()) {
|
||||
inactive = true;
|
||||
}
|
||||
return inactive;
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveInstanceIterator::push (RecursiveInstanceReceiver *receiver)
|
||||
{
|
||||
// force reset so we can validate with a receiver
|
||||
reset ();
|
||||
|
||||
receiver->begin (this);
|
||||
|
||||
try {
|
||||
|
||||
validate (receiver);
|
||||
|
||||
while (! at_end ()) {
|
||||
next (receiver);
|
||||
}
|
||||
|
||||
receiver->end (this);
|
||||
|
||||
} catch (...) {
|
||||
|
||||
receiver->end (this);
|
||||
throw;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,713 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2021 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef HDR_dbRecursiveInstanceIterator
|
||||
#define HDR_dbRecursiveInstanceIterator
|
||||
|
||||
#include "dbCommon.h"
|
||||
|
||||
#include "dbLayout.h"
|
||||
#include "dbInstElement.h"
|
||||
#include "tlAssert.h"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
class Region;
|
||||
class RecursiveInstanceReceiver;
|
||||
|
||||
/**
|
||||
* @brief An iterator delivering shapes that touch or overlap the given region recursively
|
||||
*
|
||||
* The iterator can be constructed from a layout, a cell and a region.
|
||||
* It simplifies retrieval of instances from a geometrical region while considering
|
||||
* subcells as well.
|
||||
* Some options can be specified, i.e. the level to which to look into or which cells
|
||||
* to select.
|
||||
*
|
||||
* The general iteration scheme is iterating is depth-first and child instances before parent instances.
|
||||
*/
|
||||
class DB_PUBLIC RecursiveInstanceIterator
|
||||
{
|
||||
public:
|
||||
typedef db::Layout layout_type;
|
||||
typedef db::Box box_type;
|
||||
typedef db::Region region_type;
|
||||
typedef db::Cell cell_type;
|
||||
typedef db::Cell::touching_iterator inst_iterator;
|
||||
typedef db::CellInstArray::iterator inst_array_iterator;
|
||||
typedef db::Instances::overlapping_iterator overlapping_instance_iterator;
|
||||
typedef db::Instances::touching_iterator touching_instance_iterator;
|
||||
typedef db::Instance instance_type;
|
||||
typedef db::InstElement instance_element_type;
|
||||
typedef db::ICplxTrans cplx_trans_type;
|
||||
typedef instance_element_type value_type;
|
||||
typedef db::box_tree<db::Box, db::Box, db::box_convert<db::Box>, 20, 20> box_tree_type;
|
||||
|
||||
/**
|
||||
* @brief Default constructor
|
||||
*/
|
||||
RecursiveInstanceIterator ();
|
||||
|
||||
/**
|
||||
* @brief Copy constructor
|
||||
*/
|
||||
RecursiveInstanceIterator (const RecursiveInstanceIterator &d);
|
||||
|
||||
/**
|
||||
* @brief Assignment
|
||||
*/
|
||||
RecursiveInstanceIterator &operator= (const RecursiveInstanceIterator &d);
|
||||
|
||||
/**
|
||||
* @brief Standard constructor
|
||||
*
|
||||
* @param layout The layout from which to get the cell hierarchy
|
||||
* @param cell The starting cell
|
||||
* @param region The region from which to select the instances
|
||||
* @param overlapping Specify overlapping mode
|
||||
*
|
||||
* By default the iterator operates in touching mode - i.e. instances that touch the given region
|
||||
* are returned. By specifying the "overlapping" flag with a true value, the iterator delivers instances that
|
||||
* overlap the given region by at least one database unit.
|
||||
* The cell instances are selected according to their overall bounding box.
|
||||
*/
|
||||
RecursiveInstanceIterator (const layout_type &layout, const cell_type &cell, const box_type ®ion, bool overlapping = false);
|
||||
|
||||
/**
|
||||
* @brief Standard constructor
|
||||
*
|
||||
* @param layout The layout from which to get the cell hierarchy
|
||||
* @param cell The starting cell
|
||||
* @param region The complex region from which to select the shapes
|
||||
* @param overlapping Specify overlapping mode
|
||||
*
|
||||
* By default the iterator operates in touching mode - i.e. instances that touch the given region
|
||||
* are returned. By specifying the "overlapping" flag with a true value, the iterator delivers instances that
|
||||
* overlap the given region by at least one database unit.
|
||||
* The cell instances are selected according to their overall bounding box.
|
||||
* This version offers a complex search region instead of a simple box.
|
||||
*/
|
||||
RecursiveInstanceIterator (const layout_type &layout, const cell_type &cell, const region_type ®ion, bool overlapping = false);
|
||||
|
||||
/**
|
||||
* @brief Standard constructor for "overall" iteration
|
||||
*
|
||||
* This iterator delivers all instances recursively.
|
||||
*
|
||||
* @param layout The layout from which to get the cell hierarchy
|
||||
* @param cell The starting cell
|
||||
*/
|
||||
RecursiveInstanceIterator (const layout_type &layout, const cell_type &cell);
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~RecursiveInstanceIterator ();
|
||||
|
||||
/**
|
||||
* @brief Specify the maximum hierarchy depth to look into
|
||||
*
|
||||
* A depth of 0 instructs the iterator to deliver only instances from the initial cell.
|
||||
* A higher depth instructs the iterator to look deeper.
|
||||
* The depth must be specified before the instances are being retrieved.
|
||||
*/
|
||||
void max_depth (int depth)
|
||||
{
|
||||
if (m_max_depth != depth) {
|
||||
m_max_depth = depth;
|
||||
m_needs_reinit = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the maximum hierarchy depth to search for
|
||||
*/
|
||||
int max_depth () const
|
||||
{
|
||||
return m_max_depth;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Specify the minimum hierarchy depth to look into
|
||||
*
|
||||
* A depth of 0 instructs the iterator to deliver instance from the top level and below.
|
||||
* 1 instructs to deliver instance from the first child level.
|
||||
* The minimum depth must be specified before the instances are being retrieved.
|
||||
*/
|
||||
void min_depth (int depth)
|
||||
{
|
||||
if (m_min_depth != depth) {
|
||||
m_min_depth = depth;
|
||||
m_needs_reinit = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the minimum hierarchy depth to search for
|
||||
*/
|
||||
int min_depth () const
|
||||
{
|
||||
return m_min_depth;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the layout
|
||||
*/
|
||||
const layout_type *layout () const
|
||||
{
|
||||
return mp_layout;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the top cell
|
||||
*
|
||||
* The top cell is the cell with which the iterator was started
|
||||
*/
|
||||
const cell_type *top_cell () const
|
||||
{
|
||||
return mp_top_cell;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the basic region the iterator is using (will be world if none is set)
|
||||
* In addition to the basic region, a complex region may be defined that is further confining the
|
||||
* search to a subregion of the basic region.
|
||||
*/
|
||||
const box_type ®ion () const
|
||||
{
|
||||
return m_region;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if a complex region is given
|
||||
*/
|
||||
bool has_complex_region () const
|
||||
{
|
||||
return mp_complex_region.get () != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the complex region the iterator is using
|
||||
*/
|
||||
const region_type &complex_region () const
|
||||
{
|
||||
tl_assert (mp_complex_region.get ());
|
||||
return *mp_complex_region;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the region to a basic rectangle
|
||||
* This will reset the iterator.
|
||||
*/
|
||||
void set_region (const box_type ®ion);
|
||||
|
||||
/**
|
||||
* @brief Sets a complex search region
|
||||
* This will reset the iterator to the beginning.
|
||||
*/
|
||||
void set_region (const region_type ®ion);
|
||||
|
||||
/**
|
||||
* @brief Confines the search further to the given rectangle.
|
||||
* This will reset the iterator and confine the search to the given rectangle
|
||||
* in addition to any region or complex region already defined.
|
||||
*/
|
||||
void confine_region (const box_type ®ion);
|
||||
|
||||
/**
|
||||
* @brief Confines the search further to the given complex region.
|
||||
* This will reset the iterator and confine the search to the given region
|
||||
* in addition to any simple region or complex region already defined.
|
||||
*/
|
||||
void confine_region (const region_type ®ion);
|
||||
|
||||
/**
|
||||
* @brief Gets a flag indicating whether overlapping instances are selected when a region is used
|
||||
*/
|
||||
bool overlapping () const
|
||||
{
|
||||
return m_overlapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets a flag indicating whether overlapping instances are selected when a region is used
|
||||
*/
|
||||
void set_overlapping (bool f)
|
||||
{
|
||||
if (m_overlapping != f) {
|
||||
m_overlapping = f;
|
||||
m_needs_reinit = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset the iterator
|
||||
*/
|
||||
void reset ()
|
||||
{
|
||||
m_needs_reinit = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the selected target cells
|
||||
*
|
||||
* Only instances of cells in the targets set are reported.
|
||||
* By default the iterator is configured to deliver all instances.
|
||||
* By using "set_targets" with a set of cell indexes, the reporting
|
||||
* can be confined to certain cells only. To enable all-cell reporting
|
||||
* use "enable_all_targets".
|
||||
*
|
||||
* "all_targets_enabled" can be used to check which mode is used.
|
||||
*/
|
||||
const std::set<db::cell_index_type> &targets () const
|
||||
{
|
||||
return m_targets;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets a flags indicating whether all targets are selected
|
||||
* See \targets for more details.
|
||||
*/
|
||||
bool all_targets_enabled () const
|
||||
{
|
||||
return m_all_targets;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Selects all target cells
|
||||
* See \targets for more details.
|
||||
*/
|
||||
void enable_all_targets ();
|
||||
|
||||
/**
|
||||
* @brief Selects the given targets
|
||||
*
|
||||
* This will reset the "all_targets" flag to false.
|
||||
* See \targets for more details.
|
||||
*/
|
||||
void set_targets (const std::set<db::cell_index_type> &set_targets);
|
||||
|
||||
/**
|
||||
* @brief Select cells
|
||||
*
|
||||
* Cell selection allows confining the hierarchy traversal to subtrees of the
|
||||
* hierarchy tree. This happens by "selecting" and "unselecting" cells in the traversal path.
|
||||
* "selected" cells will make iterator traverse the tree below this cell while
|
||||
* "unselected" cells make the iterator ignore this cell.
|
||||
* Cells which are neither selected nor unselected will be traversed depending
|
||||
* on their parent's state. They are traversed if their parents are and are not traversed
|
||||
* if their parents are not.
|
||||
*
|
||||
* If no specific cells have been selected before, this method will confine the selection
|
||||
* to the given cells (plus their sub-hierarchy).
|
||||
* If cells have been selected before, this will add the given cells to the selection.
|
||||
*/
|
||||
void select_cells (const std::set<db::cell_index_type> &cells);
|
||||
|
||||
/**
|
||||
* @brief Select all cells
|
||||
*
|
||||
* Makes all cells selected. After doing so, all unselect_cells calls
|
||||
* will unselect only that specific cell without children.
|
||||
*
|
||||
* See \select_cells for more details.
|
||||
*/
|
||||
void select_all_cells ();
|
||||
|
||||
/**
|
||||
* @brief Unselect cells
|
||||
*
|
||||
* This method will remove the given cells (plus their sub-hierarchy) from the selection.
|
||||
*
|
||||
* See \select_cells for more details.
|
||||
*/
|
||||
void unselect_cells (const std::set<db::cell_index_type> &cells);
|
||||
|
||||
/**
|
||||
* @brief Unselect all cells
|
||||
*
|
||||
* Makes all cells unselected. After doing so, select_cells calls
|
||||
* will select only that specific cell without children.
|
||||
*
|
||||
* See \select_cells for more details.
|
||||
*/
|
||||
void unselect_all_cells ();
|
||||
|
||||
/**
|
||||
* @brief Resets the selection
|
||||
*
|
||||
* This will reset all selections and unselections.
|
||||
* After calling this methods, all select_cells will again select the cells
|
||||
* including their children.
|
||||
*
|
||||
* See \select_cells for more details.
|
||||
*/
|
||||
void reset_selection ();
|
||||
|
||||
/**
|
||||
* @brief Returns the cells in the "enable" selection
|
||||
*
|
||||
* Cells in this set make the iterator become active, while cells in the
|
||||
* disable selection make the iterator inactive. Only when active, the
|
||||
* iterator will deliver shapes.
|
||||
*/
|
||||
const std::set<db::cell_index_type> &enables () const
|
||||
{
|
||||
return m_start;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the cells in the "disable" selection
|
||||
*/
|
||||
const std::set<db::cell_index_type> &disables () const
|
||||
{
|
||||
return m_stop;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the current transformation by which the instances must be transformed into the initial cell
|
||||
*
|
||||
* The instances delivered are not transformed. Instead, this transformation must be applied to
|
||||
* get the instance in the coordinate system of the top cell.
|
||||
*/
|
||||
const cplx_trans_type &trans () const
|
||||
{
|
||||
validate (0);
|
||||
return m_trans;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the current depth
|
||||
*
|
||||
* Returns the number of hierarchy levels we are below top level currently.
|
||||
*/
|
||||
unsigned int depth () const
|
||||
{
|
||||
validate (0);
|
||||
return (unsigned int) m_trans_stack.size ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the current instance
|
||||
*
|
||||
* Returns the instance currently referred to by the recursive iterator.
|
||||
* This instance is not transformed yet and is located in the current cell.
|
||||
*/
|
||||
instance_element_type instance () const
|
||||
{
|
||||
return *operator-> ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Access operator
|
||||
*
|
||||
* The access operator is identical to the instance method.
|
||||
*/
|
||||
instance_element_type operator* () const
|
||||
{
|
||||
return *operator-> ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Access (arrow) operator
|
||||
*
|
||||
* The access operator is identical to the instance method.
|
||||
*/
|
||||
const instance_element_type *operator-> () const;
|
||||
|
||||
/**
|
||||
* @brief End of iterator predicate
|
||||
*
|
||||
* Returns true, if the iterator is at the end of the sequence
|
||||
*/
|
||||
bool at_end () const;
|
||||
|
||||
/**
|
||||
* @brief Gets the current cell's index
|
||||
*/
|
||||
db::cell_index_type cell_index () const
|
||||
{
|
||||
return cell ()->cell_index ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the current cell's reference
|
||||
*/
|
||||
const cell_type *cell () const
|
||||
{
|
||||
validate (0);
|
||||
size_t c = reinterpret_cast<size_t> (mp_cell);
|
||||
return reinterpret_cast<const cell_type *> (c - (c & size_t (3)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Increments the iterator (operator version)
|
||||
*/
|
||||
RecursiveInstanceIterator &operator++()
|
||||
{
|
||||
next (0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Increments the iterator
|
||||
*/
|
||||
void next ()
|
||||
{
|
||||
next (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Comparison of iterators - equality
|
||||
*/
|
||||
bool operator==(const RecursiveInstanceIterator &d) const
|
||||
{
|
||||
if (at_end () != d.at_end ()) {
|
||||
return false;
|
||||
} else if (at_end ()) {
|
||||
return true;
|
||||
} else {
|
||||
return (*m_inst == *d.m_inst);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Comparison of iterators - inequality
|
||||
*/
|
||||
bool operator!=(const RecursiveInstanceIterator &d) const
|
||||
{
|
||||
return !operator==(d);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The instance path
|
||||
*/
|
||||
std::vector<instance_element_type> path () const;
|
||||
|
||||
/**
|
||||
* @brief Push-mode delivery
|
||||
*
|
||||
* This method will deliver all instances to the given receiver.
|
||||
* In contrast to pull mode, this method allows tailoring the
|
||||
* traversal of the hierarchy tree during iteration.
|
||||
* For this purpose, the receiver has methods that receive
|
||||
* events and to some extend may modify the traversal (e.g.
|
||||
* return value of enter_cell).
|
||||
*
|
||||
* See RecursiveInstanceReceiver class for more details.
|
||||
*/
|
||||
void push (RecursiveInstanceReceiver *receiver);
|
||||
|
||||
/**
|
||||
* @brief Returns a value indicating whether the current cell is inactive (disabled)
|
||||
*/
|
||||
bool is_inactive () const
|
||||
{
|
||||
return (reinterpret_cast<size_t> (mp_cell) & size_t (1)) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns a value indicating whether a new child cell of the current cell will be inactive
|
||||
*/
|
||||
bool is_child_inactive (db::cell_index_type new_child) const;
|
||||
|
||||
private:
|
||||
int m_max_depth;
|
||||
int m_min_depth;
|
||||
bool m_overlapping;
|
||||
std::set<db::cell_index_type> m_start, m_stop;
|
||||
std::set<db::cell_index_type> m_targets;
|
||||
bool m_all_targets;
|
||||
|
||||
const layout_type *mp_layout;
|
||||
const cell_type *mp_top_cell;
|
||||
|
||||
box_type m_region;
|
||||
std::unique_ptr<region_type> mp_complex_region;
|
||||
db::box_convert<db::CellInst> m_box_convert;
|
||||
|
||||
mutable inst_iterator m_inst;
|
||||
mutable inst_array_iterator m_inst_array;
|
||||
mutable instance_element_type m_combined_instance;
|
||||
mutable std::map<db::cell_index_type, bool> m_empty_cells_cache;
|
||||
mutable const cell_type *mp_cell;
|
||||
mutable cplx_trans_type m_trans;
|
||||
mutable std::vector<cplx_trans_type> m_trans_stack;
|
||||
mutable std::vector<inst_iterator> m_inst_iterators;
|
||||
mutable std::vector<inst_array_iterator> m_inst_array_iterators;
|
||||
mutable std::vector<const cell_type *> m_cells;
|
||||
mutable std::vector<box_tree_type> m_local_complex_region_stack;
|
||||
mutable std::vector<box_type> m_local_region_stack;
|
||||
mutable bool m_needs_reinit;
|
||||
mutable size_t m_inst_quad_id;
|
||||
mutable std::vector<size_t> m_inst_quad_id_stack;
|
||||
mutable std::set<db::cell_index_type> m_target_tree;
|
||||
|
||||
void init ();
|
||||
void init_region (const region_type ®ion);
|
||||
void init_region (const box_type ®ion);
|
||||
void skip_inst_iter_for_complex_region () const;
|
||||
void validate (RecursiveInstanceReceiver *receiver) const;
|
||||
void next (RecursiveInstanceReceiver *receiver);
|
||||
bool needs_visit () const;
|
||||
void next_instance (RecursiveInstanceReceiver *receiver) const;
|
||||
void new_inst (RecursiveInstanceReceiver *receiver) const;
|
||||
void new_inst_member (RecursiveInstanceReceiver *receiver) const;
|
||||
void new_cell (RecursiveInstanceReceiver *receiver) const;
|
||||
void up (RecursiveInstanceReceiver *receiver) const;
|
||||
void down (RecursiveInstanceReceiver *receiver) const;
|
||||
|
||||
bool is_outside_complex_region (const box_type &box) const;
|
||||
box_type correct_box_overlapping (const box_type &box) const;
|
||||
|
||||
void set_inactive (bool a) const
|
||||
{
|
||||
size_t c = reinterpret_cast<size_t> (mp_cell);
|
||||
c -= (c & size_t (1));
|
||||
mp_cell = reinterpret_cast<const db::Cell *> (c + (a ? 1 : 0));
|
||||
}
|
||||
|
||||
bool is_all_of_instance () const
|
||||
{
|
||||
return (reinterpret_cast<size_t> (mp_cell) & size_t (2)) != 0;
|
||||
}
|
||||
|
||||
void set_all_of_instance (bool a) const
|
||||
{
|
||||
size_t c = reinterpret_cast<size_t> (mp_cell);
|
||||
c -= (c & size_t (2));
|
||||
mp_cell = reinterpret_cast<const db::Cell *> (c + (a ? 2 : 0));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A receiver interface for "push" mode
|
||||
*
|
||||
* In push mode, the iterator will deliver the instances and hierarchy transitions
|
||||
* to this interface. See "RecursiveInstanceIterator::push" for details about this
|
||||
* mode.
|
||||
*
|
||||
* The receiver receives events for the start of the delivery, on each cell
|
||||
* entry and on each instance (followed by a cell entry).
|
||||
*/
|
||||
class DB_PUBLIC RecursiveInstanceReceiver
|
||||
{
|
||||
public:
|
||||
typedef RecursiveInstanceIterator::box_tree_type box_tree_type;
|
||||
|
||||
/**
|
||||
* @brief See new_inst for details.
|
||||
*/
|
||||
enum new_inst_mode { NI_all = 0, NI_single = 1, NI_skip = 2 };
|
||||
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
RecursiveInstanceReceiver () { }
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
virtual ~RecursiveInstanceReceiver () { }
|
||||
|
||||
/**
|
||||
* @brief Called once when the iterator begins pushing
|
||||
*/
|
||||
virtual void begin (const RecursiveInstanceIterator * /*iter*/) { }
|
||||
|
||||
/**
|
||||
* @brief Called once after the iterator pushed everything
|
||||
*/
|
||||
virtual void end (const RecursiveInstanceIterator * /*iter*/) { }
|
||||
|
||||
/**
|
||||
* @brief Enters a cell
|
||||
*
|
||||
* This method is called when the recursive shape iterator
|
||||
* enters a new cell. It is not called for the top cell. When it is called, "iter->trans()"
|
||||
* will already be updated.
|
||||
*
|
||||
* @param iter The iterator
|
||||
* @param cell The cell which is entered
|
||||
* @param region The clip box as seen from "cell" or db::Box::world if there is no clip box
|
||||
* @param complex_region A complex clip region if one is supplied together with "region"
|
||||
*/
|
||||
virtual void enter_cell (const RecursiveInstanceIterator * /*iter*/, const db::Cell * /*cell*/, const db::Box & /*region*/, const box_tree_type * /*complex_region*/) { }
|
||||
|
||||
/**
|
||||
* @brief Leaves the current cell
|
||||
*
|
||||
* This method is the counterpart for "enter_cell". It is called when traversal of "cell" ended.
|
||||
*/
|
||||
virtual void leave_cell (const RecursiveInstanceIterator * /*iter*/, const db::Cell * /*cell*/) { }
|
||||
|
||||
/**
|
||||
* @brief Enters a new instance
|
||||
*
|
||||
* This method is called before "enter_cell" and "new_inst_member" is called and will indicate the instance to follow.
|
||||
* The sequence of events is
|
||||
*
|
||||
* new_inst(A)
|
||||
* new_inst_member(A[0,0])
|
||||
* enter_cell(A)
|
||||
* ...
|
||||
* leave_cell(A)
|
||||
* new_inst_member(A[1,0])
|
||||
* enter_cell(A)
|
||||
* ...
|
||||
* leave_cell(A)
|
||||
* ...
|
||||
* new_inst(B)
|
||||
* ...
|
||||
*
|
||||
* The "all" parameter is true, if all instances of the array will be addressed.
|
||||
*
|
||||
* This method can return the following values:
|
||||
* - NI_all: iterate all members through "new_inst_member"
|
||||
* - NI_single: iterate a single member (the first one)
|
||||
* - NI_skip: skips the whole array (not a single instance is iterated)
|
||||
*/
|
||||
virtual new_inst_mode new_inst (const RecursiveInstanceIterator * /*iter*/, const db::CellInstArray & /*inst*/, const db::Box & /*region*/, const box_tree_type * /*complex_region*/, bool /*all*/) { return NI_all; }
|
||||
|
||||
/**
|
||||
* @brief Enters a new array member of the instance
|
||||
*
|
||||
* See "new_inst" for a description. This method adds the "trans" parameter
|
||||
* which holds the complex transformation for this particular instance of
|
||||
* the array.
|
||||
*
|
||||
* "all" is true, if an instance array is iterated in "all" mode (see new_inst).
|
||||
*
|
||||
* If this method returns false, this array instance (but not the whole array) is skipped and the cell is not entered.
|
||||
*/
|
||||
virtual bool new_inst_member (const RecursiveInstanceIterator * /*iter*/, const db::CellInstArray & /*inst*/, const db::ICplxTrans & /*trans*/, const db::Box & /*region*/, const box_tree_type * /*complex_region*/, bool /*all*/) { return true; }
|
||||
};
|
||||
|
||||
} // namespace db
|
||||
|
||||
#endif
|
||||
|
|
@ -263,15 +263,15 @@ Region::rounded_corners (double rinner, double router, unsigned int n) const
|
|||
}
|
||||
|
||||
void
|
||||
Region::smooth (coord_type d)
|
||||
Region::smooth (coord_type d, bool keep_hv)
|
||||
{
|
||||
process (SmoothingProcessor (d));
|
||||
process (SmoothingProcessor (d, keep_hv));
|
||||
}
|
||||
|
||||
Region
|
||||
Region::smoothed (coord_type d) const
|
||||
Region::smoothed (coord_type d, bool keep_hv) const
|
||||
{
|
||||
return processed (SmoothingProcessor (d));
|
||||
return processed (SmoothingProcessor (d, keep_hv));
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -1518,14 +1518,14 @@ public:
|
|||
/**
|
||||
* @brief Smoothes the region (in-place)
|
||||
*/
|
||||
void smooth (coord_type d);
|
||||
void smooth (coord_type d, bool keep_hv);
|
||||
|
||||
/**
|
||||
* @brief Returns the smoothed region
|
||||
*
|
||||
* @param d The smoothing accuracy
|
||||
*/
|
||||
Region smoothed (coord_type d) const;
|
||||
Region smoothed (coord_type d, bool keep_hv) const;
|
||||
|
||||
/**
|
||||
* @brief Returns the nth polygon
|
||||
|
|
|
|||
|
|
@ -614,6 +614,34 @@ RectilinearFilter::vars () const
|
|||
return 0;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
// HoleCountFilter implementation
|
||||
|
||||
HoleCountFilter::HoleCountFilter (size_t min_count, size_t max_count, bool inverse)
|
||||
: m_min_count (min_count), m_max_count (max_count), m_inverse (inverse)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
bool
|
||||
HoleCountFilter::selected (const db::Polygon &poly) const
|
||||
{
|
||||
bool ok = poly.holes () < m_max_count && poly.holes () >= m_min_count;
|
||||
return ok != m_inverse;
|
||||
}
|
||||
|
||||
bool
|
||||
HoleCountFilter::selected (const db::PolygonRef &poly) const
|
||||
{
|
||||
bool ok = poly.obj ().holes () < m_max_count && poly.obj ().holes () >= m_min_count;
|
||||
return ok != m_inverse;
|
||||
}
|
||||
|
||||
const TransformationReducer *HoleCountFilter::vars () const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
// RectilinearFilter implementation
|
||||
|
||||
|
|
@ -840,14 +868,14 @@ StrangePolygonCheckProcessor::process (const db::Polygon &poly, std::vector<db::
|
|||
// -------------------------------------------------------------------------------------------------------------
|
||||
// Smoothing processor
|
||||
|
||||
SmoothingProcessor::SmoothingProcessor (db::Coord d) : m_d (d) { }
|
||||
SmoothingProcessor::SmoothingProcessor (db::Coord d, bool keep_hv) : m_d (d), m_keep_hv (keep_hv) { }
|
||||
|
||||
SmoothingProcessor::~SmoothingProcessor () { }
|
||||
|
||||
void
|
||||
SmoothingProcessor::process (const db::Polygon &poly, std::vector<db::Polygon> &res) const
|
||||
{
|
||||
res.push_back (db::smooth (poly, m_d));
|
||||
res.push_back (db::smooth (poly, m_d, m_keep_hv));
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -286,6 +286,51 @@ private:
|
|||
bool m_inverse;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Filters by number of holes
|
||||
*
|
||||
* This filter will select all polygons with a hole count between min_holes and max_holes (exclusively)
|
||||
*/
|
||||
|
||||
struct DB_PUBLIC HoleCountFilter
|
||||
: public AllMustMatchFilter
|
||||
{
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param inverse If set to true, only polygons not matching this criterion will be filtered
|
||||
*/
|
||||
HoleCountFilter (size_t min_count, size_t max_count, bool inverse);
|
||||
|
||||
/**
|
||||
* @brief Returns true if the polygon is a rectangle
|
||||
*/
|
||||
virtual bool selected (const db::Polygon &poly) const;
|
||||
|
||||
/**
|
||||
* @brief Returns true if the polygon is a rectangle
|
||||
*/
|
||||
virtual bool selected (const db::PolygonRef &poly) const;
|
||||
|
||||
/**
|
||||
* @brief This filter does not need variants
|
||||
*/
|
||||
virtual const TransformationReducer *vars () const;
|
||||
|
||||
/**
|
||||
* @brief This filter prefers producing variants
|
||||
*/
|
||||
virtual bool wants_variants () const { return true; }
|
||||
|
||||
/**
|
||||
* @brief This filter wants merged input
|
||||
*/
|
||||
virtual bool requires_raw_input () const { return false; }
|
||||
|
||||
private:
|
||||
size_t m_min_count, m_max_count;
|
||||
bool m_inverse;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A bounding box filter for use with Region::filter or Region::filtered
|
||||
*
|
||||
|
|
@ -459,7 +504,7 @@ class DB_PUBLIC SmoothingProcessor
|
|||
: public PolygonProcessorBase
|
||||
{
|
||||
public:
|
||||
SmoothingProcessor (db::Coord d);
|
||||
SmoothingProcessor (db::Coord d, bool keep_hv);
|
||||
~SmoothingProcessor ();
|
||||
|
||||
virtual void process (const db::Polygon &poly, std::vector<db::Polygon> &res) const;
|
||||
|
|
@ -472,6 +517,7 @@ public:
|
|||
|
||||
private:
|
||||
db::Coord m_d;
|
||||
bool m_keep_hv;
|
||||
db::MagnificationReducer m_vars;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@
|
|||
#include "dbCellMapping.h"
|
||||
#include "dbPCellDeclaration.h"
|
||||
#include "dbSaveLayoutOptions.h"
|
||||
#include "dbRecursiveShapeIterator.h"
|
||||
#include "dbRecursiveInstanceIterator.h"
|
||||
#include "dbWriter.h"
|
||||
#include "dbHash.h"
|
||||
#include "tlStream.h"
|
||||
|
|
@ -1204,6 +1206,56 @@ begin_shapes_rec_overlapping_um (const db::Cell *cell, unsigned int layer, db::D
|
|||
return db::RecursiveShapeIterator (*layout, *cell, layer, db::CplxTrans (layout->dbu ()).inverted () * region, true);
|
||||
}
|
||||
|
||||
static db::RecursiveInstanceIterator
|
||||
begin_instances_rec (const db::Cell *cell)
|
||||
{
|
||||
const db::Layout *layout = cell->layout ();
|
||||
if (! layout) {
|
||||
throw tl::Exception (tl::to_string (tr ("Cell is not inside layout")));
|
||||
}
|
||||
return db::RecursiveInstanceIterator (*layout, *cell);
|
||||
}
|
||||
|
||||
static db::RecursiveInstanceIterator
|
||||
begin_instances_rec_touching (const db::Cell *cell, db::Box region)
|
||||
{
|
||||
const db::Layout *layout = cell->layout ();
|
||||
if (! layout) {
|
||||
throw tl::Exception (tl::to_string (tr ("Cell is not inside layout")));
|
||||
}
|
||||
return db::RecursiveInstanceIterator (*layout, *cell, region, false);
|
||||
}
|
||||
|
||||
static db::RecursiveInstanceIterator
|
||||
begin_instances_rec_touching_um (const db::Cell *cell, db::DBox region)
|
||||
{
|
||||
const db::Layout *layout = cell->layout ();
|
||||
if (! layout) {
|
||||
throw tl::Exception (tl::to_string (tr ("Cell is not inside layout")));
|
||||
}
|
||||
return db::RecursiveInstanceIterator (*layout, *cell, db::CplxTrans (layout->dbu ()).inverted () * region, false);
|
||||
}
|
||||
|
||||
static db::RecursiveInstanceIterator
|
||||
begin_instances_rec_overlapping (const db::Cell *cell, db::Box region)
|
||||
{
|
||||
const db::Layout *layout = cell->layout ();
|
||||
if (! layout) {
|
||||
throw tl::Exception (tl::to_string (tr ("Cell is not inside layout")));
|
||||
}
|
||||
return db::RecursiveInstanceIterator (*layout, *cell, region, true);
|
||||
}
|
||||
|
||||
static db::RecursiveInstanceIterator
|
||||
begin_instances_rec_overlapping_um (const db::Cell *cell, db::DBox region)
|
||||
{
|
||||
const db::Layout *layout = cell->layout ();
|
||||
if (! layout) {
|
||||
throw tl::Exception (tl::to_string (tr ("Cell is not inside layout")));
|
||||
}
|
||||
return db::RecursiveInstanceIterator (*layout, *cell, db::CplxTrans (layout->dbu ()).inverted () * region, true);
|
||||
}
|
||||
|
||||
static void copy_shapes2 (db::Cell *cell, const db::Cell &source_cell, const db::LayerMapping &layer_mapping)
|
||||
{
|
||||
cell->copy_shapes (source_cell, layer_mapping);
|
||||
|
|
@ -1833,6 +1885,54 @@ Class<db::Cell> decl_Cell ("db", "Cell",
|
|||
"\n"
|
||||
"This variant has been added in version 0.25.\n"
|
||||
) +
|
||||
gsi::method_ext ("begin_instances_rec", &begin_instances_rec,
|
||||
"@brief Delivers a recursive instance iterator for the instances below the cell\n"
|
||||
"@return A suitable iterator\n"
|
||||
"\n"
|
||||
"For details see the description of the \\RecursiveInstanceIterator class.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.27.\n"
|
||||
) +
|
||||
gsi::method_ext ("begin_instances_rec_touching", &begin_instances_rec_touching, gsi::arg ("region"),
|
||||
"@brief Delivers a recursive instance iterator for the instances below the cell\n"
|
||||
"@param region The search region\n"
|
||||
"@return A suitable iterator\n"
|
||||
"\n"
|
||||
"For details see the description of the \\RecursiveInstanceIterator class.\n"
|
||||
"This version gives an iterator delivering instances whose bounding box touches the given region.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.27.\n"
|
||||
) +
|
||||
gsi::method_ext ("begin_instances_rec_touching", &begin_instances_rec_touching_um, gsi::arg ("region"),
|
||||
"@brief Delivers a recursive instance iterator for the instances below the cell using a region search, with the region given in micrometer units\n"
|
||||
"@param region The search region as \\DBox object in micrometer units\n"
|
||||
"@return A suitable iterator\n"
|
||||
"\n"
|
||||
"For details see the description of the \\RecursiveInstanceIterator class.\n"
|
||||
"This version gives an iterator delivering instances whose bounding box touches the given region.\n"
|
||||
"\n"
|
||||
"This variant has been added in version 0.27.\n"
|
||||
) +
|
||||
gsi::method_ext ("begin_instances_rec_overlapping", &begin_instances_rec_overlapping, gsi::arg ("region"),
|
||||
"@brief Delivers a recursive instance iterator for the instances below the cell using a region search\n"
|
||||
"@param region The search region\n"
|
||||
"@return A suitable iterator\n"
|
||||
"\n"
|
||||
"For details see the description of the \\RecursiveInstanceIterator class.\n"
|
||||
"This version gives an iterator delivering instances whose bounding box overlaps the given region.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.27.\n"
|
||||
) +
|
||||
gsi::method_ext ("begin_instances_rec_overlapping", &begin_instances_rec_overlapping_um, gsi::arg ("region"),
|
||||
"@brief Delivers a recursive instance iterator for the instances below the cell using a region search, with the region given in micrometer units\n"
|
||||
"@param region The search region as \\DBox object in micrometer units\n"
|
||||
"@return A suitable iterator\n"
|
||||
"\n"
|
||||
"For details see the description of the \\RecursiveInstanceIterator class.\n"
|
||||
"This version gives an iterator delivering instances whose bounding box overlaps the given region.\n"
|
||||
"\n"
|
||||
"This variant has been added in version 0.27.\n"
|
||||
) +
|
||||
gsi::method_ext ("copy_shapes", ©_shapes1, gsi::arg ("source_cell"),
|
||||
"@brief Copies the shapes from the given cell into this cell\n"
|
||||
"@param source_cell The cell from where to copy shapes\n"
|
||||
|
|
|
|||
|
|
@ -185,10 +185,10 @@ static db::CompoundRegionOperationNode *new_strange_polygons_filter (db::Compoun
|
|||
return new db::CompoundRegionProcessingOperationNode (new db::StrangePolygonCheckProcessor (), input, true /*processor is owned*/);
|
||||
}
|
||||
|
||||
static db::CompoundRegionOperationNode *new_smoothed (db::CompoundRegionOperationNode *input, db::Coord d)
|
||||
static db::CompoundRegionOperationNode *new_smoothed (db::CompoundRegionOperationNode *input, db::Coord d, bool keep_hv)
|
||||
{
|
||||
check_non_null (input, "input");
|
||||
return new db::CompoundRegionProcessingOperationNode (new db::SmoothingProcessor (d), input, true /*processor is owned*/, d);
|
||||
return new db::CompoundRegionProcessingOperationNode (new db::SmoothingProcessor (d, keep_hv), input, true /*processor is owned*/, d);
|
||||
}
|
||||
|
||||
static db::CompoundRegionOperationNode *new_rounded_corners (db::CompoundRegionOperationNode *input, double rinner, double router, unsigned int n)
|
||||
|
|
@ -466,6 +466,12 @@ static db::CompoundRegionOperationNode *new_perimeter_sum_filter (db::CompoundRe
|
|||
return new db::CompoundRegionFilterOperationNode (new db::RegionPerimeterFilter (pmin, pmax, inverse), input, true, true /*sum of set*/);
|
||||
}
|
||||
|
||||
static db::CompoundRegionOperationNode *new_hole_count_filter (db::CompoundRegionOperationNode *input, bool inverse, size_t hmin, size_t hmax)
|
||||
{
|
||||
check_non_null (input, "input");
|
||||
return new db::CompoundRegionFilterOperationNode (new db::HoleCountFilter (hmin, hmax, inverse), input, true);
|
||||
}
|
||||
|
||||
static db::CompoundRegionOperationNode *new_area_filter (db::CompoundRegionOperationNode *input, bool inverse, db::coord_traits<db::Coord>::area_type amin, db::coord_traits<db::Coord>::area_type amax)
|
||||
{
|
||||
check_non_null (input, "input");
|
||||
|
|
@ -566,9 +572,10 @@ Class<db::CompoundRegionOperationNode> decl_CompoundRegionOperationNode ("db", "
|
|||
"@brief Creates a node extracting strange polygons.\n"
|
||||
"'strange polygons' are ones which cannot be oriented - e.g. '8' shape polygons."
|
||||
) +
|
||||
gsi::constructor ("new_smoothed", &new_smoothed, gsi::arg ("input"), gsi::arg ("d"),
|
||||
gsi::constructor ("new_smoothed", &new_smoothed, gsi::arg ("input"), gsi::arg ("d"), gsi::arg ("keep_hv", false),
|
||||
"@brief Creates a node smoothing the polygons.\n"
|
||||
"@param d The tolerance to be applied for the smoothing."
|
||||
"@param d The tolerance to be applied for the smoothing.\n"
|
||||
"@param keep_hv If true, horizontal and vertical edges are maintained.\n"
|
||||
) +
|
||||
gsi::constructor ("new_rounded_corners", &new_rounded_corners, gsi::arg ("input"), gsi::arg ("rinner"), gsi::arg ("router"), gsi::arg ("n"),
|
||||
"@brief Creates a node generating rounded corners.\n"
|
||||
|
|
@ -672,6 +679,11 @@ Class<db::CompoundRegionOperationNode> decl_CompoundRegionOperationNode ("db", "
|
|||
"@brief Creates a node filtering the input by area sum.\n"
|
||||
"Like \\new_area_filter, but applies to the sum of all shapes in the current set.\n"
|
||||
) +
|
||||
gsi::constructor ("new_hole_count_filter", &new_hole_count_filter, gsi::arg ("input"), gsi::arg ("inverse", false), gsi::arg ("hmin", 0), gsi::arg ("hmax", std::numeric_limits<size_t>::max (), "max"),
|
||||
"@brief Creates a node filtering the input by number of holes per polygon.\n"
|
||||
"This node renders the input if the hole count is between hmin and hmax (exclusively). If 'inverse' is set to true, the "
|
||||
"input shape is returned if the hole count is less than hmin (exclusively) or larger than hmax (inclusively)."
|
||||
) +
|
||||
gsi::constructor ("new_bbox_filter", &new_bbox_filter, gsi::arg ("input"), gsi::arg ("parameter"), gsi::arg ("inverse", false), gsi::arg ("pmin", 0), gsi::arg ("pmax", std::numeric_limits<db::coord_traits<db::Coord>::area_type>::max (), "max"),
|
||||
"@brief Creates a node filtering the input by bounding box parameters.\n"
|
||||
"This node renders the input if the specified bounding box parameter of the input shape is between pmin and pmax (exclusively). If 'inverse' is set to true, the "
|
||||
|
|
|
|||
|
|
@ -1716,9 +1716,11 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
|||
"For details see the description of the \\RecursiveShapeIterator class.\n"
|
||||
"This version is convenience overload which takes a cell object instead of a cell index.\n"
|
||||
"\n"
|
||||
"This method is deprecated. Use \\Cell#begin_shapes_rec instead.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.24.\n"
|
||||
) +
|
||||
gsi::method_ext ("begin_shapes", &begin_shapes, gsi::arg ("cell_index"), gsi::arg ("layer"),
|
||||
gsi::method_ext ("#begin_shapes", &begin_shapes, gsi::arg ("cell_index"), gsi::arg ("layer"),
|
||||
"@brief Delivers a recursive shape iterator for the shapes below the given cell on the given layer\n"
|
||||
"@param cell_index The index of the initial (top) cell\n"
|
||||
"@param layer The layer from which to get the shapes\n"
|
||||
|
|
@ -1726,9 +1728,11 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
|||
"\n"
|
||||
"For details see the description of the \\RecursiveShapeIterator class.\n"
|
||||
"\n"
|
||||
"This method is deprecated. Use \\Cell#begin_shapes_rec instead.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.18.\n"
|
||||
) +
|
||||
gsi::method_ext ("begin_shapes_touching", &begin_shapes_touching, gsi::arg ("cell_index"), gsi::arg ("layer"), gsi::arg ("region"),
|
||||
gsi::method_ext ("#begin_shapes_touching", &begin_shapes_touching, gsi::arg ("cell_index"), gsi::arg ("layer"), gsi::arg ("region"),
|
||||
"@brief Delivers a recursive shape iterator for the shapes below the given cell on the given layer using a region search\n"
|
||||
"@param cell_index The index of the starting cell\n"
|
||||
"@param layer The layer from which to get the shapes\n"
|
||||
|
|
@ -1738,9 +1742,11 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
|||
"For details see the description of the \\RecursiveShapeIterator class.\n"
|
||||
"This version gives an iterator delivering shapes whose bounding box touches the given region.\n"
|
||||
"\n"
|
||||
"This method is deprecated. Use \\Cell#begin_shapes_rec_touching instead.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.18.\n"
|
||||
) +
|
||||
gsi::method_ext ("begin_shapes_touching", &begin_shapes_touching2, gsi::arg ("cell"), gsi::arg ("layer"), gsi::arg ("region"),
|
||||
gsi::method_ext ("#begin_shapes_touching", &begin_shapes_touching2, gsi::arg ("cell"), gsi::arg ("layer"), gsi::arg ("region"),
|
||||
"@brief Delivers a recursive shape iterator for the shapes below the given cell on the given layer using a region search\n"
|
||||
"@param cell The cell object for the starting cell\n"
|
||||
"@param layer The layer from which to get the shapes\n"
|
||||
|
|
@ -1751,9 +1757,11 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
|||
"This version gives an iterator delivering shapes whose bounding box touches the given region.\n"
|
||||
"It is convenience overload which takes a cell object instead of a cell index.\n"
|
||||
"\n"
|
||||
"This method is deprecated. Use \\Cell#begin_shapes_rec_touching instead.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.24.\n"
|
||||
) +
|
||||
gsi::method_ext ("begin_shapes_overlapping", &begin_shapes_overlapping, gsi::arg ("cell_index"), gsi::arg ("layer"), gsi::arg ("region"),
|
||||
gsi::method_ext ("#begin_shapes_overlapping", &begin_shapes_overlapping, gsi::arg ("cell_index"), gsi::arg ("layer"), gsi::arg ("region"),
|
||||
"@brief Delivers a recursive shape iterator for the shapes below the given cell on the given layer using a region search\n"
|
||||
"@param cell_index The index of the starting cell\n"
|
||||
"@param layer The layer from which to get the shapes\n"
|
||||
|
|
@ -1763,9 +1771,11 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
|||
"For details see the description of the \\RecursiveShapeIterator class.\n"
|
||||
"This version gives an iterator delivering shapes whose bounding box overlaps the given region.\n"
|
||||
"\n"
|
||||
"This method is deprecated. Use \\Cell#begin_shapes_rec_overlapping instead.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.18.\n"
|
||||
) +
|
||||
gsi::method_ext ("begin_shapes_overlapping", &begin_shapes_overlapping2, gsi::arg ("cell_index"), gsi::arg ("layer"), gsi::arg ("region"),
|
||||
gsi::method_ext ("#begin_shapes_overlapping", &begin_shapes_overlapping2, gsi::arg ("cell_index"), gsi::arg ("layer"), gsi::arg ("region"),
|
||||
"@brief Delivers a recursive shape iterator for the shapes below the given cell on the given layer using a region search\n"
|
||||
"@param cell The cell object for the starting cell\n"
|
||||
"@param layer The layer from which to get the shapes\n"
|
||||
|
|
@ -1776,9 +1786,11 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
|||
"This version gives an iterator delivering shapes whose bounding box overlaps the given region.\n"
|
||||
"It is convenience overload which takes a cell object instead of a cell index.\n"
|
||||
"\n"
|
||||
"This method is deprecated. Use \\Cell#begin_shapes_rec_overlapping instead.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.24.\n"
|
||||
) +
|
||||
gsi::method_ext ("begin_shapes_touching", &begin_shapes_touching_um, gsi::arg ("cell_index"), gsi::arg ("layer"), gsi::arg ("region"),
|
||||
gsi::method_ext ("#begin_shapes_touching", &begin_shapes_touching_um, gsi::arg ("cell_index"), gsi::arg ("layer"), gsi::arg ("region"),
|
||||
"@brief Delivers a recursive shape iterator for the shapes below the given cell on the given layer using a region search, the region given in micrometer units\n"
|
||||
"@param cell_index The index of the starting cell\n"
|
||||
"@param layer The layer from which to get the shapes\n"
|
||||
|
|
@ -1788,9 +1800,11 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
|||
"For details see the description of the \\RecursiveShapeIterator class.\n"
|
||||
"This version gives an iterator delivering shapes whose bounding box touches the given region.\n"
|
||||
"\n"
|
||||
"This method is deprecated. Use \\Cell#begin_shapes_rec_touching instead.\n"
|
||||
"\n"
|
||||
"This variant has been added in version 0.25.\n"
|
||||
) +
|
||||
gsi::method_ext ("begin_shapes_touching", &begin_shapes_touching2_um, gsi::arg ("cell"), gsi::arg ("layer"), gsi::arg ("region"),
|
||||
gsi::method_ext ("#begin_shapes_touching", &begin_shapes_touching2_um, gsi::arg ("cell"), gsi::arg ("layer"), gsi::arg ("region"),
|
||||
"@brief Delivers a recursive shape iterator for the shapes below the given cell on the given layer using a region search, the region given in micrometer units\n"
|
||||
"@param cell The cell object for the starting cell\n"
|
||||
"@param layer The layer from which to get the shapes\n"
|
||||
|
|
@ -1801,9 +1815,11 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
|||
"This version gives an iterator delivering shapes whose bounding box touches the given region.\n"
|
||||
"It is convenience overload which takes a cell object instead of a cell index.\n"
|
||||
"\n"
|
||||
"This method is deprecated. Use \\Cell#begin_shapes_rec_touching instead.\n"
|
||||
"\n"
|
||||
"This variant has been added in version 0.25.\n"
|
||||
) +
|
||||
gsi::method_ext ("begin_shapes_overlapping", &begin_shapes_overlapping_um, gsi::arg ("cell_index"), gsi::arg ("layer"), gsi::arg ("region"),
|
||||
gsi::method_ext ("#begin_shapes_overlapping", &begin_shapes_overlapping_um, gsi::arg ("cell_index"), gsi::arg ("layer"), gsi::arg ("region"),
|
||||
"@brief Delivers a recursive shape iterator for the shapes below the given cell on the given layer using a region search, the region given in micrometer units\n"
|
||||
"@param cell_index The index of the starting cell\n"
|
||||
"@param layer The layer from which to get the shapes\n"
|
||||
|
|
@ -1813,9 +1829,11 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
|||
"For details see the description of the \\RecursiveShapeIterator class.\n"
|
||||
"This version gives an iterator delivering shapes whose bounding box overlaps the given region.\n"
|
||||
"\n"
|
||||
"This method is deprecated. Use \\Cell#begin_shapes_rec_overlapping instead.\n"
|
||||
"\n"
|
||||
"This variant has been added in version 0.25.\n"
|
||||
) +
|
||||
gsi::method_ext ("begin_shapes_overlapping", &begin_shapes_overlapping2_um, gsi::arg ("cell"), gsi::arg ("layer"), gsi::arg ("region"),
|
||||
gsi::method_ext ("#begin_shapes_overlapping", &begin_shapes_overlapping2_um, gsi::arg ("cell"), gsi::arg ("layer"), gsi::arg ("region"),
|
||||
"@brief Delivers a recursive shape iterator for the shapes below the given cell on the given layer using a region search, the region given in micrometer units\n"
|
||||
"@param cell The cell object for the starting cell\n"
|
||||
"@param layer The layer from which to get the shapes\n"
|
||||
|
|
@ -1826,6 +1844,8 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
|||
"This version gives an iterator delivering shapes whose bounding box overlaps the given region.\n"
|
||||
"It is convenience overload which takes a cell object instead of a cell index.\n"
|
||||
"\n"
|
||||
"This method is deprecated. Use \\Cell#begin_shapes_rec_overlapping instead.\n"
|
||||
"\n"
|
||||
"This variant has been added in version 0.25.\n"
|
||||
) +
|
||||
gsi::method_ext ("#write", &write_options2, gsi::arg ("filename"), gsi::arg ("gzip"), gsi::arg ("options"),
|
||||
|
|
|
|||
|
|
@ -1602,9 +1602,9 @@ static db::Polygon transformed_icplx_dp (const db::Polygon *p, const db::ICplxTr
|
|||
return p->transformed (t, false /*don't compress*/);
|
||||
}
|
||||
|
||||
static db::Polygon smooth (const db::Polygon *p, db::Coord d)
|
||||
static db::Polygon smooth (const db::Polygon *p, db::Coord d, bool keep_hv)
|
||||
{
|
||||
return db::smooth (*p, d);
|
||||
return db::smooth (*p, d, keep_hv);
|
||||
}
|
||||
|
||||
static db::Polygon minkowsky_sum_pe (const db::Polygon *p, const db::Edge &e, bool rh)
|
||||
|
|
@ -1787,17 +1787,18 @@ Class<db::Polygon> decl_Polygon ("db", "Polygon",
|
|||
"\n"
|
||||
"This method was introduced in version 0.22.\n"
|
||||
) +
|
||||
method_ext ("smooth", &smooth, gsi::arg ("d"),
|
||||
method_ext ("smooth", &smooth, gsi::arg ("d"), gsi::arg ("keep_hv", false),
|
||||
"@brief Smoothes a polygon\n"
|
||||
"\n"
|
||||
"Remove vertices that deviate by more than the distance d from the average contour.\n"
|
||||
"The value d is basically the roughness which is removed.\n"
|
||||
"\n"
|
||||
"@param d The smoothing \"roughness\".\n"
|
||||
"@param keep_hv If true, horizontal and vertical edges will be preserved always.\n"
|
||||
"\n"
|
||||
"@return The smoothed polygon.\n"
|
||||
"\n"
|
||||
"This method was introduced in version 0.23.\n"
|
||||
"This method was introduced in version 0.23. The 'keep_hv' optional parameter was added in version 0.27.\n"
|
||||
) +
|
||||
method_ext ("minkowsky_sum", &minkowsky_sum_pe, gsi::arg ("e"), gsi::arg ("resolve_holes"),
|
||||
"@brief Computes the Minkowsky sum of the polygon and an edge\n"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,558 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2021 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "gsiDecl.h"
|
||||
#include "dbRecursiveInstanceIterator.h"
|
||||
#include "dbRegion.h"
|
||||
|
||||
#include "tlGlobPattern.h"
|
||||
|
||||
namespace gsi
|
||||
{
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// db::RecursiveInstanceIterator binding
|
||||
|
||||
static db::RecursiveInstanceIterator *new_si1 (const db::Layout &layout, const db::Cell &cell)
|
||||
{
|
||||
return new db::RecursiveInstanceIterator (layout, cell);
|
||||
}
|
||||
|
||||
static db::RecursiveInstanceIterator *new_si2 (const db::Layout &layout, const db::Cell &cell, const db::Box &box, bool overlapping)
|
||||
{
|
||||
return new db::RecursiveInstanceIterator (layout, cell, box, overlapping);
|
||||
}
|
||||
|
||||
static db::RecursiveInstanceIterator *new_si2a (const db::Layout &layout, const db::Cell &cell, const db::Region ®ion, bool overlapping)
|
||||
{
|
||||
return new db::RecursiveInstanceIterator (layout, cell, region, overlapping);
|
||||
}
|
||||
|
||||
static db::DCplxTrans si_dtrans (const db::RecursiveInstanceIterator *r)
|
||||
{
|
||||
const db::Layout *ly = r->layout ();
|
||||
tl_assert (ly != 0);
|
||||
return db::CplxTrans (ly->dbu ()) * r->trans () * db::VCplxTrans (1.0 / ly->dbu ());
|
||||
}
|
||||
|
||||
static void set_targets1 (db::RecursiveInstanceIterator *r, const std::vector<db::cell_index_type> &cells)
|
||||
{
|
||||
std::set<db::cell_index_type> cc;
|
||||
cc.insert (cells.begin (), cells.end ());
|
||||
r->set_targets (cc);
|
||||
}
|
||||
|
||||
static db::DCplxTrans inst_dtrans (const db::RecursiveInstanceIterator *r)
|
||||
{
|
||||
const db::Layout *ly = r->layout ();
|
||||
tl_assert (ly != 0);
|
||||
return db::CplxTrans (ly->dbu ()) * (*r)->complex_trans () * db::VCplxTrans (1.0 / ly->dbu ());
|
||||
}
|
||||
|
||||
static db::ICplxTrans inst_trans (const db::RecursiveInstanceIterator *r)
|
||||
{
|
||||
return (*r)->complex_trans ();
|
||||
}
|
||||
|
||||
static db::Cell *inst_cell (const db::RecursiveInstanceIterator *r)
|
||||
{
|
||||
const db::Layout *ly = r->layout ();
|
||||
tl_assert (ly != 0);
|
||||
return const_cast<db::Cell *> (&ly->cell ((*r)->inst_ptr.cell_index ()));
|
||||
}
|
||||
|
||||
static void set_targets2 (db::RecursiveInstanceIterator *r, const std::string &pattern)
|
||||
{
|
||||
tl::GlobPattern p (pattern);
|
||||
std::set<db::cell_index_type> cc;
|
||||
for (db::Layout::const_iterator ci = r->layout ()->begin (); ci != r->layout ()->end (); ++ci) {
|
||||
if (p.match (r->layout ()->cell_name (ci->cell_index ()))) {
|
||||
cc.insert (ci->cell_index ());
|
||||
}
|
||||
}
|
||||
|
||||
r->set_targets (cc);
|
||||
}
|
||||
|
||||
static void select_cells1 (db::RecursiveInstanceIterator *r, const std::vector<db::cell_index_type> &cells)
|
||||
{
|
||||
std::set<db::cell_index_type> cc;
|
||||
cc.insert (cells.begin (), cells.end ());
|
||||
r->select_cells (cc);
|
||||
}
|
||||
|
||||
static void select_cells2 (db::RecursiveInstanceIterator *r, const std::string &pattern)
|
||||
{
|
||||
tl::GlobPattern p (pattern);
|
||||
std::set<db::cell_index_type> cc;
|
||||
for (db::Layout::const_iterator ci = r->layout ()->begin (); ci != r->layout ()->end (); ++ci) {
|
||||
if (p.match (r->layout ()->cell_name (ci->cell_index ()))) {
|
||||
cc.insert (ci->cell_index ());
|
||||
}
|
||||
}
|
||||
|
||||
r->select_cells (cc);
|
||||
}
|
||||
|
||||
static void unselect_cells1 (db::RecursiveInstanceIterator *r, const std::vector<db::cell_index_type> &cells)
|
||||
{
|
||||
std::set<db::cell_index_type> cc;
|
||||
cc.insert (cells.begin (), cells.end ());
|
||||
r->unselect_cells (cc);
|
||||
}
|
||||
|
||||
static void unselect_cells2 (db::RecursiveInstanceIterator *r, const std::string &pattern)
|
||||
{
|
||||
tl::GlobPattern p (pattern);
|
||||
std::set<db::cell_index_type> cc;
|
||||
for (db::Layout::const_iterator ci = r->layout ()->begin (); ci != r->layout ()->end (); ++ci) {
|
||||
if (p.match (r->layout ()->cell_name (ci->cell_index ()))) {
|
||||
cc.insert (ci->cell_index ());
|
||||
}
|
||||
}
|
||||
|
||||
r->unselect_cells (cc);
|
||||
}
|
||||
|
||||
static db::Region complex_region (const db::RecursiveInstanceIterator *iter)
|
||||
{
|
||||
if (iter->has_complex_region ()) {
|
||||
return iter->complex_region ();
|
||||
} else {
|
||||
return db::Region (iter->region ());
|
||||
}
|
||||
}
|
||||
|
||||
Class<db::RecursiveInstanceIterator> decl_RecursiveInstanceIterator ("db", "RecursiveInstanceIterator",
|
||||
gsi::constructor ("new", &new_si1, gsi::arg ("layout"), gsi::arg ("cell"),
|
||||
"@brief Creates a recursive instance iterator.\n"
|
||||
"@param layout The layout which shall be iterated\n"
|
||||
"@param cell The initial cell which shall be iterated (including its children)\n"
|
||||
"@param layer The layer (index) from which the shapes are taken\n"
|
||||
"\n"
|
||||
"This constructor creates a new recursive instance iterator which delivers the instances of "
|
||||
"the given cell plus its children.\n"
|
||||
) +
|
||||
gsi::constructor ("new", &new_si2, gsi::arg ("layout"), gsi::arg ("cell"), gsi::arg ("box"), gsi::arg ("overlapping", false),
|
||||
"@brief Creates a recursive instance iterator with a search region.\n"
|
||||
"@param layout The layout which shall be iterated\n"
|
||||
"@param cell The initial cell which shall be iterated (including its children)\n"
|
||||
"@param box The search region\n"
|
||||
"@param overlapping If set to true, instances overlapping the search region are reported, otherwise touching is sufficient\n"
|
||||
"\n"
|
||||
"This constructor creates a new recursive instance iterator which delivers the instances of "
|
||||
"the given cell plus its children.\n"
|
||||
"\n"
|
||||
"The search is confined to the region given by the \"box\" parameter. If \"overlapping\" is true, instances whose "
|
||||
"bounding box is overlapping the search region are reported. If \"overlapping\" is false, instances whose "
|
||||
"bounding box touches the search region are reported. The bounding box of instances is measured taking all layers "
|
||||
"of the target cell into account.\n"
|
||||
) +
|
||||
gsi::constructor ("new", &new_si2a, gsi::arg ("layout"), gsi::arg ("cell"), gsi::arg ("region"), gsi::arg ("overlapping"),
|
||||
"@brief Creates a recursive instance iterator with a search region.\n"
|
||||
"@param layout The layout which shall be iterated\n"
|
||||
"@param cell The initial cell which shall be iterated (including its children)\n"
|
||||
"@param region The search region\n"
|
||||
"@param overlapping If set to true, instances overlapping the search region are reported, otherwise touching is sufficient\n"
|
||||
"\n"
|
||||
"This constructor creates a new recursive instance iterator which delivers the instances of "
|
||||
"the given cell plus its children.\n"
|
||||
"\n"
|
||||
"The search is confined to the region given by the \"region\" parameter. The region needs to be a rectilinear region.\n"
|
||||
"If \"overlapping\" is true, instances whose "
|
||||
"bounding box is overlapping the search region are reported. If \"overlapping\" is false, instances whose "
|
||||
"bounding box touches the search region are reported. The bounding box of instances is measured taking all layers "
|
||||
"of the target cell into account.\n"
|
||||
) +
|
||||
gsi::method ("max_depth=", (void (db::RecursiveInstanceIterator::*) (int)) &db::RecursiveInstanceIterator::max_depth, gsi::arg ("depth"),
|
||||
"@brief Specifies the maximum hierarchy depth to look into\n"
|
||||
"\n"
|
||||
"A depth of 0 instructs the iterator to deliver only instances from the initial cell.\n"
|
||||
"A higher depth instructs the iterator to look deeper.\n"
|
||||
"The depth must be specified before the instances are being retrieved.\n"
|
||||
) +
|
||||
gsi::method ("max_depth", (int (db::RecursiveInstanceIterator::*) () const) &db::RecursiveInstanceIterator::max_depth,
|
||||
"@brief Gets the maximum hierarchy depth\n"
|
||||
"\n"
|
||||
"See \\max_depth= for a description of that attribute.\n"
|
||||
) +
|
||||
gsi::method ("min_depth=", (void (db::RecursiveInstanceIterator::*) (int)) &db::RecursiveInstanceIterator::min_depth, gsi::arg ("depth"),
|
||||
"@brief Specifies the minimum hierarchy depth to look into\n"
|
||||
"\n"
|
||||
"A depth of 0 instructs the iterator to deliver instances from the top level.\n"
|
||||
"1 instructs to deliver instances from the first child level.\n"
|
||||
"The minimum depth must be specified before the instances are being retrieved.\n"
|
||||
) +
|
||||
gsi::method ("min_depth", (int (db::RecursiveInstanceIterator::*) () const) &db::RecursiveInstanceIterator::min_depth,
|
||||
"@brief Gets the minimum hierarchy depth\n"
|
||||
"\n"
|
||||
"See \\min_depth= for a description of that attribute.\n"
|
||||
) +
|
||||
gsi::method ("reset", &db::RecursiveInstanceIterator::reset,
|
||||
"@brief Resets the iterator to the initial state\n"
|
||||
) +
|
||||
gsi::method ("reset_selection", &db::RecursiveInstanceIterator::reset_selection,
|
||||
"@brief Resets the selection to the default state\n"
|
||||
"\n"
|
||||
"In the initial state, the top cell and its children are selected. Child cells can be switched on and off "
|
||||
"together with their sub-hierarchy using \\select_cells and \\unselect_cells.\n"
|
||||
"\n"
|
||||
"This method will also reset the iterator.\n"
|
||||
) +
|
||||
gsi::method ("layout", &db::RecursiveInstanceIterator::layout,
|
||||
"@brief Gets the layout this iterator is connected to\n"
|
||||
) +
|
||||
gsi::method ("top_cell", &db::RecursiveInstanceIterator::top_cell,
|
||||
"@brief Gets the top cell this iterator is connected to\n"
|
||||
) +
|
||||
gsi::method ("region", &db::RecursiveInstanceIterator::region,
|
||||
"@brief Gets the basic region that is iterator is using\n"
|
||||
"The basic region is the overall box the region iterator iterates over. "
|
||||
"There may be an additional complex region that confines the region iterator. "
|
||||
"See \\complex_region for this attribute.\n"
|
||||
) +
|
||||
gsi::method_ext ("complex_region", &complex_region,
|
||||
"@brief Gets the complex region that is iterator is using\n"
|
||||
"The complex region is the effective region (a \\Region object) that the "
|
||||
"iterator is selecting from the layout. This region can be a single box "
|
||||
"or a complex region.\n"
|
||||
) +
|
||||
gsi::method ("region=", (void (db::RecursiveInstanceIterator::*)(const db::RecursiveInstanceIterator::box_type &)) &db::RecursiveInstanceIterator::set_region, gsi::arg ("box_region"),
|
||||
"@brief Sets the rectangular region that is iterator is iterating over\n"
|
||||
"See \\region for a description of this attribute.\n"
|
||||
"Setting a simple region will reset the complex region to a rectangle and reset the iterator to "
|
||||
"the beginning of the sequence."
|
||||
) +
|
||||
gsi::method ("region=", (void (db::RecursiveInstanceIterator::*)(const db::RecursiveInstanceIterator::region_type &)) &db::RecursiveInstanceIterator::set_region, gsi::arg ("complex_region"),
|
||||
"@brief Sets the complex region that is iterator is using\n"
|
||||
"See \\complex_region for a description of this attribute. Setting the complex region will "
|
||||
"reset the basic region (see \\region) to the bounding box of the complex region and "
|
||||
"reset the iterator to the beginning of the sequence.\n"
|
||||
) +
|
||||
gsi::method ("confine_region", (void (db::RecursiveInstanceIterator::*)(const db::RecursiveInstanceIterator::box_type &)) &db::RecursiveInstanceIterator::confine_region, gsi::arg ("box_region"),
|
||||
"@brief Confines the region that is iterator is iterating over\n"
|
||||
"This method is similar to setting the region (see \\region=), but will confine any region (complex or simple) already set. "
|
||||
"Essentially it does a logical AND operation between the existing and given region. "
|
||||
"Hence this method can only reduce a region, not extend it.\n"
|
||||
) +
|
||||
gsi::method ("confine_region", (void (db::RecursiveInstanceIterator::*)(const db::RecursiveInstanceIterator::region_type &)) &db::RecursiveInstanceIterator::confine_region, gsi::arg ("complex_region"),
|
||||
"@brief Confines the region that is iterator is iterating over\n"
|
||||
"This method is similar to setting the region (see \\region=), but will confine any region (complex or simple) already set. "
|
||||
"Essentially it does a logical AND operation between the existing and given region. "
|
||||
"Hence this method can only reduce a region, not extend it.\n"
|
||||
) +
|
||||
gsi::method ("overlapping?", &db::RecursiveInstanceIterator::overlapping,
|
||||
"@brief Gets a flag indicating whether overlapping instances are selected when a region is used\n"
|
||||
) +
|
||||
gsi::method ("overlapping=", &db::RecursiveInstanceIterator::set_overlapping, gsi::arg ("region"),
|
||||
"@brief Sets a flag indicating whether overlapping instances are selected when a region is used\n"
|
||||
"\n"
|
||||
"If this flag is false, instances touching the search region are returned.\n"
|
||||
) +
|
||||
gsi::method ("unselect_all_cells", &db::RecursiveInstanceIterator::unselect_all_cells,
|
||||
"@brief Unselects all cells.\n"
|
||||
"\n"
|
||||
"This method will set the \"unselected\" mark on all cells. The effect is "
|
||||
"that subsequent calls of \\select_cells will select only the specified cells, not "
|
||||
"their children, because they are still unselected.\n"
|
||||
"\n"
|
||||
"This method will also reset the iterator.\n"
|
||||
) +
|
||||
gsi::method ("select_all_cells", &db::RecursiveInstanceIterator::select_all_cells,
|
||||
"@brief Selects all cells.\n"
|
||||
"\n"
|
||||
"This method will set the \"selected\" mark on all cells. The effect is "
|
||||
"that subsequent calls of \\unselect_cells will unselect only the specified cells, not "
|
||||
"their children, because they are still unselected.\n"
|
||||
"\n"
|
||||
"This method will also reset the iterator.\n"
|
||||
) +
|
||||
gsi::method_ext ("unselect_cells", &unselect_cells1, gsi::arg ("cells"),
|
||||
"@brief Unselects the given cells.\n"
|
||||
"\n"
|
||||
"This method will sets the \"unselected\" mark on the given cells. "
|
||||
"That means that these cells or their child cells will not be visited, unless "
|
||||
"they are marked as \"selected\" again with the \\select_cells method.\n"
|
||||
"\n"
|
||||
"The cells are given as a list of cell indexes.\n"
|
||||
"\n"
|
||||
"This method will also reset the iterator.\n"
|
||||
) +
|
||||
gsi::method_ext ("unselect_cells", &unselect_cells2, gsi::arg ("cells"),
|
||||
"@brief Unselects the given cells.\n"
|
||||
"\n"
|
||||
"This method will sets the \"unselected\" mark on the given cells. "
|
||||
"That means that these cells or their child cells will not be visited, unless "
|
||||
"they are marked as \"selected\" again with the \\select_cells method.\n"
|
||||
"\n"
|
||||
"The cells are given as a glob pattern.\n"
|
||||
"A glob pattern follows the syntax of "
|
||||
"file names on the shell (i.e. \"A*\" are all cells starting with a letter \"A\").\n"
|
||||
"\n"
|
||||
"This method will also reset the iterator.\n"
|
||||
) +
|
||||
gsi::method_ext ("select_cells", &select_cells1, gsi::arg ("cells"),
|
||||
"@brief Unselects the given cells.\n"
|
||||
"\n"
|
||||
"This method will sets the \"selected\" mark on the given cells. "
|
||||
"That means that these cells or their child cells are visited, unless "
|
||||
"they are marked as \"unselected\" again with the \\unselect_cells method.\n"
|
||||
"\n"
|
||||
"The cells are given as a list of cell indexes.\n"
|
||||
"\n"
|
||||
"This method will also reset the iterator.\n"
|
||||
) +
|
||||
gsi::method_ext ("select_cells", &select_cells2, gsi::arg ("cells"),
|
||||
"@brief Unselects the given cells.\n"
|
||||
"\n"
|
||||
"This method will sets the \"selected\" mark on the given cells. "
|
||||
"That means that these cells or their child cells are visited, unless "
|
||||
"they are marked as \"unselected\" again with the \\unselect_cells method.\n"
|
||||
"\n"
|
||||
"The cells are given as a glob pattern.\n"
|
||||
"A glob pattern follows the syntax of "
|
||||
"file names on the shell (i.e. \"A*\" are all cells starting with a letter \"A\").\n"
|
||||
"\n"
|
||||
"This method will also reset the iterator.\n"
|
||||
) +
|
||||
gsi::method_ext ("targets=", &set_targets1, gsi::arg ("cells"),
|
||||
"@brief Specifies the target cells.\n"
|
||||
"\n"
|
||||
"If target cells are specified, only instances of these cells are delivered. "
|
||||
"This version takes a list of cell indexes for the targets. "
|
||||
"By default, no target cell list is present and the instances of all cells "
|
||||
"are delivered by the iterator. See \\all_targets_enabled? and \\enable_all_targets for "
|
||||
"a description of this mode. Once a target list is specified, the iteration is "
|
||||
"confined to the cells from this list."
|
||||
"\n"
|
||||
"The cells are given as a list of cell indexes.\n"
|
||||
"\n"
|
||||
"This method will also reset the iterator.\n"
|
||||
) +
|
||||
gsi::method_ext ("targets=", &set_targets2, gsi::arg ("cells"),
|
||||
"@brief Specifies the target cells.\n"
|
||||
"\n"
|
||||
"If target cells are specified, only instances of these cells are delivered. "
|
||||
"This version takes a cell list as a glob pattern. "
|
||||
"A glob pattern follows the syntax of "
|
||||
"file names on the shell (i.e. \"A*\" are all cells starting with a letter \"A\").\n"
|
||||
"Use the curly-bracket notation to list different cells, e.g \"{A,B,C}\" for cells A, B and C.\n"
|
||||
"\n"
|
||||
"By default, no target cell list is present and the instances of all cells "
|
||||
"are delivered by the iterator. See \\all_targets_enabled? and \\enable_all_targets for "
|
||||
"a description of this mode. Once a target list is specified, the iteration is "
|
||||
"confined to the cells from this list."
|
||||
"\n"
|
||||
"The cells are given as a list of cell indexes.\n"
|
||||
"\n"
|
||||
"This method will also reset the iterator.\n"
|
||||
) +
|
||||
gsi::method ("targets", &db::RecursiveInstanceIterator::targets,
|
||||
"@brief Gets the list of target cells\n"
|
||||
"See \\targets= for a description of the target cell concept. "
|
||||
"This method returns a list of cell indexes of the selected target cells."
|
||||
) +
|
||||
gsi::method ("all_targets_enabled?", &db::RecursiveInstanceIterator::all_targets_enabled,
|
||||
"@brief Gets a value indicating whether instances of all cells are reported\n"
|
||||
"See \\targets= for a description of the target cell concept. "
|
||||
) +
|
||||
gsi::method ("enable_all_targets", &db::RecursiveInstanceIterator::enable_all_targets,
|
||||
"@brief Enables 'all targets' mode in which instances of all cells are reported\n"
|
||||
"See \\targets= for a description of the target cell concept. "
|
||||
) +
|
||||
gsi::method ("trans", &db::RecursiveInstanceIterator::trans,
|
||||
"@brief Gets the accumulated transformation of the current instance parent cell to the top cell\n"
|
||||
"\n"
|
||||
"This transformation represents how the current instance is seen in the top cell.\n"
|
||||
) +
|
||||
gsi::method_ext ("dtrans", &gsi::si_dtrans,
|
||||
"@brief Gets the accumulated transformation of the current instance parent cell to the top cell\n"
|
||||
"\n"
|
||||
"This transformation represents how the current instance is seen in the top cell.\n"
|
||||
"This version returns the micon-unit transformation.\n"
|
||||
) +
|
||||
gsi::method ("at_end?", &db::RecursiveInstanceIterator::at_end,
|
||||
"@brief End of iterator predicate\n"
|
||||
"\n"
|
||||
"Returns true, if the iterator is at the end of the sequence\n"
|
||||
) +
|
||||
gsi::method ("cell", &db::RecursiveInstanceIterator::cell,
|
||||
"@brief Gets the cell the current instance sits in\n"
|
||||
) +
|
||||
gsi::method ("cell_index", &db::RecursiveInstanceIterator::cell_index,
|
||||
"@brief Gets the index of the cell the current instance sits in\n"
|
||||
"This is equivalent to 'cell.cell_index'."
|
||||
) +
|
||||
gsi::method_ext ("inst_trans", &inst_trans,
|
||||
"@brief Gets the integer-unit transformation of the current instance\n"
|
||||
"This is the transformation of the current instance inside its parent.\n"
|
||||
"'trans * inst_trans' gives the full transformation how the current cell is seen in the top cell.\n"
|
||||
"See also \\inst_dtrans and \\inst_cell.\n"
|
||||
) +
|
||||
gsi::method_ext ("inst_dtrans", &inst_dtrans,
|
||||
"@brief Gets the micron-unit transformation of the current instance\n"
|
||||
"This is the transformation of the current instance inside its parent.\n"
|
||||
"'dtrans * inst_dtrans' gives the full micron-unit transformation how the current cell is seen in the top cell.\n"
|
||||
"See also \\inst_trans and \\inst_cell.\n"
|
||||
) +
|
||||
gsi::method_ext ("inst_cell", &inst_cell,
|
||||
"@brief Gets the target cell of the current instance\n"
|
||||
"This is the cell the current instance refers to. It is one of the \\targets if a target list is given.\n"
|
||||
) +
|
||||
gsi::method ("current_inst_element", &db::RecursiveInstanceIterator::instance,
|
||||
"@brief Gets the current instance\n"
|
||||
"\n"
|
||||
"This is the instance/array element the iterator currently refers to.\n"
|
||||
"This is a \\InstElement object representing the current instance and the array element the iterator currently points at.\n"
|
||||
"\n"
|
||||
"See \\inst_trans, \\inst_dtrans and \\inst_cell for convenience methods to access the details of the current element.\n"
|
||||
) +
|
||||
gsi::method ("next", (void (db::RecursiveInstanceIterator::*) ()) &db::RecursiveInstanceIterator::next,
|
||||
"@brief Increments the iterator\n"
|
||||
"This moves the iterator to the next instance inside the search scope."
|
||||
) +
|
||||
gsi::method ("path", &db::RecursiveInstanceIterator::path,
|
||||
"@brief Gets the instantatiation path of the instance addressed currently\n"
|
||||
"\n"
|
||||
"This attribute is a sequence of \\InstElement objects describing the cell instance path from the initial "
|
||||
"cell to the current instance. The path is empty if the current instance is in the top cell.\n"
|
||||
) +
|
||||
gsi::method ("==", &db::RecursiveInstanceIterator::operator==, gsi::arg ("other"),
|
||||
"@brief Comparison of iterators - equality\n"
|
||||
"\n"
|
||||
"Two iterators are equal if they point to the same instance.\n"
|
||||
) +
|
||||
gsi::method ("!=", &db::RecursiveInstanceIterator::operator!=, gsi::arg ("other"),
|
||||
"@brief Comparison of iterators - inequality\n"
|
||||
"\n"
|
||||
"Two iterators are not equal if they do not point to the same instance.\n"
|
||||
),
|
||||
"@brief An iterator delivering instances recursively\n"
|
||||
"\n"
|
||||
"The iterator can be obtained from a cell and optionally a region.\n"
|
||||
"It simplifies retrieval of instances while considering\n"
|
||||
"subcells as well.\n"
|
||||
"Some options can be specified in addition, i.e. the hierarchy level to which to look into.\n"
|
||||
"The search can be confined to instances of certain cells (see \\targets=) or to certain regions. "
|
||||
"Subtrees can be selected for traversal or excluded from it (see \\select_cells).\n"
|
||||
"\n"
|
||||
"This is some sample code:\n"
|
||||
"\n"
|
||||
"@code\n"
|
||||
"# prints the effective instances of cell \"A\" as seen from the initial cell \"cell\"\n"
|
||||
"iter = cell.begin_instances_rec\n"
|
||||
"iter.targets = \"A\"\n"
|
||||
"while !iter.at_end?\n"
|
||||
" puts \"Instance of #{iter.inst_cell.name} in #{cell.name}: \" + (iter.dtrans * iter.inst_dtrans).to_s\n"
|
||||
" iter.next\n"
|
||||
"end\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"Here, a target cell is specified which confines the search to instances of this particular cell.\n"
|
||||
"'iter.dtrans' gives us the accumulated transformation of all parents up to the top cell. "
|
||||
"'iter.inst_dtrans' gives us the transformation from the current instance. "
|
||||
"'iter.inst_cell' finally gives us the target cell of the current instance (which is always 'A' in our case).\n"
|
||||
"\n"
|
||||
"\\Cell offers three methods to get these iterators: begin_instances_rec, begin_instances_rec_touching and begin_instances_rec_overlapping.\n"
|
||||
"\\Cell#begin_instances_rec will deliver a standard recursive instance iterator which starts from the given cell and iterates "
|
||||
"over all child cells. \\Cell#begin_instances_rec_touching creates a RecursiveInstanceIterator which delivers the instances "
|
||||
"whose bounding boxed touch the given search box. \\Layout#begin_instances_rec_overlapping gives an iterator which delivers all instances whose bounding box "
|
||||
"overlaps the search box.\n"
|
||||
"\n"
|
||||
"A RecursiveInstanceIterator object can also be created directly, like this:\n"
|
||||
"\n"
|
||||
"@code\n"
|
||||
"iter = RBA::RecursiveInstanceIterator::new(layout, cell [, options ])\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"\"layout\" is the layout object, \"cell\" the \\Cell object of the initial cell.\n"
|
||||
"\n"
|
||||
"The recursive instance iterator can be confined to a maximum hierarchy depth. By using \\max_depth=, the "
|
||||
"iterator will restrict the search depth to the given depth in the cell tree.\n"
|
||||
"In the same way, the iterator can be configured to start from a certain hierarchy depth using \\min_depth=. "
|
||||
"The hierarchy depth always applies to the parent of the instances iterated.\n"
|
||||
"\n"
|
||||
"In addition, the recursive instance iterator supports selection and exclusion of subtrees. For that purpose "
|
||||
"it keeps flags per cell telling it for which cells to turn instance delivery on and off. The \\select_cells method "
|
||||
"sets the \"start delivery\" flag while \\unselect_cells sets the \"stop delivery\" flag. In effect, using "
|
||||
"\\unselect_cells will exclude that cell plus the subtree from delivery. Parts of that subtree can be "
|
||||
"turned on again using \\select_cells. For the cells selected that way, the instances of these cells and their "
|
||||
"child cells are delivered, even if their parent was unselected.\n"
|
||||
"\n"
|
||||
"To get instances from a specific cell, i.e. \"MACRO\" plus its child cells, unselect the top cell first "
|
||||
"and the select the desired cell again:\n"
|
||||
"\n"
|
||||
"@code\n"
|
||||
"# deliver all instances inside \"MACRO\" and the sub-hierarchy:\n"
|
||||
"iter = RBA::RecursiveInstanceIterator::new(layout, cell)\n"
|
||||
"iter.unselect_cells(cell.cell_index)\n"
|
||||
"iter.select_cells(\"MACRO\")\n"
|
||||
"...\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"The \\unselect_all_cells and \\select_all_cells methods turn on the \"stop\" and \"start\" flag "
|
||||
"for all cells respectively. If you use \\unselect_all_cells and use \\select_cells for a specific cell, "
|
||||
"the iterator will deliver only the instances of the selected cell, not its children. Those are still "
|
||||
"unselected by \\unselect_all_cells:\n"
|
||||
"\n"
|
||||
"@code\n"
|
||||
"# deliver all instance inside \"MACRO\" but not of child cells:\n"
|
||||
"iter = RBA::RecursiveInstanceIterator::new(layout, cell)\n"
|
||||
"iter.unselect_all_cells\n"
|
||||
"iter.select_cells(\"MACRO\")\n"
|
||||
"...\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"Cell selection is done using cell indexes or glob pattern. Glob pattern are equivalent to the usual "
|
||||
"file name wildcards used on various command line shells. For example \"A*\" matches all cells starting with "
|
||||
"an \"A\". The curly brace notation and character classes are supported as well. For example \"C{125,512}\" matches "
|
||||
"\"C125\" and \"C512\" and \"[ABC]*\" matches all cells starting with an \"A\", a \"B\" or \"C\". \"[^ABC]*\" matches "
|
||||
"all cells not starting with one of that letters.\n"
|
||||
"\n"
|
||||
"To confine instance iteration to instances of certain cells, use the \\targets feature:\n"
|
||||
"\n"
|
||||
"@code\n"
|
||||
"# deliver all instance of \"INV1\":\n"
|
||||
"iter = RBA::RecursiveInstanceIterator::new(layout, cell)\n"
|
||||
"iter.targets = \"INV1\"\n"
|
||||
"...\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"Targets can be specified either as lists of cell indexes or through a glob pattern.\n"
|
||||
"\n"
|
||||
"Instances are always delivered depth-first with child instances before their parents. A default recursive instance "
|
||||
"iterator will first deliver leaf cells, followed by the parent of these cells.\n"
|
||||
"\n"
|
||||
"When a search region is used, instances whose bounding box touch or overlap (depending on 'overlapping' flag) will "
|
||||
"be reported. The instance bounding box taken as reference is computed using all layers of the layout.\n"
|
||||
"\n"
|
||||
"The iterator will deliver the individual elements of instance arrays, confined to the search region if one is given. "
|
||||
"Consequently the return value (\\current_inst_element) is an \\InstElement "
|
||||
"object which is basically a combination of an \\Instance object and information about the current array element.\n"
|
||||
"\\inst_cell, \\inst_trans and \\inst_dtrans are methods provided for convenience to access the current array member's transformation "
|
||||
"and the target cell of the current instance.\n"
|
||||
"\n"
|
||||
"The RecursiveInstanceIterator class has been introduced in version 0.27.\n"
|
||||
);
|
||||
|
||||
}
|
||||
|
|
@ -123,89 +123,89 @@ Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("db", "RecursiveS
|
|||
gsi::constructor ("new", &new_si1, gsi::arg ("layout"), gsi::arg ("cell"), gsi::arg ("layer"),
|
||||
"@brief Creates a recursive, single-layer shape iterator.\n"
|
||||
"@param layout The layout which shall be iterated\n"
|
||||
"@param cell The initial cell which shall be iterated (including it's children)\n"
|
||||
"@param cell The initial cell which shall be iterated (including its children)\n"
|
||||
"@param layer The layer (index) from which the shapes are taken\n"
|
||||
"\n"
|
||||
"This constructor creates a new recursive shape iterator which delivers the shapes of "
|
||||
"the given cell plus it's children from the layer given by the layer index in the \"layer\" parameter.\n"
|
||||
"the given cell plus its children from the layer given by the layer index in the \"layer\" parameter.\n"
|
||||
"\n"
|
||||
"This constructor has been introduced in version 0.23.\n"
|
||||
) +
|
||||
gsi::constructor ("new", &new_si2, gsi::arg ("layout"), gsi::arg ("cell"), gsi::arg ("layers"),
|
||||
"@brief Creates a recursive, multi-layer shape iterator.\n"
|
||||
"@param layout The layout which shall be iterated\n"
|
||||
"@param cell The initial cell which shall be iterated (including it's children)\n"
|
||||
"@param cell The initial cell which shall be iterated (including its children)\n"
|
||||
"@param layers The layer indexes from which the shapes are taken\n"
|
||||
"\n"
|
||||
"This constructor creates a new recursive shape iterator which delivers the shapes of "
|
||||
"the given cell plus it's children from the layers given by the layer indexes in the \"layers\" parameter.\n"
|
||||
"the given cell plus its children from the layers given by the layer indexes in the \"layers\" parameter.\n"
|
||||
"While iterating use the \\layer method to retrieve the layer of the current shape.\n"
|
||||
"\n"
|
||||
"This constructor has been introduced in version 0.23.\n"
|
||||
) +
|
||||
gsi::constructor ("new", &new_si3, gsi::arg ("layout"), gsi::arg ("cell"), gsi::arg ("layer"), gsi::arg ("box"), gsi::arg ("overlapping"),
|
||||
gsi::constructor ("new", &new_si3, gsi::arg ("layout"), gsi::arg ("cell"), gsi::arg ("layer"), gsi::arg ("box"), gsi::arg ("overlapping", false),
|
||||
"@brief Creates a recursive, single-layer shape iterator with a region.\n"
|
||||
"@param layout The layout which shall be iterated\n"
|
||||
"@param cell The initial cell which shall be iterated (including it's children)\n"
|
||||
"@param cell The initial cell which shall be iterated (including its children)\n"
|
||||
"@param layer The layer (index) from which the shapes are taken\n"
|
||||
"@param box The search region\n"
|
||||
"@param overlapping If set to true, shapes overlapping the search region are reported, otherwise touching is sufficient\n"
|
||||
"\n"
|
||||
"This constructor creates a new recursive shape iterator which delivers the shapes of "
|
||||
"the given cell plus it's children from the layer given by the layer index in the \"layer\" parameter.\n"
|
||||
"the given cell plus its children from the layer given by the layer index in the \"layer\" parameter.\n"
|
||||
"\n"
|
||||
"The search is confined to the region given by the \"box\" parameter. If \"overlapping\" is true, shapes whose "
|
||||
"bounding box is overlapping the search region are reported. If \"overlapping\" is false, shapes whose "
|
||||
"bounding box touches the search region are reported.\n"
|
||||
"\n"
|
||||
"This constructor has been introduced in version 0.23.\n"
|
||||
"This constructor has been introduced in version 0.23. The 'overlapping' parameter has been made optional in version 0.27.\n"
|
||||
) +
|
||||
gsi::constructor ("new", &new_si3a, gsi::arg ("layout"), gsi::arg ("cell"), gsi::arg ("layer"), gsi::arg ("region"), gsi::arg ("overlapping"),
|
||||
gsi::constructor ("new", &new_si3a, gsi::arg ("layout"), gsi::arg ("cell"), gsi::arg ("layer"), gsi::arg ("region"), gsi::arg ("overlapping", false),
|
||||
"@brief Creates a recursive, single-layer shape iterator with a region.\n"
|
||||
"@param layout The layout which shall be iterated\n"
|
||||
"@param cell The initial cell which shall be iterated (including it's children)\n"
|
||||
"@param cell The initial cell which shall be iterated (including its children)\n"
|
||||
"@param layer The layer (index) from which the shapes are taken\n"
|
||||
"@param region The search region\n"
|
||||
"@param overlapping If set to true, shapes overlapping the search region are reported, otherwise touching is sufficient\n"
|
||||
"\n"
|
||||
"This constructor creates a new recursive shape iterator which delivers the shapes of "
|
||||
"the given cell plus it's children from the layer given by the layer index in the \"layer\" parameter.\n"
|
||||
"the given cell plus its children from the layer given by the layer index in the \"layer\" parameter.\n"
|
||||
"\n"
|
||||
"The search is confined to the region given by the \"region\" parameter. The region needs to be a rectilinear region.\n"
|
||||
"If \"overlapping\" is true, shapes whose "
|
||||
"bounding box is overlapping the search region are reported. If \"overlapping\" is false, shapes whose "
|
||||
"bounding box touches the search region are reported.\n"
|
||||
"\n"
|
||||
"This constructor has been introduced in version 0.25.\n"
|
||||
"This constructor has been introduced in version 0.25. The 'overlapping' parameter has been made optional in version 0.27.\n"
|
||||
) +
|
||||
gsi::constructor ("new", &new_si4, gsi::arg ("layout"), gsi::arg ("cell"), gsi::arg ("layers"), gsi::arg ("box"), gsi::arg ("overlapping"),
|
||||
gsi::constructor ("new", &new_si4, gsi::arg ("layout"), gsi::arg ("cell"), gsi::arg ("layers"), gsi::arg ("box"), gsi::arg ("overlapping", false),
|
||||
"@brief Creates a recursive, multi-layer shape iterator with a region.\n"
|
||||
"@param layout The layout which shall be iterated\n"
|
||||
"@param cell The initial cell which shall be iterated (including it's children)\n"
|
||||
"@param cell The initial cell which shall be iterated (including its children)\n"
|
||||
"@param layers The layer indexes from which the shapes are taken\n"
|
||||
"@param box The search region\n"
|
||||
"@param overlapping If set to true, shapes overlapping the search region are reported, otherwise touching is sufficient\n"
|
||||
"\n"
|
||||
"This constructor creates a new recursive shape iterator which delivers the shapes of "
|
||||
"the given cell plus it's children from the layers given by the layer indexes in the \"layers\" parameter.\n"
|
||||
"the given cell plus its children from the layers given by the layer indexes in the \"layers\" parameter.\n"
|
||||
"While iterating use the \\layer method to retrieve the layer of the current shape.\n"
|
||||
"\n"
|
||||
"The search is confined to the region given by the \"box\" parameter. If \"overlapping\" is true, shapes whose "
|
||||
"bounding box is overlapping the search region are reported. If \"overlapping\" is false, shapes whose "
|
||||
"bounding box touches the search region are reported.\n"
|
||||
"\n"
|
||||
"This constructor has been introduced in version 0.23.\n"
|
||||
"This constructor has been introduced in version 0.23. The 'overlapping' parameter has been made optional in version 0.27.\n"
|
||||
) +
|
||||
gsi::constructor ("new", &new_si4a, gsi::arg ("layout"), gsi::arg ("cell"), gsi::arg ("layers"), gsi::arg ("region"), gsi::arg ("overlapping"),
|
||||
gsi::constructor ("new", &new_si4a, gsi::arg ("layout"), gsi::arg ("cell"), gsi::arg ("layers"), gsi::arg ("region"), gsi::arg ("overlapping", false),
|
||||
"@brief Creates a recursive, multi-layer shape iterator with a region.\n"
|
||||
"@param layout The layout which shall be iterated\n"
|
||||
"@param cell The initial cell which shall be iterated (including it's children)\n"
|
||||
"@param cell The initial cell which shall be iterated (including its children)\n"
|
||||
"@param layers The layer indexes from which the shapes are taken\n"
|
||||
"@param region The search region\n"
|
||||
"@param overlapping If set to true, shapes overlapping the search region are reported, otherwise touching is sufficient\n"
|
||||
"\n"
|
||||
"This constructor creates a new recursive shape iterator which delivers the shapes of "
|
||||
"the given cell plus it's children from the layers given by the layer indexes in the \"layers\" parameter.\n"
|
||||
"the given cell plus its children from the layers given by the layer indexes in the \"layers\" parameter.\n"
|
||||
"While iterating use the \\layer method to retrieve the layer of the current shape.\n"
|
||||
"\n"
|
||||
"The search is confined to the region given by the \"region\" parameter. The region needs to be a rectilinear region.\n"
|
||||
|
|
@ -213,10 +213,10 @@ Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("db", "RecursiveS
|
|||
"bounding box is overlapping the search region are reported. If \"overlapping\" is false, shapes whose "
|
||||
"bounding box touches the search region are reported.\n"
|
||||
"\n"
|
||||
"This constructor has been introduced in version 0.23.\n"
|
||||
"This constructor has been introduced in version 0.23. The 'overlapping' parameter has been made optional in version 0.27.\n"
|
||||
) +
|
||||
gsi::method ("max_depth=", (void (db::RecursiveShapeIterator::*) (int)) &db::RecursiveShapeIterator::max_depth, gsi::arg ("depth"),
|
||||
"@brief Specify the maximum hierarchy depth to look into\n"
|
||||
"@brief Specifies the maximum hierarchy depth to look into\n"
|
||||
"\n"
|
||||
"A depth of 0 instructs the iterator to deliver only shapes from the initial cell.\n"
|
||||
"The depth must be specified before the shapes are being retrieved.\n"
|
||||
|
|
@ -229,7 +229,23 @@ Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("db", "RecursiveS
|
|||
"\n"
|
||||
"This method has been introduced in version 0.23.\n"
|
||||
) +
|
||||
gsi::method ("reset", &db::RecursiveShapeIterator::reset,
|
||||
gsi::method ("min_depth=", (void (db::RecursiveShapeIterator::*) (int)) &db::RecursiveShapeIterator::min_depth, gsi::arg ("depth"),
|
||||
"@brief Specifies the minimum hierarchy depth to look into\n"
|
||||
"\n"
|
||||
"A depth of 0 instructs the iterator to deliver shapes from the top level.\n"
|
||||
"1 instructs to deliver shapes from the first child level.\n"
|
||||
"The minimum depth must be specified before the shapes are being retrieved.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27.\n"
|
||||
) +
|
||||
gsi::method ("min_depth", (int (db::RecursiveShapeIterator::*) () const) &db::RecursiveShapeIterator::min_depth,
|
||||
"@brief Gets the minimum hierarchy depth\n"
|
||||
"\n"
|
||||
"See \\min_depth= for a description of that attribute.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27.\n"
|
||||
) +
|
||||
gsi::method ("reset", &db::RecursiveShapeIterator::reset,
|
||||
"@brief Resets the iterator to the initial state\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.23.\n"
|
||||
|
|
@ -237,7 +253,7 @@ Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("db", "RecursiveS
|
|||
gsi::method ("reset_selection", &db::RecursiveShapeIterator::reset_selection,
|
||||
"@brief Resets the selection to the default state\n"
|
||||
"\n"
|
||||
"In the initial state, the top cell and it's children are selected. Child cells can be switched on and off "
|
||||
"In the initial state, the top cell and its children are selected. Child cells can be switched on and off "
|
||||
"together with their sub-hierarchy using \\select_cells and \\unselect_cells.\n"
|
||||
"\n"
|
||||
"This method will also reset the iterator.\n"
|
||||
|
|
@ -436,7 +452,7 @@ Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("db", "RecursiveS
|
|||
"@brief Gets the current cell's index \n"
|
||||
) +
|
||||
gsi::method ("next", (void (db::RecursiveShapeIterator::*) ()) &db::RecursiveShapeIterator::next,
|
||||
"@brief Increment the iterator\n"
|
||||
"@brief Increments the iterator\n"
|
||||
"This moves the iterator to the next shape inside the search scope."
|
||||
) +
|
||||
gsi::method ("layer", &db::RecursiveShapeIterator::layer,
|
||||
|
|
@ -462,12 +478,12 @@ Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("db", "RecursiveS
|
|||
"\n"
|
||||
"Two iterators are not equal if they do not point to the same shape.\n"
|
||||
),
|
||||
"@brief An iterator delivering shapes that touch or overlap the given region recursively\n"
|
||||
"@brief An iterator delivering shapes recursively\n"
|
||||
"\n"
|
||||
"The iterator can be obtained from a layout, specifying a starting cell, a layer and optionally a region.\n"
|
||||
"The iterator can be obtained from a cell, a layer and optionally a region.\n"
|
||||
"It simplifies retrieval of shapes from a geometrical region while considering\n"
|
||||
"subcells as well.\n"
|
||||
"Some options can be specified, i.e. the level to which to look into or\n"
|
||||
"Some options can be specified in addition, i.e. the level to which to look into or\n"
|
||||
"shape classes and shape properties. The shapes are retrieved by using the \\shape method,\n"
|
||||
"\\next moves to the next shape and \\at_end tells, if the iterator has move shapes to deliver.\n"
|
||||
"\n"
|
||||
|
|
@ -475,7 +491,7 @@ Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("db", "RecursiveS
|
|||
"\n"
|
||||
"@code\n"
|
||||
"# print the polygon-like objects as seen from the initial cell \"cell\"\n"
|
||||
"iter = layout.begin_shapes(cell_index, layer)\n"
|
||||
"iter = cell.begin_shapes_rec(layer)\n"
|
||||
"while !iter.at_end?\n"
|
||||
" if iter.shape.renders_polygon?\n"
|
||||
" polygon = iter.shape.polygon.transformed(iter.itrans)\n"
|
||||
|
|
@ -485,10 +501,10 @@ Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("db", "RecursiveS
|
|||
"end\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"\\Layout offers three methods to get these iterators: begin_shapes, begin_shapes_touching and begin_shapes_overlapping.\n"
|
||||
"\\Layout#begin_shapes will deliver a standard recursive shape iterator which starts from the given cell and iterates "
|
||||
"over all child cells. \\Layout#begin_shapes_touching delivers a RecursiveShapeIterator which delivers the shapes "
|
||||
"whose bounding boxed touch the given search box. \\Layout#begin_shapes_overlapping delivers all shapes whose bounding box "
|
||||
"\\Cell offers three methods to get these iterators: begin_shapes_rec, begin_shapes_rec_touching and begin_shapes_rec_overlapping.\n"
|
||||
"\\Cell#begin_shapes_rec will deliver a standard recursive shape iterator which starts from the given cell and iterates "
|
||||
"over all child cells. \\Cell#begin_shapes_rec_touching delivers a RecursiveShapeIterator which delivers the shapes "
|
||||
"whose bounding boxed touch the given search box. \\Cell#begin_shapes_rec_overlapping delivers all shapes whose bounding box "
|
||||
"overlaps the search box.\n"
|
||||
"\n"
|
||||
"A RecursiveShapeIterator object can also be created explicitly. This allows some more options, i.e. using "
|
||||
|
|
@ -510,7 +526,7 @@ Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("db", "RecursiveS
|
|||
"sets the \"start delivery\" flag while \\unselect_cells sets the \"stop delivery\" flag. In effect, using "
|
||||
"\\unselect_cells will exclude that cell plus the subtree from delivery. Parts of that subtree can be "
|
||||
"turned on again using \\select_cells. For the cells selected that way, the shapes of these cells and their "
|
||||
"child cells are delivered, even if their parents was unselected.\n"
|
||||
"child cells are delivered, even if their parent was unselected.\n"
|
||||
"\n"
|
||||
"To get shapes from a specific cell, i.e. \"MACRO\" plus its child cells, unselect the top cell first "
|
||||
"and the select the desired cell again:\n"
|
||||
|
|
|
|||
|
|
@ -308,6 +308,18 @@ static db::Region with_area2 (const db::Region *r, const tl::Variant &min, const
|
|||
return r->filtered (f);
|
||||
}
|
||||
|
||||
static db::Region with_holes1 (const db::Region *r, size_t n, bool inverse)
|
||||
{
|
||||
db::HoleCountFilter f (n, n + 1, inverse);
|
||||
return r->filtered (f);
|
||||
}
|
||||
|
||||
static db::Region with_holes2 (const db::Region *r, const tl::Variant &min, const tl::Variant &max, bool inverse)
|
||||
{
|
||||
db::HoleCountFilter f (min.is_nil () ? size_t (0) : min.to<size_t> (), max.is_nil () ? std::numeric_limits <size_t>::max () : max.to<size_t> (), inverse);
|
||||
return r->filtered (f);
|
||||
}
|
||||
|
||||
static db::Region with_bbox_width1 (const db::Region *r, db::Region::distance_type bbox_width, bool inverse)
|
||||
{
|
||||
db::RegionBBoxFilter f (bbox_width, bbox_width + 1, inverse, db::RegionBBoxFilter::BoxWidth);
|
||||
|
|
@ -925,6 +937,30 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method_ext ("with_holes", with_holes1, gsi::arg ("nholes"), gsi::arg ("inverse"),
|
||||
"@brief Filters the polygons by their number of holes\n"
|
||||
"Filters the polygons of the region by number of holes. If \"inverse\" is false, only "
|
||||
"polygons which have the given number of holes are returned. If \"inverse\" is true, "
|
||||
"polygons not having the given of holes are returned.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27.\n"
|
||||
) +
|
||||
method_ext ("with_holes", with_holes2, gsi::arg ("min_bholes"), gsi::arg ("max_nholes"), gsi::arg ("inverse"),
|
||||
"@brief Filter the polygons by their number of holes\n"
|
||||
"Filters the polygons of the region by number of holes. If \"inverse\" is false, only "
|
||||
"polygons which have a hole count larger or equal to \"min_nholes\" and less than \"max_nholes\" are "
|
||||
"returned. If \"inverse\" is true, "
|
||||
"polygons having a hole count less than \"min_nholes\" or larger or equal than \"max_nholes\" are "
|
||||
"returned.\n"
|
||||
"\n"
|
||||
"If you don't want to specify a lower or upper limit, pass nil to that parameter.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27.\n"
|
||||
) +
|
||||
method_ext ("with_bbox_width", with_bbox_width1, gsi::arg ("width"), gsi::arg ("inverse"),
|
||||
"@brief Filter the polygons by bounding box width\n"
|
||||
"Filters the polygons of the region by the width of their bounding box. If \"inverse\" is false, only "
|
||||
|
|
@ -1376,9 +1412,10 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"See \\round_corners for a description of this method. This version returns a new region instead of "
|
||||
"modifying self (out-of-place)."
|
||||
) +
|
||||
method ("smooth", &db::Region::smooth, gsi::arg ("d"),
|
||||
method ("smooth", &db::Region::smooth, gsi::arg ("d"), gsi::arg ("keep_hv", false),
|
||||
"@brief Smoothing\n"
|
||||
"@param d The smoothing tolerance (in database units)\n"
|
||||
"@param keep_hv If true, horizontal and vertical edges are maintained\n"
|
||||
"\n"
|
||||
"This method will simplify the merged polygons of the region by removing vertexes if the "
|
||||
"resulting polygon stays equivalent with the original polygon. Equivalence is measured "
|
||||
|
|
@ -1387,9 +1424,10 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"This method modifies the region. \\smoothed is a method that does the same but returns a new "
|
||||
"region without modifying self. Merged semantics applies for this method.\n"
|
||||
) +
|
||||
method ("smoothed", &db::Region::smoothed, gsi::arg ("d"),
|
||||
method ("smoothed", &db::Region::smoothed, gsi::arg ("d"), gsi::arg ("keep_hv", false),
|
||||
"@brief Smoothing\n"
|
||||
"@param d The smoothing tolerance (in database units)\n"
|
||||
"@param keep_hv If true, horizontal and vertical edges are maintained\n"
|
||||
"\n"
|
||||
"See \\smooth for a description of this method. This version returns a new region instead of "
|
||||
"modifying self (out-of-place). It has been introduced in version 0.25."
|
||||
|
|
|
|||
|
|
@ -733,7 +733,8 @@ TEST(11_RoundAndSmoothed)
|
|||
r1_sized -= r1;
|
||||
|
||||
db::Region rounded = r1_sized.rounded_corners (3000, 5000, 100);
|
||||
db::Region smoothed = rounded.smoothed (100);
|
||||
db::Region smoothed = rounded.smoothed (100, false);
|
||||
db::Region smoothed_keep_hv = rounded.smoothed (100, true);
|
||||
|
||||
db::Layout target;
|
||||
unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index));
|
||||
|
|
@ -741,6 +742,7 @@ TEST(11_RoundAndSmoothed)
|
|||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), r1_sized);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), rounded);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), smoothed);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (13, 0)), smoothed_keep_hv);
|
||||
|
||||
CHECKPOINT();
|
||||
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au11.gds");
|
||||
|
|
|
|||
|
|
@ -1188,8 +1188,8 @@ TEST(100)
|
|||
db::Polygon p;
|
||||
p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0]));
|
||||
|
||||
EXPECT_EQ (smooth (p, 5).to_string (), "(0,-100;0,0;50,10;100,-10;150,0;150,-100)");
|
||||
EXPECT_EQ (smooth (p, 20).to_string (), "(0,-100;0,0;150,0;150,-100)");
|
||||
EXPECT_EQ (smooth (p, 5, true).to_string (), "(0,-100;0,0;50,10;100,-10;150,0;150,-100)");
|
||||
EXPECT_EQ (smooth (p, 20, true).to_string (), "(0,-100;0,0;150,0;150,-100)");
|
||||
}
|
||||
|
||||
// smoothing
|
||||
|
|
@ -1207,8 +1207,8 @@ TEST(101)
|
|||
db::Polygon p;
|
||||
p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0]));
|
||||
|
||||
EXPECT_EQ (smooth (p, 5).to_string (), "(100,-10;50,10;0,0;0,100;150,100;150,0)");
|
||||
EXPECT_EQ (smooth (p, 20).to_string (), "(0,0;0,100;150,100;150,0)");
|
||||
EXPECT_EQ (smooth (p, 5, true).to_string (), "(100,-10;50,10;0,0;0,100;150,100;150,0)");
|
||||
EXPECT_EQ (smooth (p, 20, true).to_string (), "(0,0;0,100;150,100;150,0)");
|
||||
}
|
||||
|
||||
// smoothing
|
||||
|
|
@ -1224,8 +1224,8 @@ TEST(102)
|
|||
db::Polygon p;
|
||||
p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0]));
|
||||
|
||||
EXPECT_EQ (smooth (p, 20).to_string (), "()");
|
||||
EXPECT_EQ (smooth (p, 5).to_string (), "(100,-10;150,0;0,0;50,10)");
|
||||
EXPECT_EQ (smooth (p, 20, true).to_string (), "()");
|
||||
EXPECT_EQ (smooth (p, 5, true).to_string (), "(100,-10;150,0;0,0;50,10)");
|
||||
}
|
||||
|
||||
// smoothing
|
||||
|
|
@ -1251,9 +1251,9 @@ TEST(103)
|
|||
db::Polygon p;
|
||||
p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0]));
|
||||
|
||||
EXPECT_EQ (smooth (p, 0).to_string (), "(59881,-249925;56852,-237283;56961,-237258;60061,-236492;63152,-235686;66231,-234839;69300,-233952;69407,-233919;73105,-246382;72992,-246417;69760,-247351;66516,-248243;63261,-249092;59995,-249899)");
|
||||
EXPECT_EQ (smooth (p, 50).to_string (), "(59881,-249925;56852,-237283;63152,-235686;69407,-233919;73105,-246382;69760,-247351)");
|
||||
EXPECT_EQ (smooth (p, 5000).to_string (), "(59881,-249925;56852,-237283;69407,-233919;73105,-246382)");
|
||||
EXPECT_EQ (smooth (p, 0, true).to_string (), "(59881,-249925;56852,-237283;56961,-237258;60061,-236492;63152,-235686;66231,-234839;69300,-233952;69407,-233919;73105,-246382;72992,-246417;69760,-247351;66516,-248243;63261,-249092;59995,-249899)");
|
||||
EXPECT_EQ (smooth (p, 50, true).to_string (), "(59881,-249925;56852,-237283;63152,-235686;69407,-233919;73105,-246382;69760,-247351)");
|
||||
EXPECT_EQ (smooth (p, 5000, true).to_string (), "(59881,-249925;56852,-237283;69407,-233919;73105,-246382)");
|
||||
}
|
||||
|
||||
// smoothing
|
||||
|
|
@ -1272,7 +1272,8 @@ TEST(104)
|
|||
db::Polygon p;
|
||||
p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0]));
|
||||
|
||||
EXPECT_EQ (smooth (p, 12).to_string (), "(-244,-942;-942,-246;248,943;943,246)");
|
||||
EXPECT_EQ (smooth (p, 12, false).to_string (), "(-244,-942;-942,-246;248,943;943,246)");
|
||||
EXPECT_EQ (smooth (p, 12, true).to_string (), "(-245,-942;-942,-247;-942,-246;247,943;248,943;943,246;-244,-942)");
|
||||
}
|
||||
|
||||
// smoothing
|
||||
|
|
@ -1292,11 +1293,46 @@ TEST(105)
|
|||
db::Polygon p;
|
||||
p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0]));
|
||||
|
||||
EXPECT_EQ (smooth (p, 0).to_string (), "(0,0;0,1000;100,1000;100,1100;800,1100;800,1000;2000,1000;2000,0)");
|
||||
EXPECT_EQ (smooth (p, 50).to_string (), "(0,0;0,1000;100,1000;100,1100;800,1100;800,1000;2000,1000;2000,0)");
|
||||
EXPECT_EQ (smooth (p, 80).to_string (), "(0,0;0,1000;100,1100;800,1100;800,1000;2000,1000;2000,0)");
|
||||
EXPECT_EQ (smooth (p, 90).to_string (), "(0,0;100,1100;800,1100;800,1000;2000,1000;2000,0)");
|
||||
EXPECT_EQ (smooth (p, 100).to_string (), "(0,0;0,1000;2000,1000;2000,0)");
|
||||
EXPECT_EQ (smooth (p, 0, false).to_string (), "(0,0;0,1000;100,1000;100,1100;800,1100;800,1000;2000,1000;2000,0)");
|
||||
EXPECT_EQ (smooth (p, 50, false).to_string (), "(0,0;0,1000;100,1000;100,1100;800,1100;800,1000;2000,1000;2000,0)");
|
||||
EXPECT_EQ (smooth (p, 80, false).to_string (), "(0,0;0,1000;100,1100;800,1100;800,1000;2000,1000;2000,0)");
|
||||
EXPECT_EQ (smooth (p, 90, false).to_string (), "(0,0;100,1100;800,1100;800,1000;2000,1000;2000,0)");
|
||||
EXPECT_EQ (smooth (p, 100, false).to_string (), "(0,0;0,1000;2000,1000;2000,0)");
|
||||
EXPECT_EQ (smooth (p, 100, true).to_string (), "(0,0;0,1000;100,1000;100,1100;800,1100;800,1000;2000,1000;2000,0)");
|
||||
}
|
||||
|
||||
// smoothing
|
||||
TEST(106)
|
||||
{
|
||||
db::Point pattern [] = {
|
||||
db::Point (0, 0),
|
||||
db::Point (0, 73235),
|
||||
db::Point (100, 74568),
|
||||
db::Point (700, 82468),
|
||||
db::Point (1200, 90468),
|
||||
db::Point (2000, 106468),
|
||||
db::Point (2300, 114468),
|
||||
db::Point (2700, 130468),
|
||||
db::Point (2800, 138468),
|
||||
db::Point (2800, 154468),
|
||||
db::Point (2700, 162468),
|
||||
db::Point (2300, 178468),
|
||||
db::Point (2000, 186468),
|
||||
db::Point (1200, 202468),
|
||||
db::Point (700, 210468),
|
||||
db::Point (100, 218368),
|
||||
db::Point (0, 219701),
|
||||
db::Point (0, 272971),
|
||||
db::Point (126450, 272971),
|
||||
db::Point (126450, 0),
|
||||
};
|
||||
|
||||
db::Polygon p;
|
||||
p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0]));
|
||||
|
||||
EXPECT_EQ (smooth (p, 0, false).to_string (), "(0,0;0,73235;100,74568;700,82468;1200,90468;2000,106468;2300,114468;2700,130468;2800,138468;2800,154468;2700,162468;2300,178468;2000,186468;1200,202468;700,210468;100,218368;0,219701;0,272971;126450,272971;126450,0)");
|
||||
EXPECT_EQ (smooth (p, 100, false).to_string (), "(0,0;100,74568;1200,90468;2300,114468;2800,138468;2700,162468;2000,186468;700,210468;0,219701;0,272971;126450,272971;126450,0)");
|
||||
EXPECT_EQ (smooth (p, 100, true).to_string (), "(0,0;0,73235;1200,90468;2300,114468;2800,138468;2800,154468;2000,186468;700,210468;0,219701;0,272971;126450,272971;126450,0)");
|
||||
}
|
||||
|
||||
// rounding
|
||||
|
|
@ -1501,7 +1537,7 @@ TEST(203)
|
|||
in.push_back (pp);
|
||||
ep.simple_merge (in, out, false /*no cut line*/);
|
||||
pp = out.front ();
|
||||
pp = smooth (pp, 1);
|
||||
pp = smooth (pp, 1, true);
|
||||
|
||||
EXPECT_EQ (pp.hull ().size (), size_t (300));
|
||||
EXPECT_EQ (extract_rad (pp, rinner, router, n, &pr), true);
|
||||
|
|
@ -1547,7 +1583,7 @@ TEST(204)
|
|||
in.push_back (pp);
|
||||
ep.simple_merge (in, out, false /*no cut line*/);
|
||||
pp = out.front ();
|
||||
pp = smooth (pp, 1);
|
||||
pp = smooth (pp, 1, true);
|
||||
|
||||
EXPECT_EQ (pp.hull ().size (), size_t (200));
|
||||
EXPECT_EQ (extract_rad (pp, rinner, router, n, &pr), true);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,621 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2021 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "dbRecursiveInstanceIterator.h"
|
||||
#include "dbRegion.h"
|
||||
#include "dbLayoutDiff.h"
|
||||
#include "tlString.h"
|
||||
#include "tlUnitTest.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
std::string collect(db::RecursiveInstanceIterator &s, const db::Layout &layout)
|
||||
{
|
||||
std::string res;
|
||||
while (! s.at_end ()) {
|
||||
if (! res.empty ()) {
|
||||
res += "/";
|
||||
}
|
||||
if (s.cell ()) {
|
||||
res += std::string ("[") + layout.cell_name (s.cell ()->cell_index ()) + "]";
|
||||
} else {
|
||||
res += "[]";
|
||||
}
|
||||
res += s->inst_ptr.to_string (true);
|
||||
++s;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
std::string collect_with_copy(db::RecursiveInstanceIterator s, const db::Layout &layout)
|
||||
{
|
||||
s.reset ();
|
||||
return collect (s, layout);
|
||||
}
|
||||
|
||||
TEST(1)
|
||||
{
|
||||
db::Manager m (true);
|
||||
db::Layout g (&m);
|
||||
g.insert_layer (0);
|
||||
g.insert_layer (1);
|
||||
g.insert_layer (2);
|
||||
|
||||
db::Cell &c0 (g.cell (g.add_cell ()));
|
||||
|
||||
db::RecursiveInstanceIterator idef;
|
||||
EXPECT_EQ (idef.at_end (), true);
|
||||
EXPECT_EQ (collect (idef, g), "");
|
||||
EXPECT_EQ (collect_with_copy (idef, g), "");
|
||||
|
||||
db::RecursiveInstanceIterator i00 (g, c0, db::Box (0, 0, 100, 100));
|
||||
EXPECT_EQ (collect (i00, g), "");
|
||||
EXPECT_EQ (collect_with_copy (i00, g), "");
|
||||
|
||||
db::Cell &c1 (g.cell (g.add_cell ()));
|
||||
db::Cell &c2 (g.cell (g.add_cell ()));
|
||||
db::Cell &c3 (g.cell (g.add_cell ()));
|
||||
|
||||
db::RecursiveInstanceIterator i0 (g, c0, db::Box (0, 0, 100, 100));
|
||||
EXPECT_EQ (collect (i0, g), "");
|
||||
EXPECT_EQ (collect_with_copy (i0, g), "");
|
||||
|
||||
db::Box b (0, 100, 1000, 1200);
|
||||
c0.shapes (0).insert (b);
|
||||
c1.shapes (0).insert (b);
|
||||
c2.shapes (0).insert (b);
|
||||
c3.shapes (0).insert (b);
|
||||
|
||||
c0.shapes (2).insert (b);
|
||||
c0.shapes (2).insert (b.moved (db::Vector (50, 50)));
|
||||
|
||||
db::Trans tt;
|
||||
c0.insert (db::CellInstArray (db::CellInst (c1.cell_index ()), tt));
|
||||
c0.insert (db::CellInstArray (db::CellInst (c2.cell_index ()), db::Trans (db::Vector (100, -100))));
|
||||
c0.insert (db::CellInstArray (db::CellInst (c3.cell_index ()), db::Trans (1)));
|
||||
c2.insert (db::CellInstArray (db::CellInst (c3.cell_index ()), db::Trans (db::Vector (1100, 0))));
|
||||
|
||||
std::string x;
|
||||
|
||||
db::RecursiveInstanceIterator i1 (g, c0, db::Box (0, 0, 100, 100));
|
||||
x = collect(i1, g);
|
||||
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$1]$3 r0 100,-100");
|
||||
x = collect_with_copy(i1, g);
|
||||
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$1]$3 r0 100,-100");
|
||||
|
||||
db::RecursiveInstanceIterator i1_1inf (g, c0, db::Box (0, 0, 100, 100));
|
||||
i1_1inf.min_depth(0);
|
||||
x = collect(i1_1inf, g);
|
||||
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$1]$3 r0 100,-100");
|
||||
x = collect_with_copy(i1_1inf, g);
|
||||
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$1]$3 r0 100,-100");
|
||||
|
||||
db::RecursiveInstanceIterator i1_11 (g, c0, db::Box (0, 0, 2000, 100));
|
||||
i1_11.min_depth(0);
|
||||
i1_11.max_depth(0);
|
||||
x = collect(i1_11, g);
|
||||
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$1]$3 r0 100,-100");
|
||||
x = collect_with_copy(i1_11, g);
|
||||
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$1]$3 r0 100,-100");
|
||||
|
||||
db::RecursiveInstanceIterator i1_12 (g, c0, db::Box (0, 0, 2000, 100));
|
||||
i1_12.min_depth(0);
|
||||
i1_12.max_depth(1);
|
||||
x = collect(i1_12, g);
|
||||
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$3]$4 r0 1100,0/[$1]$3 r0 100,-100");
|
||||
x = collect_with_copy(i1_12, g);
|
||||
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$3]$4 r0 1100,0/[$1]$3 r0 100,-100");
|
||||
|
||||
db::RecursiveInstanceIterator i1_22 (g, c0, db::Box (0, 0, 2000, 100));
|
||||
i1_22.min_depth(1);
|
||||
i1_22.max_depth(1);
|
||||
x = collect(i1_22, g);
|
||||
EXPECT_EQ (x, "[$3]$4 r0 1100,0");
|
||||
x = collect_with_copy(i1_22, g);
|
||||
EXPECT_EQ (x, "[$3]$4 r0 1100,0");
|
||||
|
||||
db::RecursiveInstanceIterator i1o (g, c0, db::Box (0, 0, 100, 100), true);
|
||||
x = collect(i1o, g);
|
||||
EXPECT_EQ (x, "");
|
||||
x = collect_with_copy(i1o, g);
|
||||
EXPECT_EQ (x, "");
|
||||
i1o = db::RecursiveInstanceIterator (g, c0, db::Box (0, 0, 100, 101), true);
|
||||
x = collect(i1o, g);
|
||||
EXPECT_EQ (x, "[$1]$2 r0 0,0");
|
||||
x = collect_with_copy(i1o, g);
|
||||
EXPECT_EQ (x, "[$1]$2 r0 0,0");
|
||||
i1o = db::RecursiveInstanceIterator (g, c0, db::Box (0, 0, 101, 101), true);
|
||||
x = collect(i1o, g);
|
||||
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$1]$3 r0 100,-100");
|
||||
x = collect_with_copy(i1o, g);
|
||||
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$1]$3 r0 100,-100");
|
||||
|
||||
db::RecursiveInstanceIterator i2 (g, c0, db::Box (-100, 0, 100, 100));
|
||||
db::RecursiveInstanceIterator i2c = i2;
|
||||
x = collect(i2, g);
|
||||
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
||||
x = collect_with_copy(i2, g);
|
||||
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
||||
x = collect(i2c, g);
|
||||
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
||||
x = collect_with_copy(i2c, g);
|
||||
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
||||
db::RecursiveInstanceIterator i2o (g, c0, db::Box (-100, 0, 100, 100), true);
|
||||
x = collect(i2o, g);
|
||||
EXPECT_EQ (x, "");
|
||||
x = collect_with_copy(i2o, g);
|
||||
EXPECT_EQ (x, "");
|
||||
i2o = db::RecursiveInstanceIterator (g, c0, db::Box (-101, 0, 101, 101), true);
|
||||
x = collect(i2o, g);
|
||||
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
||||
x = collect_with_copy(i2o, g);
|
||||
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
||||
|
||||
db::Region r;
|
||||
r.insert (db::Box (-600, -100, -500, 0));
|
||||
r.insert (db::Box (1600, 0, 1700, 100));
|
||||
db::RecursiveInstanceIterator i2r (g, c0, r);
|
||||
db::RecursiveInstanceIterator i2rc = i2r;
|
||||
x = collect(i2r, g);
|
||||
EXPECT_EQ (x, "[$3]$4 r0 1100,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
||||
x = collect_with_copy(i2r, g);
|
||||
EXPECT_EQ (x, "[$3]$4 r0 1100,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
||||
x = collect(i2rc, g);
|
||||
EXPECT_EQ (x, "[$3]$4 r0 1100,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
||||
x = collect_with_copy(i2rc, g);
|
||||
EXPECT_EQ (x, "[$3]$4 r0 1100,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
||||
db::RecursiveInstanceIterator i2ro (g, c0, r, true);
|
||||
x = collect(i2ro, g);
|
||||
EXPECT_EQ (x, "[$3]$4 r0 1100,0/[$1]$3 r0 100,-100");
|
||||
x = collect_with_copy(i2ro, g);
|
||||
EXPECT_EQ (x, "[$3]$4 r0 1100,0/[$1]$3 r0 100,-100");
|
||||
|
||||
db::RecursiveInstanceIterator i4 (g, c0, db::Box (-100, 0, 2000, 100));
|
||||
db::RecursiveInstanceIterator i4_copy (g, c0, db::Box (-100, 0, 2000, 100));
|
||||
i4.max_depth (0);
|
||||
x = collect(i4, g);
|
||||
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
||||
x = collect_with_copy(i4, g);
|
||||
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
||||
|
||||
EXPECT_EQ (i4 == i4, true);
|
||||
EXPECT_EQ (i4 != i4, false);
|
||||
EXPECT_EQ (i4 == i4_copy, false);
|
||||
EXPECT_EQ (i4 != i4_copy, true);
|
||||
i4 = i4_copy;
|
||||
EXPECT_EQ (i4 == i4_copy, true);
|
||||
EXPECT_EQ (i4 != i4_copy, false);
|
||||
i4.max_depth (1);
|
||||
x = collect(i4, g);
|
||||
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$3]$4 r0 1100,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
||||
x = collect_with_copy(i4, g);
|
||||
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$3]$4 r0 1100,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
||||
|
||||
i4 = i4_copy;
|
||||
x = collect(i4, g);
|
||||
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$3]$4 r0 1100,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
||||
x = collect_with_copy(i4, g);
|
||||
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$3]$4 r0 1100,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
||||
|
||||
db::RecursiveInstanceIterator i5 (g, c0, db::Box::world ());
|
||||
x = collect(i5, g);
|
||||
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$3]$4 r0 1100,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
||||
x = collect_with_copy(i5, g);
|
||||
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$3]$4 r0 1100,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
||||
|
||||
std::set<db::cell_index_type> cc;
|
||||
db::RecursiveInstanceIterator ii;
|
||||
|
||||
ii = db::RecursiveInstanceIterator (g, c0, db::Box::world ());
|
||||
cc.clear ();
|
||||
cc.insert (c2.cell_index ());
|
||||
ii.unselect_all_cells ();
|
||||
ii.select_cells (cc);
|
||||
x = collect(ii, g);
|
||||
EXPECT_EQ (x, "[$3]$4 r0 1100,0");
|
||||
x = collect_with_copy(ii, g);
|
||||
EXPECT_EQ (x, "[$3]$4 r0 1100,0");
|
||||
ii.reset ();
|
||||
x = collect(ii, g);
|
||||
EXPECT_EQ (x, "[$3]$4 r0 1100,0");
|
||||
x = collect_with_copy(ii, g);
|
||||
EXPECT_EQ (x, "[$3]$4 r0 1100,0");
|
||||
|
||||
ii.reset_selection ();
|
||||
x = collect(ii, g);
|
||||
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$3]$4 r0 1100,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
||||
x = collect_with_copy(ii, g);
|
||||
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$3]$4 r0 1100,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
||||
|
||||
ii.reset_selection ();
|
||||
cc.clear ();
|
||||
cc.insert (c0.cell_index ());
|
||||
cc.insert (c2.cell_index ());
|
||||
ii.unselect_cells (cc);
|
||||
cc.clear ();
|
||||
cc.insert (c2.cell_index ());
|
||||
ii.select_cells (cc);
|
||||
x = collect(ii, g);
|
||||
EXPECT_EQ (x, "[$3]$4 r0 1100,0");
|
||||
x = collect_with_copy(ii, g);
|
||||
EXPECT_EQ (x, "[$3]$4 r0 1100,0");
|
||||
|
||||
ii = db::RecursiveInstanceIterator (g, c0, db::Box::world ());
|
||||
ii.unselect_all_cells ();
|
||||
cc.clear ();
|
||||
cc.insert (c0.cell_index ());
|
||||
ii.select_cells (cc);
|
||||
x = collect(ii, g);
|
||||
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
||||
x = collect_with_copy(ii, g);
|
||||
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
||||
|
||||
db::RecursiveInstanceIterator i1z (g, c0);
|
||||
EXPECT_EQ (i1z.all_targets_enabled (), true);
|
||||
std::set<db::cell_index_type> ct;
|
||||
ct.insert (c3.cell_index ());
|
||||
i1z.set_targets (ct);
|
||||
EXPECT_EQ (i1z.all_targets_enabled (), false);
|
||||
EXPECT_EQ (i1z.targets () == ct, true);
|
||||
i1z.enable_all_targets ();
|
||||
EXPECT_EQ (i1z.all_targets_enabled (), true);
|
||||
|
||||
i1z.set_targets (ct);
|
||||
EXPECT_EQ (i1z.all_targets_enabled (), false);
|
||||
|
||||
x = collect(i1z, g);
|
||||
EXPECT_EQ (x, "[$3]$4 r0 1100,0/[$1]$4 r90 0,0");
|
||||
x = collect_with_copy(i1z, g);
|
||||
EXPECT_EQ (x, "[$3]$4 r0 1100,0/[$1]$4 r90 0,0");
|
||||
}
|
||||
|
||||
static db::Layout boxes2layout (const std::set<db::Box> &boxes)
|
||||
{
|
||||
db::Layout l;
|
||||
l.insert_layer(0, db::LayerProperties (1, 0));
|
||||
db::Cell &top (l.cell (l.add_cell ()));
|
||||
|
||||
for (std::set<db::Box>::const_iterator b = boxes.begin (); b != boxes.end (); ++b) {
|
||||
top.shapes (0).insert (*b);
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class FlatPusher
|
||||
: public db::RecursiveInstanceReceiver
|
||||
{
|
||||
public:
|
||||
FlatPusher (std::set<db::Box> *boxes) : mp_boxes (boxes) { }
|
||||
|
||||
void enter_cell (const db::RecursiveInstanceIterator *iter, const db::Cell *cell, const db::Box & /*region*/, const box_tree_type * /*complex_region*/)
|
||||
{
|
||||
mp_boxes->insert (iter->trans () * cell->bbox ());
|
||||
}
|
||||
|
||||
private:
|
||||
std::set<db::Box> *mp_boxes;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
TEST(2)
|
||||
{
|
||||
// Big fun with cells
|
||||
|
||||
db::Manager m (true);
|
||||
db::Layout g (&m);
|
||||
g.insert_layer(0);
|
||||
|
||||
db::Cell &c0 (g.cell (g.add_cell ()));
|
||||
db::Cell &c1 (g.cell (g.add_cell ()));
|
||||
|
||||
db::Box basic_box (0, 0, 10, 10);
|
||||
c1.shapes (0).insert (basic_box);
|
||||
|
||||
std::set<db::Box> boxes;
|
||||
|
||||
for (int i = 0; i < 100000; ++i) {
|
||||
|
||||
int x = rand () % 10000;
|
||||
int y = rand () % 10000;
|
||||
|
||||
boxes.insert (basic_box.moved (db::Vector (x, y)));
|
||||
|
||||
c0.insert (db::CellInstArray (db::CellInst (c1.cell_index ()), db::Trans (db::Vector (x, y))));
|
||||
|
||||
}
|
||||
|
||||
db::Box search_box (2500, 2500, 7500, 7500);
|
||||
|
||||
std::set<db::Box> selected_boxes;
|
||||
std::set<db::Box> selected_boxes2;
|
||||
|
||||
for (db::RecursiveInstanceIterator iter = db::RecursiveInstanceIterator (g, c0, search_box, true); !iter.at_end (); ++iter) {
|
||||
selected_boxes.insert (iter.trans () * iter->inst_ptr.bbox ());
|
||||
}
|
||||
|
||||
for (std::set<db::Box>::const_iterator b = boxes.begin (); b != boxes.end (); ++b) {
|
||||
if (search_box.overlaps (*b)) {
|
||||
selected_boxes2.insert (*b);
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_EQ (selected_boxes.size () > 100, true);
|
||||
EXPECT_EQ (db::compare_layouts (boxes2layout (selected_boxes), boxes2layout (selected_boxes2), db::layout_diff::f_verbose, 0, 100 /*max diff lines*/), true);
|
||||
|
||||
// push mode
|
||||
{
|
||||
selected_boxes.clear ();
|
||||
FlatPusher pusher (&selected_boxes);
|
||||
db::RecursiveInstanceIterator (g, c0, search_box, true).push (&pusher);
|
||||
}
|
||||
|
||||
EXPECT_EQ (selected_boxes.size () > 100, true);
|
||||
EXPECT_EQ (db::compare_layouts (boxes2layout (selected_boxes), boxes2layout (selected_boxes2), db::layout_diff::f_verbose, 0, 100 /*max diff lines*/), true);
|
||||
|
||||
db::Box search_box2 (500, 500, 1000, 1000);
|
||||
|
||||
selected_boxes.clear ();
|
||||
selected_boxes2.clear ();
|
||||
|
||||
db::Region reg;
|
||||
reg.insert (search_box);
|
||||
reg.insert (search_box2);
|
||||
|
||||
for (db::RecursiveInstanceIterator iter = db::RecursiveInstanceIterator (g, c0, reg, true); !iter.at_end (); ++iter) {
|
||||
selected_boxes.insert (iter.trans () * iter->bbox (db::box_convert<db::CellInst> (g)));
|
||||
}
|
||||
|
||||
for (std::set<db::Box>::const_iterator b = boxes.begin (); b != boxes.end (); ++b) {
|
||||
if (search_box.overlaps (*b) || search_box2.overlaps (*b)) {
|
||||
selected_boxes2.insert (*b);
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_EQ (selected_boxes.size () > 100, true);
|
||||
EXPECT_EQ (db::compare_layouts (boxes2layout (selected_boxes), boxes2layout (selected_boxes2), db::layout_diff::f_verbose, 0, 100 /*max diff lines*/), true);
|
||||
|
||||
// push mode
|
||||
{
|
||||
selected_boxes.clear ();
|
||||
FlatPusher pusher (&selected_boxes);
|
||||
db::RecursiveInstanceIterator (g, c0, reg, true).push (&pusher);
|
||||
}
|
||||
|
||||
EXPECT_EQ (selected_boxes.size () > 100, true);
|
||||
EXPECT_EQ (db::compare_layouts (boxes2layout (selected_boxes), boxes2layout (selected_boxes2), db::layout_diff::f_verbose, 0, 100 /*max diff lines*/), true);
|
||||
}
|
||||
|
||||
TEST(3)
|
||||
{
|
||||
// Big fun with cells - 2 hierarchy levels
|
||||
|
||||
db::Manager m (true);
|
||||
db::Layout g (&m);
|
||||
g.insert_layer(0);
|
||||
|
||||
db::Cell &c0 (g.cell (g.add_cell ()));
|
||||
db::Cell &c1 (g.cell (g.add_cell ()));
|
||||
db::Cell &c2 (g.cell (g.add_cell ()));
|
||||
|
||||
db::Box basic_box (0, 0, 10, 10);
|
||||
c2.shapes (0).insert (basic_box);
|
||||
c1.insert (db::CellInstArray (c2.cell_index (), db::Trans (db::Vector (1, -1))));
|
||||
|
||||
std::set<db::Box> boxes;
|
||||
|
||||
int nboxes = 100000;
|
||||
for (int i = 0; i < nboxes; ++i) {
|
||||
|
||||
int x, y;
|
||||
|
||||
do {
|
||||
x = rand () % 10000;
|
||||
y = rand () % 10000;
|
||||
} while (boxes.find (basic_box.moved (db::Vector (x + 1, y - 1))) != boxes.end ());
|
||||
|
||||
boxes.insert (basic_box.moved (db::Vector (x + 1, y - 1)));
|
||||
|
||||
c0.insert (db::CellInstArray (db::CellInst (c1.cell_index ()), db::Trans (db::Vector (x, y))));
|
||||
|
||||
}
|
||||
|
||||
db::Box search_box (2500, 2500, 7500, 7500);
|
||||
|
||||
std::set<db::Box> selected_boxes;
|
||||
std::set<db::Box> selected_boxes2;
|
||||
|
||||
db::RecursiveInstanceIterator iter = db::RecursiveInstanceIterator (g, c0, search_box, true);
|
||||
std::set<db::cell_index_type> tc;
|
||||
tc.insert (c2.cell_index ());
|
||||
iter.set_targets (tc);
|
||||
int n = 0;
|
||||
for ( ; !iter.at_end (); ++iter) {
|
||||
++n;
|
||||
selected_boxes.insert (iter.trans () * iter->bbox (db::box_convert<db::CellInst> (g)));
|
||||
}
|
||||
|
||||
int nn = 0;
|
||||
for (std::set<db::Box>::const_iterator b = boxes.begin (); b != boxes.end (); ++b) {
|
||||
if (search_box.overlaps (*b)) {
|
||||
++nn;
|
||||
selected_boxes2.insert (*b);
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_EQ (n, nn);
|
||||
|
||||
EXPECT_EQ (selected_boxes.size () > 100, true);
|
||||
EXPECT_EQ (db::compare_layouts (boxes2layout (selected_boxes), boxes2layout (selected_boxes2), db::layout_diff::f_verbose, 0, 100 /*max diff lines*/), true);
|
||||
|
||||
// push mode
|
||||
{
|
||||
selected_boxes.clear ();
|
||||
FlatPusher pusher (&selected_boxes);
|
||||
db::RecursiveInstanceIterator (g, c0, search_box, true).push (&pusher);
|
||||
}
|
||||
|
||||
EXPECT_EQ (selected_boxes.size () > 100, true);
|
||||
EXPECT_EQ (db::compare_layouts (boxes2layout (selected_boxes), boxes2layout (selected_boxes2), db::layout_diff::f_verbose, 0, 100 /*max diff lines*/), true);
|
||||
|
||||
db::Box search_box2 (500, 500, 1000, 1000);
|
||||
|
||||
selected_boxes.clear ();
|
||||
selected_boxes2.clear ();
|
||||
|
||||
db::Region reg;
|
||||
reg.insert (search_box);
|
||||
reg.insert (search_box2);
|
||||
|
||||
for (db::RecursiveInstanceIterator iter = db::RecursiveInstanceIterator (g, c0, reg, true); !iter.at_end (); ++iter) {
|
||||
selected_boxes.insert (iter.trans () * iter->bbox (db::box_convert<db::CellInst> (g)));
|
||||
}
|
||||
|
||||
for (std::set<db::Box>::const_iterator b = boxes.begin (); b != boxes.end (); ++b) {
|
||||
if (search_box.overlaps (*b) || search_box2.overlaps (*b)) {
|
||||
selected_boxes2.insert (*b);
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_EQ (selected_boxes.size () > 100, true);
|
||||
EXPECT_EQ (db::compare_layouts (boxes2layout (selected_boxes), boxes2layout (selected_boxes2), db::layout_diff::f_verbose, 0, 100 /*max diff lines*/), true);
|
||||
|
||||
// push mode
|
||||
{
|
||||
selected_boxes.clear ();
|
||||
FlatPusher pusher (&selected_boxes);
|
||||
db::RecursiveInstanceIterator (g, c0, reg, true).push (&pusher);
|
||||
}
|
||||
|
||||
EXPECT_EQ (selected_boxes.size () > 100, true);
|
||||
EXPECT_EQ (db::compare_layouts (boxes2layout (selected_boxes), boxes2layout (selected_boxes2), db::layout_diff::f_verbose, 0, 100 /*max diff lines*/), true);
|
||||
}
|
||||
|
||||
TEST(4)
|
||||
{
|
||||
// Big fun with cells - 2 hierarchy levels + touching mode
|
||||
|
||||
db::Manager m (true);
|
||||
db::Layout g (&m);
|
||||
g.insert_layer(0);
|
||||
|
||||
db::Cell &c0 (g.cell (g.add_cell ()));
|
||||
db::Cell &c1 (g.cell (g.add_cell ()));
|
||||
db::Cell &c2 (g.cell (g.add_cell ()));
|
||||
|
||||
db::Box basic_box (0, 0, 10, 10);
|
||||
c2.shapes (0).insert (basic_box);
|
||||
c1.insert (db::CellInstArray (c2.cell_index (), db::Trans (db::Vector (1, -1))));
|
||||
|
||||
std::set<db::Box> boxes;
|
||||
|
||||
int nboxes = 100000;
|
||||
for (int i = 0; i < nboxes; ++i) {
|
||||
|
||||
int x, y;
|
||||
|
||||
do {
|
||||
x = rand () % 10000;
|
||||
y = rand () % 10000;
|
||||
} while (boxes.find (basic_box.moved (db::Vector (x + 1, y - 1))) != boxes.end ());
|
||||
|
||||
boxes.insert (basic_box.moved (db::Vector (x + 1, y - 1)));
|
||||
|
||||
c0.insert (db::CellInstArray (db::CellInst (c1.cell_index ()), db::Trans (db::Vector (x, y))));
|
||||
|
||||
}
|
||||
|
||||
db::Box search_box (2500, 2500, 7500, 7500);
|
||||
|
||||
std::set<db::Box> selected_boxes;
|
||||
std::set<db::Box> selected_boxes2;
|
||||
|
||||
db::RecursiveInstanceIterator iter = db::RecursiveInstanceIterator (g, c0, search_box);
|
||||
std::set<db::cell_index_type> tc;
|
||||
tc.insert (c2.cell_index ());
|
||||
iter.set_targets (tc);
|
||||
int n = 0;
|
||||
for ( ; !iter.at_end (); ++iter) {
|
||||
++n;
|
||||
selected_boxes.insert (iter.trans () * iter->bbox (db::box_convert<db::CellInst> (g)));
|
||||
}
|
||||
|
||||
int nn = 0;
|
||||
for (std::set<db::Box>::const_iterator b = boxes.begin (); b != boxes.end (); ++b) {
|
||||
if (search_box.touches (*b)) {
|
||||
++nn;
|
||||
selected_boxes2.insert (*b);
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_EQ (n, nn);
|
||||
|
||||
EXPECT_EQ (selected_boxes.size () > 100, true);
|
||||
EXPECT_EQ (db::compare_layouts (boxes2layout (selected_boxes), boxes2layout (selected_boxes2), db::layout_diff::f_verbose, 0, 100 /*max diff lines*/), true);
|
||||
|
||||
// push mode
|
||||
{
|
||||
selected_boxes.clear ();
|
||||
FlatPusher pusher (&selected_boxes);
|
||||
db::RecursiveInstanceIterator (g, c0, search_box).push (&pusher);
|
||||
}
|
||||
|
||||
EXPECT_EQ (selected_boxes.size () > 100, true);
|
||||
EXPECT_EQ (db::compare_layouts (boxes2layout (selected_boxes), boxes2layout (selected_boxes2), db::layout_diff::f_verbose, 0, 100 /*max diff lines*/), true);
|
||||
|
||||
db::Box search_box2 (500, 500, 1000, 1000);
|
||||
|
||||
selected_boxes.clear ();
|
||||
selected_boxes2.clear ();
|
||||
|
||||
db::Region reg;
|
||||
reg.insert (search_box);
|
||||
reg.insert (search_box2);
|
||||
|
||||
for (db::RecursiveInstanceIterator iter = db::RecursiveInstanceIterator (g, c0, reg); !iter.at_end (); ++iter) {
|
||||
selected_boxes.insert (iter.trans () * iter->bbox (db::box_convert<db::CellInst> (g)));
|
||||
}
|
||||
|
||||
for (std::set<db::Box>::const_iterator b = boxes.begin (); b != boxes.end (); ++b) {
|
||||
if (search_box.touches (*b) || search_box2.touches (*b)) {
|
||||
selected_boxes2.insert (*b);
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_EQ (selected_boxes.size () > 100, true);
|
||||
EXPECT_EQ (db::compare_layouts (boxes2layout (selected_boxes), boxes2layout (selected_boxes2), db::layout_diff::f_verbose, 0, 100 /*max diff lines*/), true);
|
||||
|
||||
// push mode
|
||||
{
|
||||
selected_boxes.clear ();
|
||||
FlatPusher pusher (&selected_boxes);
|
||||
db::RecursiveInstanceIterator (g, c0, reg).push (&pusher);
|
||||
}
|
||||
|
||||
EXPECT_EQ (selected_boxes.size () > 100, true);
|
||||
EXPECT_EQ (db::compare_layouts (boxes2layout (selected_boxes), boxes2layout (selected_boxes2), db::layout_diff::f_verbose, 0, 100 /*max diff lines*/), true);
|
||||
}
|
||||
|
||||
|
|
@ -723,20 +723,24 @@ static db::Layout boxes2layout (const std::set<db::Box> &boxes)
|
|||
return l;
|
||||
}
|
||||
|
||||
class FlatPusher
|
||||
: public db::RecursiveShapeReceiver
|
||||
{
|
||||
public:
|
||||
FlatPusher (std::set<db::Box> *boxes) : mp_boxes (boxes) { }
|
||||
namespace {
|
||||
|
||||
void shape (const db::RecursiveShapeIterator * /*iter*/, const db::Shape &shape, const db::ICplxTrans &trans, const db::Box & /*region*/, const box_tree_type * /*complex_region*/)
|
||||
class FlatPusher
|
||||
: public db::RecursiveShapeReceiver
|
||||
{
|
||||
mp_boxes->insert (trans * shape.bbox ());
|
||||
}
|
||||
public:
|
||||
FlatPusher (std::set<db::Box> *boxes) : mp_boxes (boxes) { }
|
||||
|
||||
private:
|
||||
std::set<db::Box> *mp_boxes;
|
||||
};
|
||||
void shape (const db::RecursiveShapeIterator * /*iter*/, const db::Shape &shape, const db::ICplxTrans &trans, const db::Box & /*region*/, const box_tree_type * /*complex_region*/)
|
||||
{
|
||||
mp_boxes->insert (trans * shape.bbox ());
|
||||
}
|
||||
|
||||
private:
|
||||
std::set<db::Box> *mp_boxes;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
TEST(4)
|
||||
{
|
||||
|
|
@ -1023,6 +1027,8 @@ TEST(10)
|
|||
|
||||
db::Box b (1000, -500, 2000, 500);
|
||||
c2.shapes (0).insert (b);
|
||||
c0.shapes (0).insert (b.moved (db::Vector (-1000, 500)));
|
||||
c0.shapes (0).insert (b.moved (db::Vector (-2000, 500)));
|
||||
|
||||
db::Trans tt;
|
||||
c0.insert (db::CellInstArray (db::CellInst (c1.cell_index ()), tt, db::Vector (0, 6000), db::Vector (6000, 0), 2, 2));
|
||||
|
|
@ -1036,6 +1042,9 @@ TEST(10)
|
|||
"begin\n"
|
||||
"new_inst($2,all)\n"
|
||||
"new_inst_member($2,r0 *1 0,0,all)\n"
|
||||
// It's a bit weird to have shape events after new_inst_member, but remember, new_inst_member is a query callback, not an event.
|
||||
"shape(box (0,0;1000,1000),r0 *1 0,0)\n"
|
||||
"shape(box (-1000,0;0,1000),r0 *1 0,0)\n"
|
||||
"enter_cell($2)\n"
|
||||
"new_inst($3,all)\n"
|
||||
"new_inst_member($3,r0 *1 0,0,all)\n"
|
||||
|
|
@ -1126,6 +1135,8 @@ TEST(10)
|
|||
"begin\n"
|
||||
"new_inst($2,all)\n"
|
||||
"new_inst_member($2,r0 *1 0,0,all)\n"
|
||||
"shape(box (0,0;1000,1000),r0 *1 0,0)\n"
|
||||
"shape(box (-1000,0;0,1000),r0 *1 0,0)\n"
|
||||
"enter_cell($2)\n"
|
||||
"new_inst($3,all)\n"
|
||||
"leave_cell($2)\n"
|
||||
|
|
@ -1152,6 +1163,8 @@ TEST(10)
|
|||
"begin\n"
|
||||
"new_inst($2,all)\n"
|
||||
"new_inst_member($2,r0 *1 0,0,all)\n"
|
||||
"shape(box (0,0;1000,1000),r0 *1 0,0)\n"
|
||||
"shape(box (-1000,0;0,1000),r0 *1 0,0)\n"
|
||||
"enter_cell($2)\n"
|
||||
"new_inst($3,all)\n"
|
||||
"new_inst_member($3,r0 *1 0,0,all)\n"
|
||||
|
|
@ -1194,6 +1207,8 @@ TEST(10)
|
|||
"begin\n"
|
||||
"new_inst($2,all)\n"
|
||||
"new_inst_member($2,r0 *1 0,0,all)\n"
|
||||
"shape(box (0,0;1000,1000),r0 *1 0,0)\n"
|
||||
"shape(box (-1000,0;0,1000),r0 *1 0,0)\n"
|
||||
"enter_cell($2)\n"
|
||||
"new_inst($3,all)\n"
|
||||
"new_inst_member($3,r0 *1 0,0,all)\n" // -> skipped
|
||||
|
|
@ -1271,6 +1286,8 @@ TEST(10)
|
|||
EXPECT_EQ (rr2.text (),
|
||||
"begin\n"
|
||||
"new_inst($2,all)\n"
|
||||
"shape(box (0,0;1000,1000),r0 *1 0,0)\n"
|
||||
"shape(box (-1000,0;0,1000),r0 *1 0,0)\n"
|
||||
"end\n"
|
||||
);
|
||||
|
||||
|
|
@ -1282,6 +1299,8 @@ TEST(10)
|
|||
"begin\n"
|
||||
"new_inst($2)\n"
|
||||
"new_inst_member($2,r0 *1 0,0)\n"
|
||||
"shape(box (0,0;1000,1000),r0 *1 0,0)\n"
|
||||
"shape(box (-1000,0;0,1000),r0 *1 0,0)\n"
|
||||
"enter_cell($2)\n"
|
||||
"new_inst($3)\n"
|
||||
"new_inst_member($3,r0 *1 0,0)\n"
|
||||
|
|
|
|||
|
|
@ -1973,6 +1973,27 @@ TEST(35c_interact_with_count_text)
|
|||
EXPECT_EQ (r.selected_not_interacting (rr, 3, 4).to_string (), "(0,0;0,200;100,200;100,0)");
|
||||
}
|
||||
|
||||
TEST(40_with_holes)
|
||||
{
|
||||
db::Region r;
|
||||
r.insert (db::Box (db::Point (0, 0), db::Point (100, 200)));
|
||||
db::Region rr;
|
||||
rr.insert (db::Box (db::Point (10, 10), db::Point (20, 20)));
|
||||
rr.insert (db::Box (db::Point (30, 30), db::Point (40, 40)));
|
||||
r.set_merged_semantics (true);
|
||||
r.set_min_coherence (false);
|
||||
|
||||
r -= rr;
|
||||
|
||||
EXPECT_EQ (rr.filtered (db::HoleCountFilter (0, 1, false)).to_string (), "(10,10;10,20;20,20;20,10);(30,30;30,40;40,40;40,30)");
|
||||
EXPECT_EQ (r.filtered (db::HoleCountFilter (2, 3, false)).to_string (), "(0,0;0,200;100,200;100,0/10,10;20,10;20,20;10,20/30,30;40,30;40,40;30,40)");
|
||||
EXPECT_EQ (r.filtered (db::HoleCountFilter (1, 2, false)).to_string (), "");
|
||||
EXPECT_EQ (r.filtered (db::HoleCountFilter (1, 3, false)).to_string (), "(0,0;0,200;100,200;100,0/10,10;20,10;20,20;10,20/30,30;40,30;40,40;30,40)");
|
||||
EXPECT_EQ (r.filtered (db::HoleCountFilter (0, 2, false)).to_string (), "");
|
||||
EXPECT_EQ (r.filtered (db::HoleCountFilter (2, 5, false)).to_string (), "(0,0;0,200;100,200;100,0/10,10;20,10;20,20;10,20/30,30;40,30;40,40;30,40)");
|
||||
EXPECT_EQ (r.filtered (db::HoleCountFilter (3, 5, true)).to_string (), "(0,0;0,200;100,200;100,0/10,10;20,10;20,20;10,20/30,30;40,30;40,40;30,40)");
|
||||
}
|
||||
|
||||
TEST(100_Processors)
|
||||
{
|
||||
db::Region r;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ include($$PWD/../../lib_ut.pri)
|
|||
|
||||
SOURCES = \
|
||||
dbCompoundOperationTests.cc \
|
||||
dbRecursiveInstanceIteratorTests.cc \
|
||||
dbRegionUtilsTests.cc \
|
||||
dbUtilsTests.cc \
|
||||
dbWriterTools.cc \
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ module DRC
|
|||
# @li \global#space @/li
|
||||
# @li \global#squares @/li
|
||||
# @li \global#width @/li
|
||||
# @li \global#with_holes @/li
|
||||
# @/ul
|
||||
#
|
||||
# The following documentation will list the methods available for DRC expression objects.
|
||||
|
|
@ -434,7 +435,7 @@ CODE
|
|||
# result. Without "if_any" three corners are returned for each triangle.
|
||||
|
||||
def count
|
||||
DRCOpNodeCountFilter::new(@engine, self)
|
||||
DRCOpNodeCountFilter::new(@engine, self, :new_count_filter, "count")
|
||||
end
|
||||
|
||||
# %DRC%
|
||||
|
|
@ -738,16 +739,18 @@ CODE
|
|||
# %DRC%
|
||||
# @name smoothed
|
||||
# @brief Applies smoothing
|
||||
# @synopsis expression.smoothed(d)
|
||||
# @synopsis expression.smoothed(d [, keep_hv ])
|
||||
#
|
||||
# This operation acts on polygons and applies polygon smoothing with the tolerance d. See \Layer#smoothed for more details.
|
||||
# This operation acts on polygons and applies polygon smoothing with the tolerance d. 'keep_hv' indicates
|
||||
# whether horizontal and vertical edges are maintained. Default is 'no' which means such edges may be distorted.
|
||||
# See \Layer#smoothed for more details.
|
||||
#
|
||||
# The "smoothed" method is available as a plain function or as a method on \DRC# expressions.
|
||||
# The plain function is equivalent to "primary.smoothed".
|
||||
|
||||
def smoothed(d)
|
||||
def smoothed(d, keep_hv = false)
|
||||
@engine._context("smoothed") do
|
||||
DRCOpNodeFilter::new(@engine, self, :new_smoothed, "smoothed", @engine._make_value(d))
|
||||
DRCOpNodeFilter::new(@engine, self, :new_smoothed, "smoothed", @engine._make_value(d), keep_hv)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -1003,6 +1006,24 @@ CODE
|
|||
return DRCOpNodeFilter::new(@engine, self, :new_edges, "edges")
|
||||
end
|
||||
|
||||
# %DRC%
|
||||
# @name with_holes
|
||||
# @brief Selects all input polygons with the specified number of holes
|
||||
# @synopsis expression.with_holes (in condition)
|
||||
#
|
||||
# This operation can be used as a plain function in which case it acts on primary
|
||||
# shapes or can be used as method on another DRC expression.
|
||||
# The following example selects all polygons with more than 2 holes:
|
||||
#
|
||||
# @code
|
||||
# out = in.drc(with_holes > 2)
|
||||
# out = in.drc(primary.with_holes > 2) # equivalent
|
||||
# @/code
|
||||
|
||||
def with_holes
|
||||
return DRCOpNodeCountFilter::new(@engine, self, :new_hole_count_filter, "with_holes")
|
||||
end
|
||||
|
||||
# %DRC%
|
||||
# @name merged
|
||||
# @brief Returns the merged input polygons, optionally selecting multi-overlap
|
||||
|
|
@ -1552,16 +1573,19 @@ class DRCOpNodeCountFilter < DRCOpNodeWithCompare
|
|||
|
||||
attr_accessor :input
|
||||
attr_accessor :inverse
|
||||
attr_accessor :method
|
||||
attr_accessor :name
|
||||
|
||||
def initialize(engine, input)
|
||||
def initialize(engine, input, method, name)
|
||||
super(engine)
|
||||
self.input = input
|
||||
self.inverse = false
|
||||
self.description = "count"
|
||||
self.description = name
|
||||
self.method = method
|
||||
end
|
||||
|
||||
def _description_for_dump
|
||||
self.inverse ? "count" : "not_count"
|
||||
self.inverse ? name : "not_" + name
|
||||
end
|
||||
|
||||
def do_create_node(cache)
|
||||
|
|
@ -1570,7 +1594,7 @@ class DRCOpNodeCountFilter < DRCOpNodeWithCompare
|
|||
if self.lt || self.le
|
||||
args << (self.lt ? @engine._make_numeric_value(self.lt) : @engine._make_numeric_value(self.le) + 1)
|
||||
end
|
||||
RBA::CompoundRegionOperationNode::new_count_filter(*args)
|
||||
RBA::CompoundRegionOperationNode::send(self.method, *args)
|
||||
end
|
||||
|
||||
def inverted
|
||||
|
|
|
|||
|
|
@ -953,6 +953,19 @@ CODE
|
|||
CODE
|
||||
end
|
||||
|
||||
# %DRC%
|
||||
# @name with_holes
|
||||
# @brief Selects all input polygons according to their number of holes in DRC expressions
|
||||
# @synopsis with_holes (in condition)
|
||||
#
|
||||
# "with_holes" represents a polygon selector for
|
||||
# \DRC# expressions selecting polygons of the primary by their number of holes
|
||||
# (see \Layer#drc and \DRC#with_holes for more details).
|
||||
|
||||
def with_holes
|
||||
primary.with_holes
|
||||
end
|
||||
|
||||
# %DRC%
|
||||
# @name enclosing
|
||||
# @brief Performs an enclosing check
|
||||
|
|
|
|||
|
|
@ -498,6 +498,20 @@ module DRC
|
|||
end
|
||||
end
|
||||
|
||||
# %DRC%
|
||||
# @name warn
|
||||
# @brief Prints a warning
|
||||
# @synopsis warn(message)
|
||||
# Similar to \log, but the message is printed formatted as a warning
|
||||
|
||||
def warn(arg)
|
||||
if @log_file
|
||||
@log_file.puts("WARNING: " + arg)
|
||||
else
|
||||
RBA::Logger::warn(arg)
|
||||
end
|
||||
end
|
||||
|
||||
# %DRC%
|
||||
# @name log_file
|
||||
# @brief Specify the log file where to send to log to
|
||||
|
|
@ -1840,7 +1854,7 @@ CODE
|
|||
|
||||
def run_timed(desc, obj)
|
||||
|
||||
info(desc)
|
||||
log(desc)
|
||||
|
||||
# enable progress
|
||||
if obj.is_a?(RBA::Region) || obj.is_a?(RBA::Edges) || obj.is_a?(RBA::EdgePairs) || obj.is_a?(RBA::Texts)
|
||||
|
|
|
|||
|
|
@ -488,7 +488,7 @@ CODE
|
|||
#
|
||||
# This method is available for polygon layers only.
|
||||
|
||||
%w(bbox_height bbox_max bbox_min bbox_width perimeter).each do |f|
|
||||
%w(bbox_height bbox_max bbox_min bbox_width perimeter holes).each do |f|
|
||||
[true, false].each do |inv|
|
||||
mn = (inv ? "without" : "with") + "_" + f
|
||||
eval <<"CODE"
|
||||
|
|
@ -517,6 +517,61 @@ CODE
|
|||
end
|
||||
end
|
||||
|
||||
# %DRC%
|
||||
# @name with_holes
|
||||
# @brief Selects all polygons with the specified number of holes
|
||||
# @synopsis layer.with_holes(count)
|
||||
# @synopsis layer.with_holes(min_count, max_count)
|
||||
# @synopsis layer.with_holes(min_count .. max_count)
|
||||
#
|
||||
# This method is available for polygon layers. It will select all polygons from the input layer
|
||||
# which have the specified number of holes.
|
||||
|
||||
# %DRC%
|
||||
# @name without_holes
|
||||
# @brief Selects all polygons with the specified number of holes
|
||||
# @synopsis layer.without_holes(count)
|
||||
# @synopsis layer.without_holes(min_count, max_count)
|
||||
# @synopsis layer.without_holes(min_count .. max_count)
|
||||
#
|
||||
# This method is available for polygon layers. It will select all polygons from the input layer
|
||||
# which do not have the specified number of holes.
|
||||
|
||||
%w(holes).each do |f|
|
||||
[true, false].each do |inv|
|
||||
mn = (inv ? "without" : "with") + "_" + f
|
||||
eval <<"CODE"
|
||||
def #{mn}(*args)
|
||||
|
||||
@engine._context("#{mn}") do
|
||||
|
||||
requires_region
|
||||
if args.size == 1
|
||||
a = args[0]
|
||||
if a.is_a?(Range)
|
||||
min = @engine._make_numeric_value_with_nil(a.begin)
|
||||
max = @engine._make_numeric_value_with_nil(a.end)
|
||||
max && (max += 1)
|
||||
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, RBA::Region, :with_#{f}, min, max, #{inv.inspect}))
|
||||
else
|
||||
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, RBA::Region, :with_#{f}, @engine._make_value(a), #{inv.inspect}))
|
||||
end
|
||||
elsif args.size == 2
|
||||
min = @engine._make_numeric_value_with_nil(args[0])
|
||||
max = @engine._make_numeric_value_with_nil(args[1])
|
||||
max && (max += 1)
|
||||
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, RBA::Region, :with_#{f}, min, max, #{inv.inspect}))
|
||||
else
|
||||
raise("Invalid number of arguments (1 or 2 expected)")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
CODE
|
||||
end
|
||||
end
|
||||
|
||||
# %DRC%
|
||||
# @name with_bbox_aspect_ratio
|
||||
# @brief Selects polygons by the aspect ratio of their bounding box
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ module DRC
|
|||
drc._rdb_index = rdb_index
|
||||
drc._generator = generator
|
||||
|
||||
drc_progress = RBA::AbstractProgress::new("DRC: " + macro.path)
|
||||
|
||||
begin
|
||||
|
||||
# Set a debugger scope so that our errors end up with the debugger set to the DRC's line
|
||||
|
|
@ -46,6 +48,9 @@ module DRC
|
|||
# cleans up and creates layout and report views
|
||||
drc._finish
|
||||
|
||||
# unlocks the UI
|
||||
drc_progress._destroy
|
||||
|
||||
end
|
||||
|
||||
timer.stop
|
||||
|
|
|
|||
|
|
@ -238,3 +238,13 @@ TEST(17d)
|
|||
{
|
||||
run_test (_this, "17", true);
|
||||
}
|
||||
|
||||
TEST(18)
|
||||
{
|
||||
run_test (_this, "18", false);
|
||||
}
|
||||
|
||||
TEST(18d)
|
||||
{
|
||||
run_test (_this, "18", true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1152,3 +1152,14 @@ TEST(28_inputFragmentation)
|
|||
{
|
||||
run_test (_this, "28", true);
|
||||
}
|
||||
|
||||
TEST(29_holes)
|
||||
{
|
||||
run_test (_this, "29", false);
|
||||
}
|
||||
|
||||
TEST(29d_holes)
|
||||
{
|
||||
run_test (_this, "29", true);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ static void configure_from_line_edit (lay::Dispatcher *dispatcher, QLineEdit *le
|
|||
Value value = Value (0);
|
||||
tl::from_string (tl::to_string (le->text ()), value);
|
||||
dispatcher->config_set (cfg_name, tl::to_string (value));
|
||||
lay::indicate_error (le, 0);
|
||||
lay::indicate_error (le, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (le, &ex);
|
||||
}
|
||||
|
|
@ -114,7 +114,7 @@ EditorOptionsGeneric::apply (lay::Dispatcher *root)
|
|||
try {
|
||||
db::DVector eg;
|
||||
egc.from_string_picky (tl::to_string (mp_ui->edit_grid_le->text ()), eg);
|
||||
lay::indicate_error (mp_ui->edit_grid_le, 0);
|
||||
lay::indicate_error (mp_ui->edit_grid_le, (tl::Exception *) 0);
|
||||
root->config_set (cfg_edit_grid, egc.to_string (eg));
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (mp_ui->edit_grid_le, &ex);
|
||||
|
|
@ -166,7 +166,7 @@ EditorOptionsGeneric::setup (lay::Dispatcher *root)
|
|||
mp_ui->edit_grid_le->setText (tl::to_qstring (egc.to_string (eg)));
|
||||
}
|
||||
grid_changed (mp_ui->grid_cb->currentIndex ());
|
||||
lay::indicate_error (mp_ui->edit_grid_le, 0);
|
||||
lay::indicate_error (mp_ui->edit_grid_le, (tl::Exception *) 0);
|
||||
|
||||
// edit & move angle
|
||||
|
||||
|
|
@ -196,7 +196,7 @@ EditorOptionsGeneric::setup (lay::Dispatcher *root)
|
|||
unsigned int max_shapes = 1000;
|
||||
root->config_get (cfg_edit_max_shapes_of_instances, max_shapes);
|
||||
mp_ui->max_shapes_le->setText (tl::to_qstring (tl::to_string (max_shapes)));
|
||||
lay::indicate_error (mp_ui->max_shapes_le, 0);
|
||||
lay::indicate_error (mp_ui->max_shapes_le, (tl::Exception *) 0);
|
||||
|
||||
bool show_shapes = true;
|
||||
root->config_get (cfg_edit_show_shapes_of_instances, show_shapes);
|
||||
|
|
@ -356,7 +356,7 @@ EditorOptionsPath::setup (lay::Dispatcher *root)
|
|||
double w = 0.0;
|
||||
root->config_get (cfg_edit_path_width, w);
|
||||
mp_ui->width_le->setText (tl::to_qstring (tl::to_string (w)));
|
||||
lay::indicate_error (mp_ui->width_le, 0);
|
||||
lay::indicate_error (mp_ui->width_le, (tl::Exception *) 0);
|
||||
|
||||
// path type and extensions
|
||||
|
||||
|
|
@ -377,9 +377,9 @@ EditorOptionsPath::setup (lay::Dispatcher *root)
|
|||
root->config_get (cfg_edit_path_ext_var_begin, bgnext);
|
||||
root->config_get (cfg_edit_path_ext_var_end, endext);
|
||||
mp_ui->start_ext_le->setText (tl::to_qstring (tl::to_string (bgnext)));
|
||||
lay::indicate_error (mp_ui->start_ext_le, 0);
|
||||
lay::indicate_error (mp_ui->start_ext_le, (tl::Exception *) 0);
|
||||
mp_ui->end_ext_le->setText (tl::to_qstring (tl::to_string (endext)));
|
||||
lay::indicate_error (mp_ui->end_ext_le, 0);
|
||||
lay::indicate_error (mp_ui->end_ext_le, (tl::Exception *) 0);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
|
@ -631,7 +631,7 @@ EditorOptionsInst::setup (lay::Dispatcher *root)
|
|||
double angle = 0.0;
|
||||
root->config_get (cfg_edit_inst_angle, angle);
|
||||
mp_ui->angle_le->setText (tl::to_qstring (tl::to_string (angle)));
|
||||
lay::indicate_error (mp_ui->angle_le, 0);
|
||||
lay::indicate_error (mp_ui->angle_le, (tl::Exception *) 0);
|
||||
|
||||
bool mirror = false;
|
||||
root->config_get (cfg_edit_inst_mirror, mirror);
|
||||
|
|
@ -640,7 +640,7 @@ EditorOptionsInst::setup (lay::Dispatcher *root)
|
|||
double scale = 1.0;
|
||||
root->config_get (cfg_edit_inst_scale, scale);
|
||||
mp_ui->scale_le->setText (tl::to_qstring (tl::to_string (scale)));
|
||||
lay::indicate_error (mp_ui->scale_le, 0);
|
||||
lay::indicate_error (mp_ui->scale_le, (tl::Exception *) 0);
|
||||
|
||||
// array
|
||||
bool array = false;
|
||||
|
|
@ -657,17 +657,17 @@ EditorOptionsInst::setup (lay::Dispatcher *root)
|
|||
root->config_get (cfg_edit_inst_column_y, column_y);
|
||||
|
||||
mp_ui->rows_le->setText (tl::to_qstring (tl::to_string (rows)));
|
||||
lay::indicate_error (mp_ui->rows_le, 0);
|
||||
lay::indicate_error (mp_ui->rows_le, (tl::Exception *) 0);
|
||||
mp_ui->row_x_le->setText (tl::to_qstring (tl::to_string (row_x)));
|
||||
lay::indicate_error (mp_ui->row_x_le, 0);
|
||||
lay::indicate_error (mp_ui->row_x_le, (tl::Exception *) 0);
|
||||
mp_ui->row_y_le->setText (tl::to_qstring (tl::to_string (row_y)));
|
||||
lay::indicate_error (mp_ui->row_y_le, 0);
|
||||
lay::indicate_error (mp_ui->row_y_le, (tl::Exception *) 0);
|
||||
mp_ui->columns_le->setText (tl::to_qstring (tl::to_string (columns)));
|
||||
lay::indicate_error (mp_ui->columns_le, 0);
|
||||
lay::indicate_error (mp_ui->columns_le, (tl::Exception *) 0);
|
||||
mp_ui->column_x_le->setText (tl::to_qstring (tl::to_string (column_x)));
|
||||
lay::indicate_error (mp_ui->column_x_le, 0);
|
||||
lay::indicate_error (mp_ui->column_x_le, (tl::Exception *) 0);
|
||||
mp_ui->column_y_le->setText (tl::to_qstring (tl::to_string (column_y)));
|
||||
lay::indicate_error (mp_ui->column_y_le, 0);
|
||||
lay::indicate_error (mp_ui->column_y_le, (tl::Exception *) 0);
|
||||
|
||||
// place origin of cell flag
|
||||
bool place_origin = false;
|
||||
|
|
|
|||
|
|
@ -405,7 +405,7 @@ InstPropertiesPage::create_applicator (db::Cell & /*cell*/, const db::Instance &
|
|||
throw tl::Exception (tl::to_string (QObject::tr ("Not a valid cell or PCell name: %s")).c_str (), tl::to_string (cell_name_le->text ()).c_str ());
|
||||
}
|
||||
|
||||
lay::indicate_error (cell_name_le, 0);
|
||||
lay::indicate_error (cell_name_le, (tl::Exception *) 0);
|
||||
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (cell_name_le, &ex);
|
||||
|
|
@ -447,7 +447,7 @@ InstPropertiesPage::create_applicator (db::Cell & /*cell*/, const db::Instance &
|
|||
|
||||
try {
|
||||
tl::from_string (tl::to_string (pos_x_le->text ()), x);
|
||||
lay::indicate_error (pos_x_le, 0);
|
||||
lay::indicate_error (pos_x_le, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (pos_x_le, &ex);
|
||||
has_error = true;
|
||||
|
|
@ -455,7 +455,7 @@ InstPropertiesPage::create_applicator (db::Cell & /*cell*/, const db::Instance &
|
|||
|
||||
try {
|
||||
tl::from_string (tl::to_string (pos_y_le->text ()), y);
|
||||
lay::indicate_error (pos_y_le, 0);
|
||||
lay::indicate_error (pos_y_le, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (pos_y_le, &ex);
|
||||
has_error = true;
|
||||
|
|
@ -472,7 +472,7 @@ InstPropertiesPage::create_applicator (db::Cell & /*cell*/, const db::Instance &
|
|||
double angle = 0.0;
|
||||
try {
|
||||
tl::from_string (tl::to_string (angle_le->text ()), angle);
|
||||
lay::indicate_error (angle_le, 0);
|
||||
lay::indicate_error (angle_le, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (angle_le, &ex);
|
||||
has_error = true;
|
||||
|
|
@ -481,7 +481,7 @@ InstPropertiesPage::create_applicator (db::Cell & /*cell*/, const db::Instance &
|
|||
double mag = 0.0;
|
||||
try {
|
||||
tl::from_string (tl::to_string (mag_le->text ()), mag);
|
||||
lay::indicate_error (mag_le, 0);
|
||||
lay::indicate_error (mag_le, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (mag_le, &ex);
|
||||
has_error = true;
|
||||
|
|
@ -510,7 +510,7 @@ InstPropertiesPage::create_applicator (db::Cell & /*cell*/, const db::Instance &
|
|||
|
||||
try {
|
||||
tl::from_string (tl::to_string (column_x_le->text ()), cx);
|
||||
lay::indicate_error (column_x_le, 0);
|
||||
lay::indicate_error (column_x_le, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (column_x_le, &ex);
|
||||
has_error = true;
|
||||
|
|
@ -518,7 +518,7 @@ InstPropertiesPage::create_applicator (db::Cell & /*cell*/, const db::Instance &
|
|||
|
||||
try {
|
||||
tl::from_string (tl::to_string (column_y_le->text ()), cy);
|
||||
lay::indicate_error (column_y_le, 0);
|
||||
lay::indicate_error (column_y_le, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (column_y_le, &ex);
|
||||
has_error = true;
|
||||
|
|
@ -526,7 +526,7 @@ InstPropertiesPage::create_applicator (db::Cell & /*cell*/, const db::Instance &
|
|||
|
||||
try {
|
||||
tl::from_string (tl::to_string (row_x_le->text ()), rx);
|
||||
lay::indicate_error (row_x_le, 0);
|
||||
lay::indicate_error (row_x_le, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (row_x_le, &ex);
|
||||
has_error = true;
|
||||
|
|
@ -534,7 +534,7 @@ InstPropertiesPage::create_applicator (db::Cell & /*cell*/, const db::Instance &
|
|||
|
||||
try {
|
||||
tl::from_string (tl::to_string (row_y_le->text ()), ry);
|
||||
lay::indicate_error (row_y_le, 0);
|
||||
lay::indicate_error (row_y_le, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (row_y_le, &ex);
|
||||
has_error = true;
|
||||
|
|
@ -542,7 +542,7 @@ InstPropertiesPage::create_applicator (db::Cell & /*cell*/, const db::Instance &
|
|||
|
||||
try {
|
||||
tl::from_string (tl::to_string (rows_le->text ()), rows);
|
||||
lay::indicate_error (rows_le, 0);
|
||||
lay::indicate_error (rows_le, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (rows_le, &ex);
|
||||
has_error = true;
|
||||
|
|
@ -550,7 +550,7 @@ InstPropertiesPage::create_applicator (db::Cell & /*cell*/, const db::Instance &
|
|||
|
||||
try {
|
||||
tl::from_string (tl::to_string (columns_le->text ()), cols);
|
||||
lay::indicate_error (columns_le, 0);
|
||||
lay::indicate_error (columns_le, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (columns_le, &ex);
|
||||
has_error = true;
|
||||
|
|
@ -766,7 +766,7 @@ InstPropertiesPage::update_pcell_parameters ()
|
|||
tl::Exception ex (tl::to_string (QObject::tr ("Not a valid cell or PCell name: %s")).c_str (), tl::to_string (cell_name_le->text ()).c_str ());
|
||||
lay::indicate_error (cell_name_le, &ex);
|
||||
} else {
|
||||
lay::indicate_error (cell_name_le, 0);
|
||||
lay::indicate_error (cell_name_le, (tl::Exception *) 0);
|
||||
}
|
||||
|
||||
if (pc.first && layout->pcell_declaration (pc.second)) {
|
||||
|
|
|
|||
|
|
@ -1387,7 +1387,7 @@ MainService::cm_round_corners ()
|
|||
std::vector <db::Polygon> in;
|
||||
ep.merge (primary, in, 0 /*min_wc*/, false /*resolve holes*/, true /*min coherence*/);
|
||||
for (std::vector <db::Polygon>::iterator p = in.begin (); p != in.end (); ++p) {
|
||||
*p = smooth (*p, 1);
|
||||
*p = smooth (*p, 1, true);
|
||||
}
|
||||
|
||||
std::vector <db::Polygon> out = in;
|
||||
|
|
|
|||
|
|
@ -496,7 +496,7 @@ PCellParametersPage::get_parameters (bool *ok)
|
|||
tl::from_string (tl::to_string (le->text ()), v);
|
||||
|
||||
parameters.back () = tl::Variant (v);
|
||||
lay::indicate_error (le, 0);
|
||||
lay::indicate_error (le, (tl::Exception *) 0);
|
||||
|
||||
} catch (tl::Exception &ex) {
|
||||
|
||||
|
|
@ -520,7 +520,7 @@ PCellParametersPage::get_parameters (bool *ok)
|
|||
tl::from_string (tl::to_string (le->text ()), v);
|
||||
|
||||
parameters.back () = tl::Variant (v);
|
||||
lay::indicate_error (le, 0);
|
||||
lay::indicate_error (le, (tl::Exception *) 0);
|
||||
|
||||
} catch (tl::Exception &ex) {
|
||||
|
||||
|
|
|
|||
|
|
@ -509,7 +509,7 @@ PolygonPropertiesPage::create_applicator (db::Shapes & /*shapes*/, const db::Sha
|
|||
|
||||
}
|
||||
|
||||
lay::indicate_error (pointListEdit, 0);
|
||||
lay::indicate_error (pointListEdit, (tl::Exception *) 0);
|
||||
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (pointListEdit, &ex);
|
||||
|
|
@ -609,7 +609,7 @@ BoxPropertiesPage::get_box (int mode) const
|
|||
|
||||
try {
|
||||
tl::from_string (tl::to_string (x1_le_1->text ()), x1);
|
||||
lay::indicate_error (x1_le_1, 0);
|
||||
lay::indicate_error (x1_le_1, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (x1_le_1, &ex);
|
||||
has_error = true;
|
||||
|
|
@ -617,7 +617,7 @@ BoxPropertiesPage::get_box (int mode) const
|
|||
|
||||
try {
|
||||
tl::from_string (tl::to_string (y1_le_1->text ()), y1);
|
||||
lay::indicate_error (y1_le_1, 0);
|
||||
lay::indicate_error (y1_le_1, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (y1_le_1, &ex);
|
||||
has_error = true;
|
||||
|
|
@ -625,7 +625,7 @@ BoxPropertiesPage::get_box (int mode) const
|
|||
|
||||
try {
|
||||
tl::from_string (tl::to_string (x2_le_1->text ()), x2);
|
||||
lay::indicate_error (x2_le_1, 0);
|
||||
lay::indicate_error (x2_le_1, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (x2_le_1, &ex);
|
||||
has_error = true;
|
||||
|
|
@ -633,7 +633,7 @@ BoxPropertiesPage::get_box (int mode) const
|
|||
|
||||
try {
|
||||
tl::from_string (tl::to_string (y2_le_1->text ()), y2);
|
||||
lay::indicate_error (y2_le_1, 0);
|
||||
lay::indicate_error (y2_le_1, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (y2_le_1, &ex);
|
||||
has_error = true;
|
||||
|
|
@ -669,7 +669,7 @@ BoxPropertiesPage::get_box (int mode) const
|
|||
|
||||
try {
|
||||
tl::from_string (tl::to_string (cx_le_2->text ()), cx);
|
||||
lay::indicate_error (cx_le_2, 0);
|
||||
lay::indicate_error (cx_le_2, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (cx_le_2, &ex);
|
||||
has_error = true;
|
||||
|
|
@ -677,7 +677,7 @@ BoxPropertiesPage::get_box (int mode) const
|
|||
|
||||
try {
|
||||
tl::from_string (tl::to_string (cy_le_2->text ()), cy);
|
||||
lay::indicate_error (cy_le_2, 0);
|
||||
lay::indicate_error (cy_le_2, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (cy_le_2, &ex);
|
||||
has_error = true;
|
||||
|
|
@ -685,7 +685,7 @@ BoxPropertiesPage::get_box (int mode) const
|
|||
|
||||
try {
|
||||
tl::from_string (tl::to_string (w_le_2->text ()), w);
|
||||
lay::indicate_error (w_le_2, 0);
|
||||
lay::indicate_error (w_le_2, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (w_le_2, &ex);
|
||||
has_error = true;
|
||||
|
|
@ -693,7 +693,7 @@ BoxPropertiesPage::get_box (int mode) const
|
|||
|
||||
try {
|
||||
tl::from_string (tl::to_string (h_le_2->text ()), h);
|
||||
lay::indicate_error (h_le_2, 0);
|
||||
lay::indicate_error (h_le_2, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (h_le_2, &ex);
|
||||
has_error = true;
|
||||
|
|
@ -834,7 +834,7 @@ TextPropertiesPage::create_applicator (db::Shapes & /*shapes*/, const db::Shape
|
|||
|
||||
try {
|
||||
tl::from_string (tl::to_string (x_le->text ()), x);
|
||||
lay::indicate_error (x_le, 0);
|
||||
lay::indicate_error (x_le, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (x_le, &ex);
|
||||
has_error = true;
|
||||
|
|
@ -842,7 +842,7 @@ TextPropertiesPage::create_applicator (db::Shapes & /*shapes*/, const db::Shape
|
|||
|
||||
try {
|
||||
tl::from_string (tl::to_string (y_le->text ()), y);
|
||||
lay::indicate_error (y_le, 0);
|
||||
lay::indicate_error (y_le, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (y_le, &ex);
|
||||
has_error = true;
|
||||
|
|
@ -875,7 +875,7 @@ TextPropertiesPage::create_applicator (db::Shapes & /*shapes*/, const db::Shape
|
|||
if (! size_le->text ().isEmpty ()) {
|
||||
try {
|
||||
size = coord_from_string (tl::to_string (size_le->text ()).c_str (), dbu, du, t);
|
||||
lay::indicate_error (size_le, 0);
|
||||
lay::indicate_error (size_le, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (size_le, &ex);
|
||||
has_error = true;
|
||||
|
|
@ -1084,7 +1084,7 @@ EditablePathPropertiesPage::create_applicator (db::Shapes & /*shapes*/, const db
|
|||
throw tl::Exception (tl::to_string (QObject::tr ("The path must have at least one point")));
|
||||
}
|
||||
|
||||
lay::indicate_error (ptlist_le, 0);
|
||||
lay::indicate_error (ptlist_le, (tl::Exception *) 0);
|
||||
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (ptlist_le, &ex);
|
||||
|
|
@ -1094,7 +1094,7 @@ EditablePathPropertiesPage::create_applicator (db::Shapes & /*shapes*/, const db
|
|||
db::Coord w = 0;
|
||||
try {
|
||||
w = coord_from_string (tl::to_string (width_le->text ()).c_str (), dbu, du, t);
|
||||
lay::indicate_error (width_le, 0);
|
||||
lay::indicate_error (width_le, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (width_le, &ex);
|
||||
has_error = true;
|
||||
|
|
@ -1111,14 +1111,14 @@ EditablePathPropertiesPage::create_applicator (db::Shapes & /*shapes*/, const db
|
|||
case 2: // variable
|
||||
try {
|
||||
se = coord_from_string (tl::to_string (start_ext_le->text ()).c_str (), dbu, du, t);
|
||||
lay::indicate_error (start_ext_le, 0);
|
||||
lay::indicate_error (start_ext_le, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (start_ext_le, &ex);
|
||||
has_error = true;
|
||||
}
|
||||
try {
|
||||
ee = coord_from_string (tl::to_string (end_ext_le->text ()).c_str (), dbu, du, t);
|
||||
lay::indicate_error (end_ext_le, 0);
|
||||
lay::indicate_error (end_ext_le, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (end_ext_le, &ex);
|
||||
has_error = true;
|
||||
|
|
|
|||
|
|
@ -201,25 +201,6 @@ Class<tl::Timer> decl_Timer ("tl", "Timer",
|
|||
// ----------------------------------------------------------------
|
||||
// Progress reporter objects
|
||||
|
||||
namespace tl {
|
||||
|
||||
template <> struct type_traits<tl::Progress> : public type_traits<void> {
|
||||
typedef tl::false_tag has_copy_constructor;
|
||||
typedef tl::false_tag has_default_constructor;
|
||||
};
|
||||
|
||||
template <> struct type_traits<tl::RelativeProgress> : public type_traits<void> {
|
||||
typedef tl::false_tag has_copy_constructor;
|
||||
typedef tl::false_tag has_default_constructor;
|
||||
};
|
||||
|
||||
template <> struct type_traits<tl::AbsoluteProgress> : public type_traits<void> {
|
||||
typedef tl::false_tag has_copy_constructor;
|
||||
typedef tl::false_tag has_default_constructor;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace gsi
|
||||
{
|
||||
|
||||
|
|
@ -247,6 +228,27 @@ Class<tl::Progress> decl_Progress ("tl", "Progress",
|
|||
"This class has been introduced in version 0.23.\n"
|
||||
);
|
||||
|
||||
static tl::AbstractProgress *abstract_progress (const std::string &desc)
|
||||
{
|
||||
return new tl::AbstractProgress (desc);
|
||||
}
|
||||
|
||||
Class<tl::AbstractProgress> decl_AbstractProgress (decl_Progress, "tl", "AbstractProgress",
|
||||
gsi::constructor ("new", &abstract_progress, gsi::arg ("desc"),
|
||||
"@brief Creates an abstract progress reporter with the given description\n"
|
||||
),
|
||||
"@brief The abstract progress reporter\n"
|
||||
"\n"
|
||||
"The abstract progress reporter acts as a 'bracket' for a sequence of operations which are connected "
|
||||
"logically. For example, a DRC script consists of multiple operations. An abstract progress reportert "
|
||||
"is instantiated during the run time of the DRC script. This way, the application leaves the UI open while "
|
||||
"the DRC executes and log messages can be collected.\n"
|
||||
"\n"
|
||||
"The abstract progress does not have a value.\n"
|
||||
"\n"
|
||||
"This class has been introduced in version 0.27.\n"
|
||||
);
|
||||
|
||||
static tl::RelativeProgress *rel_progress_2 (const std::string &desc, size_t max)
|
||||
{
|
||||
return new tl::RelativeProgress (desc, max);
|
||||
|
|
|
|||
|
|
@ -77,28 +77,6 @@ static void _call_f_filterEvent_2477 (const qt_gsi::GenericMethod * /*decl*/, vo
|
|||
}
|
||||
|
||||
|
||||
// bool QCoreApplication::notify(QObject *, QEvent *)
|
||||
|
||||
|
||||
static void _init_f_notify_2411 (qt_gsi::GenericMethod *decl)
|
||||
{
|
||||
static gsi::ArgSpecBase argspec_0 ("arg1");
|
||||
decl->add_arg<QObject * > (argspec_0);
|
||||
static gsi::ArgSpecBase argspec_1 ("arg2");
|
||||
decl->add_arg<QEvent * > (argspec_1);
|
||||
decl->set_return<bool > ();
|
||||
}
|
||||
|
||||
static void _call_f_notify_2411 (const qt_gsi::GenericMethod * /*decl*/, void *cls, gsi::SerialArgs &args, gsi::SerialArgs &ret)
|
||||
{
|
||||
__SUPPRESS_UNUSED_WARNING(args);
|
||||
tl::Heap heap;
|
||||
QObject *arg1 = gsi::arg_reader<QObject * >() (args, heap);
|
||||
QEvent *arg2 = gsi::arg_reader<QEvent * >() (args, heap);
|
||||
ret.write<bool > ((bool)((QCoreApplication *)cls)->notify (arg1, arg2));
|
||||
}
|
||||
|
||||
|
||||
// static void QCoreApplication::addLibraryPath(const QString &)
|
||||
|
||||
|
||||
|
|
@ -941,7 +919,6 @@ static gsi::Methods methods_QCoreApplication () {
|
|||
gsi::Methods methods;
|
||||
methods += new qt_gsi::GenericStaticMethod ("staticMetaObject", "@brief Obtains the static MetaObject for this class.", &_init_smo, &_call_smo);
|
||||
methods += new qt_gsi::GenericMethod ("filterEvent", "@brief Method bool QCoreApplication::filterEvent(void *message, long int *result)\n", false, &_init_f_filterEvent_2477, &_call_f_filterEvent_2477);
|
||||
methods += new qt_gsi::GenericMethod ("notify", "@brief Method bool QCoreApplication::notify(QObject *, QEvent *)\n", false, &_init_f_notify_2411, &_call_f_notify_2411);
|
||||
methods += gsi::qt_signal ("aboutToQuit()", "aboutToQuit", "@brief Signal declaration for QCoreApplication::aboutToQuit()\nYou can bind a procedure to this signal.");
|
||||
methods += gsi::qt_signal<QObject * > ("destroyed(QObject *)", "destroyed", gsi::arg("arg1"), "@brief Signal declaration for QCoreApplication::destroyed(QObject *)\nYou can bind a procedure to this signal.");
|
||||
methods += gsi::qt_signal<int > ("unixSignal(int)", "unixSignal", gsi::arg("arg1"), "@brief Signal declaration for QCoreApplication::unixSignal(int)\nYou can bind a procedure to this signal.");
|
||||
|
|
@ -1054,21 +1031,6 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
// [adaptor impl] bool QCoreApplication::notify(QObject *, QEvent *)
|
||||
bool cbs_notify_2411_0(QObject *arg1, QEvent *arg2)
|
||||
{
|
||||
return QCoreApplication::notify(arg1, arg2);
|
||||
}
|
||||
|
||||
virtual bool notify(QObject *arg1, QEvent *arg2)
|
||||
{
|
||||
if (cb_notify_2411_0.can_issue()) {
|
||||
return cb_notify_2411_0.issue<QCoreApplication_Adaptor, bool, QObject *, QEvent *>(&QCoreApplication_Adaptor::cbs_notify_2411_0, arg1, arg2);
|
||||
} else {
|
||||
return QCoreApplication::notify(arg1, arg2);
|
||||
}
|
||||
}
|
||||
|
||||
// [emitter impl] void QCoreApplication::aboutToQuit()
|
||||
void emitter_QCoreApplication_aboutToQuit_0()
|
||||
{
|
||||
|
|
@ -1163,7 +1125,6 @@ public:
|
|||
}
|
||||
|
||||
gsi::Callback cb_eventFilter_2411_0;
|
||||
gsi::Callback cb_notify_2411_0;
|
||||
gsi::Callback cb_childEvent_1701_0;
|
||||
gsi::Callback cb_customEvent_1217_0;
|
||||
gsi::Callback cb_disconnectNotify_1731_0;
|
||||
|
|
@ -1326,32 +1287,6 @@ static void _set_callback_cbs_eventFilter_2411_0 (void *cls, const gsi::Callback
|
|||
}
|
||||
|
||||
|
||||
// bool QCoreApplication::notify(QObject *, QEvent *)
|
||||
|
||||
static void _init_cbs_notify_2411_0 (qt_gsi::GenericMethod *decl)
|
||||
{
|
||||
static gsi::ArgSpecBase argspec_0 ("arg1");
|
||||
decl->add_arg<QObject * > (argspec_0);
|
||||
static gsi::ArgSpecBase argspec_1 ("arg2");
|
||||
decl->add_arg<QEvent * > (argspec_1);
|
||||
decl->set_return<bool > ();
|
||||
}
|
||||
|
||||
static void _call_cbs_notify_2411_0 (const qt_gsi::GenericMethod * /*decl*/, void *cls, gsi::SerialArgs &args, gsi::SerialArgs &ret)
|
||||
{
|
||||
__SUPPRESS_UNUSED_WARNING(args);
|
||||
tl::Heap heap;
|
||||
QObject *arg1 = args.read<QObject * > (heap);
|
||||
QEvent *arg2 = args.read<QEvent * > (heap);
|
||||
ret.write<bool > ((bool)((QCoreApplication_Adaptor *)cls)->cbs_notify_2411_0 (arg1, arg2));
|
||||
}
|
||||
|
||||
static void _set_callback_cbs_notify_2411_0 (void *cls, const gsi::Callback &cb)
|
||||
{
|
||||
((QCoreApplication_Adaptor *)cls)->cb_notify_2411_0 = cb;
|
||||
}
|
||||
|
||||
|
||||
// exposed int QCoreApplication::receivers(const char *signal)
|
||||
|
||||
static void _init_fp_receivers_c1731 (qt_gsi::GenericMethod *decl)
|
||||
|
|
@ -1445,8 +1380,6 @@ static gsi::Methods methods_QCoreApplication_Adaptor () {
|
|||
methods += new qt_gsi::GenericMethod ("*event", "@hide", false, &_init_cbs_event_1217_0, &_call_cbs_event_1217_0, &_set_callback_cbs_event_1217_0);
|
||||
methods += new qt_gsi::GenericMethod ("eventFilter", "@brief Virtual method bool QCoreApplication::eventFilter(QObject *, QEvent *)\nThis method can be reimplemented in a derived class.", false, &_init_cbs_eventFilter_2411_0, &_call_cbs_eventFilter_2411_0);
|
||||
methods += new qt_gsi::GenericMethod ("eventFilter", "@hide", false, &_init_cbs_eventFilter_2411_0, &_call_cbs_eventFilter_2411_0, &_set_callback_cbs_eventFilter_2411_0);
|
||||
methods += new qt_gsi::GenericMethod ("notify", "@brief Virtual method bool QCoreApplication::notify(QObject *, QEvent *)\nThis method can be reimplemented in a derived class.", false, &_init_cbs_notify_2411_0, &_call_cbs_notify_2411_0);
|
||||
methods += new qt_gsi::GenericMethod ("notify", "@hide", false, &_init_cbs_notify_2411_0, &_call_cbs_notify_2411_0, &_set_callback_cbs_notify_2411_0);
|
||||
methods += new qt_gsi::GenericMethod ("*receivers", "@brief Method int QCoreApplication::receivers(const char *signal)\nThis method is protected and can only be called from inside a derived class.", true, &_init_fp_receivers_c1731, &_call_fp_receivers_c1731);
|
||||
methods += new qt_gsi::GenericMethod ("*sender", "@brief Method QObject *QCoreApplication::sender()\nThis method is protected and can only be called from inside a derived class.", true, &_init_fp_sender_c0, &_call_fp_sender_c0);
|
||||
methods += new qt_gsi::GenericMethod ("*timerEvent", "@brief Virtual method void QCoreApplication::timerEvent(QTimerEvent *)\nThis method can be reimplemented in a derived class.", false, &_init_cbs_timerEvent_1730_0, &_call_cbs_timerEvent_1730_0);
|
||||
|
|
|
|||
|
|
@ -101,28 +101,6 @@ static void _call_f_isSessionRestored_c0 (const qt_gsi::GenericMethod * /*decl*/
|
|||
}
|
||||
|
||||
|
||||
// bool QApplication::notify(QObject *, QEvent *)
|
||||
|
||||
|
||||
static void _init_f_notify_2411 (qt_gsi::GenericMethod *decl)
|
||||
{
|
||||
static gsi::ArgSpecBase argspec_0 ("arg1");
|
||||
decl->add_arg<QObject * > (argspec_0);
|
||||
static gsi::ArgSpecBase argspec_1 ("arg2");
|
||||
decl->add_arg<QEvent * > (argspec_1);
|
||||
decl->set_return<bool > ();
|
||||
}
|
||||
|
||||
static void _call_f_notify_2411 (const qt_gsi::GenericMethod * /*decl*/, void *cls, gsi::SerialArgs &args, gsi::SerialArgs &ret)
|
||||
{
|
||||
__SUPPRESS_UNUSED_WARNING(args);
|
||||
tl::Heap heap;
|
||||
QObject *arg1 = gsi::arg_reader<QObject * >() (args, heap);
|
||||
QEvent *arg2 = gsi::arg_reader<QEvent * >() (args, heap);
|
||||
ret.write<bool > ((bool)((QApplication *)cls)->notify (arg1, arg2));
|
||||
}
|
||||
|
||||
|
||||
// QString QApplication::sessionId()
|
||||
|
||||
|
||||
|
|
@ -1534,7 +1512,6 @@ static gsi::Methods methods_QApplication () {
|
|||
methods += new qt_gsi::GenericMethod (":autoSipEnabled", "@brief Method bool QApplication::autoSipEnabled()\n", true, &_init_f_autoSipEnabled_c0, &_call_f_autoSipEnabled_c0);
|
||||
methods += new qt_gsi::GenericMethod (":inputContext", "@brief Method QInputContext *QApplication::inputContext()\n", true, &_init_f_inputContext_c0, &_call_f_inputContext_c0);
|
||||
methods += new qt_gsi::GenericMethod ("isSessionRestored?", "@brief Method bool QApplication::isSessionRestored()\n", true, &_init_f_isSessionRestored_c0, &_call_f_isSessionRestored_c0);
|
||||
methods += new qt_gsi::GenericMethod ("notify", "@brief Method bool QApplication::notify(QObject *, QEvent *)\nThis is a reimplementation of QCoreApplication::notify", false, &_init_f_notify_2411, &_call_f_notify_2411);
|
||||
methods += new qt_gsi::GenericMethod ("sessionId", "@brief Method QString QApplication::sessionId()\n", true, &_init_f_sessionId_c0, &_call_f_sessionId_c0);
|
||||
methods += new qt_gsi::GenericMethod ("sessionKey", "@brief Method QString QApplication::sessionKey()\n", true, &_init_f_sessionKey_c0, &_call_f_sessionKey_c0);
|
||||
methods += new qt_gsi::GenericMethod ("setAutoSipEnabled|autoSipEnabled=", "@brief Method void QApplication::setAutoSipEnabled(const bool enabled)\n", false, &_init_f_setAutoSipEnabled_1559, &_call_f_setAutoSipEnabled_1559);
|
||||
|
|
@ -1686,21 +1663,6 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
// [adaptor impl] bool QApplication::notify(QObject *, QEvent *)
|
||||
bool cbs_notify_2411_0(QObject *arg1, QEvent *arg2)
|
||||
{
|
||||
return QApplication::notify(arg1, arg2);
|
||||
}
|
||||
|
||||
virtual bool notify(QObject *arg1, QEvent *arg2)
|
||||
{
|
||||
if (cb_notify_2411_0.can_issue()) {
|
||||
return cb_notify_2411_0.issue<QApplication_Adaptor, bool, QObject *, QEvent *>(&QApplication_Adaptor::cbs_notify_2411_0, arg1, arg2);
|
||||
} else {
|
||||
return QApplication::notify(arg1, arg2);
|
||||
}
|
||||
}
|
||||
|
||||
// [emitter impl] void QApplication::aboutToQuit()
|
||||
void emitter_QApplication_aboutToQuit_0()
|
||||
{
|
||||
|
|
@ -1813,7 +1775,6 @@ public:
|
|||
}
|
||||
|
||||
gsi::Callback cb_eventFilter_2411_0;
|
||||
gsi::Callback cb_notify_2411_0;
|
||||
gsi::Callback cb_childEvent_1701_0;
|
||||
gsi::Callback cb_customEvent_1217_0;
|
||||
gsi::Callback cb_disconnectNotify_1731_0;
|
||||
|
|
@ -2025,32 +1986,6 @@ static void _call_emitter_lastWindowClosed_0 (const qt_gsi::GenericMethod * /*de
|
|||
}
|
||||
|
||||
|
||||
// bool QApplication::notify(QObject *, QEvent *)
|
||||
|
||||
static void _init_cbs_notify_2411_0 (qt_gsi::GenericMethod *decl)
|
||||
{
|
||||
static gsi::ArgSpecBase argspec_0 ("arg1");
|
||||
decl->add_arg<QObject * > (argspec_0);
|
||||
static gsi::ArgSpecBase argspec_1 ("arg2");
|
||||
decl->add_arg<QEvent * > (argspec_1);
|
||||
decl->set_return<bool > ();
|
||||
}
|
||||
|
||||
static void _call_cbs_notify_2411_0 (const qt_gsi::GenericMethod * /*decl*/, void *cls, gsi::SerialArgs &args, gsi::SerialArgs &ret)
|
||||
{
|
||||
__SUPPRESS_UNUSED_WARNING(args);
|
||||
tl::Heap heap;
|
||||
QObject *arg1 = args.read<QObject * > (heap);
|
||||
QEvent *arg2 = args.read<QEvent * > (heap);
|
||||
ret.write<bool > ((bool)((QApplication_Adaptor *)cls)->cbs_notify_2411_0 (arg1, arg2));
|
||||
}
|
||||
|
||||
static void _set_callback_cbs_notify_2411_0 (void *cls, const gsi::Callback &cb)
|
||||
{
|
||||
((QApplication_Adaptor *)cls)->cb_notify_2411_0 = cb;
|
||||
}
|
||||
|
||||
|
||||
// exposed int QApplication::receivers(const char *signal)
|
||||
|
||||
static void _init_fp_receivers_c1731 (qt_gsi::GenericMethod *decl)
|
||||
|
|
@ -2147,8 +2082,6 @@ static gsi::Methods methods_QApplication_Adaptor () {
|
|||
methods += new qt_gsi::GenericMethod ("emit_focusChanged", "@brief Emitter for signal void QApplication::focusChanged(QWidget *old, QWidget *now)\nCall this method to emit this signal.", false, &_init_emitter_focusChanged_2522, &_call_emitter_focusChanged_2522);
|
||||
methods += new qt_gsi::GenericMethod ("emit_fontDatabaseChanged", "@brief Emitter for signal void QApplication::fontDatabaseChanged()\nCall this method to emit this signal.", false, &_init_emitter_fontDatabaseChanged_0, &_call_emitter_fontDatabaseChanged_0);
|
||||
methods += new qt_gsi::GenericMethod ("emit_lastWindowClosed", "@brief Emitter for signal void QApplication::lastWindowClosed()\nCall this method to emit this signal.", false, &_init_emitter_lastWindowClosed_0, &_call_emitter_lastWindowClosed_0);
|
||||
methods += new qt_gsi::GenericMethod ("notify", "@brief Virtual method bool QApplication::notify(QObject *, QEvent *)\nThis method can be reimplemented in a derived class.", false, &_init_cbs_notify_2411_0, &_call_cbs_notify_2411_0);
|
||||
methods += new qt_gsi::GenericMethod ("notify", "@hide", false, &_init_cbs_notify_2411_0, &_call_cbs_notify_2411_0, &_set_callback_cbs_notify_2411_0);
|
||||
methods += new qt_gsi::GenericMethod ("*receivers", "@brief Method int QApplication::receivers(const char *signal)\nThis method is protected and can only be called from inside a derived class.", true, &_init_fp_receivers_c1731, &_call_fp_receivers_c1731);
|
||||
methods += new qt_gsi::GenericMethod ("*sender", "@brief Method QObject *QApplication::sender()\nThis method is protected and can only be called from inside a derived class.", true, &_init_fp_sender_c0, &_call_fp_sender_c0);
|
||||
methods += new qt_gsi::GenericMethod ("*timerEvent", "@brief Virtual method void QApplication::timerEvent(QTimerEvent *)\nThis method can be reimplemented in a derived class.", false, &_init_cbs_timerEvent_1730_0, &_call_cbs_timerEvent_1730_0);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
#
|
||||
# Partial QMAKE project file for Qt bindings
|
||||
#
|
||||
# DO NOT EDIT THIS FILE.
|
||||
# This file has been created automatically
|
||||
#
|
||||
|
||||
SOURCES += \
|
||||
gsiQtUiToolsMain.cc \
|
||||
$$PWD/gsiDeclQUiLoader.cc
|
||||
|
||||
HEADERS += gsiQtUiToolsCommon.h
|
||||
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
|
||||
|
||||
DESTDIR = $$OUT_PWD/../../..
|
||||
TARGET = klayout_QtUiTools
|
||||
|
||||
include($$PWD/../../../lib.pri)
|
||||
|
||||
DEFINES += MAKE_GSI_QTUITOOLS_LIBRARY
|
||||
|
||||
INCLUDEPATH += $$TL_INC $$GSI_INC $$QTBASIC_INC
|
||||
DEPENDPATH += $$TL_INC $$GSI_INC $$QTBASIC_INC
|
||||
|
||||
LIBS += -L$$DESTDIR -lklayout_tl -lklayout_gsi -lklayout_qtbasic
|
||||
|
||||
SOURCES += \
|
||||
|
||||
HEADERS += \
|
||||
|
||||
include(QtUiTools.pri)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,86 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2021 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file generated/gsiDeclQtUiToolsTypeTraits.h
|
||||
* @brief Type traits for the Qt binding classes
|
||||
*
|
||||
* DO NOT EDIT THIS FILE.
|
||||
* This file has been created automatically
|
||||
*/
|
||||
|
||||
#ifndef _HDR_gsiDeclQtUiToolsTypeTraits
|
||||
#define _HDR_gsiDeclQtUiToolsTypeTraits
|
||||
|
||||
#include "gsiTypes.h"
|
||||
|
||||
|
||||
struct QMetaObject;
|
||||
namespace tl {
|
||||
template <> struct type_traits<QMetaObject> : public type_traits<void> {
|
||||
};
|
||||
}
|
||||
|
||||
class QObject;
|
||||
namespace tl {
|
||||
template <> struct type_traits<QObject> : public type_traits<void> {
|
||||
typedef tl::false_tag has_copy_constructor;
|
||||
};
|
||||
}
|
||||
|
||||
class QObject_Adaptor;
|
||||
namespace tl {
|
||||
template <> struct type_traits<QObject_Adaptor> : public type_traits<void> {
|
||||
typedef tl::false_tag has_copy_constructor;
|
||||
};
|
||||
}
|
||||
|
||||
class QSysInfo;
|
||||
namespace tl {
|
||||
template <> struct type_traits<QSysInfo> : public type_traits<void> {
|
||||
};
|
||||
}
|
||||
|
||||
class QUiLoader;
|
||||
namespace tl {
|
||||
template <> struct type_traits<QUiLoader> : public type_traits<void> {
|
||||
typedef tl::false_tag has_copy_constructor;
|
||||
};
|
||||
}
|
||||
|
||||
class QUiLoader_Adaptor;
|
||||
namespace tl {
|
||||
template <> struct type_traits<QUiLoader_Adaptor> : public type_traits<void> {
|
||||
typedef tl::false_tag has_copy_constructor;
|
||||
};
|
||||
}
|
||||
|
||||
class Qt_Namespace;
|
||||
namespace tl {
|
||||
template <> struct type_traits<Qt_Namespace> : public type_traits<void> {
|
||||
typedef tl::false_tag has_copy_constructor;
|
||||
typedef tl::false_tag has_default_constructor;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2021 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
External declarations for for Qt bindings
|
||||
|
||||
DO NOT EDIT THIS FILE.
|
||||
This file has been created automatically
|
||||
*/
|
||||
|
||||
#if !defined(HDR_gsiQtUiToolsExternals)
|
||||
#define HDR_gsiQtUiToolsExternals
|
||||
|
||||
#include "gsiClass.h"
|
||||
#include "gsiQtUiToolsCommon.h"
|
||||
|
||||
class QUiLoader;
|
||||
|
||||
namespace tl { template <> struct type_traits<QUiLoader> : public type_traits<void> {
|
||||
typedef tl::false_tag has_copy_constructor;
|
||||
}; }
|
||||
|
||||
namespace gsi { GSI_QTUITOOLS_PUBLIC gsi::Class<QUiLoader> &qtdecl_QUiLoader (); }
|
||||
|
||||
|
||||
#define QT_EXTERNAL_BASE(X) gsi::qtdecl_##X(),
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
/**
|
||||
* Common header for Qt binding definition library
|
||||
*
|
||||
* DO NOT EDIT THIS FILE.
|
||||
* This file has been created automatically
|
||||
*/
|
||||
|
||||
#include "tlDefs.h"
|
||||
|
||||
#if !defined(HDR_gsiQtUiToolsCommon_h)
|
||||
# define HDR_gsiQtUiToolsCommon_h
|
||||
|
||||
# ifdef MAKE_GSI_QTUITOOLS_LIBRARY
|
||||
# define GSI_QTUITOOLS_PUBLIC DEF_INSIDE_PUBLIC
|
||||
# define GSI_QTUITOOLS_PUBLIC_TEMPLATE DEF_INSIDE_PUBLIC_TEMPLATE
|
||||
# define GSI_QTUITOOLS_LOCAL DEF_INSIDE_LOCAL
|
||||
# else
|
||||
# define GSI_QTUITOOLS_PUBLIC DEF_OUTSIDE_PUBLIC
|
||||
# define GSI_QTUITOOLS_PUBLIC_TEMPLATE DEF_OUTSIDE_PUBLIC_TEMPLATE
|
||||
# define GSI_QTUITOOLS_LOCAL DEF_OUTSIDE_LOCAL
|
||||
# endif
|
||||
|
||||
#define FORCE_LINK_GSI_QTUITOOLS GSI_QTUITOOLS_PUBLIC int _force_link_gsiQtUiTools_f (); int _force_link_gsiQtUiTools = _force_link_gsiQtUiTools_f ();
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
/**
|
||||
* Main source file for Qt binding definition library
|
||||
*
|
||||
* DO NOT EDIT THIS FILE.
|
||||
* This file has been created automatically
|
||||
*/
|
||||
|
||||
#include "gsiQtUiToolsCommon.h"
|
||||
|
||||
GSI_QTUITOOLS_PUBLIC int _force_link_gsiQtUiTools_f () { return 0; }
|
||||
|
||||
|
|
@ -1,16 +1,36 @@
|
|||
|
||||
include($$PWD/../../klayout.pri)
|
||||
|
||||
TEMPLATE = subdirs
|
||||
|
||||
SUBDIRS = \
|
||||
QtCore \
|
||||
QtGui \
|
||||
QtXml \
|
||||
QtSql \
|
||||
QtNetwork \
|
||||
QtDesigner
|
||||
QtGui
|
||||
|
||||
QtGui.depends += QtCore
|
||||
QtNetwork.depends += QtCore
|
||||
QtSql.depends += QtCore
|
||||
QtDesigner.depends += QtCore
|
||||
QtXml.depends += QtCore
|
||||
|
||||
equals(HAVE_QT_NETWORK, "1") {
|
||||
SUBDIRS += QtNetwork
|
||||
QtNetwork.depends += QtCore
|
||||
}
|
||||
|
||||
equals(HAVE_QT_SQL, "1") {
|
||||
SUBDIRS += QtSql
|
||||
QtSql.depends += QtCore
|
||||
}
|
||||
|
||||
equals(HAVE_QT_DESIGNER, "1") {
|
||||
SUBDIRS += QtDesigner
|
||||
QtDesigner.depends += QtCore
|
||||
}
|
||||
|
||||
equals(HAVE_QT_XML, "1") {
|
||||
SUBDIRS += QtXml
|
||||
QtXml.depends += QtCore
|
||||
}
|
||||
|
||||
equals(HAVE_QT_UITOOLS, "1") {
|
||||
SUBDIRS += QtUiTools
|
||||
QtUiTools.depends += QtCore
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -72,28 +72,6 @@ static void _call_f_installNativeEventFilter_3266 (const qt_gsi::GenericMethod *
|
|||
}
|
||||
|
||||
|
||||
// bool QCoreApplication::notify(QObject *, QEvent *)
|
||||
|
||||
|
||||
static void _init_f_notify_2411 (qt_gsi::GenericMethod *decl)
|
||||
{
|
||||
static gsi::ArgSpecBase argspec_0 ("arg1");
|
||||
decl->add_arg<QObject * > (argspec_0);
|
||||
static gsi::ArgSpecBase argspec_1 ("arg2");
|
||||
decl->add_arg<QEvent * > (argspec_1);
|
||||
decl->set_return<bool > ();
|
||||
}
|
||||
|
||||
static void _call_f_notify_2411 (const qt_gsi::GenericMethod * /*decl*/, void *cls, gsi::SerialArgs &args, gsi::SerialArgs &ret)
|
||||
{
|
||||
__SUPPRESS_UNUSED_WARNING(args);
|
||||
tl::Heap heap;
|
||||
QObject *arg1 = gsi::arg_reader<QObject * >() (args, heap);
|
||||
QEvent *arg2 = gsi::arg_reader<QEvent * >() (args, heap);
|
||||
ret.write<bool > ((bool)((QCoreApplication *)cls)->notify (arg1, arg2));
|
||||
}
|
||||
|
||||
|
||||
// void QCoreApplication::removeNativeEventFilter(QAbstractNativeEventFilter *filterObj)
|
||||
|
||||
|
||||
|
|
@ -924,7 +902,6 @@ static gsi::Methods methods_QCoreApplication () {
|
|||
gsi::Methods methods;
|
||||
methods += new qt_gsi::GenericStaticMethod ("staticMetaObject", "@brief Obtains the static MetaObject for this class.", &_init_smo, &_call_smo);
|
||||
methods += new qt_gsi::GenericMethod ("installNativeEventFilter", "@brief Method void QCoreApplication::installNativeEventFilter(QAbstractNativeEventFilter *filterObj)\n", false, &_init_f_installNativeEventFilter_3266, &_call_f_installNativeEventFilter_3266);
|
||||
methods += new qt_gsi::GenericMethod ("notify", "@brief Method bool QCoreApplication::notify(QObject *, QEvent *)\n", false, &_init_f_notify_2411, &_call_f_notify_2411);
|
||||
methods += new qt_gsi::GenericMethod ("removeNativeEventFilter", "@brief Method void QCoreApplication::removeNativeEventFilter(QAbstractNativeEventFilter *filterObj)\n", false, &_init_f_removeNativeEventFilter_3266, &_call_f_removeNativeEventFilter_3266);
|
||||
methods += gsi::qt_signal ("aboutToQuit()", "aboutToQuit", "@brief Signal declaration for QCoreApplication::aboutToQuit()\nYou can bind a procedure to this signal.");
|
||||
methods += gsi::qt_signal ("applicationNameChanged()", "applicationNameChanged", "@brief Signal declaration for QCoreApplication::applicationNameChanged()\nYou can bind a procedure to this signal.");
|
||||
|
|
@ -1076,21 +1053,6 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
// [adaptor impl] bool QCoreApplication::notify(QObject *, QEvent *)
|
||||
bool cbs_notify_2411_0(QObject *arg1, QEvent *arg2)
|
||||
{
|
||||
return QCoreApplication::notify(arg1, arg2);
|
||||
}
|
||||
|
||||
virtual bool notify(QObject *arg1, QEvent *arg2)
|
||||
{
|
||||
if (cb_notify_2411_0.can_issue()) {
|
||||
return cb_notify_2411_0.issue<QCoreApplication_Adaptor, bool, QObject *, QEvent *>(&QCoreApplication_Adaptor::cbs_notify_2411_0, arg1, arg2);
|
||||
} else {
|
||||
return QCoreApplication::notify(arg1, arg2);
|
||||
}
|
||||
}
|
||||
|
||||
// [emitter impl] void QCoreApplication::objectNameChanged(const QString &objectName)
|
||||
void emitter_QCoreApplication_objectNameChanged_4567(const QString &objectName)
|
||||
{
|
||||
|
|
@ -1186,7 +1148,6 @@ public:
|
|||
}
|
||||
|
||||
gsi::Callback cb_eventFilter_2411_0;
|
||||
gsi::Callback cb_notify_2411_0;
|
||||
gsi::Callback cb_childEvent_1701_0;
|
||||
gsi::Callback cb_customEvent_1217_0;
|
||||
gsi::Callback cb_disconnectNotify_2394_0;
|
||||
|
|
@ -1395,32 +1356,6 @@ static void _call_fp_isSignalConnected_c2394 (const qt_gsi::GenericMethod * /*de
|
|||
}
|
||||
|
||||
|
||||
// bool QCoreApplication::notify(QObject *, QEvent *)
|
||||
|
||||
static void _init_cbs_notify_2411_0 (qt_gsi::GenericMethod *decl)
|
||||
{
|
||||
static gsi::ArgSpecBase argspec_0 ("arg1");
|
||||
decl->add_arg<QObject * > (argspec_0);
|
||||
static gsi::ArgSpecBase argspec_1 ("arg2");
|
||||
decl->add_arg<QEvent * > (argspec_1);
|
||||
decl->set_return<bool > ();
|
||||
}
|
||||
|
||||
static void _call_cbs_notify_2411_0 (const qt_gsi::GenericMethod * /*decl*/, void *cls, gsi::SerialArgs &args, gsi::SerialArgs &ret)
|
||||
{
|
||||
__SUPPRESS_UNUSED_WARNING(args);
|
||||
tl::Heap heap;
|
||||
QObject *arg1 = args.read<QObject * > (heap);
|
||||
QEvent *arg2 = args.read<QEvent * > (heap);
|
||||
ret.write<bool > ((bool)((QCoreApplication_Adaptor *)cls)->cbs_notify_2411_0 (arg1, arg2));
|
||||
}
|
||||
|
||||
static void _set_callback_cbs_notify_2411_0 (void *cls, const gsi::Callback &cb)
|
||||
{
|
||||
((QCoreApplication_Adaptor *)cls)->cb_notify_2411_0 = cb;
|
||||
}
|
||||
|
||||
|
||||
// emitter void QCoreApplication::objectNameChanged(const QString &objectName)
|
||||
|
||||
static void _init_emitter_objectNameChanged_4567 (qt_gsi::GenericMethod *decl)
|
||||
|
|
@ -1559,8 +1494,6 @@ static gsi::Methods methods_QCoreApplication_Adaptor () {
|
|||
methods += new qt_gsi::GenericMethod ("eventFilter", "@brief Virtual method bool QCoreApplication::eventFilter(QObject *, QEvent *)\nThis method can be reimplemented in a derived class.", false, &_init_cbs_eventFilter_2411_0, &_call_cbs_eventFilter_2411_0);
|
||||
methods += new qt_gsi::GenericMethod ("eventFilter", "@hide", false, &_init_cbs_eventFilter_2411_0, &_call_cbs_eventFilter_2411_0, &_set_callback_cbs_eventFilter_2411_0);
|
||||
methods += new qt_gsi::GenericMethod ("*isSignalConnected", "@brief Method bool QCoreApplication::isSignalConnected(const QMetaMethod &signal)\nThis method is protected and can only be called from inside a derived class.", true, &_init_fp_isSignalConnected_c2394, &_call_fp_isSignalConnected_c2394);
|
||||
methods += new qt_gsi::GenericMethod ("notify", "@brief Virtual method bool QCoreApplication::notify(QObject *, QEvent *)\nThis method can be reimplemented in a derived class.", false, &_init_cbs_notify_2411_0, &_call_cbs_notify_2411_0);
|
||||
methods += new qt_gsi::GenericMethod ("notify", "@hide", false, &_init_cbs_notify_2411_0, &_call_cbs_notify_2411_0, &_set_callback_cbs_notify_2411_0);
|
||||
methods += new qt_gsi::GenericMethod ("emit_objectNameChanged", "@brief Emitter for signal void QCoreApplication::objectNameChanged(const QString &objectName)\nCall this method to emit this signal.", false, &_init_emitter_objectNameChanged_4567, &_call_emitter_objectNameChanged_4567);
|
||||
methods += new qt_gsi::GenericMethod ("emit_organizationDomainChanged", "@brief Emitter for signal void QCoreApplication::organizationDomainChanged()\nCall this method to emit this signal.", false, &_init_emitter_organizationDomainChanged_0, &_call_emitter_organizationDomainChanged_0);
|
||||
methods += new qt_gsi::GenericMethod ("emit_organizationNameChanged", "@brief Emitter for signal void QCoreApplication::organizationNameChanged()\nCall this method to emit this signal.", false, &_init_emitter_organizationNameChanged_0, &_call_emitter_organizationNameChanged_0);
|
||||
|
|
|
|||
|
|
@ -99,28 +99,6 @@ static void _call_f_isSessionRestored_c0 (const qt_gsi::GenericMethod * /*decl*/
|
|||
}
|
||||
|
||||
|
||||
// bool QGuiApplication::notify(QObject *, QEvent *)
|
||||
|
||||
|
||||
static void _init_f_notify_2411 (qt_gsi::GenericMethod *decl)
|
||||
{
|
||||
static gsi::ArgSpecBase argspec_0 ("arg1");
|
||||
decl->add_arg<QObject * > (argspec_0);
|
||||
static gsi::ArgSpecBase argspec_1 ("arg2");
|
||||
decl->add_arg<QEvent * > (argspec_1);
|
||||
decl->set_return<bool > ();
|
||||
}
|
||||
|
||||
static void _call_f_notify_2411 (const qt_gsi::GenericMethod * /*decl*/, void *cls, gsi::SerialArgs &args, gsi::SerialArgs &ret)
|
||||
{
|
||||
__SUPPRESS_UNUSED_WARNING(args);
|
||||
tl::Heap heap;
|
||||
QObject *arg1 = gsi::arg_reader<QObject * >() (args, heap);
|
||||
QEvent *arg2 = gsi::arg_reader<QEvent * >() (args, heap);
|
||||
ret.write<bool > ((bool)((QGuiApplication *)cls)->notify (arg1, arg2));
|
||||
}
|
||||
|
||||
|
||||
// QString QGuiApplication::sessionId()
|
||||
|
||||
|
||||
|
|
@ -831,7 +809,6 @@ static gsi::Methods methods_QGuiApplication () {
|
|||
methods += new qt_gsi::GenericMethod ("devicePixelRatio", "@brief Method double QGuiApplication::devicePixelRatio()\n", true, &_init_f_devicePixelRatio_c0, &_call_f_devicePixelRatio_c0);
|
||||
methods += new qt_gsi::GenericMethod ("isSavingSession?", "@brief Method bool QGuiApplication::isSavingSession()\n", true, &_init_f_isSavingSession_c0, &_call_f_isSavingSession_c0);
|
||||
methods += new qt_gsi::GenericMethod ("isSessionRestored?", "@brief Method bool QGuiApplication::isSessionRestored()\n", true, &_init_f_isSessionRestored_c0, &_call_f_isSessionRestored_c0);
|
||||
methods += new qt_gsi::GenericMethod ("notify", "@brief Method bool QGuiApplication::notify(QObject *, QEvent *)\nThis is a reimplementation of QCoreApplication::notify", false, &_init_f_notify_2411, &_call_f_notify_2411);
|
||||
methods += new qt_gsi::GenericMethod ("sessionId", "@brief Method QString QGuiApplication::sessionId()\n", true, &_init_f_sessionId_c0, &_call_f_sessionId_c0);
|
||||
methods += new qt_gsi::GenericMethod ("sessionKey", "@brief Method QString QGuiApplication::sessionKey()\n", true, &_init_f_sessionKey_c0, &_call_f_sessionKey_c0);
|
||||
methods += gsi::qt_signal ("aboutToQuit()", "aboutToQuit", "@brief Signal declaration for QGuiApplication::aboutToQuit()\nYou can bind a procedure to this signal.");
|
||||
|
|
@ -1034,21 +1011,6 @@ public:
|
|||
emit QGuiApplication::layoutDirectionChanged(direction);
|
||||
}
|
||||
|
||||
// [adaptor impl] bool QGuiApplication::notify(QObject *, QEvent *)
|
||||
bool cbs_notify_2411_0(QObject *arg1, QEvent *arg2)
|
||||
{
|
||||
return QGuiApplication::notify(arg1, arg2);
|
||||
}
|
||||
|
||||
virtual bool notify(QObject *arg1, QEvent *arg2)
|
||||
{
|
||||
if (cb_notify_2411_0.can_issue()) {
|
||||
return cb_notify_2411_0.issue<QGuiApplication_Adaptor, bool, QObject *, QEvent *>(&QGuiApplication_Adaptor::cbs_notify_2411_0, arg1, arg2);
|
||||
} else {
|
||||
return QGuiApplication::notify(arg1, arg2);
|
||||
}
|
||||
}
|
||||
|
||||
// [emitter impl] void QGuiApplication::objectNameChanged(const QString &objectName)
|
||||
void emitter_QGuiApplication_objectNameChanged_4567(const QString &objectName)
|
||||
{
|
||||
|
|
@ -1168,7 +1130,6 @@ public:
|
|||
}
|
||||
|
||||
gsi::Callback cb_eventFilter_2411_0;
|
||||
gsi::Callback cb_notify_2411_0;
|
||||
gsi::Callback cb_childEvent_1701_0;
|
||||
gsi::Callback cb_customEvent_1217_0;
|
||||
gsi::Callback cb_disconnectNotify_2394_0;
|
||||
|
|
@ -1495,32 +1456,6 @@ static void _call_emitter_layoutDirectionChanged_2316 (const qt_gsi::GenericMeth
|
|||
}
|
||||
|
||||
|
||||
// bool QGuiApplication::notify(QObject *, QEvent *)
|
||||
|
||||
static void _init_cbs_notify_2411_0 (qt_gsi::GenericMethod *decl)
|
||||
{
|
||||
static gsi::ArgSpecBase argspec_0 ("arg1");
|
||||
decl->add_arg<QObject * > (argspec_0);
|
||||
static gsi::ArgSpecBase argspec_1 ("arg2");
|
||||
decl->add_arg<QEvent * > (argspec_1);
|
||||
decl->set_return<bool > ();
|
||||
}
|
||||
|
||||
static void _call_cbs_notify_2411_0 (const qt_gsi::GenericMethod * /*decl*/, void *cls, gsi::SerialArgs &args, gsi::SerialArgs &ret)
|
||||
{
|
||||
__SUPPRESS_UNUSED_WARNING(args);
|
||||
tl::Heap heap;
|
||||
QObject *arg1 = args.read<QObject * > (heap);
|
||||
QEvent *arg2 = args.read<QEvent * > (heap);
|
||||
ret.write<bool > ((bool)((QGuiApplication_Adaptor *)cls)->cbs_notify_2411_0 (arg1, arg2));
|
||||
}
|
||||
|
||||
static void _set_callback_cbs_notify_2411_0 (void *cls, const gsi::Callback &cb)
|
||||
{
|
||||
((QGuiApplication_Adaptor *)cls)->cb_notify_2411_0 = cb;
|
||||
}
|
||||
|
||||
|
||||
// emitter void QGuiApplication::objectNameChanged(const QString &objectName)
|
||||
|
||||
static void _init_emitter_objectNameChanged_4567 (qt_gsi::GenericMethod *decl)
|
||||
|
|
@ -1738,8 +1673,6 @@ static gsi::Methods methods_QGuiApplication_Adaptor () {
|
|||
methods += new qt_gsi::GenericMethod ("*isSignalConnected", "@brief Method bool QGuiApplication::isSignalConnected(const QMetaMethod &signal)\nThis method is protected and can only be called from inside a derived class.", true, &_init_fp_isSignalConnected_c2394, &_call_fp_isSignalConnected_c2394);
|
||||
methods += new qt_gsi::GenericMethod ("emit_lastWindowClosed", "@brief Emitter for signal void QGuiApplication::lastWindowClosed()\nCall this method to emit this signal.", false, &_init_emitter_lastWindowClosed_0, &_call_emitter_lastWindowClosed_0);
|
||||
methods += new qt_gsi::GenericMethod ("emit_layoutDirectionChanged", "@brief Emitter for signal void QGuiApplication::layoutDirectionChanged(Qt::LayoutDirection direction)\nCall this method to emit this signal.", false, &_init_emitter_layoutDirectionChanged_2316, &_call_emitter_layoutDirectionChanged_2316);
|
||||
methods += new qt_gsi::GenericMethod ("notify", "@brief Virtual method bool QGuiApplication::notify(QObject *, QEvent *)\nThis method can be reimplemented in a derived class.", false, &_init_cbs_notify_2411_0, &_call_cbs_notify_2411_0);
|
||||
methods += new qt_gsi::GenericMethod ("notify", "@hide", false, &_init_cbs_notify_2411_0, &_call_cbs_notify_2411_0, &_set_callback_cbs_notify_2411_0);
|
||||
methods += new qt_gsi::GenericMethod ("emit_objectNameChanged", "@brief Emitter for signal void QGuiApplication::objectNameChanged(const QString &objectName)\nCall this method to emit this signal.", false, &_init_emitter_objectNameChanged_4567, &_call_emitter_objectNameChanged_4567);
|
||||
methods += new qt_gsi::GenericMethod ("emit_organizationDomainChanged", "@brief Emitter for signal void QGuiApplication::organizationDomainChanged()\nCall this method to emit this signal.", false, &_init_emitter_organizationDomainChanged_0, &_call_emitter_organizationDomainChanged_0);
|
||||
methods += new qt_gsi::GenericMethod ("emit_organizationNameChanged", "@brief Emitter for signal void QGuiApplication::organizationNameChanged()\nCall this method to emit this signal.", false, &_init_emitter_organizationNameChanged_0, &_call_emitter_organizationNameChanged_0);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
#
|
||||
# Partial QMAKE project file for Qt bindings
|
||||
#
|
||||
# DO NOT EDIT THIS FILE.
|
||||
# This file has been created automatically
|
||||
#
|
||||
|
||||
SOURCES += \
|
||||
gsiQtUiToolsMain.cc \
|
||||
$$PWD/gsiDeclQUiLoader.cc
|
||||
|
||||
HEADERS += gsiQtUiToolsCommon.h
|
||||
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
|
||||
|
||||
DESTDIR = $$OUT_PWD/../../..
|
||||
TARGET = klayout_QtUiTools
|
||||
|
||||
include($$PWD/../../../lib.pri)
|
||||
|
||||
DEFINES += MAKE_GSI_QTUITOOLS_LIBRARY
|
||||
|
||||
INCLUDEPATH += $$TL_INC $$GSI_INC $$QTBASIC_INC
|
||||
DEPENDPATH += $$TL_INC $$GSI_INC $$QTBASIC_INC
|
||||
|
||||
LIBS += -L$$DESTDIR -lklayout_tl -lklayout_gsi -lklayout_qtbasic -lklayout_QtCore
|
||||
|
||||
SOURCES += \
|
||||
|
||||
HEADERS += \
|
||||
|
||||
include(QtUiTools.pri)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,138 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2021 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file generated/gsiDeclQtUiToolsTypeTraits.h
|
||||
* @brief Type traits for the Qt binding classes
|
||||
*
|
||||
* DO NOT EDIT THIS FILE.
|
||||
* This file has been created automatically
|
||||
*/
|
||||
|
||||
#ifndef _HDR_gsiDeclQtUiToolsTypeTraits
|
||||
#define _HDR_gsiDeclQtUiToolsTypeTraits
|
||||
|
||||
#include "gsiTypes.h"
|
||||
|
||||
|
||||
struct QByteArrayDataPtr;
|
||||
namespace tl {
|
||||
template <> struct type_traits<QByteArrayDataPtr> : public type_traits<void> {
|
||||
};
|
||||
}
|
||||
|
||||
class QMessageLogContext;
|
||||
namespace tl {
|
||||
template <> struct type_traits<QMessageLogContext> : public type_traits<void> {
|
||||
typedef tl::false_tag has_copy_constructor;
|
||||
};
|
||||
}
|
||||
|
||||
class QMessageLogger;
|
||||
namespace tl {
|
||||
template <> struct type_traits<QMessageLogger> : public type_traits<void> {
|
||||
typedef tl::false_tag has_copy_constructor;
|
||||
};
|
||||
}
|
||||
|
||||
struct QMetaObject;
|
||||
namespace tl {
|
||||
template <> struct type_traits<QMetaObject> : public type_traits<void> {
|
||||
};
|
||||
}
|
||||
|
||||
#include <QMetaObject>
|
||||
namespace tl {
|
||||
template <> struct type_traits<QMetaObject::Connection> : public type_traits<void> {
|
||||
};
|
||||
}
|
||||
|
||||
class QObject;
|
||||
namespace tl {
|
||||
template <> struct type_traits<QObject> : public type_traits<void> {
|
||||
typedef tl::false_tag has_copy_constructor;
|
||||
};
|
||||
}
|
||||
|
||||
class QObject_Adaptor;
|
||||
namespace tl {
|
||||
template <> struct type_traits<QObject_Adaptor> : public type_traits<void> {
|
||||
typedef tl::false_tag has_copy_constructor;
|
||||
};
|
||||
}
|
||||
|
||||
class QRegExp;
|
||||
namespace tl {
|
||||
template <> struct type_traits<QRegExp> : public type_traits<void> {
|
||||
};
|
||||
}
|
||||
|
||||
class QSignalBlocker;
|
||||
namespace tl {
|
||||
template <> struct type_traits<QSignalBlocker> : public type_traits<void> {
|
||||
typedef tl::false_tag has_copy_constructor;
|
||||
typedef tl::false_tag has_default_constructor;
|
||||
};
|
||||
}
|
||||
|
||||
struct QStringDataPtr;
|
||||
namespace tl {
|
||||
template <> struct type_traits<QStringDataPtr> : public type_traits<void> {
|
||||
};
|
||||
}
|
||||
|
||||
class QStringMatcher;
|
||||
namespace tl {
|
||||
template <> struct type_traits<QStringMatcher> : public type_traits<void> {
|
||||
};
|
||||
}
|
||||
|
||||
class QSysInfo;
|
||||
namespace tl {
|
||||
template <> struct type_traits<QSysInfo> : public type_traits<void> {
|
||||
};
|
||||
}
|
||||
|
||||
class QUiLoader;
|
||||
namespace tl {
|
||||
template <> struct type_traits<QUiLoader> : public type_traits<void> {
|
||||
typedef tl::false_tag has_copy_constructor;
|
||||
};
|
||||
}
|
||||
|
||||
class QUiLoader_Adaptor;
|
||||
namespace tl {
|
||||
template <> struct type_traits<QUiLoader_Adaptor> : public type_traits<void> {
|
||||
typedef tl::false_tag has_copy_constructor;
|
||||
};
|
||||
}
|
||||
|
||||
class Qt_Namespace;
|
||||
namespace tl {
|
||||
template <> struct type_traits<Qt_Namespace> : public type_traits<void> {
|
||||
typedef tl::false_tag has_copy_constructor;
|
||||
typedef tl::false_tag has_default_constructor;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2021 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
External declarations for for Qt bindings
|
||||
|
||||
DO NOT EDIT THIS FILE.
|
||||
This file has been created automatically
|
||||
*/
|
||||
|
||||
#if !defined(HDR_gsiQtUiToolsExternals)
|
||||
#define HDR_gsiQtUiToolsExternals
|
||||
|
||||
#include "gsiClass.h"
|
||||
#include "gsiQtUiToolsCommon.h"
|
||||
|
||||
class QUiLoader;
|
||||
|
||||
namespace tl { template <> struct type_traits<QUiLoader> : public type_traits<void> {
|
||||
typedef tl::false_tag has_copy_constructor;
|
||||
}; }
|
||||
|
||||
namespace gsi { GSI_QTUITOOLS_PUBLIC gsi::Class<QUiLoader> &qtdecl_QUiLoader (); }
|
||||
|
||||
|
||||
#define QT_EXTERNAL_BASE(X) gsi::qtdecl_##X(),
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
/**
|
||||
* Common header for Qt binding definition library
|
||||
*
|
||||
* DO NOT EDIT THIS FILE.
|
||||
* This file has been created automatically
|
||||
*/
|
||||
|
||||
#include "tlDefs.h"
|
||||
|
||||
#if !defined(HDR_gsiQtUiToolsCommon_h)
|
||||
# define HDR_gsiQtUiToolsCommon_h
|
||||
|
||||
# ifdef MAKE_GSI_QTUITOOLS_LIBRARY
|
||||
# define GSI_QTUITOOLS_PUBLIC DEF_INSIDE_PUBLIC
|
||||
# define GSI_QTUITOOLS_PUBLIC_TEMPLATE DEF_INSIDE_PUBLIC_TEMPLATE
|
||||
# define GSI_QTUITOOLS_LOCAL DEF_INSIDE_LOCAL
|
||||
# else
|
||||
# define GSI_QTUITOOLS_PUBLIC DEF_OUTSIDE_PUBLIC
|
||||
# define GSI_QTUITOOLS_PUBLIC_TEMPLATE DEF_OUTSIDE_PUBLIC_TEMPLATE
|
||||
# define GSI_QTUITOOLS_LOCAL DEF_OUTSIDE_LOCAL
|
||||
# endif
|
||||
|
||||
#define FORCE_LINK_GSI_QTUITOOLS GSI_QTUITOOLS_PUBLIC int _force_link_gsiQtUiTools_f (); int _force_link_gsiQtUiTools = _force_link_gsiQtUiTools_f ();
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
/**
|
||||
* Main source file for Qt binding definition library
|
||||
*
|
||||
* DO NOT EDIT THIS FILE.
|
||||
* This file has been created automatically
|
||||
*/
|
||||
|
||||
#include "gsiQtUiToolsCommon.h"
|
||||
|
||||
GSI_QTUITOOLS_PUBLIC int _force_link_gsiQtUiTools_f () { return 0; }
|
||||
|
||||
|
|
@ -69,28 +69,6 @@ static void _call_f_autoSipEnabled_c0 (const qt_gsi::GenericMethod * /*decl*/, v
|
|||
}
|
||||
|
||||
|
||||
// bool QApplication::notify(QObject *, QEvent *)
|
||||
|
||||
|
||||
static void _init_f_notify_2411 (qt_gsi::GenericMethod *decl)
|
||||
{
|
||||
static gsi::ArgSpecBase argspec_0 ("arg1");
|
||||
decl->add_arg<QObject * > (argspec_0);
|
||||
static gsi::ArgSpecBase argspec_1 ("arg2");
|
||||
decl->add_arg<QEvent * > (argspec_1);
|
||||
decl->set_return<bool > ();
|
||||
}
|
||||
|
||||
static void _call_f_notify_2411 (const qt_gsi::GenericMethod * /*decl*/, void *cls, gsi::SerialArgs &args, gsi::SerialArgs &ret)
|
||||
{
|
||||
__SUPPRESS_UNUSED_WARNING(args);
|
||||
tl::Heap heap;
|
||||
QObject *arg1 = gsi::arg_reader<QObject * >() (args, heap);
|
||||
QEvent *arg2 = gsi::arg_reader<QEvent * >() (args, heap);
|
||||
ret.write<bool > ((bool)((QApplication *)cls)->notify (arg1, arg2));
|
||||
}
|
||||
|
||||
|
||||
// void QApplication::setAutoSipEnabled(const bool enabled)
|
||||
|
||||
|
||||
|
|
@ -1074,7 +1052,6 @@ static gsi::Methods methods_QApplication () {
|
|||
gsi::Methods methods;
|
||||
methods += new qt_gsi::GenericStaticMethod ("staticMetaObject", "@brief Obtains the static MetaObject for this class.", &_init_smo, &_call_smo);
|
||||
methods += new qt_gsi::GenericMethod (":autoSipEnabled", "@brief Method bool QApplication::autoSipEnabled()\n", true, &_init_f_autoSipEnabled_c0, &_call_f_autoSipEnabled_c0);
|
||||
methods += new qt_gsi::GenericMethod ("notify", "@brief Method bool QApplication::notify(QObject *, QEvent *)\nThis is a reimplementation of QGuiApplication::notify", false, &_init_f_notify_2411, &_call_f_notify_2411);
|
||||
methods += new qt_gsi::GenericMethod ("setAutoSipEnabled|autoSipEnabled=", "@brief Method void QApplication::setAutoSipEnabled(const bool enabled)\n", false, &_init_f_setAutoSipEnabled_1559, &_call_f_setAutoSipEnabled_1559);
|
||||
methods += new qt_gsi::GenericMethod ("setStyleSheet|styleSheet=", "@brief Method void QApplication::setStyleSheet(const QString &sheet)\n", false, &_init_f_setStyleSheet_2025, &_call_f_setStyleSheet_2025);
|
||||
methods += new qt_gsi::GenericMethod (":styleSheet", "@brief Method QString QApplication::styleSheet()\n", true, &_init_f_styleSheet_c0, &_call_f_styleSheet_c0);
|
||||
|
|
@ -1296,21 +1273,6 @@ public:
|
|||
emit QApplication::layoutDirectionChanged(direction);
|
||||
}
|
||||
|
||||
// [adaptor impl] bool QApplication::notify(QObject *, QEvent *)
|
||||
bool cbs_notify_2411_0(QObject *arg1, QEvent *arg2)
|
||||
{
|
||||
return QApplication::notify(arg1, arg2);
|
||||
}
|
||||
|
||||
virtual bool notify(QObject *arg1, QEvent *arg2)
|
||||
{
|
||||
if (cb_notify_2411_0.can_issue()) {
|
||||
return cb_notify_2411_0.issue<QApplication_Adaptor, bool, QObject *, QEvent *>(&QApplication_Adaptor::cbs_notify_2411_0, arg1, arg2);
|
||||
} else {
|
||||
return QApplication::notify(arg1, arg2);
|
||||
}
|
||||
}
|
||||
|
||||
// [emitter impl] void QApplication::objectNameChanged(const QString &objectName)
|
||||
void emitter_QApplication_objectNameChanged_4567(const QString &objectName)
|
||||
{
|
||||
|
|
@ -1430,7 +1392,6 @@ public:
|
|||
}
|
||||
|
||||
gsi::Callback cb_eventFilter_2411_0;
|
||||
gsi::Callback cb_notify_2411_0;
|
||||
gsi::Callback cb_childEvent_1701_0;
|
||||
gsi::Callback cb_customEvent_1217_0;
|
||||
gsi::Callback cb_disconnectNotify_2394_0;
|
||||
|
|
@ -1778,32 +1739,6 @@ static void _call_emitter_layoutDirectionChanged_2316 (const qt_gsi::GenericMeth
|
|||
}
|
||||
|
||||
|
||||
// bool QApplication::notify(QObject *, QEvent *)
|
||||
|
||||
static void _init_cbs_notify_2411_0 (qt_gsi::GenericMethod *decl)
|
||||
{
|
||||
static gsi::ArgSpecBase argspec_0 ("arg1");
|
||||
decl->add_arg<QObject * > (argspec_0);
|
||||
static gsi::ArgSpecBase argspec_1 ("arg2");
|
||||
decl->add_arg<QEvent * > (argspec_1);
|
||||
decl->set_return<bool > ();
|
||||
}
|
||||
|
||||
static void _call_cbs_notify_2411_0 (const qt_gsi::GenericMethod * /*decl*/, void *cls, gsi::SerialArgs &args, gsi::SerialArgs &ret)
|
||||
{
|
||||
__SUPPRESS_UNUSED_WARNING(args);
|
||||
tl::Heap heap;
|
||||
QObject *arg1 = args.read<QObject * > (heap);
|
||||
QEvent *arg2 = args.read<QEvent * > (heap);
|
||||
ret.write<bool > ((bool)((QApplication_Adaptor *)cls)->cbs_notify_2411_0 (arg1, arg2));
|
||||
}
|
||||
|
||||
static void _set_callback_cbs_notify_2411_0 (void *cls, const gsi::Callback &cb)
|
||||
{
|
||||
((QApplication_Adaptor *)cls)->cb_notify_2411_0 = cb;
|
||||
}
|
||||
|
||||
|
||||
// emitter void QApplication::objectNameChanged(const QString &objectName)
|
||||
|
||||
static void _init_emitter_objectNameChanged_4567 (qt_gsi::GenericMethod *decl)
|
||||
|
|
@ -2022,8 +1957,6 @@ static gsi::Methods methods_QApplication_Adaptor () {
|
|||
methods += new qt_gsi::GenericMethod ("*isSignalConnected", "@brief Method bool QApplication::isSignalConnected(const QMetaMethod &signal)\nThis method is protected and can only be called from inside a derived class.", true, &_init_fp_isSignalConnected_c2394, &_call_fp_isSignalConnected_c2394);
|
||||
methods += new qt_gsi::GenericMethod ("emit_lastWindowClosed", "@brief Emitter for signal void QApplication::lastWindowClosed()\nCall this method to emit this signal.", false, &_init_emitter_lastWindowClosed_0, &_call_emitter_lastWindowClosed_0);
|
||||
methods += new qt_gsi::GenericMethod ("emit_layoutDirectionChanged", "@brief Emitter for signal void QApplication::layoutDirectionChanged(Qt::LayoutDirection direction)\nCall this method to emit this signal.", false, &_init_emitter_layoutDirectionChanged_2316, &_call_emitter_layoutDirectionChanged_2316);
|
||||
methods += new qt_gsi::GenericMethod ("notify", "@brief Virtual method bool QApplication::notify(QObject *, QEvent *)\nThis method can be reimplemented in a derived class.", false, &_init_cbs_notify_2411_0, &_call_cbs_notify_2411_0);
|
||||
methods += new qt_gsi::GenericMethod ("notify", "@hide", false, &_init_cbs_notify_2411_0, &_call_cbs_notify_2411_0, &_set_callback_cbs_notify_2411_0);
|
||||
methods += new qt_gsi::GenericMethod ("emit_objectNameChanged", "@brief Emitter for signal void QApplication::objectNameChanged(const QString &objectName)\nCall this method to emit this signal.", false, &_init_emitter_objectNameChanged_4567, &_call_emitter_objectNameChanged_4567);
|
||||
methods += new qt_gsi::GenericMethod ("emit_organizationDomainChanged", "@brief Emitter for signal void QApplication::organizationDomainChanged()\nCall this method to emit this signal.", false, &_init_emitter_organizationDomainChanged_0, &_call_emitter_organizationDomainChanged_0);
|
||||
methods += new qt_gsi::GenericMethod ("emit_organizationNameChanged", "@brief Emitter for signal void QApplication::organizationNameChanged()\nCall this method to emit this signal.", false, &_init_emitter_organizationNameChanged_0, &_call_emitter_organizationNameChanged_0);
|
||||
|
|
|
|||
|
|
@ -1,26 +1,53 @@
|
|||
|
||||
include($$PWD/../../klayout.pri)
|
||||
|
||||
TEMPLATE = subdirs
|
||||
|
||||
SUBDIRS = \
|
||||
QtCore \
|
||||
QtGui \
|
||||
QtNetwork \
|
||||
QtSql \
|
||||
QtWidgets \
|
||||
QtDesigner \
|
||||
QtMultimedia \
|
||||
QtPrintSupport \
|
||||
QtSvg \
|
||||
QtXmlPatterns \
|
||||
QtXml
|
||||
QtWidgets
|
||||
|
||||
QtGui.depends += QtCore
|
||||
QtNetwork.depends += QtCore
|
||||
QtSql.depends += QtCore
|
||||
QtWidgets.depends += QtGui
|
||||
QtDesigner.depends += QtCore
|
||||
QtMultimedia.depends += QtCore QtWidgets QtNetwork
|
||||
QtPrintSupport.depends += QtCore QtWidgets
|
||||
QtSvg.depends += QtCore QtWidgets
|
||||
QtXmlPatterns.depends += QtCore
|
||||
QtXml.depends += QtCore
|
||||
|
||||
equals(HAVE_QT_NETWORK, "1") {
|
||||
SUBDIRS += QtNetwork
|
||||
QtNetwork.depends += QtCore
|
||||
}
|
||||
|
||||
equals(HAVE_QT_SQL, "1") {
|
||||
SUBDIRS += QtSql
|
||||
QtSql.depends += QtCore
|
||||
}
|
||||
|
||||
equals(HAVE_QT_SVG, "1") {
|
||||
SUBDIRS += QtSvg
|
||||
QtSvg.depends += QtCore QtWidgets
|
||||
}
|
||||
|
||||
equals(HAVE_QT_PRINTSUPPORT, "1") {
|
||||
SUBDIRS += QtPrintSupport
|
||||
QtPrintSupport.depends += QtCore QtWidgets
|
||||
}
|
||||
|
||||
equals(HAVE_QT_MULTIMEDIA, "1") {
|
||||
SUBDIRS += QtMultimedia
|
||||
QtMultimedia.depends += QtCore QtWidgets QtNetwork
|
||||
}
|
||||
|
||||
equals(HAVE_QT_DESIGNER, "1") {
|
||||
SUBDIRS += QtDesigner
|
||||
QtDesigner.depends += QtCore
|
||||
}
|
||||
|
||||
equals(HAVE_QT_XML, "1") {
|
||||
SUBDIRS += QtXml QtXmlPatterns
|
||||
QtXmlPatterns.depends += QtCore
|
||||
QtXml.depends += QtCore
|
||||
}
|
||||
|
||||
equals(HAVE_QT_UITOOLS, "1") {
|
||||
SUBDIRS += QtUiTools
|
||||
QtUiTools.depends += QtCore
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,9 @@
|
|||
|
||||
*/
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
#if !defined(HAVE_QT_DESIGNER)
|
||||
# define FORCE_LINK_GSI_QTDESIGNER
|
||||
#elif QT_VERSION >= 0x050000
|
||||
# include "../qt5/QtDesigner/gsiQtExternals.h"
|
||||
#else
|
||||
# include "../qt4/QtDesigner/gsiQtExternals.h"
|
||||
|
|
|
|||
|
|
@ -20,7 +20,9 @@
|
|||
|
||||
*/
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
#if !defined(HAVE_QT_MULTIMEDIA)
|
||||
# define FORCE_LINK_GSI_QTMULTIMEDIA
|
||||
#elif QT_VERSION >= 0x050000
|
||||
# include "../qt5/QtMultimedia/gsiQtExternals.h"
|
||||
#else
|
||||
// no present in Qt4
|
||||
|
|
|
|||
|
|
@ -20,7 +20,9 @@
|
|||
|
||||
*/
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
#if !defined(HAVE_QT_NETWORK)
|
||||
# define FORCE_LINK_GSI_QTNETWORK
|
||||
#elif QT_VERSION >= 0x050000
|
||||
# include "../qt5/QtNetwork/gsiQtExternals.h"
|
||||
#else
|
||||
# include "../qt4/QtNetwork/gsiQtExternals.h"
|
||||
|
|
|
|||
|
|
@ -20,7 +20,9 @@
|
|||
|
||||
*/
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
#if !defined(HAVE_QT_PRINTSUPPORT)
|
||||
# define FORCE_LINK_GSI_QTPRINTSUPPORT
|
||||
#elif QT_VERSION >= 0x050000
|
||||
# include "../qt5/QtPrintSupport/gsiQtExternals.h"
|
||||
#else
|
||||
// no present in Qt4
|
||||
|
|
|
|||
|
|
@ -20,7 +20,9 @@
|
|||
|
||||
*/
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
#if !defined(HAVE_QT_SQL)
|
||||
# define FORCE_LINK_GSI_QTSQL
|
||||
#elif QT_VERSION >= 0x050000
|
||||
# include "../qt5/QtSql/gsiQtExternals.h"
|
||||
#else
|
||||
# include "../qt4/QtSql/gsiQtExternals.h"
|
||||
|
|
|
|||
|
|
@ -20,7 +20,9 @@
|
|||
|
||||
*/
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
#if !defined(HAVE_QT_SVG)
|
||||
# define FORCE_LINK_GSI_QTSVG
|
||||
#elif QT_VERSION >= 0x050000
|
||||
# include "../qt5/QtSvg/gsiQtExternals.h"
|
||||
#else
|
||||
// no present in Qt4
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2021 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#if !defined(HAVE_QT_UITOOLS)
|
||||
# define FORCE_LINK_GSI_QTUITOOLS
|
||||
#elif QT_VERSION >= 0x050000
|
||||
# include "../qt5/QtUiTools/gsiQtExternals.h"
|
||||
#else
|
||||
# include "../qt4/QtUiTools/gsiQtExternals.h"
|
||||
#endif
|
||||
|
|
@ -20,7 +20,9 @@
|
|||
|
||||
*/
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
#if !defined(HAVE_QT_XML)
|
||||
# define FORCE_LINK_GSI_QTXML
|
||||
#elif QT_VERSION >= 0x050000
|
||||
# include "../qt5/QtXml/gsiQtExternals.h"
|
||||
#else
|
||||
# include "../qt4/QtXml/gsiQtExternals.h"
|
||||
|
|
|
|||
|
|
@ -20,7 +20,9 @@
|
|||
|
||||
*/
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
#if !defined(HAVE_QT_XML)
|
||||
# define FORCE_LINK_GSI_QTXMLPATTERNS
|
||||
#elif QT_VERSION >= 0x050000
|
||||
# include "../qt5/QtXmlPatterns/gsiQtExternals.h"
|
||||
#else
|
||||
// Not present in Qt4
|
||||
|
|
|
|||
|
|
@ -17,5 +17,19 @@ SOURCES += \
|
|||
gsiQtHelper.cc
|
||||
|
||||
HEADERS += \
|
||||
gsiDeclQtAllTypeTraits.h \
|
||||
gsiQt.h \
|
||||
gsiQtBasicCommon.h \
|
||||
gsiQtBasicCommon.h \ \
|
||||
gsiQtCoreExternals.h \
|
||||
gsiQtDesignerExternals.h \
|
||||
gsiQtGuiExternals.h \
|
||||
gsiQtHelper.h \
|
||||
gsiQtMultimediaExternals.h \
|
||||
gsiQtNetworkExternals.h \
|
||||
gsiQtPrintSupportExternals.h \
|
||||
gsiQtSqlExternals.h \
|
||||
gsiQtSvgExternals.h \
|
||||
gsiQtUiToolsExternals.h \
|
||||
gsiQtWidgetsExternals.h \
|
||||
gsiQtXmlExternals.h \
|
||||
gsiQtXmlPatternsExternals.h
|
||||
|
|
|
|||
|
|
@ -1343,7 +1343,7 @@ Object::from_string (const char *str, const char *base_dir)
|
|||
|
||||
tl::URI fp_uri (m_filename);
|
||||
if (base_dir && ! tl::is_absolute (fp_uri.path ())) {
|
||||
m_filename = tl::URI (base_dir).resolved (fp_uri).to_string ();
|
||||
m_filename = tl::URI (base_dir).resolved (fp_uri).to_abstract_path ();
|
||||
}
|
||||
|
||||
read_file ();
|
||||
|
|
|
|||
|
|
@ -219,7 +219,7 @@ PropertiesPage::get_xmin_xmax (double &xmin, double &xmax, bool &has_error_out)
|
|||
|
||||
try {
|
||||
tl::from_string (tl::to_string (from_le->text ()), xmin);
|
||||
lay::indicate_error (from_le, 0);
|
||||
lay::indicate_error (from_le, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (from_le, &ex);
|
||||
has_error = true;
|
||||
|
|
@ -227,7 +227,7 @@ PropertiesPage::get_xmin_xmax (double &xmin, double &xmax, bool &has_error_out)
|
|||
|
||||
try {
|
||||
tl::from_string (tl::to_string (to_le->text ()), xmax);
|
||||
lay::indicate_error (to_le, 0);
|
||||
lay::indicate_error (to_le, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (to_le, &ex);
|
||||
has_error = true;
|
||||
|
|
@ -336,7 +336,7 @@ PropertiesPage::value_changed ()
|
|||
double x = 0.0;
|
||||
try {
|
||||
tl::from_string (tl::to_string (value_le->text ()), x);
|
||||
lay::indicate_error (value_le, 0);
|
||||
lay::indicate_error (value_le, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (value_le, &ex);
|
||||
has_error = true;
|
||||
|
|
@ -805,7 +805,7 @@ PropertiesPage::apply ()
|
|||
if (w <= 0.0 || h <= 0.0) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Pixel width or height must be positive, non-null values")));
|
||||
}
|
||||
lay::indicate_error (width_le, 0);
|
||||
lay::indicate_error (width_le, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (width_le, &ex);
|
||||
has_error = true;
|
||||
|
|
@ -813,7 +813,7 @@ PropertiesPage::apply ()
|
|||
|
||||
try {
|
||||
tl::from_string (tl::to_string (height_le->text ()), h);
|
||||
lay::indicate_error (height_le, 0);
|
||||
lay::indicate_error (height_le, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (height_le, &ex);
|
||||
has_error = true;
|
||||
|
|
@ -821,7 +821,7 @@ PropertiesPage::apply ()
|
|||
|
||||
try {
|
||||
tl::from_string (tl::to_string (x_offset_le->text ()), x);
|
||||
lay::indicate_error (x_offset_le, 0);
|
||||
lay::indicate_error (x_offset_le, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (x_offset_le, &ex);
|
||||
has_error = true;
|
||||
|
|
@ -829,7 +829,7 @@ PropertiesPage::apply ()
|
|||
|
||||
try {
|
||||
tl::from_string (tl::to_string (y_offset_le->text ()), y);
|
||||
lay::indicate_error (y_offset_le, 0);
|
||||
lay::indicate_error (y_offset_le, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (y_offset_le, &ex);
|
||||
has_error = true;
|
||||
|
|
@ -837,7 +837,7 @@ PropertiesPage::apply ()
|
|||
|
||||
try {
|
||||
tl::from_string (tl::to_string (angle_le->text ()), a);
|
||||
lay::indicate_error (angle_le, 0);
|
||||
lay::indicate_error (angle_le, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (angle_le, &ex);
|
||||
has_error = true;
|
||||
|
|
@ -848,7 +848,7 @@ PropertiesPage::apply ()
|
|||
if (sa <= -45 || sa >= 45) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("The shear angle must be larger than -45 and less than 45 degree")));
|
||||
}
|
||||
lay::indicate_error (shear_le, 0);
|
||||
lay::indicate_error (shear_le, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (shear_le, &ex);
|
||||
has_error = true;
|
||||
|
|
@ -859,7 +859,7 @@ PropertiesPage::apply ()
|
|||
if (tx <= -90 || tx >= 90) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("The perspective tilt angles must be larger than -90 and less than 90 degree")));
|
||||
}
|
||||
lay::indicate_error (persp_tx_le, 0);
|
||||
lay::indicate_error (persp_tx_le, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (persp_tx_le, &ex);
|
||||
has_error = true;
|
||||
|
|
@ -870,7 +870,7 @@ PropertiesPage::apply ()
|
|||
if (ty <= -90 || ty >= 90) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("The perspective tilt angles must be larger than -90 and less than 90 degree")));
|
||||
}
|
||||
lay::indicate_error (persp_ty_le, 0);
|
||||
lay::indicate_error (persp_ty_le, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (persp_ty_le, &ex);
|
||||
has_error = true;
|
||||
|
|
|
|||
|
|
@ -40,6 +40,15 @@ equals(HAVE_QTBINDINGS, "1") {
|
|||
DEFINES += HAVE_QTBINDINGS
|
||||
}
|
||||
|
||||
!equals(HAVE_QT_UITOOLS, "0") {
|
||||
# auto-select uitools, not all distributions have it
|
||||
contains(QT_MODULES, "uitools") {
|
||||
HAVE_QT_UITOOLS = 1
|
||||
} else {
|
||||
HAVE_QT_UITOOLS = 0
|
||||
}
|
||||
}
|
||||
|
||||
equals(HAVE_64BIT_COORD, "1") {
|
||||
DEFINES += HAVE_64BIT_COORD
|
||||
}
|
||||
|
|
@ -160,18 +169,77 @@ equals(HAVE_QT, "0") {
|
|||
} else {
|
||||
|
||||
DEFINES += HAVE_QT
|
||||
QT += core network xml sql
|
||||
QT += core xml network
|
||||
|
||||
equals(HAVE_QT5, "1") {
|
||||
QT += designer printsupport widgets
|
||||
equals(HAVE_QTBINDINGS, "1") {
|
||||
QT += multimedia multimediawidgets xmlpatterns svg gui
|
||||
equals(HAVE_QTBINDINGS, "1") {
|
||||
# sql isn't needed by the base application
|
||||
!equals(HAVE_QT_SQL, "0") {
|
||||
QT += sql
|
||||
}
|
||||
} else {
|
||||
# questionable: use uitools instead?
|
||||
CONFIG += designer
|
||||
}
|
||||
|
||||
equals(HAVE_QT5, "1") {
|
||||
|
||||
QT += widgets gui printsupport xmlpatterns
|
||||
|
||||
equals(HAVE_QTBINDINGS, "1") {
|
||||
!equals(HAVE_QT_DESIGNER, "0") {
|
||||
# designer isn't needed by the base application
|
||||
QT += designer
|
||||
}
|
||||
!equals(HAVE_QT_MULTIMEDIA, "0") {
|
||||
# multimedia isn't needed by the base application
|
||||
QT += multimedia multimediawidgets
|
||||
}
|
||||
!equals(HAVE_QT_SVG, "0") {
|
||||
# svg isn't needed by the base application
|
||||
QT += svg
|
||||
}
|
||||
!equals(HAVE_QT_UITOOLS, "0") {
|
||||
# uitools isn't needed by the base application
|
||||
QT += uitools
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
equals(HAVE_QTBINDINGS, "1") {
|
||||
!equals(HAVE_QT_DESIGNER, "0") {
|
||||
# designer isn't needed by the base application
|
||||
CONFIG += designer
|
||||
}
|
||||
!equals(HAVE_QT_UITOOLS, "0") {
|
||||
# uitools isn't needed by the base application
|
||||
CONFIG += uitools
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
!equals(HAVE_QT_UITOOLS, "0") {
|
||||
DEFINES += HAVE_QT_UITOOLS
|
||||
}
|
||||
!equals(HAVE_QT_NETWORK, "0") {
|
||||
DEFINES += HAVE_QT_NETWORK
|
||||
}
|
||||
!equals(HAVE_QT_SQL, "0") {
|
||||
DEFINES += HAVE_QT_SQL
|
||||
}
|
||||
!equals(HAVE_QT_SVG, "0") {
|
||||
DEFINES += HAVE_QT_SVG
|
||||
}
|
||||
!equals(HAVE_QT_PRINTSUPPORT, "0") {
|
||||
DEFINES += HAVE_QT_PRINTSUPPORT
|
||||
}
|
||||
!equals(HAVE_QT_MULTIMEDIA, "0") {
|
||||
DEFINES += HAVE_QT_MULTIMEDIA
|
||||
}
|
||||
!equals(HAVE_QT_DESIGNER, "0") {
|
||||
DEFINES += HAVE_QT_DESIGNER
|
||||
}
|
||||
!equals(HAVE_QT_XML, "0") {
|
||||
DEFINES += HAVE_QT_XML
|
||||
}
|
||||
}
|
||||
|
||||
VERSION_STRING = $$KLAYOUT_VERSION
|
||||
|
|
|
|||
|
|
@ -51,18 +51,30 @@
|
|||
|
||||
// pulls in the Qt GSI binding modules
|
||||
# include "gsiQtGuiExternals.h"
|
||||
# include "gsiQtWidgetsExternals.h"
|
||||
# include "gsiQtCoreExternals.h"
|
||||
# include "gsiQtMultimediaExternals.h"
|
||||
# include "gsiQtPrintSupportExternals.h"
|
||||
# include "gsiQtXmlExternals.h"
|
||||
# include "gsiQtXmlPatternsExternals.h"
|
||||
# include "gsiQtSqlExternals.h"
|
||||
# include "gsiQtSvgExternals.h"
|
||||
# include "gsiQtNetworkExternals.h"
|
||||
# include "gsiQtDesignerExternals.h"
|
||||
# include "gsiQtUiToolsExternals.h"
|
||||
|
||||
FORCE_LINK_GSI_QTCORE
|
||||
FORCE_LINK_GSI_QTGUI
|
||||
FORCE_LINK_GSI_QTWIDGETS
|
||||
FORCE_LINK_GSI_QTMULTIMEDIA
|
||||
FORCE_LINK_GSI_QTPRINTSUPPORT
|
||||
FORCE_LINK_GSI_QTXML
|
||||
FORCE_LINK_GSI_QTXMLPATTERNS
|
||||
FORCE_LINK_GSI_QTDESIGNER
|
||||
FORCE_LINK_GSI_QTNETWORK
|
||||
FORCE_LINK_GSI_QTSQL
|
||||
FORCE_LINK_GSI_QTSVG
|
||||
FORCE_LINK_GSI_QTUITOOLS
|
||||
|
||||
#else
|
||||
# define QT_EXTERNAL_BASE(x)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ include($$PWD/../../klayout.pri)
|
|||
|
||||
TARGET = klayout
|
||||
|
||||
include($$PWD/../../klayout.pri)
|
||||
include($$PWD/../../app.pri)
|
||||
include($$PWD/../../with_all_libs.pri)
|
||||
|
||||
|
|
@ -25,8 +26,42 @@ INCLUDEPATH += $$QTBASIC_INC
|
|||
DEPENDPATH += $$QTBASIC_INC
|
||||
|
||||
equals(HAVE_QTBINDINGS, "1") {
|
||||
LIBS += -lklayout_qtbasic -lklayout_QtGui -lklayout_QtXml -lklayout_QtNetwork -lklayout_QtSql -lklayout_QtDesigner
|
||||
equals(HAVE_QT5, "1") {
|
||||
LIBS += -lklayout_QtMultimedia -lklayout_QtPrintSupport -lklayout_QtSvg -lklayout_QtWidgets -lklayout_QtXmlPatterns
|
||||
|
||||
LIBS += -lklayout_qtbasic -lklayout_QtGui
|
||||
|
||||
!equals(HAVE_QT_XML, "0") {
|
||||
LIBS += -lklayout_QtXml
|
||||
}
|
||||
!equals(HAVE_QT_NETWORK, "0") {
|
||||
LIBS += -lklayout_QtNetwork
|
||||
}
|
||||
!equals(HAVE_QT_SQL, "0") {
|
||||
LIBS += -lklayout_QtSql
|
||||
}
|
||||
!equals(HAVE_QT_DESIGNER, "0") {
|
||||
LIBS += -lklayout_QtDesigner
|
||||
}
|
||||
!equals(HAVE_QT_UITOOLS, "0") {
|
||||
LIBS += -lklayout_QtUiTools
|
||||
}
|
||||
|
||||
equals(HAVE_QT5, "1") {
|
||||
|
||||
LIBS += -lklayout_QtWidgets
|
||||
|
||||
!equals(HAVE_QT_MULTIMEDIA, "0") {
|
||||
LIBS += -lklayout_QtMultimedia
|
||||
}
|
||||
!equals(HAVE_QT_PRINTSUPPORT, "0") {
|
||||
LIBS += -lklayout_QtPrintSupport
|
||||
}
|
||||
!equals(HAVE_QT_SVG, "0") {
|
||||
LIBS += -lklayout_QtSvg
|
||||
}
|
||||
!equals(HAVE_QT_XML, "0") {
|
||||
LIBS += -lklayout_QtXmlPatterns
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1383,63 +1383,6 @@ p, li { white-space: pre-wrap; }
|
|||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame_5">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<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>
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton">
|
||||
<property name="text">
|
||||
<string>Close</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<action name="actionNewFolder">
|
||||
<property name="icon">
|
||||
|
|
@ -1596,22 +1539,5 @@ p, li { white-space: pre-wrap; }
|
|||
<resources>
|
||||
<include location="layResources.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>pushButton</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>MacroEditorDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>905</x>
|
||||
<y>694</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>929</x>
|
||||
<y>696</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
<li>QtSql: database support</li>
|
||||
<li>QtNetwork: various network protocols and supporting classes</li>
|
||||
<li>QtDesigner: dynamically load designer files (.ui)</li>
|
||||
<li>QtUiTools: dynamically load designer files (.ui)</li>
|
||||
<li>QtMultimedia (Qt5): multimedia support</li>
|
||||
<li>QtPrintSupport (Qt5): print support</li>
|
||||
<li>QtSvg (Qt5): SVG implementation</li>
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ Class<lay::HelpDialog> decl_HelpDialog (QT_EXTERNAL_BASE (QDialog) "lay", "HelpD
|
|||
LAYBASIC_PUBLIC Class<lay::BrowserSource> &laybasicdecl_BrowserSource ();
|
||||
|
||||
Class<lay::HelpSource> decl_HelpSource (laybasicdecl_BrowserSource (), "lay", "HelpSource",
|
||||
#if defined(HAVE_QTBINDINGS)
|
||||
#if defined(HAVE_QTBINDINGS) && defined(HAVE_QT_XML)
|
||||
gsi::method ("get_dom", &lay::HelpSource::get_dom, "@brief For internal use") +
|
||||
#endif
|
||||
gsi::method ("urls", &lay::HelpSource::urls, "@brief Reserved for internal use") +
|
||||
|
|
|
|||
|
|
@ -203,7 +203,10 @@ INCLUDEPATH += $$QTBASIC_INC
|
|||
DEPENDPATH += $$QTBASIC_INC
|
||||
|
||||
equals(HAVE_QTBINDINGS, "1") {
|
||||
LIBS += -lklayout_qtbasic -lklayout_QtGui -lklayout_QtXml -lklayout_QtCore
|
||||
LIBS += -lklayout_qtbasic -lklayout_QtGui -lklayout_QtCore
|
||||
!equals(HAVE_QT_XML, "0") {
|
||||
LIBS += -lklayout_QtXml
|
||||
}
|
||||
equals(HAVE_QT5, "1") {
|
||||
LIBS += -lklayout_QtWidgets
|
||||
}
|
||||
|
|
|
|||
|
|
@ -200,11 +200,33 @@ LogFile::timeout ()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
LogFile::set_max_entries (size_t n)
|
||||
{
|
||||
QMutexLocker locker (&m_lock);
|
||||
|
||||
m_max_entries = n;
|
||||
|
||||
while (m_messages.size () > m_max_entries) {
|
||||
m_messages.pop_front ();
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
LogFile::max_entries () const
|
||||
{
|
||||
return m_max_entries;
|
||||
}
|
||||
|
||||
void
|
||||
LogFile::add (LogFileEntry::mode_type mode, const std::string &msg, bool continued)
|
||||
{
|
||||
QMutexLocker locker (&m_lock);
|
||||
|
||||
if (m_max_entries == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_messages.size () >= m_max_entries) {
|
||||
m_messages.pop_front ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -192,6 +192,18 @@ public slots:
|
|||
return m_log_receiver;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the maximum number of entries to show
|
||||
*
|
||||
* Setting this value to 0 basically disables the log collection
|
||||
*/
|
||||
void set_max_entries (size_t n);
|
||||
|
||||
/**
|
||||
* @brief Gets the maximum number of entries to show
|
||||
*/
|
||||
size_t max_entries () const;
|
||||
|
||||
private slots:
|
||||
void timeout ();
|
||||
|
||||
|
|
|
|||
|
|
@ -244,6 +244,7 @@ MacroEditorDialog::MacroEditorDialog (lay::Dispatcher *pr, lym::MacroCollection
|
|||
m_highlighters (this),
|
||||
m_in_exec (false),
|
||||
m_in_breakpoint (false),
|
||||
m_ignore_exec_events (false),
|
||||
mp_exec_controller (0),
|
||||
mp_current_interpreter (0),
|
||||
m_continue (false),
|
||||
|
|
@ -355,8 +356,8 @@ MacroEditorDialog::MacroEditorDialog (lay::Dispatcher *pr, lym::MacroCollection
|
|||
QMenu *m = new QMenu (searchEditBox);
|
||||
m->addAction (actionUseRegularExpressions);
|
||||
m->addAction (actionCaseSensitive);
|
||||
connect (actionUseRegularExpressions, SIGNAL (triggered ()), this, SLOT (apply_search ()));
|
||||
connect (actionCaseSensitive, SIGNAL (triggered ()), this, SLOT (apply_search ()));
|
||||
connect (actionUseRegularExpressions, SIGNAL (triggered ()), this, SLOT (search_editing ()));
|
||||
connect (actionCaseSensitive, SIGNAL (triggered ()), this, SLOT (search_editing ()));
|
||||
|
||||
addAction (actionSearchReplace);
|
||||
connect (actionSearchReplace, SIGNAL (triggered ()), this, SLOT (search_replace ()));
|
||||
|
|
@ -364,7 +365,11 @@ MacroEditorDialog::MacroEditorDialog (lay::Dispatcher *pr, lym::MacroCollection
|
|||
searchEditBox->set_clear_button_enabled (true);
|
||||
searchEditBox->set_options_button_enabled (true);
|
||||
searchEditBox->set_options_menu (m);
|
||||
searchEditBox->set_escape_signal_enabled (true);
|
||||
searchEditBox->set_tab_signal_enabled (true);
|
||||
replaceText->set_clear_button_enabled (true);
|
||||
replaceText->set_escape_signal_enabled (true);
|
||||
replaceText->set_tab_signal_enabled (true);
|
||||
#if QT_VERSION >= 0x40700
|
||||
searchEditBox->setPlaceholderText (tr ("Find text ..."));
|
||||
replaceText->setPlaceholderText (tr ("Replace text ..."));
|
||||
|
|
@ -382,8 +387,6 @@ MacroEditorDialog::MacroEditorDialog (lay::Dispatcher *pr, lym::MacroCollection
|
|||
tabWidget->setMovable (true);
|
||||
tabWidget->setTabsClosable (true);
|
||||
connect (tabWidget, SIGNAL (tabCloseRequested (int)), this, SLOT (tab_close_requested (int)));
|
||||
closeButton->hide ();
|
||||
closeButtonSeparator->hide ();
|
||||
#endif
|
||||
|
||||
dbgOn->setEnabled (true);
|
||||
|
|
@ -411,7 +414,6 @@ MacroEditorDialog::MacroEditorDialog (lay::Dispatcher *pr, lym::MacroCollection
|
|||
connect (helpButton, SIGNAL (clicked ()), this, SLOT (help_button_clicked ()));
|
||||
connect (addButton, SIGNAL (clicked ()), this, SLOT (add_button_clicked ()));
|
||||
connect (actionAddMacro, SIGNAL (triggered ()), this, SLOT (add_button_clicked ()));
|
||||
connect (closeButton, SIGNAL (clicked ()), this, SLOT (close_button_clicked ()));
|
||||
connect (deleteButton, SIGNAL (clicked ()), this, SLOT (delete_button_clicked ()));
|
||||
connect (actionDelete, SIGNAL (triggered ()), this, SLOT (delete_button_clicked ()));
|
||||
connect (renameButton, SIGNAL (clicked ()), this, SLOT (rename_button_clicked ()));
|
||||
|
|
@ -438,9 +440,16 @@ MacroEditorDialog::MacroEditorDialog (lay::Dispatcher *pr, lym::MacroCollection
|
|||
connect (callStack, SIGNAL (itemDoubleClicked (QListWidgetItem *)), this, SLOT (stack_element_double_clicked (QListWidgetItem *)));
|
||||
connect (singleStepButton, SIGNAL (clicked ()), this, SLOT (single_step_button_clicked ()));
|
||||
connect (nextStepButton, SIGNAL (clicked ()), this, SLOT (next_step_button_clicked ()));
|
||||
connect (searchEditBox, SIGNAL (textEdited (const QString &)), this, SLOT (search_editing ()));
|
||||
connect (searchEditBox, SIGNAL (returnPressed ()), this, SLOT (search_edited ()));
|
||||
connect (searchEditBox, SIGNAL (editingFinished ()), this, SLOT (search_edited ()));
|
||||
connect (searchEditBox, SIGNAL (textEdited (QString)), this, SLOT (apply_search ()));
|
||||
connect (searchEditBox, SIGNAL (esc_pressed ()), this, SLOT (search_finished ()));
|
||||
connect (searchEditBox, SIGNAL (tab_pressed ()), this, SLOT (find_next_button_clicked ()));
|
||||
connect (searchEditBox, SIGNAL (backtab_pressed ()), this, SLOT (find_prev_button_clicked ()));
|
||||
connect (replaceText, SIGNAL (esc_pressed ()), this, SLOT (search_finished ()));
|
||||
connect (replaceText, SIGNAL (tab_pressed ()), this, SLOT (find_next_button_clicked ()));
|
||||
connect (replaceText, SIGNAL (backtab_pressed ()), this, SLOT (find_prev_button_clicked ()));
|
||||
connect (replaceText, SIGNAL (returnPressed ()), this, SLOT (replace_next_button_clicked ()));
|
||||
connect (replaceModeButton, SIGNAL (clicked ()), this, SLOT (replace_mode_button_clicked ()));
|
||||
connect (replaceNextButton, SIGNAL (clicked ()), this, SLOT (replace_next_button_clicked ()));
|
||||
connect (findNextButton, SIGNAL (clicked ()), this, SLOT (find_next_button_clicked ()));
|
||||
|
|
@ -946,15 +955,13 @@ MacroEditorDialog::showEvent (QShowEvent *)
|
|||
void
|
||||
MacroEditorDialog::reject ()
|
||||
{
|
||||
closeEvent (0);
|
||||
QDialog::reject ();
|
||||
// .. ignore Esc ..
|
||||
}
|
||||
|
||||
void
|
||||
MacroEditorDialog::accept ()
|
||||
{
|
||||
closeEvent (0);
|
||||
QDialog::accept ();
|
||||
// .. ignore Enter ..
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1105,12 +1112,6 @@ MacroEditorDialog::can_exit ()
|
|||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
MacroEditorDialog::search_replace ()
|
||||
{
|
||||
searchEditBox->setFocus (Qt::TabFocusReason);
|
||||
}
|
||||
|
||||
void
|
||||
MacroEditorDialog::add_edit_trace (bool compress)
|
||||
{
|
||||
|
|
@ -1882,6 +1883,18 @@ BEGIN_PROTECTED
|
|||
END_PROTECTED
|
||||
}
|
||||
|
||||
void
|
||||
MacroEditorDialog::set_editor_focus ()
|
||||
{
|
||||
MacroEditorPage *page = dynamic_cast<MacroEditorPage *> (tabWidget->currentWidget ());
|
||||
if (! page) {
|
||||
return;
|
||||
}
|
||||
|
||||
lay::SignalBlocker signal_blocker (searchEditBox);
|
||||
page->set_editor_focus ();
|
||||
}
|
||||
|
||||
void
|
||||
MacroEditorDialog::replace_mode_button_clicked ()
|
||||
{
|
||||
|
|
@ -1905,10 +1918,27 @@ MacroEditorDialog::find_next_button_clicked ()
|
|||
|
||||
apply_search (true);
|
||||
page->find_next ();
|
||||
page->set_editor_focus ();
|
||||
if (sender () != searchEditBox && sender () != replaceText) {
|
||||
set_editor_focus ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
MacroEditorDialog::find_prev_button_clicked ()
|
||||
{
|
||||
MacroEditorPage *page = dynamic_cast<MacroEditorPage *> (tabWidget->currentWidget ());
|
||||
if (! page) {
|
||||
return;
|
||||
}
|
||||
|
||||
apply_search (true);
|
||||
page->find_prev ();
|
||||
if (sender () != searchEditBox && sender () != replaceText) {
|
||||
set_editor_focus ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MacroEditorDialog::replace_next_button_clicked ()
|
||||
{
|
||||
MacroEditorPage *page = dynamic_cast<MacroEditorPage *> (tabWidget->currentWidget ());
|
||||
|
|
@ -1918,10 +1948,12 @@ MacroEditorDialog::replace_next_button_clicked ()
|
|||
|
||||
apply_search (true);
|
||||
page->replace_and_find_next (replaceText->text ());
|
||||
page->set_editor_focus ();
|
||||
if (sender () != replaceText) {
|
||||
set_editor_focus ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
MacroEditorDialog::replace_all_button_clicked ()
|
||||
{
|
||||
MacroEditorPage *page = dynamic_cast<MacroEditorPage *> (tabWidget->currentWidget ());
|
||||
|
|
@ -1931,7 +1963,34 @@ MacroEditorDialog::replace_all_button_clicked ()
|
|||
|
||||
apply_search (true);
|
||||
page->replace_all (replaceText->text ());
|
||||
page->set_editor_focus ();
|
||||
set_editor_focus ();
|
||||
}
|
||||
|
||||
void
|
||||
MacroEditorDialog::search_requested (const QString &s)
|
||||
{
|
||||
searchEditBox->setText (s);
|
||||
searchEditBox->setFocus ();
|
||||
search_editing ();
|
||||
}
|
||||
|
||||
void
|
||||
MacroEditorDialog::search_replace ()
|
||||
{
|
||||
searchEditBox->setFocus (Qt::TabFocusReason);
|
||||
}
|
||||
|
||||
void
|
||||
MacroEditorDialog::search_editing ()
|
||||
{
|
||||
MacroEditorPage *page = dynamic_cast<MacroEditorPage *> (tabWidget->currentWidget ());
|
||||
if (! page) {
|
||||
return;
|
||||
}
|
||||
|
||||
apply_search ();
|
||||
page->find_reset (); // search from the initial position
|
||||
page->find_next ();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1942,6 +2001,18 @@ MacroEditorDialog::search_edited ()
|
|||
md_search_edited ();
|
||||
}
|
||||
|
||||
void
|
||||
MacroEditorDialog::search_finished ()
|
||||
{
|
||||
MacroEditorPage *page = dynamic_cast<MacroEditorPage *> (tabWidget->currentWidget ());
|
||||
if (! page) {
|
||||
return;
|
||||
}
|
||||
|
||||
page->find_reset (); // search from the initial position
|
||||
set_editor_focus ();
|
||||
}
|
||||
|
||||
void
|
||||
MacroEditorDialog::do_search_edited ()
|
||||
{
|
||||
|
|
@ -1951,8 +2022,9 @@ MacroEditorDialog::do_search_edited ()
|
|||
}
|
||||
|
||||
apply_search ();
|
||||
page->find_reset (); // search from the initial position
|
||||
page->find_next ();
|
||||
page->set_editor_focus ();
|
||||
set_editor_focus ();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1963,7 +2035,7 @@ MacroEditorDialog::apply_search (bool if_needed)
|
|||
return;
|
||||
}
|
||||
|
||||
if (searchEditBox->text ().size () > 0) {
|
||||
if (! searchEditBox->text ().isEmpty ()) {
|
||||
QRegExp re (searchEditBox->text (),
|
||||
actionCaseSensitive->isChecked () ? Qt::CaseSensitive : Qt::CaseInsensitive,
|
||||
actionUseRegularExpressions->isChecked () ? QRegExp::RegExp : QRegExp::FixedString);
|
||||
|
|
@ -2080,7 +2152,7 @@ BEGIN_PROTECTED
|
|||
END_PROTECTED
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
MacroEditorDialog::help_requested(const QString &s)
|
||||
{
|
||||
lay::MainWindow::instance ()->show_assistant_topic (tl::to_string (s));
|
||||
|
|
@ -2779,54 +2851,77 @@ MacroEditorDialog::start_exec (gsi::Interpreter *ec)
|
|||
if (m_in_exec) {
|
||||
tl_assert (ec != mp_exec_controller);
|
||||
return;
|
||||
} else if (m_ignore_exec_events) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_file_to_widget.clear ();
|
||||
m_include_expanders.clear ();
|
||||
m_include_paths_to_ids.clear ();
|
||||
m_include_file_id_cache.clear ();
|
||||
// prevents recursion
|
||||
m_ignore_exec_events = true;
|
||||
|
||||
m_last_process_events = tl::Clock::current ();
|
||||
try {
|
||||
|
||||
m_in_exec = true;
|
||||
mp_exec_controller = ec;
|
||||
m_in_breakpoint = false;
|
||||
m_continue = true;
|
||||
m_trace_count = 0;
|
||||
m_current_stack_depth = -1;
|
||||
m_process_events_interval = 0.05;
|
||||
m_file_to_widget.clear ();
|
||||
m_include_expanders.clear ();
|
||||
m_include_paths_to_ids.clear ();
|
||||
m_include_file_id_cache.clear ();
|
||||
|
||||
for (std::map<lym::Macro *, MacroEditorPage *>::const_iterator f = m_tab_widgets.begin (); f != m_tab_widgets.end (); ++f) {
|
||||
f->second->exec_model ()->set_current_line (-1);
|
||||
f->second->exec_model ()->set_run_mode (true);
|
||||
m_last_process_events = tl::Clock::current ();
|
||||
|
||||
m_in_exec = true;
|
||||
mp_exec_controller = ec;
|
||||
m_in_breakpoint = false;
|
||||
m_continue = true;
|
||||
m_trace_count = 0;
|
||||
m_current_stack_depth = -1;
|
||||
m_process_events_interval = 0.05;
|
||||
|
||||
for (std::map<lym::Macro *, MacroEditorPage *>::const_iterator f = m_tab_widgets.begin (); f != m_tab_widgets.end (); ++f) {
|
||||
f->second->exec_model ()->set_current_line (-1);
|
||||
f->second->exec_model ()->set_run_mode (true);
|
||||
}
|
||||
|
||||
do_update_ui_to_run_mode ();
|
||||
|
||||
} catch (...) {
|
||||
// .. ignore exceptions here ..
|
||||
}
|
||||
|
||||
do_update_ui_to_run_mode ();
|
||||
m_ignore_exec_events = false;
|
||||
}
|
||||
|
||||
void
|
||||
MacroEditorDialog::end_exec (gsi::Interpreter *ec)
|
||||
{
|
||||
// ignore calls from other interpreters
|
||||
if (m_in_exec && ec != mp_exec_controller) {
|
||||
if ((m_in_exec && ec != mp_exec_controller) || m_ignore_exec_events) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (QApplication::activeModalWidget () == this) {
|
||||
// close this window if it was shown in modal mode
|
||||
QDialog::accept ();
|
||||
// prevents recursion
|
||||
m_ignore_exec_events = true;
|
||||
|
||||
try {
|
||||
|
||||
m_in_exec = false;
|
||||
mp_exec_controller = 0;
|
||||
m_continue = false;
|
||||
m_current_stack_depth = -1;
|
||||
|
||||
if (QApplication::activeModalWidget () == this) {
|
||||
// close this window if it was shown in modal mode
|
||||
QDialog::accept ();
|
||||
}
|
||||
|
||||
for (std::map<lym::Macro *, MacroEditorPage *>::const_iterator f = m_tab_widgets.begin (); f != m_tab_widgets.end (); ++f) {
|
||||
f->second->exec_model ()->set_run_mode (false);
|
||||
}
|
||||
|
||||
do_update_ui_to_run_mode ();
|
||||
|
||||
} catch (...) {
|
||||
// .. ignore exceptions here ..
|
||||
}
|
||||
|
||||
m_in_exec = false;
|
||||
mp_exec_controller = 0;
|
||||
m_continue = false;
|
||||
m_current_stack_depth = -1;
|
||||
|
||||
for (std::map<lym::Macro *, MacroEditorPage *>::const_iterator f = m_tab_widgets.begin (); f != m_tab_widgets.end (); ++f) {
|
||||
f->second->exec_model ()->set_run_mode (false);
|
||||
}
|
||||
|
||||
do_update_ui_to_run_mode ();
|
||||
m_ignore_exec_events = false;
|
||||
}
|
||||
|
||||
const size_t pseudo_file_offset = std::numeric_limits<size_t>::max () / 2;
|
||||
|
|
@ -3172,7 +3267,6 @@ MacroEditorDialog::do_update_ui_to_run_mode ()
|
|||
|
||||
addButton->setEnabled (! m_in_exec);
|
||||
actionAddMacro->setEnabled (! m_in_exec);
|
||||
closeButton->setEnabled (! m_in_exec);
|
||||
deleteButton->setEnabled (! m_in_exec);
|
||||
actionDelete->setEnabled (! m_in_exec);
|
||||
renameButton->setEnabled (! m_in_exec);
|
||||
|
|
@ -3270,6 +3364,7 @@ MacroEditorDialog::create_page (lym::Macro *macro)
|
|||
editor->exec_model ()->set_run_mode (m_in_exec);
|
||||
editor->connect_macro (macro);
|
||||
connect (editor.get (), SIGNAL (help_requested (const QString &)), this, SLOT (help_requested (const QString &)));
|
||||
connect (editor.get (), SIGNAL (search_requested (const QString &)), this, SLOT (search_requested (const QString &)));
|
||||
connect (editor.get (), SIGNAL (edit_trace (bool)), this, SLOT (add_edit_trace (bool)));
|
||||
return editor.release ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -209,12 +209,16 @@ private slots:
|
|||
void commit ();
|
||||
void stack_element_double_clicked (QListWidgetItem *item);
|
||||
void search_edited ();
|
||||
void search_editing ();
|
||||
void search_finished ();
|
||||
void tab_close_requested (int);
|
||||
void replace_mode_button_clicked ();
|
||||
void replace_next_button_clicked ();
|
||||
void replace_all_button_clicked ();
|
||||
void find_next_button_clicked ();
|
||||
void find_prev_button_clicked ();
|
||||
void help_requested (const QString &s);
|
||||
void search_requested (const QString &s);
|
||||
void macro_changed (lym::Macro *macro);
|
||||
void macro_deleted (lym::Macro *macro);
|
||||
void macro_collection_deleted (lym::MacroCollection *collection);
|
||||
|
|
@ -288,6 +292,7 @@ private:
|
|||
void update_watches ();
|
||||
lym::Macro *new_macro ();
|
||||
void do_search_edited ();
|
||||
void set_editor_focus ();
|
||||
void select_trace (size_t index);
|
||||
bool configure (const std::string &name, const std::string &value);
|
||||
void config_finalize ();
|
||||
|
|
@ -318,7 +323,7 @@ private:
|
|||
std::map<std::string, size_t> m_include_paths_to_ids;
|
||||
std::map<std::pair<size_t, int>, std::pair<size_t, int> > m_include_file_id_cache;
|
||||
std::vector<lay::MacroEditorTree *> m_macro_trees;
|
||||
bool m_in_exec, m_in_breakpoint;
|
||||
bool m_in_exec, m_in_breakpoint, m_ignore_exec_events;
|
||||
gsi::Interpreter *mp_exec_controller, *mp_current_interpreter;
|
||||
bool m_continue;
|
||||
int m_trace_count;
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include "lymMacroInterpreter.h"
|
||||
#include "tlExceptions.h"
|
||||
#include "tlString.h"
|
||||
#include "layQtTools.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
|
|
@ -42,6 +43,9 @@
|
|||
#include <QChar>
|
||||
#include <QResource>
|
||||
#include <QBuffer>
|
||||
#include <QTimer>
|
||||
#include <QListWidget>
|
||||
#include <QApplication>
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
|
@ -475,7 +479,7 @@ void MacroEditorSidePanel::paintEvent (QPaintEvent *)
|
|||
// MacroEditorPage implementation
|
||||
|
||||
MacroEditorPage::MacroEditorPage (QWidget * /*parent*/, MacroEditorHighlighters *highlighters)
|
||||
: mp_macro (0), mp_highlighters (highlighters), mp_highlighter (0), m_error_line (-1), m_ntab (8), m_nindent (2)
|
||||
: mp_macro (0), mp_highlighters (highlighters), mp_highlighter (0), m_error_line (-1), m_ntab (8), m_nindent (2), m_ignore_cursor_changed_event (false)
|
||||
{
|
||||
QVBoxLayout *layout = new QVBoxLayout (this);
|
||||
|
||||
|
|
@ -499,11 +503,26 @@ MacroEditorPage::MacroEditorPage (QWidget * /*parent*/, MacroEditorHighlighters
|
|||
|
||||
connect (mp_text, SIGNAL (textChanged ()), this, SLOT (text_changed ()));
|
||||
connect (mp_text, SIGNAL (cursorPositionChanged ()), this, SLOT (cursor_position_changed ()));
|
||||
connect (mp_text->horizontalScrollBar (), SIGNAL (valueChanged (int)), this, SLOT (hide_completer ()));
|
||||
connect (mp_text->verticalScrollBar (), SIGNAL (valueChanged (int)), this, SLOT (hide_completer ()));
|
||||
connect (mp_exec_model, SIGNAL (breakpoints_changed ()), this, SLOT (breakpoints_changed ()));
|
||||
connect (mp_exec_model, SIGNAL (current_line_changed ()), this, SLOT (current_line_changed ()));
|
||||
connect (mp_exec_model, SIGNAL (run_mode_changed ()), this, SLOT (run_mode_changed ()));
|
||||
|
||||
mp_text->installEventFilter (this);
|
||||
|
||||
mp_completer_popup = new QWidget (window (), Qt::ToolTip);
|
||||
mp_completer_popup->setWindowModality (Qt::NonModal);
|
||||
QHBoxLayout *ly = new QHBoxLayout (mp_completer_popup);
|
||||
ly->setMargin (0);
|
||||
mp_completer_list = new QListWidget (mp_completer_popup);
|
||||
ly->addWidget (mp_completer_list);
|
||||
mp_completer_popup->hide ();
|
||||
|
||||
mp_completer_timer = new QTimer (this);
|
||||
mp_completer_timer->setInterval (1000);
|
||||
mp_completer_timer->setSingleShot (true);
|
||||
connect (mp_completer_timer, SIGNAL (timeout ()), this, SLOT (completer_timer ()));
|
||||
}
|
||||
|
||||
void MacroEditorPage::update ()
|
||||
|
|
@ -566,12 +585,23 @@ void MacroEditorPage::current_line_changed ()
|
|||
|
||||
void MacroEditorPage::run_mode_changed ()
|
||||
{
|
||||
if (mp_exec_model->run_mode ()) {
|
||||
set_error_line (0);
|
||||
// this prevents recursion when the following lines trigger anything that routes through the interpreter
|
||||
bool bl = mp_exec_model->blockSignals (true);
|
||||
|
||||
try {
|
||||
|
||||
if (mp_exec_model->run_mode ()) {
|
||||
set_error_line (0);
|
||||
}
|
||||
|
||||
mp_text->setReadOnly (! mp_macro || mp_macro->is_readonly () || mp_exec_model->run_mode ());
|
||||
update_extra_selections ();
|
||||
|
||||
} catch (...) {
|
||||
// .. ignore exceptions here ..
|
||||
}
|
||||
|
||||
mp_text->setReadOnly (! mp_macro || mp_macro->is_readonly () || mp_exec_model->run_mode ());
|
||||
update_extra_selections ();
|
||||
mp_exec_model->blockSignals (bl);
|
||||
}
|
||||
|
||||
void MacroEditorPage::breakpoints_changed ()
|
||||
|
|
@ -598,9 +628,110 @@ static bool valid_element (const SyntaxHighlighterElement &e)
|
|||
return e.basic_attribute_id != lay::dsComment && e.basic_attribute_id != lay::dsString;
|
||||
}
|
||||
|
||||
void MacroEditorPage::complete ()
|
||||
{
|
||||
QTextCursor c = mp_text->textCursor ();
|
||||
if (c.selectionStart () != c.selectionEnd ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
c.select (QTextCursor::WordUnderCursor);
|
||||
if (mp_completer_list->currentItem ()) {
|
||||
QString s = mp_completer_list->currentItem ()->text ();
|
||||
c.insertText (s);
|
||||
}
|
||||
}
|
||||
|
||||
void MacroEditorPage::fill_completer_list ()
|
||||
{
|
||||
QTextCursor c = mp_text->textCursor ();
|
||||
if (c.selectionStart () != c.selectionEnd ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int pos = c.anchor ();
|
||||
c.select (QTextCursor::WordUnderCursor);
|
||||
int pos0 = c.selectionStart ();
|
||||
if (pos0 >= pos) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString ssel = c.selectedText ();
|
||||
QString s = ssel.mid (0, pos - pos0);
|
||||
|
||||
QString text = mp_text->toPlainText ();
|
||||
|
||||
std::set<QString> words;
|
||||
|
||||
int i = 0;
|
||||
while (i >= 0) {
|
||||
i = text.indexOf (s, i);
|
||||
if (i >= 0) {
|
||||
QString::iterator c = text.begin () + i;
|
||||
QString w;
|
||||
while (c->isLetterOrNumber () || c->toLatin1 () == '_') {
|
||||
w += *c;
|
||||
++c;
|
||||
}
|
||||
if (! w.isEmpty () && w != s && w != ssel) {
|
||||
words.insert (w);
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
for (std::set<QString>::const_iterator w = words.begin (); w != words.end (); ++w) {
|
||||
mp_completer_list->addItem (*w);
|
||||
}
|
||||
}
|
||||
|
||||
void MacroEditorPage::completer_timer ()
|
||||
{
|
||||
if (! mp_text->hasFocus ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mp_completer_list->clear ();
|
||||
fill_completer_list ();
|
||||
|
||||
if (mp_completer_list->count () > 0) {
|
||||
|
||||
mp_completer_list->setCurrentRow (0);
|
||||
|
||||
QTextCursor c = mp_text->textCursor ();
|
||||
c.clearSelection ();
|
||||
QRect r = mp_text->cursorRect (c);
|
||||
QPoint pos = mp_text->mapToGlobal (r.bottomLeft ());
|
||||
|
||||
QSize sz = mp_completer_list->sizeHint ();
|
||||
QFontMetrics fm (mp_completer_list->font ());
|
||||
mp_completer_popup->setGeometry (pos.x (), pos.y () + r.height () / 3, sz.width (), 4 + 4 * fm.height () /*sz.height ()*/);
|
||||
mp_completer_popup->show ();
|
||||
|
||||
mp_text->setFocus ();
|
||||
|
||||
} else {
|
||||
mp_completer_popup->hide ();
|
||||
}
|
||||
}
|
||||
|
||||
void MacroEditorPage::hide_completer ()
|
||||
{
|
||||
mp_completer_popup->hide ();
|
||||
}
|
||||
|
||||
void MacroEditorPage::cursor_position_changed ()
|
||||
{
|
||||
if (m_ignore_cursor_changed_event) {
|
||||
return;
|
||||
}
|
||||
|
||||
mp_completer_popup->hide ();
|
||||
mp_completer_timer->stop ();
|
||||
mp_completer_timer->start ();
|
||||
|
||||
QTextCursor cursor = mp_text->textCursor ();
|
||||
m_edit_cursor = cursor;
|
||||
|
||||
// prepare a format for the bracket highlights
|
||||
QTextCharFormat fmt;
|
||||
|
|
@ -861,11 +992,23 @@ void MacroEditorPage::connect_macro (lym::Macro *macro)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
MacroEditorPage::find_reset ()
|
||||
{
|
||||
m_ignore_cursor_changed_event = true;
|
||||
mp_text->setTextCursor (m_edit_cursor);
|
||||
m_ignore_cursor_changed_event = false;
|
||||
}
|
||||
|
||||
bool
|
||||
MacroEditorPage::find_prev ()
|
||||
{
|
||||
update_extra_selections ();
|
||||
|
||||
if (m_current_search == QRegExp ()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QTextCursor c = mp_text->textCursor ();
|
||||
|
||||
bool first = true;
|
||||
|
|
@ -891,7 +1034,9 @@ MacroEditorPage::find_prev ()
|
|||
QTextCursor newc (b);
|
||||
newc.setPosition (i + b.position () + l);
|
||||
newc.setPosition (i + b.position (), QTextCursor::KeepAnchor);
|
||||
m_ignore_cursor_changed_event = true;
|
||||
mp_text->setTextCursor (newc);
|
||||
m_ignore_cursor_changed_event = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -913,6 +1058,10 @@ MacroEditorPage::find_next ()
|
|||
{
|
||||
update_extra_selections ();
|
||||
|
||||
if (m_current_search == QRegExp ()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QTextCursor c = mp_text->textCursor ();
|
||||
|
||||
bool first = true;
|
||||
|
|
@ -926,7 +1075,9 @@ MacroEditorPage::find_next ()
|
|||
QTextCursor newc (b);
|
||||
newc.setPosition (i + b.position () + m_current_search.matchedLength ());
|
||||
newc.setPosition (i + b.position (), QTextCursor::KeepAnchor);
|
||||
m_ignore_cursor_changed_event = true;
|
||||
mp_text->setTextCursor (newc);
|
||||
m_ignore_cursor_changed_event = false;
|
||||
emit edit_trace (false);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1152,263 +1303,391 @@ MacroEditorPage::current_pos () const
|
|||
return mp_text->textCursor ().position () - mp_text->textCursor ().block ().position ();
|
||||
}
|
||||
|
||||
bool
|
||||
MacroEditorPage::tab_key_pressed ()
|
||||
{
|
||||
if (mp_text->isReadOnly ()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QTextBlock bs, be;
|
||||
bool adjust_end = false;
|
||||
|
||||
bool indent = false;
|
||||
if (mp_text->textCursor ().hasSelection ()) {
|
||||
bs = mp_text->document ()->findBlock (mp_text->textCursor ().selectionStart ());
|
||||
be = mp_text->document ()->findBlock (mp_text->textCursor ().selectionEnd ());
|
||||
if (be != bs) {
|
||||
indent = true;
|
||||
QTextCursor se (mp_text->document ());
|
||||
se.setPosition (mp_text->textCursor ().selectionEnd ());
|
||||
if (se.atBlockStart ()) {
|
||||
be = be.previous ();
|
||||
adjust_end = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (indent) {
|
||||
|
||||
// tab out
|
||||
QTextCursor c (mp_text->document ());
|
||||
c.setPosition (bs.position ());
|
||||
c.beginEditBlock ();
|
||||
|
||||
for (QTextBlock b = bs; ; b = b.next()) {
|
||||
|
||||
c.setPosition (b.position ());
|
||||
QString text = b.text ();
|
||||
|
||||
bool has_tabs = false;
|
||||
int p = 0;
|
||||
int i = 0;
|
||||
for (; i < text.length (); ++i) {
|
||||
if (text [i] == QChar::fromLatin1 (' ')) {
|
||||
++p;
|
||||
} else if (text [i] == QChar::fromLatin1 ('\t')) {
|
||||
p = (p - p % m_ntab) + m_ntab;
|
||||
has_tabs = true;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (has_tabs) {
|
||||
for ( ; i > 0; --i) {
|
||||
c.deleteChar ();
|
||||
}
|
||||
c.insertText (QString (m_nindent + p, QChar::fromLatin1 (' ')));
|
||||
} else {
|
||||
c.insertText (QString (m_nindent, QChar::fromLatin1 (' ')));
|
||||
}
|
||||
|
||||
if (b == be) {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
c.endEditBlock ();
|
||||
|
||||
c.setPosition (bs.position ());
|
||||
if (adjust_end) {
|
||||
c.setPosition (be.next ().position (), QTextCursor::KeepAnchor);
|
||||
} else {
|
||||
c.setPosition (be.position () + be.text ().length (), QTextCursor::KeepAnchor);
|
||||
}
|
||||
mp_text->setTextCursor (c);
|
||||
|
||||
} else {
|
||||
|
||||
QTextCursor c = mp_text->textCursor ();
|
||||
QString text = c.block ().text ();
|
||||
int col = c.position () - c.block ().position ();
|
||||
|
||||
int p = 0;
|
||||
for (int i = 0; i < text.length () && i < col; ++i) {
|
||||
if (text [i] == QChar::fromLatin1 ('\t')) {
|
||||
p = (p - p % m_ntab) + m_ntab;
|
||||
} else {
|
||||
++p;
|
||||
}
|
||||
}
|
||||
|
||||
c.insertText (QString (m_nindent - p % m_nindent, QChar::fromLatin1 (' ')));
|
||||
mp_text->setTextCursor (c);
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
MacroEditorPage::back_tab_key_pressed ()
|
||||
{
|
||||
if (!mp_text->textCursor ().hasSelection () || mp_text->isReadOnly ()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// tab in
|
||||
QTextBlock bs = mp_text->document ()->findBlock (mp_text->textCursor ().selectionStart ());
|
||||
QTextBlock be = mp_text->document ()->findBlock (mp_text->textCursor ().selectionEnd ());
|
||||
bool adjust_end = false;
|
||||
if (be != bs) {
|
||||
QTextCursor se (mp_text->document ());
|
||||
se.setPosition (mp_text->textCursor ().selectionEnd ());
|
||||
if (se.atBlockStart ()) {
|
||||
be = be.previous ();
|
||||
adjust_end = true;
|
||||
}
|
||||
}
|
||||
|
||||
QTextCursor c (mp_text->document ());
|
||||
c.setPosition (bs.position ());
|
||||
c.beginEditBlock ();
|
||||
|
||||
for (QTextBlock b = bs; ; b = b.next()) {
|
||||
|
||||
c.setPosition (b.position ());
|
||||
QString text = b.text ();
|
||||
int n = m_nindent;
|
||||
int p = 0;
|
||||
for (int i = 0; i < text.length () && n > 0; ++i) {
|
||||
if (text [i] == QChar::fromLatin1 (' ')) {
|
||||
++p;
|
||||
--n;
|
||||
c.deleteChar ();
|
||||
} else if (text [i] == QChar::fromLatin1 ('\t')) {
|
||||
c.deleteChar ();
|
||||
int pp = p;
|
||||
p = (p - p % m_ntab) + m_ntab;
|
||||
if (p - pp >= n) {
|
||||
if (p - pp > n) {
|
||||
c.insertText (QString (p - pp - n, QChar::fromLatin1 (' ')));
|
||||
}
|
||||
n = 0;
|
||||
} else {
|
||||
n -= p - pp;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (b == be) {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
c.endEditBlock ();
|
||||
|
||||
c.setPosition (bs.position ());
|
||||
if (adjust_end) {
|
||||
c.setPosition (be.next ().position (), QTextCursor::KeepAnchor);
|
||||
} else {
|
||||
c.setPosition (be.position () + be.text ().length (), QTextCursor::KeepAnchor);
|
||||
}
|
||||
mp_text->setTextCursor (c);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
MacroEditorPage::backspace_pressed ()
|
||||
{
|
||||
if (mp_text->textCursor ().hasSelection () || mp_text->isReadOnly()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QTextCursor c = mp_text->textCursor ();
|
||||
QString text = c.block ().text ();
|
||||
int col = c.position () - c.block ().position ();
|
||||
if (col > 0) {
|
||||
|
||||
int p = 0;
|
||||
bool only_space_before = true;
|
||||
|
||||
for (int i = 0; i < text.length () && i < col; ++i) {
|
||||
if (text [i] == QChar::fromLatin1 ('\t')) {
|
||||
p = (p - p % m_ntab) + m_ntab;
|
||||
} else if (text [i] == QChar::fromLatin1 (' ')) {
|
||||
++p;
|
||||
} else {
|
||||
only_space_before = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (only_space_before) {
|
||||
|
||||
for (int i = 0; i < col; ++i) {
|
||||
c.deletePreviousChar ();
|
||||
}
|
||||
|
||||
c.insertText (QString (std::max (0, ((p - 1) / m_nindent) * m_nindent), QChar::fromLatin1 (' ')));
|
||||
mp_text->setTextCursor (c);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
MacroEditorPage::return_pressed ()
|
||||
{
|
||||
if (mp_text->isReadOnly ()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Implement auto-indent on return
|
||||
|
||||
QTextCursor c = mp_text->textCursor ();
|
||||
QTextBlock b = c.block ();
|
||||
|
||||
c.insertBlock ();
|
||||
|
||||
QString l;
|
||||
if (b.isValid ()) {
|
||||
QString text = b.text ();
|
||||
for (int i = 0; i < text.length (); ++i) {
|
||||
if (text [i] == QChar::fromLatin1 ('\t') || text [i] == QChar::fromLatin1 (' ')) {
|
||||
l += text [i];
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c.insertText (l);
|
||||
mp_text->setTextCursor (c);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool is_tab_key (QKeyEvent *ke)
|
||||
{
|
||||
return ke->key () == Qt::Key_Tab && (ke->modifiers () & Qt::ShiftModifier) == 0;
|
||||
}
|
||||
|
||||
static bool is_backtab_key (QKeyEvent *ke)
|
||||
{
|
||||
return ke->key () == Qt::Key_Backtab || (ke->key () == Qt::Key_Tab && (ke->modifiers () & Qt::ShiftModifier) != 0);
|
||||
}
|
||||
|
||||
static bool is_backspace_key (QKeyEvent *ke)
|
||||
{
|
||||
return ke->key () == Qt::Key_Backspace;
|
||||
}
|
||||
|
||||
static bool is_escape_key (QKeyEvent *ke)
|
||||
{
|
||||
return ke->key () == Qt::Key_Escape;
|
||||
}
|
||||
|
||||
static bool is_return_key (QKeyEvent *ke)
|
||||
{
|
||||
return ke->key () == Qt::Key_Return;
|
||||
}
|
||||
|
||||
static bool is_help_key (QKeyEvent *ke)
|
||||
{
|
||||
return ke->key () == Qt::Key_F1;
|
||||
}
|
||||
|
||||
static bool is_find_next_key (QKeyEvent *ke)
|
||||
{
|
||||
return ke->key () == Qt::Key_F3;
|
||||
}
|
||||
|
||||
static bool is_find_key (QKeyEvent *ke)
|
||||
{
|
||||
return ke->key () == Qt::Key_F && (ke->modifiers () & Qt::ControlModifier) != 0;
|
||||
}
|
||||
|
||||
static bool is_up_key (QKeyEvent *ke)
|
||||
{
|
||||
return ke->key () == Qt::Key_Up;
|
||||
}
|
||||
|
||||
static bool is_down_key (QKeyEvent *ke)
|
||||
{
|
||||
return ke->key () == Qt::Key_Down;
|
||||
}
|
||||
|
||||
|
||||
static bool is_any_known_key (QKeyEvent *ke)
|
||||
{
|
||||
return is_tab_key (ke) ||
|
||||
is_backtab_key (ke) ||
|
||||
is_backspace_key (ke) ||
|
||||
is_escape_key (ke) ||
|
||||
is_return_key (ke) ||
|
||||
is_help_key (ke) ||
|
||||
is_find_next_key (ke) ||
|
||||
is_find_key (ke) ||
|
||||
is_up_key (ke) ||
|
||||
is_down_key (ke);
|
||||
}
|
||||
|
||||
bool
|
||||
MacroEditorPage::eventFilter (QObject *watched, QEvent *event)
|
||||
{
|
||||
if (watched == mp_text) {
|
||||
|
||||
if (event->type () == QEvent::KeyPress) {
|
||||
if (event->type () == QEvent::ShortcutOverride) {
|
||||
|
||||
// override shortcuts if the collide with keys we accept ourselves
|
||||
QKeyEvent *ke = dynamic_cast<QKeyEvent *> (event);
|
||||
if (! ke) {
|
||||
return false; // should not happen
|
||||
}
|
||||
|
||||
if (is_any_known_key (ke)) {
|
||||
event->accept ();
|
||||
return true;
|
||||
}
|
||||
|
||||
} else if (event->type () == QEvent::FocusOut) {
|
||||
|
||||
hide_completer ();
|
||||
return true;
|
||||
|
||||
} else if (event->type () == QEvent::KeyPress) {
|
||||
|
||||
m_error_line = -1;
|
||||
mp_text->setExtraSelections (QList<QTextEdit::ExtraSelection> ());
|
||||
|
||||
QKeyEvent *ke = dynamic_cast<QKeyEvent *> (event);
|
||||
if (ke && ke->key () == Qt::Key_Tab && (ke->modifiers () & Qt::ShiftModifier) == 0) {
|
||||
if (! ke) {
|
||||
return false; // should not happen
|
||||
}
|
||||
|
||||
if (!mp_text->isReadOnly ()) {
|
||||
|
||||
QTextBlock bs, be;
|
||||
bool adjust_end = false;
|
||||
|
||||
bool indent = false;
|
||||
if (mp_text->textCursor ().hasSelection ()) {
|
||||
bs = mp_text->document ()->findBlock (mp_text->textCursor ().selectionStart ());
|
||||
be = mp_text->document ()->findBlock (mp_text->textCursor ().selectionEnd ());
|
||||
if (be != bs) {
|
||||
indent = true;
|
||||
QTextCursor se (mp_text->document ());
|
||||
se.setPosition (mp_text->textCursor ().selectionEnd ());
|
||||
if (se.atBlockStart ()) {
|
||||
be = be.previous ();
|
||||
adjust_end = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (indent) {
|
||||
|
||||
// tab out
|
||||
QTextCursor c (mp_text->document ());
|
||||
c.setPosition (bs.position ());
|
||||
c.beginEditBlock ();
|
||||
|
||||
for (QTextBlock b = bs; ; b = b.next()) {
|
||||
|
||||
c.setPosition (b.position ());
|
||||
QString text = b.text ();
|
||||
|
||||
bool has_tabs = false;
|
||||
int p = 0;
|
||||
int i = 0;
|
||||
for (; i < text.length (); ++i) {
|
||||
if (text [i] == QChar::fromLatin1 (' ')) {
|
||||
++p;
|
||||
} else if (text [i] == QChar::fromLatin1 ('\t')) {
|
||||
p = (p - p % m_ntab) + m_ntab;
|
||||
has_tabs = true;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (has_tabs) {
|
||||
for ( ; i > 0; --i) {
|
||||
c.deleteChar ();
|
||||
}
|
||||
c.insertText (QString (m_nindent + p, QChar::fromLatin1 (' ')));
|
||||
} else {
|
||||
c.insertText (QString (m_nindent, QChar::fromLatin1 (' ')));
|
||||
}
|
||||
|
||||
if (b == be) {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
c.endEditBlock ();
|
||||
|
||||
c.setPosition (bs.position ());
|
||||
if (adjust_end) {
|
||||
c.setPosition (be.next ().position (), QTextCursor::KeepAnchor);
|
||||
} else {
|
||||
c.setPosition (be.position () + be.text ().length (), QTextCursor::KeepAnchor);
|
||||
}
|
||||
mp_text->setTextCursor (c);
|
||||
|
||||
} else {
|
||||
|
||||
QTextCursor c = mp_text->textCursor ();
|
||||
QString text = c.block ().text ();
|
||||
int col = c.position () - c.block ().position ();
|
||||
|
||||
int p = 0;
|
||||
for (int i = 0; i < text.length () && i < col; ++i) {
|
||||
if (text [i] == QChar::fromLatin1 ('\t')) {
|
||||
p = (p - p % m_ntab) + m_ntab;
|
||||
} else {
|
||||
++p;
|
||||
}
|
||||
}
|
||||
|
||||
c.insertText (QString (m_nindent - p % m_nindent, QChar::fromLatin1 (' ')));
|
||||
mp_text->setTextCursor (c);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
} else if (ke && (ke->key () == Qt::Key_Backtab || (ke->key () == Qt::Key_Tab && (ke->modifiers () & Qt::ShiftModifier) != 0))) {
|
||||
|
||||
if (mp_text->textCursor ().hasSelection () && !mp_text->isReadOnly ()) {
|
||||
|
||||
// tab in
|
||||
QTextBlock bs = mp_text->document ()->findBlock (mp_text->textCursor ().selectionStart ());
|
||||
QTextBlock be = mp_text->document ()->findBlock (mp_text->textCursor ().selectionEnd ());
|
||||
bool adjust_end = false;
|
||||
if (be != bs) {
|
||||
QTextCursor se (mp_text->document ());
|
||||
se.setPosition (mp_text->textCursor ().selectionEnd ());
|
||||
if (se.atBlockStart ()) {
|
||||
be = be.previous ();
|
||||
adjust_end = true;
|
||||
}
|
||||
}
|
||||
|
||||
QTextCursor c (mp_text->document ());
|
||||
c.setPosition (bs.position ());
|
||||
c.beginEditBlock ();
|
||||
|
||||
for (QTextBlock b = bs; ; b = b.next()) {
|
||||
|
||||
c.setPosition (b.position ());
|
||||
QString text = b.text ();
|
||||
int n = m_nindent;
|
||||
int p = 0;
|
||||
for (int i = 0; i < text.length () && n > 0; ++i) {
|
||||
if (text [i] == QChar::fromLatin1 (' ')) {
|
||||
++p;
|
||||
--n;
|
||||
c.deleteChar ();
|
||||
} else if (text [i] == QChar::fromLatin1 ('\t')) {
|
||||
c.deleteChar ();
|
||||
int pp = p;
|
||||
p = (p - p % m_ntab) + m_ntab;
|
||||
if (p - pp >= n) {
|
||||
if (p - pp > n) {
|
||||
c.insertText (QString (p - pp - n, QChar::fromLatin1 (' ')));
|
||||
}
|
||||
n = 0;
|
||||
} else {
|
||||
n -= p - pp;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (b == be) {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
c.endEditBlock ();
|
||||
|
||||
c.setPosition (bs.position ());
|
||||
if (adjust_end) {
|
||||
c.setPosition (be.next ().position (), QTextCursor::KeepAnchor);
|
||||
} else {
|
||||
c.setPosition (be.position () + be.text ().length (), QTextCursor::KeepAnchor);
|
||||
}
|
||||
mp_text->setTextCursor (c);
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
} else if (ke && ke->key () == Qt::Key_Backspace) {
|
||||
|
||||
if (!mp_text->textCursor ().hasSelection () && !mp_text->isReadOnly()) {
|
||||
|
||||
QTextCursor c = mp_text->textCursor ();
|
||||
QString text = c.block ().text ();
|
||||
int col = c.position () - c.block ().position ();
|
||||
if (col > 0) {
|
||||
|
||||
int p = 0;
|
||||
bool only_space_before = true;
|
||||
|
||||
for (int i = 0; i < text.length () && i < col; ++i) {
|
||||
if (text [i] == QChar::fromLatin1 ('\t')) {
|
||||
p = (p - p % m_ntab) + m_ntab;
|
||||
} else if (text [i] == QChar::fromLatin1 (' ')) {
|
||||
++p;
|
||||
} else {
|
||||
only_space_before = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (only_space_before) {
|
||||
|
||||
for (int i = 0; i < col; ++i) {
|
||||
c.deletePreviousChar ();
|
||||
}
|
||||
|
||||
c.insertText (QString (std::max (0, ((p - 1) / m_nindent) * m_nindent), QChar::fromLatin1 (' ')));
|
||||
mp_text->setTextCursor (c);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else if (ke && ke->key () == Qt::Key_Escape) {
|
||||
|
||||
// Handle Esc to clear the selection
|
||||
|
||||
QTextCursor c = mp_text->textCursor ();
|
||||
c.clearSelection ();
|
||||
mp_text->setTextCursor (c);
|
||||
|
||||
return true;
|
||||
|
||||
} else if (ke && ke->key () == Qt::Key_Return) {
|
||||
|
||||
if (!mp_text->isReadOnly ()) {
|
||||
|
||||
// Implement auto-indent on return
|
||||
|
||||
QTextCursor c = mp_text->textCursor ();
|
||||
QTextBlock b = c.block ();
|
||||
|
||||
c.insertBlock ();
|
||||
|
||||
QString l;
|
||||
if (b.isValid ()) {
|
||||
QString text = b.text ();
|
||||
for (int i = 0; i < text.length (); ++i) {
|
||||
if (text [i] == QChar::fromLatin1 ('\t') || text [i] == QChar::fromLatin1 (' ')) {
|
||||
l += text [i];
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c.insertText (l);
|
||||
mp_text->setTextCursor (c);
|
||||
if (is_tab_key (ke)) {
|
||||
|
||||
if (mp_completer_popup->isVisible ()) {
|
||||
complete ();
|
||||
return true;
|
||||
|
||||
} else {
|
||||
return tab_key_pressed ();
|
||||
}
|
||||
|
||||
} else if (ke && ke->key () == Qt::Key_F1) {
|
||||
} else if (is_backtab_key (ke)) {
|
||||
|
||||
return back_tab_key_pressed ();
|
||||
|
||||
} else if (is_backspace_key (ke)) {
|
||||
|
||||
return backspace_pressed ();
|
||||
|
||||
} else if (is_escape_key (ke)) {
|
||||
|
||||
// Handle Esc to return to the before-find position and clear the selection or to hide popup
|
||||
|
||||
if (mp_completer_popup->isVisible ()) {
|
||||
mp_completer_popup->hide ();
|
||||
} else {
|
||||
find_reset ();
|
||||
QTextCursor c = mp_text->textCursor ();
|
||||
c.clearSelection ();
|
||||
mp_text->setTextCursor (c);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
} else if (is_return_key (ke)) {
|
||||
|
||||
if (mp_completer_popup->isVisible ()) {
|
||||
complete ();
|
||||
return true;
|
||||
} else {
|
||||
return return_pressed ();
|
||||
}
|
||||
|
||||
} else if (is_help_key (ke)) {
|
||||
|
||||
QTextCursor c = mp_text->textCursor ();
|
||||
if (c.selectionStart () == c.selectionEnd ()) {
|
||||
|
|
@ -1418,7 +1697,19 @@ MacroEditorPage::eventFilter (QObject *watched, QEvent *event)
|
|||
|
||||
return true;
|
||||
|
||||
} else if (ke && ke->key () == Qt::Key_F3) {
|
||||
} else if (mp_completer_popup->isVisible () && (is_up_key (ke) || is_down_key (ke))) {
|
||||
|
||||
QApplication::sendEvent (mp_completer_list, event);
|
||||
return true;
|
||||
|
||||
} else if (is_find_key (ke)) {
|
||||
|
||||
QTextCursor c = mp_text->textCursor ();
|
||||
emit search_requested (c.selectedText ());
|
||||
|
||||
return true;
|
||||
|
||||
} else if (is_find_next_key (ke)) {
|
||||
|
||||
// Jump to the next occurence of the search string
|
||||
|
||||
|
|
|
|||
|
|
@ -45,6 +45,9 @@ typedef QTextEdit TextEditWidget;
|
|||
|
||||
class QLabel;
|
||||
class QSyntaxHighlighter;
|
||||
class QTimer;
|
||||
class QWindow;
|
||||
class QListWidget;
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
|
@ -254,8 +257,8 @@ public:
|
|||
return m_current_search;
|
||||
}
|
||||
|
||||
void find_reset ();
|
||||
bool find_next ();
|
||||
|
||||
bool find_prev ();
|
||||
|
||||
void replace_and_find_next (const QString &replace);
|
||||
|
|
@ -268,6 +271,7 @@ public:
|
|||
|
||||
signals:
|
||||
void help_requested (const QString &s);
|
||||
void search_requested (const QString &s);
|
||||
void edit_trace (bool);
|
||||
|
||||
public slots:
|
||||
|
|
@ -280,6 +284,8 @@ protected slots:
|
|||
void breakpoints_changed ();
|
||||
void current_line_changed ();
|
||||
void run_mode_changed ();
|
||||
void completer_timer ();
|
||||
void hide_completer ();
|
||||
|
||||
private:
|
||||
lym::Macro *mp_macro;
|
||||
|
|
@ -294,8 +300,20 @@ private:
|
|||
int m_ntab, m_nindent;
|
||||
std::set<QTextBlock> m_breakpoints;
|
||||
QRegExp m_current_search;
|
||||
QTextCursor m_edit_cursor;
|
||||
bool m_ignore_cursor_changed_event;
|
||||
QTimer *mp_completer_timer;
|
||||
QWidget *mp_completer_popup;
|
||||
QListWidget *mp_completer_list;
|
||||
|
||||
void update_extra_selections ();
|
||||
bool return_pressed ();
|
||||
bool backspace_pressed ();
|
||||
bool back_tab_key_pressed ();
|
||||
bool tab_key_pressed ();
|
||||
void fill_completer_list ();
|
||||
void complete ();
|
||||
|
||||
bool eventFilter (QObject *watched, QEvent *event);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@
|
|||
#include "tlAssert.h"
|
||||
#include "tlStream.h"
|
||||
#include "tlExceptions.h"
|
||||
#include "tlExpression.h"
|
||||
#include "dbMemStatistics.h"
|
||||
#include "dbManager.h"
|
||||
#include "dbStream.h"
|
||||
|
|
@ -1773,13 +1774,17 @@ MainWindow::cm_goto_position ()
|
|||
|
||||
double x = 0.0, y = 0.0, s = 0.0;
|
||||
std::string tt (tl::to_string (text));
|
||||
|
||||
tl::Extractor ex (tt.c_str ());
|
||||
ex >> x >> "," >> y;
|
||||
x = tl::Eval ().parse (ex).execute ().to_double ();
|
||||
ex.test (",");
|
||||
y = tl::Eval ().parse (ex).execute ().to_double ();
|
||||
|
||||
db::DPoint pt (x, y);
|
||||
|
||||
if (! ex.at_end ()) {
|
||||
ex >> "," >> s >> tl::Extractor::end ();
|
||||
ex.test (",");
|
||||
s = tl::Eval ().parse (ex).execute ().to_double ();
|
||||
current_view ()->goto_window (pt, s);
|
||||
} else {
|
||||
current_view ()->goto_window (pt);
|
||||
|
|
@ -2520,21 +2525,30 @@ MainWindow::cm_new_layout ()
|
|||
std::string technology = m_initial_technology;
|
||||
static std::string s_new_cell_cell_name ("TOP");
|
||||
static double s_new_cell_window_size = 2.0;
|
||||
static std::vector<db::LayerProperties> s_layers;
|
||||
|
||||
double dbu = 0.0;
|
||||
|
||||
lay::NewLayoutPropertiesDialog dialog (this);
|
||||
if (dialog.exec_dialog (technology, s_new_cell_cell_name, dbu, s_new_cell_window_size, m_new_layout_current_panel)) {
|
||||
if (dialog.exec_dialog (technology, s_new_cell_cell_name, dbu, s_new_cell_window_size, s_layers, m_new_layout_current_panel)) {
|
||||
|
||||
lay::CellViewRef cellview = create_or_load_layout (0, 0, technology, m_new_layout_current_panel ? 2 : 1 /*= new view*/);
|
||||
std::unique_ptr <lay::LayoutHandle> handle (new lay::LayoutHandle (new db::Layout (& manager ()), std::string ()));
|
||||
handle->rename ("new");
|
||||
|
||||
if (dbu > 1e-10) {
|
||||
cellview->layout ().dbu (dbu);
|
||||
handle->layout ().dbu (dbu);
|
||||
}
|
||||
db::cell_index_type new_ci = cellview->layout ().add_cell (s_new_cell_cell_name.empty () ? 0 : s_new_cell_cell_name.c_str ());
|
||||
cellview.set_cell (new_ci);
|
||||
db::cell_index_type new_ci = handle->layout ().add_cell (s_new_cell_cell_name.empty () ? 0 : s_new_cell_cell_name.c_str ());
|
||||
|
||||
current_view ()->zoom_box_and_set_hier_levels (db::DBox (-0.5 * s_new_cell_window_size, -0.5 * s_new_cell_window_size, 0.5 * s_new_cell_window_size, 0.5 * s_new_cell_window_size), std::make_pair (0, 1));
|
||||
for (std::vector<db::LayerProperties>::const_iterator l = s_layers.begin (); l != s_layers.end (); ++l) {
|
||||
handle->layout ().insert_layer (*l);
|
||||
}
|
||||
|
||||
lay::LayoutView *mp_view = (m_new_layout_current_panel && current_view ()) ? current_view () : view (create_view ());
|
||||
|
||||
unsigned int ci = mp_view->add_layout (handle.release (), true);
|
||||
mp_view->cellview_ref (ci).set_cell (new_ci);
|
||||
mp_view->zoom_box_and_set_hier_levels (db::DBox (-0.5 * s_new_cell_window_size, -0.5 * s_new_cell_window_size, 0.5 * s_new_cell_window_size, 0.5 * s_new_cell_window_size), std::make_pair (0, 1));
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -86,14 +86,13 @@ ProgressReporter::set_progress_bar (lay::ProgressBar *pb)
|
|||
void
|
||||
ProgressReporter::register_object (tl::Progress *progress)
|
||||
{
|
||||
if (mp_objects.empty ()) {
|
||||
if (begin () == end ()) {
|
||||
// to avoid recursions of any kind, disallow any user interaction except
|
||||
// cancelling the operation
|
||||
QApplication::instance ()->installEventFilter (this);
|
||||
}
|
||||
|
||||
mp_objects.push_back (*progress); // this keeps the outmost one visible. push_front would make the latest one visible.
|
||||
// mp_objects.push_front (progress);
|
||||
tl::ProgressAdaptor::register_object (progress);
|
||||
|
||||
if (m_start_time == tl::Clock () && ! m_pw_visible) {
|
||||
m_start_time = tl::Clock::current ();
|
||||
|
|
@ -104,33 +103,47 @@ ProgressReporter::register_object (tl::Progress *progress)
|
|||
set_visible (true);
|
||||
}
|
||||
|
||||
update_and_yield ();
|
||||
if (progress->is_abstract ()) {
|
||||
if (mp_pb) {
|
||||
mp_pb->update_progress (progress);
|
||||
}
|
||||
process_events ();
|
||||
} else {
|
||||
update_and_yield ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ProgressReporter::unregister_object (tl::Progress *progress)
|
||||
{
|
||||
progress->unlink ();
|
||||
tl::ProgressAdaptor::unregister_object (progress);
|
||||
|
||||
// close or refresh window
|
||||
if (mp_objects.empty ()) {
|
||||
if (begin () == end ()) {
|
||||
|
||||
if (m_pw_visible) {
|
||||
set_visible (false);
|
||||
}
|
||||
|
||||
m_start_time = tl::Clock ();
|
||||
}
|
||||
|
||||
update_and_yield ();
|
||||
if (mp_pb) {
|
||||
mp_pb->update_progress (0);
|
||||
}
|
||||
|
||||
process_events ();
|
||||
|
||||
if (mp_objects.empty ()) {
|
||||
QApplication::instance ()->removeEventFilter (this);
|
||||
|
||||
} else {
|
||||
update_and_yield ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ProgressReporter::trigger (tl::Progress * /*progress*/)
|
||||
{
|
||||
if (! mp_objects.empty ()) {
|
||||
if (begin () != end ()) {
|
||||
// make dialog visible after some time has passed
|
||||
if (! m_pw_visible && (tl::Clock::current () - m_start_time).seconds () > 1.0) {
|
||||
set_visible (true);
|
||||
|
|
@ -152,27 +165,22 @@ ProgressReporter::yield (tl::Progress * /*progress*/)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
ProgressReporter::signal_break ()
|
||||
{
|
||||
for (tl::list<tl::Progress>::iterator k = mp_objects.begin (); k != mp_objects.end (); ++k) {
|
||||
k->signal_break ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ProgressReporter::update_and_yield ()
|
||||
{
|
||||
if (m_pw_visible && ! mp_objects.empty ()) {
|
||||
if (mp_pb) {
|
||||
mp_pb->update_progress (mp_objects.first ());
|
||||
QWidget *w = mp_pb->progress_get_widget ();
|
||||
if (w) {
|
||||
mp_objects.first ()->render_progress (w);
|
||||
}
|
||||
}
|
||||
process_events (); // Qt4 seems to need this
|
||||
if (! m_pw_visible) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mp_pb && first ()) {
|
||||
mp_pb->update_progress (first ());
|
||||
QWidget *w = mp_pb->progress_get_widget ();
|
||||
if (w) {
|
||||
first ()->render_progress (w);
|
||||
}
|
||||
}
|
||||
|
||||
process_events (); // Qt4 seems to need this
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -202,8 +210,8 @@ ProgressReporter::set_visible (bool vis)
|
|||
if (mp_pb) {
|
||||
if (!vis) {
|
||||
mp_pb->progress_remove_widget ();
|
||||
} else if (mp_pb->progress_wants_widget () && mp_objects.first ()) {
|
||||
mp_pb->progress_add_widget (mp_objects.first ()->progress_widget ());
|
||||
} else if (mp_pb->progress_wants_widget () && first ()) {
|
||||
mp_pb->progress_add_widget (first ()->progress_widget ());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -68,16 +68,9 @@ public:
|
|||
virtual void yield (tl::Progress *progress);
|
||||
virtual bool eventFilter (QObject *dest, QEvent *event);
|
||||
|
||||
void signal_break ();
|
||||
void set_progress_bar (lay::ProgressBar *pb);
|
||||
|
||||
bool is_busy () const
|
||||
{
|
||||
return !mp_objects.empty ();
|
||||
}
|
||||
|
||||
private:
|
||||
tl::list<tl::Progress> mp_objects;
|
||||
tl::Clock m_start_time;
|
||||
lay::ProgressBar *mp_pb;
|
||||
bool m_pw_visible;
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include <QFrame>
|
||||
#include <QGridLayout>
|
||||
#include <QLabel>
|
||||
#include <QListView>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
|
|
@ -59,7 +60,7 @@ private:
|
|||
|
||||
ProgressBarWidget::ProgressBarWidget (QWidget *parent, const char *name)
|
||||
: QWidget (parent),
|
||||
m_value (0.0), m_width (64), m_length (0), m_fw (1), m_bw (0)
|
||||
m_value (0.0), m_width (200), m_length (0), m_fw (1), m_bw (0)
|
||||
{
|
||||
setObjectName (QString::fromUtf8 (name));
|
||||
setMinimumSize (64, 10);
|
||||
|
|
@ -134,13 +135,46 @@ ProgressBarWidget::resizeEvent (QResizeEvent *)
|
|||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
ProgressWidget::ProgressWidget (ProgressReporter *pr, QWidget *parent, bool full_width)
|
||||
ProgressWidget::ProgressWidget (ProgressReporter *pr, QWidget *parent, bool fw)
|
||||
: QFrame (parent),
|
||||
mp_widget (0), mp_pr (pr)
|
||||
mp_widget (0), mp_pr (pr), m_log_file (0, true), m_log_visible (false)
|
||||
{
|
||||
QVBoxLayout *top_layout = new QVBoxLayout (this);
|
||||
top_layout->addStretch (1);
|
||||
|
||||
mp_log_frame = new QFrame (this);
|
||||
mp_log_frame->setFrameShape (QFrame::NoFrame);
|
||||
mp_log_frame->hide ();
|
||||
top_layout->addWidget (mp_log_frame);
|
||||
|
||||
QVBoxLayout *log_layout = new QVBoxLayout (mp_log_frame);
|
||||
|
||||
QListView *log_view = new QListView (this);
|
||||
log_view->setModel (&m_log_file);
|
||||
log_view->setUniformItemSizes (true);
|
||||
log_layout->addWidget (log_view);
|
||||
|
||||
QFrame *attn_frame = new QFrame (this);
|
||||
attn_frame->setFrameShape (QFrame::NoFrame);
|
||||
attn_frame->hide ();
|
||||
log_layout->addWidget (attn_frame);
|
||||
|
||||
QHBoxLayout *attn_layout = new QHBoxLayout (attn_frame);
|
||||
attn_layout->setContentsMargins (0, 0, 0, 0);
|
||||
|
||||
QLabel *attn_label1 = new QLabel (attn_frame);
|
||||
attn_label1->setPixmap (QPixmap (QString::fromUtf8 (":/warn_16.png")));
|
||||
attn_layout->addWidget (attn_label1);
|
||||
|
||||
QLabel *attn_label2 = new QLabel (attn_frame);
|
||||
attn_label2->setText (tr ("There are errors or warnings"));
|
||||
attn_layout->addWidget (attn_label2);
|
||||
|
||||
attn_layout->addStretch (1);
|
||||
|
||||
connect (&m_log_file, SIGNAL (layoutChanged ()), log_view, SLOT (scrollToBottom ()));
|
||||
connect (&m_log_file, SIGNAL (attention_changed (bool)), attn_frame, SLOT (setVisible (bool)));
|
||||
|
||||
QFrame *bar_frame = new QFrame (this);
|
||||
top_layout->addWidget (bar_frame);
|
||||
|
||||
|
|
@ -157,12 +191,11 @@ ProgressWidget::ProgressWidget (ProgressReporter *pr, QWidget *parent, bool full
|
|||
|
||||
int col = 0;
|
||||
|
||||
if (! full_width) {
|
||||
layout->addItem (new QSpacerItem (8, 8, QSizePolicy::Expanding, QSizePolicy::Expanding), 0, col, 1, 1);
|
||||
layout->setColumnStretch (col++, 1);
|
||||
}
|
||||
layout->addItem (new QSpacerItem (8, 8, QSizePolicy::Expanding, QSizePolicy::Expanding), 0, col, 1, 1);
|
||||
m_left_col = col++;
|
||||
|
||||
mp_label = new QLabel (bar_frame);
|
||||
layout->setColumnStretch(col, 2);
|
||||
layout->addWidget (mp_label, 0, col++, 1, 1);
|
||||
|
||||
layout->addItem (new QSpacerItem (8, 8, QSizePolicy::Fixed, QSizePolicy::Fixed), 0, col++, 1, 1);
|
||||
|
|
@ -171,7 +204,6 @@ ProgressWidget::ProgressWidget (ProgressReporter *pr, QWidget *parent, bool full
|
|||
progress_bar_frame->setFrameStyle (QFrame::Box | QFrame::Plain);
|
||||
progress_bar_frame->setSizePolicy (QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
layout->addWidget (progress_bar_frame, 0, col, 1, 1);
|
||||
layout->setColumnStretch(col++, 2);
|
||||
|
||||
QGridLayout *pbf_layout = new QGridLayout (progress_bar_frame);
|
||||
progress_bar_frame->setLayout (pbf_layout);
|
||||
|
|
@ -191,16 +223,41 @@ ProgressWidget::ProgressWidget (ProgressReporter *pr, QWidget *parent, bool full
|
|||
mp_cancel_button->setText (QObject::tr ("Cancel"));
|
||||
layout->addWidget (mp_cancel_button, 0, col++, 1, 1);
|
||||
|
||||
if (! full_width) {
|
||||
layout->addItem (new QSpacerItem (8, 8, QSizePolicy::Expanding, QSizePolicy::Expanding), 0, col, 1, 1);
|
||||
layout->setColumnStretch (col++, 1);
|
||||
}
|
||||
layout->addItem (new QSpacerItem (8, 8, QSizePolicy::Expanding, QSizePolicy::Expanding), 0, col, 1, 1);
|
||||
m_right_col = col++;
|
||||
|
||||
layout->addItem (new QSpacerItem (10, 10, QSizePolicy::Fixed, QSizePolicy::Fixed), 1, 0, 1, col);
|
||||
|
||||
m_widget_col = col;
|
||||
|
||||
connect (mp_cancel_button, SIGNAL (clicked ()), this, SLOT (signal_break ()));
|
||||
|
||||
set_full_width (fw);
|
||||
}
|
||||
|
||||
void
|
||||
ProgressWidget::set_log_visible (bool f)
|
||||
{
|
||||
if (f != m_log_visible) {
|
||||
m_log_visible = f;
|
||||
mp_log_frame->setVisible (f);
|
||||
set_full_width (m_full_width);
|
||||
}
|
||||
}
|
||||
void
|
||||
ProgressWidget::set_full_width (bool fw)
|
||||
{
|
||||
m_full_width = fw;
|
||||
|
||||
bool f = (fw || m_log_visible);
|
||||
mp_layout->setColumnStretch (m_left_col, f ? 0 : 1);
|
||||
mp_layout->setColumnStretch (m_right_col, f ? 0 : 1);
|
||||
}
|
||||
|
||||
bool
|
||||
ProgressWidget::full_width () const
|
||||
{
|
||||
return m_full_width;
|
||||
}
|
||||
|
||||
QWidget *
|
||||
|
|
@ -233,6 +290,13 @@ ProgressWidget::remove_widget ()
|
|||
void
|
||||
ProgressWidget::set_progress (tl::Progress *progress)
|
||||
{
|
||||
if (! progress || progress->is_abstract ()) {
|
||||
m_log_file.clear ();
|
||||
m_log_file.set_max_entries (progress ? 1000 : 0);
|
||||
set_log_visible (progress != 0);
|
||||
return;
|
||||
}
|
||||
|
||||
bool can_cancel = false;
|
||||
std::string text;
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue