mirror of
https://github.com/KLayout/klayout.git
synced 2026-09-03 08:26:27 +02:00
WIP: turned ext module into plugins.
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
|
||||
TEMPLATE = subdirs
|
||||
|
||||
SUBDIRS = lay_plugin
|
||||
|
||||
@@ -0,0 +1,279 @@
|
||||
<ui version="4.0" >
|
||||
<class>BooleanOptionsDialog</class>
|
||||
<widget class="QDialog" name="BooleanOptionsDialog" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>535</width>
|
||||
<height>349</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>Boolean Operation</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox" >
|
||||
<property name="title" >
|
||||
<string>Boolean Operation Setup</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="2" column="3" >
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="4" >
|
||||
<widget class="Line" name="line" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1" >
|
||||
<widget class="QComboBox" name="mode_cbx" >
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>Union (OR)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>Intersection (AND)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>Difference (A NOT B)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>Difference (B NOT A)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>Symmetric Difference (XOR)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" >
|
||||
<widget class="QLabel" name="label_2" >
|
||||
<property name="text" >
|
||||
<string>Source B</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" >
|
||||
<widget class="QLabel" name="label" >
|
||||
<property name="text" >
|
||||
<string>Source A</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" >
|
||||
<widget class="QLabel" name="label_4" >
|
||||
<property name="text" >
|
||||
<string>Mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" >
|
||||
<widget class="QLabel" name="label_3" >
|
||||
<property name="text" >
|
||||
<string>Result</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0" >
|
||||
<widget class="QLabel" name="label_7" >
|
||||
<property name="text" >
|
||||
<string>Hierarchy</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0" colspan="4" >
|
||||
<widget class="Line" name="line_2" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" >
|
||||
<widget class="QLabel" name="label_5" >
|
||||
<property name="text" >
|
||||
<string>Layout and cell</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2" >
|
||||
<widget class="QLabel" name="label_6" >
|
||||
<property name="text" >
|
||||
<string>Layer</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2" >
|
||||
<widget class="QLabel" name="label_8" >
|
||||
<property name="text" >
|
||||
<string>Layer</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1" >
|
||||
<widget class="QLabel" name="label_9" >
|
||||
<property name="text" >
|
||||
<string>Layout and cell</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" >
|
||||
<widget class="lay::CellViewSelectionComboBox" name="cva_cbx" />
|
||||
</item>
|
||||
<item row="2" column="1" >
|
||||
<widget class="lay::CellViewSelectionComboBox" name="cvb_cbx" />
|
||||
</item>
|
||||
<item row="6" column="1" >
|
||||
<widget class="lay::CellViewSelectionComboBox" name="cvr_cbx" />
|
||||
</item>
|
||||
<item row="1" column="2" >
|
||||
<widget class="lay::LayerSelectionComboBox" name="layera_cbx" />
|
||||
</item>
|
||||
<item row="2" column="2" >
|
||||
<widget class="lay::LayerSelectionComboBox" name="layerb_cbx" />
|
||||
</item>
|
||||
<item row="6" column="2" >
|
||||
<widget class="lay::LayerSelectionComboBox" name="layerr_cbx" />
|
||||
</item>
|
||||
<item row="6" column="3" >
|
||||
<widget class="QLabel" name="label_10" >
|
||||
<property name="text" >
|
||||
<string>(Layer is overwritten)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1" colspan="3" >
|
||||
<widget class="QCheckBox" name="min_coherence_cb" >
|
||||
<property name="text" >
|
||||
<string>Minimum coherence (for touching corners)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1" colspan="3" >
|
||||
<widget class="QComboBox" name="hier_mode_cbx" >
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>Flat</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>Top cell only</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>Individually for current and subcells (semi hierarchical)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>506</width>
|
||||
<height>51</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons" >
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>lay::CellViewSelectionComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>layWidgets.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>lay::LayerSelectionComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>layWidgets.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>BooleanOptionsDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>BooleanOptionsDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -0,0 +1,247 @@
|
||||
<ui version="4.0" >
|
||||
<class>MergeOptionsDialog</class>
|
||||
<widget class="QDialog" name="MergeOptionsDialog" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>641</width>
|
||||
<height>331</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>Merge Operation</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox" >
|
||||
<property name="title" >
|
||||
<string>Merge Operation Setup</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="7" column="1" colspan="3" >
|
||||
<widget class="QComboBox" name="hier_mode_cbx" >
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>Flat</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>Top cell only</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>Individually for current and subcells (semi hierarchical)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="3" >
|
||||
<widget class="QLabel" name="label_10" >
|
||||
<property name="text" >
|
||||
<string>(Layer is overwritten)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2" >
|
||||
<widget class="QLabel" name="label_8" >
|
||||
<property name="text" >
|
||||
<string>Layer</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1" >
|
||||
<widget class="lay::CellViewSelectionComboBox" name="cvr_cbx" />
|
||||
</item>
|
||||
<item row="3" column="1" >
|
||||
<widget class="QLineEdit" name="threshold_le" />
|
||||
</item>
|
||||
<item row="6" column="0" colspan="4" >
|
||||
<widget class="Line" name="line_2" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0" >
|
||||
<widget class="QLabel" name="label_7" >
|
||||
<property name="text" >
|
||||
<string>Hierarchy</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" >
|
||||
<widget class="lay::CellViewSelectionComboBox" name="cv_cbx" />
|
||||
</item>
|
||||
<item row="5" column="0" >
|
||||
<widget class="QLabel" name="label_3" >
|
||||
<property name="text" >
|
||||
<string>Result</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" >
|
||||
<widget class="QLabel" name="label" >
|
||||
<property name="text" >
|
||||
<string>Source</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2" >
|
||||
<widget class="QLabel" name="label_6" >
|
||||
<property name="text" >
|
||||
<string>Layer</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="4" >
|
||||
<widget class="Line" name="line" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1" colspan="3" >
|
||||
<widget class="QCheckBox" name="min_coherence_cb" >
|
||||
<property name="text" >
|
||||
<string>Minimum coherence (for touching corners)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3" >
|
||||
<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 row="1" column="2" >
|
||||
<widget class="lay::LayerSelectionComboBox" name="layer_cbx" />
|
||||
</item>
|
||||
<item row="5" column="2" >
|
||||
<widget class="lay::LayerSelectionComboBox" name="layerr_cbx" />
|
||||
</item>
|
||||
<item row="3" column="2" colspan="2" >
|
||||
<widget class="QLabel" name="label_2" >
|
||||
<property name="text" >
|
||||
<string>(0: all polygons, 1: at least two overlapping ...)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" >
|
||||
<widget class="QLabel" name="label_5" >
|
||||
<property name="text" >
|
||||
<string>Layout and cell</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1" >
|
||||
<widget class="QLabel" name="label_9" >
|
||||
<property name="text" >
|
||||
<string>Layout and cell</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" >
|
||||
<widget class="QLabel" name="label_4" >
|
||||
<property name="text" >
|
||||
<string>Overlap threshold</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0" >
|
||||
<size>
|
||||
<width>506</width>
|
||||
<height>51</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons" >
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>lay::CellViewSelectionComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>layWidgets.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>lay::LayerSelectionComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>layWidgets.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>MergeOptionsDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>MergeOptionsDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -0,0 +1,288 @@
|
||||
<ui version="4.0" >
|
||||
<class>SizingOptionsDialog</class>
|
||||
<widget class="QDialog" name="SizingOptionsDialog" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>567</width>
|
||||
<height>331</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>Sizing Operation</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox" >
|
||||
<property name="title" >
|
||||
<string>Sizing Operation Setup</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="8" column="1" colspan="3" >
|
||||
<widget class="QComboBox" name="hier_mode_cbx" >
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>Flat</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>Top cell only</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>Individually for current and subcells (semi hierarchical)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="3" >
|
||||
<widget class="QLabel" name="label_10" >
|
||||
<property name="text" >
|
||||
<string>(Layer is overwritten)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2" >
|
||||
<widget class="QLabel" name="label_8" >
|
||||
<property name="text" >
|
||||
<string>Layer</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1" >
|
||||
<widget class="lay::CellViewSelectionComboBox" name="cvr_cbx" />
|
||||
</item>
|
||||
<item row="3" column="1" >
|
||||
<widget class="QLineEdit" name="value_le" />
|
||||
</item>
|
||||
<item row="7" column="0" colspan="4" >
|
||||
<widget class="Line" name="line_2" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0" >
|
||||
<widget class="QLabel" name="label_7" >
|
||||
<property name="text" >
|
||||
<string>Hierarchy</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" >
|
||||
<widget class="lay::CellViewSelectionComboBox" name="cv_cbx" />
|
||||
</item>
|
||||
<item row="6" column="0" >
|
||||
<widget class="QLabel" name="label_3" >
|
||||
<property name="text" >
|
||||
<string>Result</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" >
|
||||
<widget class="QLabel" name="label" >
|
||||
<property name="text" >
|
||||
<string>Source</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2" >
|
||||
<widget class="QLabel" name="label_6" >
|
||||
<property name="text" >
|
||||
<string>Layer</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="4" >
|
||||
<widget class="Line" name="line" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1" colspan="3" >
|
||||
<widget class="QCheckBox" name="min_coherence_cb" >
|
||||
<property name="text" >
|
||||
<string>Minimum coherence (for touching corners)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3" >
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="2" >
|
||||
<widget class="lay::LayerSelectionComboBox" name="layer_cbx" />
|
||||
</item>
|
||||
<item row="6" column="2" >
|
||||
<widget class="lay::LayerSelectionComboBox" name="layerr_cbx" />
|
||||
</item>
|
||||
<item row="3" column="2" colspan="2" >
|
||||
<widget class="QLabel" name="label_2" >
|
||||
<property name="text" >
|
||||
<string>Single value or pair (one per direction: sx,sy)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" >
|
||||
<widget class="QLabel" name="label_5" >
|
||||
<property name="text" >
|
||||
<string>Layout and cell</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1" >
|
||||
<widget class="QLabel" name="label_9" >
|
||||
<property name="text" >
|
||||
<string>Layout and cell</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" >
|
||||
<widget class="QLabel" name="label_4" >
|
||||
<property name="text" >
|
||||
<string>Sizing value</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" >
|
||||
<widget class="QLabel" name="label_11" >
|
||||
<property name="text" >
|
||||
<string>Cutoff mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1" >
|
||||
<widget class="QComboBox" name="cutoff_cbx" >
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>Strict (diagonal)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>Strong (octagon)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>Moderate (sharp bends only)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>Weak (sharps bends >135 deg.)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>Long limit (x10)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>Extreme limit (x100)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>506</width>
|
||||
<height>51</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons" >
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>lay::CellViewSelectionComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>layWidgets.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>lay::LayerSelectionComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>layWidgets.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>SizingOptionsDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>SizingOptionsDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -0,0 +1,394 @@
|
||||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2018 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 "layBooleanOperationsDialogs.h"
|
||||
|
||||
#include "layLayoutView.h"
|
||||
#include "tlExceptions.h"
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// BooleanOptionsDialog implementation
|
||||
|
||||
BooleanOptionsDialog::BooleanOptionsDialog (QWidget *parent)
|
||||
: QDialog (parent),
|
||||
mp_view (0)
|
||||
{
|
||||
setObjectName (QString::fromUtf8 ("boolean_options_dialog"));
|
||||
Ui::BooleanOptionsDialog::setupUi (this);
|
||||
|
||||
connect (cva_cbx, SIGNAL (activated (int)), this, SLOT (cv_changed (int)));
|
||||
connect (cvb_cbx, SIGNAL (activated (int)), this, SLOT (cv_changed (int)));
|
||||
connect (cvr_cbx, SIGNAL (activated (int)), this, SLOT (cv_changed (int)));
|
||||
}
|
||||
|
||||
BooleanOptionsDialog::~BooleanOptionsDialog ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void
|
||||
BooleanOptionsDialog::cv_changed (int)
|
||||
{
|
||||
if (! mp_view) {
|
||||
return;
|
||||
}
|
||||
|
||||
layera_cbx->set_view (mp_view, cva_cbx->currentIndex ());
|
||||
layerb_cbx->set_view (mp_view, cvb_cbx->currentIndex ());
|
||||
layerr_cbx->set_view (mp_view, cvr_cbx->currentIndex ());
|
||||
}
|
||||
|
||||
bool
|
||||
BooleanOptionsDialog::exec_dialog (lay::LayoutView *view, int &cv_a, int &layer_a, int &cv_b, int &layer_b, int &cv_r, int &layer_r, int &mode, int &hier_mode, bool &min_coherence)
|
||||
{
|
||||
mp_view = view;
|
||||
|
||||
bool res = false;
|
||||
cva_cbx->set_layout_view (view);
|
||||
cva_cbx->set_current_cv_index (cv_a);
|
||||
cvb_cbx->set_layout_view (view);
|
||||
cvb_cbx->set_current_cv_index (cv_b);
|
||||
cvb_cbx->setEnabled (true);
|
||||
cvr_cbx->set_layout_view (view);
|
||||
cvr_cbx->set_current_cv_index (cv_r);
|
||||
|
||||
cv_changed (0 /*dummy*/);
|
||||
|
||||
layera_cbx->set_current_layer (layer_a);
|
||||
layerb_cbx->set_current_layer (layer_b);
|
||||
layerb_cbx->setEnabled (true);
|
||||
layerr_cbx->set_current_layer (layer_r);
|
||||
|
||||
hier_mode_cbx->setCurrentIndex (hier_mode);
|
||||
mode_cbx->setCurrentIndex (mode);
|
||||
min_coherence_cb->setChecked (min_coherence);
|
||||
|
||||
if (QDialog::exec ()) {
|
||||
|
||||
cv_a = cva_cbx->current_cv_index ();
|
||||
cv_b = cvb_cbx->current_cv_index ();
|
||||
cv_r = cvr_cbx->current_cv_index ();
|
||||
layer_a = layera_cbx->current_layer ();
|
||||
layer_b = layerb_cbx->current_layer ();
|
||||
layer_r = layerr_cbx->current_layer ();
|
||||
|
||||
hier_mode = hier_mode_cbx->currentIndex ();
|
||||
mode = mode_cbx->currentIndex ();
|
||||
min_coherence = min_coherence_cb->isChecked ();
|
||||
|
||||
res = true;
|
||||
|
||||
}
|
||||
|
||||
mp_view = 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
void
|
||||
BooleanOptionsDialog::accept ()
|
||||
{
|
||||
BEGIN_PROTECTED;
|
||||
|
||||
int cv_a = cva_cbx->current_cv_index ();
|
||||
if (cv_a < 0) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("No layout specified for source 'A'")));
|
||||
}
|
||||
|
||||
int cv_b = cvb_cbx->current_cv_index ();
|
||||
if (cv_b < 0) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("No layout specified for source 'B'")));
|
||||
}
|
||||
|
||||
int cv_r = cvr_cbx->current_cv_index ();
|
||||
if (cv_r < 0) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("No layout specified for result")));
|
||||
}
|
||||
|
||||
if (fabs (mp_view->cellview (cv_a)->layout ().dbu () - mp_view->cellview (cv_r)->layout ().dbu ()) > db::epsilon ||
|
||||
fabs (mp_view->cellview (cv_b)->layout ().dbu () - mp_view->cellview (cv_r)->layout ().dbu ()) > db::epsilon) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("All source and result layouts must have the same database unit")));
|
||||
}
|
||||
|
||||
if (layera_cbx->current_layer () < 0) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("No layer specified for source 'A'")));
|
||||
}
|
||||
if (layerb_cbx->current_layer () < 0) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("No layer specified for source 'B'")));
|
||||
}
|
||||
if (layerr_cbx->current_layer () < 0) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("No layer specified for result layer")));
|
||||
}
|
||||
|
||||
if (hier_mode_cbx->currentIndex () == 2 &&
|
||||
cva_cbx->current_cv_index () != cvb_cbx->current_cv_index () &&
|
||||
cva_cbx->current_cv_index () != cvr_cbx->current_cv_index ()) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("All source layouts and result layout must be same in 'cell by cell' mode")));
|
||||
}
|
||||
|
||||
QDialog::accept ();
|
||||
END_PROTECTED;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// SizingOptionsDialog implementation
|
||||
|
||||
SizingOptionsDialog::SizingOptionsDialog (QWidget *parent)
|
||||
: QDialog (parent),
|
||||
mp_view (0)
|
||||
{
|
||||
setObjectName (QString::fromUtf8 ("sizing_options_dialog"));
|
||||
Ui::SizingOptionsDialog::setupUi (this);
|
||||
|
||||
connect (cv_cbx, SIGNAL (activated (int)), this, SLOT (cv_changed (int)));
|
||||
connect (cvr_cbx, SIGNAL (activated (int)), this, SLOT (cv_changed (int)));
|
||||
}
|
||||
|
||||
SizingOptionsDialog::~SizingOptionsDialog ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void
|
||||
SizingOptionsDialog::cv_changed (int)
|
||||
{
|
||||
if (! mp_view) {
|
||||
return;
|
||||
}
|
||||
|
||||
layer_cbx->set_view (mp_view, cv_cbx->currentIndex ());
|
||||
layerr_cbx->set_view (mp_view, cvr_cbx->currentIndex ());
|
||||
}
|
||||
|
||||
bool
|
||||
SizingOptionsDialog::exec_dialog (lay::LayoutView *view, int &cv, int &layer, int &cv_r, int &layer_r, double &dx, double &dy, unsigned int &size_mode, int &hier_mode, bool &min_coherence)
|
||||
{
|
||||
mp_view = view;
|
||||
|
||||
bool res = false;
|
||||
cv_cbx->set_layout_view (view);
|
||||
cv_cbx->set_current_cv_index (cv);
|
||||
cvr_cbx->set_layout_view (view);
|
||||
cvr_cbx->set_current_cv_index (cv_r);
|
||||
|
||||
cv_changed (0 /*dummy*/);
|
||||
|
||||
layer_cbx->set_current_layer (layer);
|
||||
layerr_cbx->set_current_layer (layer_r);
|
||||
|
||||
hier_mode_cbx->setCurrentIndex (hier_mode);
|
||||
cutoff_cbx->setCurrentIndex (size_mode);
|
||||
if (dx == dy) {
|
||||
value_le->setText (tl::to_qstring (tl::sprintf ("%.12g", dx)));
|
||||
} else {
|
||||
value_le->setText (tl::to_qstring (tl::sprintf ("%.12g,%.12g", dx, dy)));
|
||||
}
|
||||
min_coherence_cb->setChecked (min_coherence);
|
||||
|
||||
if (QDialog::exec ()) {
|
||||
|
||||
cv = cv_cbx->current_cv_index ();
|
||||
cv_r = cvr_cbx->current_cv_index ();
|
||||
layer = layer_cbx->current_layer ();
|
||||
layer_r = layerr_cbx->current_layer ();
|
||||
|
||||
hier_mode = hier_mode_cbx->currentIndex ();
|
||||
min_coherence = min_coherence_cb->isChecked ();
|
||||
size_mode = cutoff_cbx->currentIndex ();
|
||||
|
||||
tl::string t (tl::to_string (value_le->text ()));
|
||||
tl::Extractor ex (t.c_str ());
|
||||
ex.read (dx);
|
||||
if (ex.test (",")) {
|
||||
ex.read (dy);
|
||||
} else {
|
||||
dy = dx;
|
||||
}
|
||||
|
||||
res = true;
|
||||
|
||||
}
|
||||
|
||||
mp_view = 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
void
|
||||
SizingOptionsDialog::accept ()
|
||||
{
|
||||
BEGIN_PROTECTED;
|
||||
|
||||
int cv = cv_cbx->current_cv_index ();
|
||||
if (cv < 0) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("No layout specified for source")));
|
||||
}
|
||||
|
||||
int cv_r = cvr_cbx->current_cv_index ();
|
||||
if (cv_r < 0) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("No layout specified for result")));
|
||||
}
|
||||
|
||||
if (fabs (mp_view->cellview (cv)->layout ().dbu () - mp_view->cellview (cv_r)->layout ().dbu ()) > db::epsilon) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Source and result layouts must have the same database unit")));
|
||||
}
|
||||
|
||||
if (layer_cbx->current_layer () < 0) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("No layer specified for source")));
|
||||
}
|
||||
if (layerr_cbx->current_layer () < 0) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("No layer specified for result layer")));
|
||||
}
|
||||
|
||||
if (hier_mode_cbx->currentIndex () == 2 &&
|
||||
cv_cbx->current_cv_index () != cvr_cbx->current_cv_index ()) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Source layout and result layout must be same in 'cell by cell' mode")));
|
||||
}
|
||||
|
||||
double x, y;
|
||||
tl::string t (tl::to_string (value_le->text ()));
|
||||
tl::Extractor ex (t.c_str ());
|
||||
ex.read (x);
|
||||
if (ex.test (",")) {
|
||||
ex.read (y);
|
||||
}
|
||||
|
||||
QDialog::accept ();
|
||||
END_PROTECTED;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// MergeOptionsDialog implementation
|
||||
|
||||
MergeOptionsDialog::MergeOptionsDialog (QWidget *parent)
|
||||
: QDialog (parent),
|
||||
mp_view (0)
|
||||
{
|
||||
setObjectName (QString::fromUtf8 ("merge_options_dialog"));
|
||||
Ui::MergeOptionsDialog::setupUi (this);
|
||||
|
||||
connect (cv_cbx, SIGNAL (activated (int)), this, SLOT (cv_changed (int)));
|
||||
connect (cvr_cbx, SIGNAL (activated (int)), this, SLOT (cv_changed (int)));
|
||||
}
|
||||
|
||||
MergeOptionsDialog::~MergeOptionsDialog ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void
|
||||
MergeOptionsDialog::cv_changed (int)
|
||||
{
|
||||
if (! mp_view) {
|
||||
return;
|
||||
}
|
||||
|
||||
layer_cbx->set_view (mp_view, cv_cbx->currentIndex ());
|
||||
layerr_cbx->set_view (mp_view, cvr_cbx->currentIndex ());
|
||||
}
|
||||
|
||||
bool
|
||||
MergeOptionsDialog::exec_dialog (lay::LayoutView *view, int &cv, int &layer, int &cv_r, int &layer_r, unsigned int &min_wc, int &hier_mode, bool &min_coherence)
|
||||
{
|
||||
mp_view = view;
|
||||
|
||||
bool res = false;
|
||||
cv_cbx->set_layout_view (view);
|
||||
cv_cbx->set_current_cv_index (cv);
|
||||
cvr_cbx->set_layout_view (view);
|
||||
cvr_cbx->set_current_cv_index (cv_r);
|
||||
|
||||
cv_changed (0 /*dummy*/);
|
||||
|
||||
layer_cbx->set_current_layer (layer);
|
||||
layerr_cbx->set_current_layer (layer_r);
|
||||
|
||||
hier_mode_cbx->setCurrentIndex (hier_mode);
|
||||
threshold_le->setText (tl::to_qstring (tl::sprintf ("%u", min_wc)));
|
||||
min_coherence_cb->setChecked (min_coherence);
|
||||
|
||||
if (QDialog::exec ()) {
|
||||
|
||||
cv = cv_cbx->current_cv_index ();
|
||||
cv_r = cvr_cbx->current_cv_index ();
|
||||
layer = layer_cbx->current_layer ();
|
||||
layer_r = layerr_cbx->current_layer ();
|
||||
|
||||
hier_mode = hier_mode_cbx->currentIndex ();
|
||||
min_coherence = min_coherence_cb->isChecked ();
|
||||
|
||||
std::string t (tl::to_string (threshold_le->text ()));
|
||||
tl::Extractor ex (t.c_str ());
|
||||
ex.read (min_wc);
|
||||
|
||||
res = true;
|
||||
|
||||
}
|
||||
|
||||
mp_view = 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
void
|
||||
MergeOptionsDialog::accept ()
|
||||
{
|
||||
BEGIN_PROTECTED;
|
||||
|
||||
int cv = cv_cbx->current_cv_index ();
|
||||
if (cv < 0) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("No layout specified for source")));
|
||||
}
|
||||
|
||||
int cv_r = cvr_cbx->current_cv_index ();
|
||||
if (cv_r < 0) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("No layout specified for result")));
|
||||
}
|
||||
|
||||
if (fabs (mp_view->cellview (cv)->layout ().dbu () - mp_view->cellview (cv_r)->layout ().dbu ()) > db::epsilon) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Source and result layouts must have the same database unit")));
|
||||
}
|
||||
|
||||
if (layer_cbx->current_layer () < 0) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("No layer specified for source")));
|
||||
}
|
||||
if (layerr_cbx->current_layer () < 0) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("No layer specified for result")));
|
||||
}
|
||||
|
||||
if (hier_mode_cbx->currentIndex () == 2 &&
|
||||
cv_cbx->current_cv_index () != cvr_cbx->current_cv_index ()) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Source layout and result layout must be same in 'cell by cell' mode")));
|
||||
}
|
||||
|
||||
unsigned int min_wc = 0;
|
||||
std::string t (tl::to_string (threshold_le->text ()));
|
||||
tl::Extractor ex (t.c_str ());
|
||||
ex.read (min_wc);
|
||||
|
||||
QDialog::accept ();
|
||||
END_PROTECTED;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2018 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_layDialogs
|
||||
#define HDR_layDialogs
|
||||
|
||||
#include "ui_BooleanOptionsDialog.h"
|
||||
#include "ui_SizingOptionsDialog.h"
|
||||
#include "ui_MergeOptionsDialog.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
class Layout;
|
||||
}
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
||||
class CellView;
|
||||
class LayoutView;
|
||||
|
||||
/**
|
||||
* @brief The boolean operation options
|
||||
*/
|
||||
class BooleanOptionsDialog
|
||||
: public QDialog,
|
||||
public Ui::BooleanOptionsDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
BooleanOptionsDialog (QWidget *parent);
|
||||
virtual ~BooleanOptionsDialog ();
|
||||
|
||||
bool exec_dialog (lay::LayoutView *view, int &cv_a, int &layer_a, int &cv_b, int &layer_b, int &cv_res, int &layer_res, int &mode, int &hier_mode, bool &min_coherence);
|
||||
|
||||
public slots:
|
||||
void cv_changed (int);
|
||||
|
||||
private:
|
||||
virtual void accept ();
|
||||
|
||||
lay::LayoutView *mp_view;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The sizing operation options
|
||||
*/
|
||||
class SizingOptionsDialog
|
||||
: public QDialog,
|
||||
public Ui::SizingOptionsDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SizingOptionsDialog (QWidget *parent);
|
||||
virtual ~SizingOptionsDialog ();
|
||||
|
||||
bool exec_dialog (lay::LayoutView *view, int &cv, int &layer, int &cv_res, int &layer_res, double &dx, double &dy, unsigned int &size_mode, int &hier_mode, bool &min_coherence);
|
||||
|
||||
public slots:
|
||||
void cv_changed (int);
|
||||
|
||||
private:
|
||||
virtual void accept ();
|
||||
|
||||
lay::LayoutView *mp_view;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The merge operation options
|
||||
*/
|
||||
class MergeOptionsDialog
|
||||
: public QDialog,
|
||||
public Ui::MergeOptionsDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MergeOptionsDialog (QWidget *parent);
|
||||
virtual ~MergeOptionsDialog ();
|
||||
|
||||
bool exec_dialog (lay::LayoutView *view, int &cv, int &layer, int &cv_res, int &layer_res, unsigned int &min_wc, int &hier_mode, bool &min_coherence);
|
||||
|
||||
public slots:
|
||||
void cv_changed (int);
|
||||
|
||||
private:
|
||||
virtual void accept ();
|
||||
|
||||
lay::LayoutView *mp_view;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,506 @@
|
||||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2018 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 "layBooleanOperationsDialogs.h"
|
||||
|
||||
#include "layPlugin.h"
|
||||
#include "layTipDialog.h"
|
||||
#include "layLayoutView.h"
|
||||
|
||||
#include "dbShapeProcessor.h"
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
||||
class BooleanOperationsPlugin
|
||||
: public lay::Plugin
|
||||
{
|
||||
public:
|
||||
BooleanOperationsPlugin (Plugin *parent, lay::LayoutView *view)
|
||||
: lay::Plugin (parent), mp_view (view)
|
||||
{
|
||||
m_boolean_cva = -1;
|
||||
m_boolean_cvb = -1;
|
||||
m_boolean_cvr = -1;
|
||||
m_boolean_layera = -1;
|
||||
m_boolean_layerb = -1;
|
||||
m_boolean_layerr = -1;
|
||||
m_boolean_hier_mode = 0;
|
||||
m_boolean_mode = 0;
|
||||
m_boolean_mincoh = true;
|
||||
m_boolean_minwc = 0;
|
||||
m_boolean_sizex = m_boolean_sizey = 0.0;
|
||||
m_boolean_size_mode = 2;
|
||||
}
|
||||
|
||||
~BooleanOperationsPlugin ()
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
void menu_activated (const std::string &symbol)
|
||||
{
|
||||
if (symbol == "lay::boolean") {
|
||||
boolean ();
|
||||
} else if (symbol == "lay::merge") {
|
||||
merge ();
|
||||
} else if (symbol == "lay::size") {
|
||||
size ();
|
||||
}
|
||||
}
|
||||
|
||||
void boolean ()
|
||||
{
|
||||
struct { int *cv; int *layer; } specs [] = {
|
||||
{ &m_boolean_cva, &m_boolean_layera },
|
||||
{ &m_boolean_cvb, &m_boolean_layerb },
|
||||
{ &m_boolean_cvr, &m_boolean_layerr }
|
||||
};
|
||||
|
||||
for (unsigned int i = 0; i < sizeof (specs) / sizeof (specs[0]); ++i) {
|
||||
|
||||
int &cv = *(specs[i].cv);
|
||||
int &layer = *(specs[i].layer);
|
||||
|
||||
if (cv >= int (mp_view->cellviews ())) {
|
||||
cv = -1;
|
||||
}
|
||||
|
||||
int index = mp_view->active_cellview_index ();
|
||||
if (cv < 0) {
|
||||
cv = index;
|
||||
}
|
||||
|
||||
if (cv < 0 || ! mp_view->cellview (cv)->layout ().is_valid_layer ((unsigned int) layer)) {
|
||||
layer = -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
lay::BooleanOptionsDialog dialog (mp_view);
|
||||
if (dialog.exec_dialog (mp_view, m_boolean_cva, m_boolean_layera, m_boolean_cvb, m_boolean_layerb, m_boolean_cvr, m_boolean_layerr, m_boolean_mode, m_boolean_hier_mode, m_boolean_mincoh)) {
|
||||
|
||||
mp_view->cancel ();
|
||||
|
||||
bool supports_undo = true;
|
||||
|
||||
if (db::transactions_enabled ()) {
|
||||
|
||||
lay::TipDialog td (QApplication::activeWindow (),
|
||||
tl::to_string (QObject::tr ("Undo buffering for the following operation can be memory and time consuming.\nChoose \"Yes\" to use undo buffering or \"No\" for no undo buffering. Warning: in the latter case, the undo history will be lost.\n\nChoose undo buffering?")),
|
||||
"boolean-undo-buffering",
|
||||
lay::TipDialog::yesnocancel_buttons);
|
||||
|
||||
lay::TipDialog::button_type button = lay::TipDialog::null_button;
|
||||
td.exec_dialog (button);
|
||||
if (button == lay::TipDialog::cancel_button) {
|
||||
return;
|
||||
}
|
||||
|
||||
supports_undo = (button == lay::TipDialog::yes_button);
|
||||
|
||||
} else {
|
||||
supports_undo = false;
|
||||
}
|
||||
|
||||
if (mp_view->manager ()) {
|
||||
if (! supports_undo) {
|
||||
mp_view->manager ()->clear ();
|
||||
} else {
|
||||
mp_view->manager ()->transaction (tl::to_string (QObject::tr ("Boolean operation")));
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
db::BooleanOp::BoolOp op_mode;
|
||||
switch (m_boolean_mode) {
|
||||
default:
|
||||
op_mode = db::BooleanOp::Or;
|
||||
break;
|
||||
case 1:
|
||||
op_mode = db::BooleanOp::And;
|
||||
break;
|
||||
case 2:
|
||||
op_mode = db::BooleanOp::ANotB;
|
||||
break;
|
||||
case 3:
|
||||
op_mode = db::BooleanOp::BNotA;
|
||||
break;
|
||||
case 4:
|
||||
op_mode = db::BooleanOp::Xor;
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_boolean_hier_mode == 0) {
|
||||
|
||||
// flat mode
|
||||
db::ShapeProcessor p (true);
|
||||
p.boolean (mp_view->cellview (m_boolean_cva)->layout (), *mp_view->cellview (m_boolean_cva).cell (), m_boolean_layera,
|
||||
mp_view->cellview (m_boolean_cvb)->layout (), *mp_view->cellview (m_boolean_cvb).cell (), m_boolean_layerb,
|
||||
mp_view->cellview (m_boolean_cvr).cell ()->shapes (m_boolean_layerr), op_mode, true, true, m_boolean_mincoh);
|
||||
|
||||
// clear the result layer for all called cells in flat mode
|
||||
std::set<db::cell_index_type> called_cells;
|
||||
mp_view->cellview (m_boolean_cvr).cell ()->collect_called_cells (called_cells);
|
||||
for (std::set<db::cell_index_type>::const_iterator c = called_cells.begin (); c != called_cells.end (); ++c) {
|
||||
mp_view->cellview (m_boolean_cvr)->layout ().cell (*c).shapes (m_boolean_layerr).clear ();
|
||||
}
|
||||
|
||||
} else if (m_boolean_hier_mode == 1) {
|
||||
|
||||
// top cell only mode
|
||||
db::ShapeProcessor p (true);
|
||||
p.boolean (mp_view->cellview (m_boolean_cva)->layout (), *mp_view->cellview (m_boolean_cva).cell (), m_boolean_layera,
|
||||
mp_view->cellview (m_boolean_cvb)->layout (), *mp_view->cellview (m_boolean_cvb).cell (), m_boolean_layerb,
|
||||
mp_view->cellview (m_boolean_cvr).cell ()->shapes (m_boolean_layerr), op_mode, false, true, m_boolean_mincoh);
|
||||
|
||||
} else if (m_boolean_hier_mode == 2) {
|
||||
|
||||
// subcells cell by cell
|
||||
std::set<db::cell_index_type> called_cells;
|
||||
mp_view->cellview (m_boolean_cva).cell ()->collect_called_cells (called_cells);
|
||||
called_cells.insert (mp_view->cellview (m_boolean_cva).cell_index ());
|
||||
|
||||
db::ShapeProcessor p (true);
|
||||
db::Layout &layout = mp_view->cellview (m_boolean_cva)->layout ();
|
||||
for (std::set<db::cell_index_type>::const_iterator c = called_cells.begin (); c != called_cells.end (); ++c) {
|
||||
db::Cell &cell = layout.cell (*c);
|
||||
p.boolean (layout, cell, m_boolean_layera,
|
||||
layout, cell, m_boolean_layerb,
|
||||
cell.shapes (m_boolean_layerr), op_mode, false, true, m_boolean_mincoh);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (supports_undo && mp_view->manager ()) {
|
||||
mp_view->manager ()->commit ();
|
||||
}
|
||||
|
||||
} catch (...) {
|
||||
if (supports_undo && mp_view->manager ()) {
|
||||
mp_view->manager ()->commit ();
|
||||
}
|
||||
throw;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void merge ()
|
||||
{
|
||||
struct { int *cv; int *layer; } specs [] = {
|
||||
{ &m_boolean_cva, &m_boolean_layera },
|
||||
{ &m_boolean_cvr, &m_boolean_layerr }
|
||||
};
|
||||
|
||||
for (unsigned int i = 0; i < sizeof (specs) / sizeof (specs[0]); ++i) {
|
||||
|
||||
int &cv = *(specs[i].cv);
|
||||
int &layer = *(specs[i].layer);
|
||||
|
||||
if (cv >= int (mp_view->cellviews ())) {
|
||||
cv = -1;
|
||||
}
|
||||
|
||||
int index = mp_view->active_cellview_index ();
|
||||
if (cv < 0) {
|
||||
cv = index;
|
||||
}
|
||||
|
||||
if (cv < 0 || ! mp_view->cellview (cv)->layout ().is_valid_layer ((unsigned int) layer)) {
|
||||
layer = -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
lay::MergeOptionsDialog dialog (mp_view);
|
||||
if (dialog.exec_dialog (mp_view, m_boolean_cva, m_boolean_layera, m_boolean_cvr, m_boolean_layerr, m_boolean_minwc, m_boolean_hier_mode, m_boolean_mincoh)) {
|
||||
|
||||
mp_view->cancel ();
|
||||
|
||||
bool supports_undo = true;
|
||||
|
||||
if (db::transactions_enabled ()) {
|
||||
|
||||
lay::TipDialog td (QApplication::activeWindow (),
|
||||
tl::to_string (QObject::tr ("Undo buffering for the following operation can be memory and time consuming.\nChoose \"Yes\" to use undo buffering or \"No\" for no undo buffering. Warning: in the latter case, the undo history will be lost.\n\nChoose undo buffering?")),
|
||||
"merge-undo-buffering",
|
||||
lay::TipDialog::yesnocancel_buttons);
|
||||
|
||||
lay::TipDialog::button_type button = lay::TipDialog::null_button;
|
||||
td.exec_dialog (button);
|
||||
if (button == lay::TipDialog::cancel_button) {
|
||||
return;
|
||||
}
|
||||
|
||||
supports_undo = (button == lay::TipDialog::yes_button);
|
||||
|
||||
} else {
|
||||
supports_undo = false;
|
||||
}
|
||||
|
||||
if (mp_view->manager ()) {
|
||||
if (! supports_undo) {
|
||||
mp_view->manager ()->clear ();
|
||||
} else {
|
||||
mp_view->manager ()->transaction (tl::to_string (QObject::tr ("Merge operation")));
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
if (m_boolean_hier_mode == 0) {
|
||||
|
||||
// flat mode
|
||||
db::ShapeProcessor p (true);
|
||||
p.merge (mp_view->cellview (m_boolean_cva)->layout (), *mp_view->cellview (m_boolean_cva).cell (), m_boolean_layera,
|
||||
mp_view->cellview (m_boolean_cvr).cell ()->shapes (m_boolean_layerr), true, m_boolean_minwc, true, m_boolean_mincoh);
|
||||
|
||||
// clear the result layer for all called cells in flat mode
|
||||
std::set<db::cell_index_type> called_cells;
|
||||
mp_view->cellview (m_boolean_cvr).cell ()->collect_called_cells (called_cells);
|
||||
for (std::set<db::cell_index_type>::const_iterator c = called_cells.begin (); c != called_cells.end (); ++c) {
|
||||
mp_view->cellview (m_boolean_cvr)->layout ().cell (*c).shapes (m_boolean_layerr).clear ();
|
||||
}
|
||||
|
||||
} else if (m_boolean_hier_mode == 1) {
|
||||
|
||||
// top cell only mode
|
||||
db::ShapeProcessor p (true);
|
||||
p.merge (mp_view->cellview (m_boolean_cva)->layout (), *mp_view->cellview (m_boolean_cva).cell (), m_boolean_layera,
|
||||
mp_view->cellview (m_boolean_cvr).cell ()->shapes (m_boolean_layerr), false, m_boolean_minwc, true, m_boolean_mincoh);
|
||||
|
||||
} else if (m_boolean_hier_mode == 2) {
|
||||
|
||||
// subcells cell by cell
|
||||
std::set<db::cell_index_type> called_cells;
|
||||
mp_view->cellview (m_boolean_cva).cell ()->collect_called_cells (called_cells);
|
||||
called_cells.insert (mp_view->cellview (m_boolean_cva).cell_index ());
|
||||
|
||||
db::ShapeProcessor p (true);
|
||||
db::Layout &layout = mp_view->cellview (m_boolean_cva)->layout ();
|
||||
for (std::set<db::cell_index_type>::const_iterator c = called_cells.begin (); c != called_cells.end (); ++c) {
|
||||
db::Cell &cell = layout.cell (*c);
|
||||
p.merge (layout, cell, m_boolean_layera,
|
||||
cell.shapes (m_boolean_layerr), false, m_boolean_minwc, true, m_boolean_mincoh);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (supports_undo && mp_view->manager ()) {
|
||||
mp_view->manager ()->commit ();
|
||||
}
|
||||
|
||||
} catch (...) {
|
||||
if (supports_undo && mp_view->manager ()) {
|
||||
mp_view->manager ()->commit ();
|
||||
}
|
||||
throw;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void size ()
|
||||
{
|
||||
struct { int *cv; int *layer; } specs [] = {
|
||||
{ &m_boolean_cva, &m_boolean_layera },
|
||||
{ &m_boolean_cvr, &m_boolean_layerr }
|
||||
};
|
||||
|
||||
for (unsigned int i = 0; i < sizeof (specs) / sizeof (specs[0]); ++i) {
|
||||
|
||||
int &cv = *(specs[i].cv);
|
||||
int &layer = *(specs[i].layer);
|
||||
|
||||
if (cv >= int (mp_view->cellviews ())) {
|
||||
cv = -1;
|
||||
}
|
||||
|
||||
int index = mp_view->active_cellview_index ();
|
||||
if (cv < 0) {
|
||||
cv = index;
|
||||
}
|
||||
|
||||
if (cv < 0 || ! mp_view->cellview (cv)->layout ().is_valid_layer ((unsigned int) layer)) {
|
||||
layer = -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
lay::SizingOptionsDialog dialog (mp_view);
|
||||
if (dialog.exec_dialog (mp_view, m_boolean_cva, m_boolean_layera, m_boolean_cvr, m_boolean_layerr, m_boolean_sizex, m_boolean_sizey, m_boolean_size_mode, m_boolean_hier_mode, m_boolean_mincoh)) {
|
||||
|
||||
mp_view->cancel ();
|
||||
|
||||
bool supports_undo = true;
|
||||
|
||||
if (db::transactions_enabled ()) {
|
||||
|
||||
lay::TipDialog td (QApplication::activeWindow (),
|
||||
tl::to_string (QObject::tr ("Undo buffering for the following operation can be memory and time consuming.\nChoose \"Yes\" to use undo buffering or \"No\" for no undo buffering. Warning: in the latter case, the undo history will be lost.\n\nChoose undo buffering?")),
|
||||
"size-undo-buffering",
|
||||
lay::TipDialog::yesnocancel_buttons);
|
||||
|
||||
lay::TipDialog::button_type button = lay::TipDialog::null_button;
|
||||
td.exec_dialog (button);
|
||||
if (button == lay::TipDialog::cancel_button) {
|
||||
return;
|
||||
}
|
||||
|
||||
supports_undo = (button == lay::TipDialog::yes_button);
|
||||
|
||||
} else {
|
||||
supports_undo = false;
|
||||
}
|
||||
|
||||
db::Coord dx_int, dy_int;
|
||||
dx_int = db::coord_traits<db::Coord>::rounded (m_boolean_sizex / mp_view->cellview (m_boolean_cva)->layout ().dbu ());
|
||||
dy_int = db::coord_traits<db::Coord>::rounded (m_boolean_sizey / mp_view->cellview (m_boolean_cva)->layout ().dbu ());
|
||||
|
||||
if (mp_view->manager ()) {
|
||||
if (! supports_undo) {
|
||||
mp_view->manager ()->clear ();
|
||||
} else {
|
||||
mp_view->manager ()->transaction (tl::to_string (QObject::tr ("Sizing operation")));
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
if (m_boolean_hier_mode == 0) {
|
||||
|
||||
// flat mode
|
||||
db::ShapeProcessor p (true);
|
||||
p.size (mp_view->cellview (m_boolean_cva)->layout (), *mp_view->cellview (m_boolean_cva).cell (), m_boolean_layera,
|
||||
mp_view->cellview (m_boolean_cvr).cell ()->shapes (m_boolean_layerr), dx_int, dy_int, m_boolean_size_mode, true, true, m_boolean_mincoh);
|
||||
|
||||
// clear the result layer for all called cells in flat mode
|
||||
std::set<db::cell_index_type> called_cells;
|
||||
mp_view->cellview (m_boolean_cvr).cell ()->collect_called_cells (called_cells);
|
||||
for (std::set<db::cell_index_type>::const_iterator c = called_cells.begin (); c != called_cells.end (); ++c) {
|
||||
mp_view->cellview (m_boolean_cvr)->layout ().cell (*c).shapes (m_boolean_layerr).clear ();
|
||||
}
|
||||
|
||||
} else if (m_boolean_hier_mode == 1) {
|
||||
|
||||
// top cell only mode
|
||||
db::ShapeProcessor p (true);
|
||||
p.size (mp_view->cellview (m_boolean_cva)->layout (), *mp_view->cellview (m_boolean_cva).cell (), m_boolean_layera,
|
||||
mp_view->cellview (m_boolean_cvr).cell ()->shapes (m_boolean_layerr), dx_int, dy_int, m_boolean_size_mode, false, true, m_boolean_mincoh);
|
||||
|
||||
} else if (m_boolean_hier_mode == 2) {
|
||||
|
||||
// subcells cell by cell
|
||||
std::set<db::cell_index_type> called_cells;
|
||||
mp_view->cellview (m_boolean_cva).cell ()->collect_called_cells (called_cells);
|
||||
called_cells.insert (mp_view->cellview (m_boolean_cva).cell_index ());
|
||||
|
||||
db::ShapeProcessor p (true);
|
||||
db::Layout &layout = mp_view->cellview (m_boolean_cva)->layout ();
|
||||
for (std::set<db::cell_index_type>::const_iterator c = called_cells.begin (); c != called_cells.end (); ++c) {
|
||||
db::Cell &cell = layout.cell (*c);
|
||||
p.size (layout, cell, m_boolean_layera,
|
||||
cell.shapes (m_boolean_layerr), dx_int, dy_int, m_boolean_size_mode, false, true, m_boolean_mincoh);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (supports_undo && mp_view->manager ()) {
|
||||
mp_view->manager ()->commit ();
|
||||
}
|
||||
|
||||
} catch (...) {
|
||||
if (supports_undo && mp_view->manager ()) {
|
||||
mp_view->manager ()->commit ();
|
||||
}
|
||||
throw;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
lay::LayoutView *mp_view;
|
||||
int m_boolean_cva, m_boolean_cvb, m_boolean_cvr;
|
||||
int m_boolean_layera, m_boolean_layerb, m_boolean_layerr;
|
||||
int m_boolean_hier_mode, m_boolean_mode;
|
||||
bool m_boolean_mincoh;
|
||||
unsigned int m_boolean_minwc;
|
||||
double m_boolean_sizex, m_boolean_sizey;
|
||||
unsigned int m_boolean_size_mode;
|
||||
};
|
||||
|
||||
class BooleanOperationsPluginDeclaration
|
||||
: public lay::PluginDeclaration
|
||||
{
|
||||
public:
|
||||
BooleanOperationsPluginDeclaration ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
virtual void get_options (std::vector < std::pair<std::string, std::string> > & /*options*/) const
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
virtual lay::ConfigPage *config_page (QWidget * /*parent*/, std::string & /*title*/) const
|
||||
{
|
||||
// .. nothing yet ..
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void get_menu_entries (std::vector<lay::MenuEntry> &menu_entries) const
|
||||
{
|
||||
lay::PluginDeclaration::get_menu_entries (menu_entries);
|
||||
menu_entries.push_back (lay::MenuEntry ("ops_group", "edit_menu.layer_menu.end"));
|
||||
menu_entries.push_back (lay::MenuEntry ("lay::boolean", "boolean:edit:edit_mode", "edit_menu.layer_menu.end", tl::to_string (QObject::tr ("Boolean Operations"))));
|
||||
menu_entries.push_back (lay::MenuEntry ("lay::merge", "merge:edit:edit_mode", "edit_menu.layer_menu.end", tl::to_string (QObject::tr ("Merge"))));
|
||||
menu_entries.push_back (lay::MenuEntry ("lay::size", "size:edit:edit_mode", "edit_menu.layer_menu.end", tl::to_string (QObject::tr ("Size"))));
|
||||
}
|
||||
|
||||
virtual bool configure (const std::string & /*name*/, const std::string & /*value*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void config_finalize ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
lay::Plugin *create_plugin (db::Manager *, lay::PluginRoot *root, lay::LayoutView *view) const
|
||||
{
|
||||
return new BooleanOperationsPlugin (root, view);
|
||||
}
|
||||
};
|
||||
|
||||
static tl::RegisteredClass<lay::PluginDeclaration> config_decl (new lay::BooleanOperationsPluginDeclaration (), 3010, "lay::BooleanOperationsPlugin");
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
|
||||
TARGET = bool
|
||||
DESTDIR = $$OUT_PWD/../../../../lay_plugins
|
||||
|
||||
include($$PWD/../../../lay_plugin.pri)
|
||||
|
||||
HEADERS = \
|
||||
layBooleanOperationsDialogs.h
|
||||
|
||||
SOURCES = \
|
||||
layBooleanOperationsDialogs.cc \
|
||||
layBooleanOperationsPlugin.cc
|
||||
|
||||
FORMS = \
|
||||
BooleanOptionsDialog.ui \
|
||||
SizingOptionsDialog.ui \
|
||||
MergeOptionsDialog.ui \
|
||||
@@ -0,0 +1,5 @@
|
||||
|
||||
TEMPLATE = subdirs
|
||||
|
||||
SUBDIRS = lay_plugin
|
||||
|
||||
@@ -0,0 +1,217 @@
|
||||
<ui version="4.0" >
|
||||
<class>DiffToolDialog</class>
|
||||
<widget class="QDialog" name="DiffToolDialog" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>498</width>
|
||||
<height>404</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>Diff Tool</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox" >
|
||||
<property name="title" >
|
||||
<string>Input</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0" >
|
||||
<widget class="QLabel" name="label" >
|
||||
<property name="text" >
|
||||
<string>Layout A </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" >
|
||||
<widget class="QLabel" name="label_2" >
|
||||
<property name="text" >
|
||||
<string>Layout B</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" >
|
||||
<widget class="lay::CellViewSelectionComboBox" name="layouta" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy>
|
||||
<hsizetype>7</hsizetype>
|
||||
<vsizetype>5</vsizetype>
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy" >
|
||||
<enum>QComboBox::AdjustToContentsOnFirstShow</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" >
|
||||
<widget class="lay::CellViewSelectionComboBox" name="layoutb" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy>
|
||||
<hsizetype>7</hsizetype>
|
||||
<vsizetype>5</vsizetype>
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy" >
|
||||
<enum>QComboBox::AdjustToContentsOnFirstShow</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2" >
|
||||
<property name="title" >
|
||||
<string>Options</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="smart_cbx" >
|
||||
<property name="text" >
|
||||
<string>Don't use names to match cells (use geometrical properties)</string>
|
||||
</property>
|
||||
<property name="checked" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="xor_cbx" >
|
||||
<property name="text" >
|
||||
<string>Run XOR on differences</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="summarize_cbx" >
|
||||
<property name="text" >
|
||||
<string>Summarize missing layers</string>
|
||||
</property>
|
||||
<property name="checked" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="detailed_cbx" >
|
||||
<property name="text" >
|
||||
<string>Detailed information</string>
|
||||
</property>
|
||||
<property name="checked" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="expand_cell_arrays_cbx" >
|
||||
<property name="text" >
|
||||
<string>Expand cell arrays (compare single instance by instance)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="exact_cbx" >
|
||||
<property name="text" >
|
||||
<string>Exact compare (includes properties, text orientation and similar)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>472</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons" >
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>lay::CellViewSelectionComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>layWidgets.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>buttonBox</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>DiffToolDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>DiffToolDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -0,0 +1,116 @@
|
||||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2018 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 "layDiffToolDialog.h"
|
||||
|
||||
#include "layPlugin.h"
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
||||
class DiffPlugin
|
||||
: public lay::Plugin
|
||||
{
|
||||
public:
|
||||
DiffPlugin (Plugin *parent, lay::LayoutView *view)
|
||||
: lay::Plugin (parent), mp_view (view)
|
||||
{
|
||||
mp_dialog = new lay::DiffToolDialog (0);
|
||||
}
|
||||
|
||||
~DiffPlugin ()
|
||||
{
|
||||
delete mp_dialog;
|
||||
mp_dialog = 0;
|
||||
}
|
||||
|
||||
void menu_activated (const std::string &symbol)
|
||||
{
|
||||
if (symbol == "lay::diff_tool") {
|
||||
|
||||
if (mp_dialog->exec_dialog (mp_view)) {
|
||||
|
||||
// ... implementation is in layDiffToolDialog.cc ...
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
lay::LayoutView *mp_view;
|
||||
lay::DiffToolDialog *mp_dialog;
|
||||
};
|
||||
|
||||
class DiffPluginDeclaration
|
||||
: public lay::PluginDeclaration
|
||||
{
|
||||
public:
|
||||
DiffPluginDeclaration ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
virtual void get_options (std::vector < std::pair<std::string, std::string> > &options) const
|
||||
{
|
||||
options.push_back (std::pair<std::string, std::string> (cfg_diff_run_xor, "false"));
|
||||
options.push_back (std::pair<std::string, std::string> (cfg_diff_detailed, "false"));
|
||||
options.push_back (std::pair<std::string, std::string> (cfg_diff_summarize, "false"));
|
||||
options.push_back (std::pair<std::string, std::string> (cfg_diff_expand_cell_arrays, "false"));
|
||||
options.push_back (std::pair<std::string, std::string> (cfg_diff_exact, "false"));
|
||||
}
|
||||
|
||||
virtual lay::ConfigPage *config_page (QWidget * /*parent*/, std::string & /*title*/) const
|
||||
{
|
||||
// .. nothing yet ..
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void get_menu_entries (std::vector<lay::MenuEntry> &menu_entries) const
|
||||
{
|
||||
lay::PluginDeclaration::get_menu_entries (menu_entries);
|
||||
menu_entries.push_back (lay::MenuEntry ("lay::diff_tool", "diff_tool:edit", "tools_menu.post_verification_group", tl::to_string (QObject::tr ("Diff Tool"))));
|
||||
}
|
||||
|
||||
virtual bool configure (const std::string & /*name*/, const std::string & /*value*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void config_finalize ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
lay::Plugin *create_plugin (db::Manager *, lay::PluginRoot *root, lay::LayoutView *view) const
|
||||
{
|
||||
return new DiffPlugin (root, view);
|
||||
}
|
||||
};
|
||||
|
||||
static tl::RegisteredClass<lay::PluginDeclaration> config_decl (new lay::DiffPluginDeclaration (), 3001, "lay::DiffPlugin");
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,766 @@
|
||||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2018 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 "layDiffToolDialog.h"
|
||||
#include "rdb.h"
|
||||
#include "dbLayoutDiff.h"
|
||||
#include "dbRecursiveShapeIterator.h"
|
||||
#include "dbShapeProcessor.h"
|
||||
#include "tlTimer.h"
|
||||
#include "tlProgress.h"
|
||||
#include "layCellView.h"
|
||||
#include "layLayoutView.h"
|
||||
#include "tlExceptions.h"
|
||||
|
||||
#include "ui_DiffToolDialog.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
||||
std::string cfg_diff_run_xor ("diff-run-xor");
|
||||
std::string cfg_diff_detailed ("diff-detailed");
|
||||
std::string cfg_diff_smart ("diff-smart");
|
||||
std::string cfg_diff_summarize ("diff-summarize");
|
||||
std::string cfg_diff_expand_cell_arrays ("diff-expand-cell-arrays");
|
||||
std::string cfg_diff_exact ("diff-exact");
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// RdbDifferenceReceiver definition
|
||||
|
||||
class RdbDifferenceReceiver
|
||||
: public db::DifferenceReceiver
|
||||
{
|
||||
public:
|
||||
RdbDifferenceReceiver (const db::Layout &la, const db::Layout &lb, rdb::Database *rdb, bool detailed, bool with_properties, bool run_xor);
|
||||
|
||||
void dbu_differs (double dbu_a, double dbu_b);
|
||||
void layer_in_a_only (const db::LayerProperties &la);
|
||||
void layer_in_b_only (const db::LayerProperties &lb);
|
||||
void layer_name_differs (const db::LayerProperties &la, const db::LayerProperties &lb);
|
||||
void cell_in_a_only (const std::string &cellname, db::cell_index_type ci);
|
||||
void cell_in_b_only (const std::string &cellname, db::cell_index_type ci);
|
||||
void cell_name_differs (const std::string &cellname_a, db::cell_index_type cia, const std::string &cellname_b, db::cell_index_type cib);
|
||||
void bbox_differs (const db::Box &ba, const db::Box &bb);
|
||||
void begin_cell (const std::string &cellname, db::cell_index_type cia, db::cell_index_type cib);
|
||||
void begin_inst_differences ();
|
||||
void instances_in_a (const std::vector <db::CellInstArrayWithProperties> &insts_a, const std::vector <std::string> &cell_names, const db::PropertiesRepository &props);
|
||||
void instances_in_b (const std::vector <db::CellInstArrayWithProperties> &insts_b, const std::vector <std::string> &cell_names, const db::PropertiesRepository &props);
|
||||
void instances_in_a_only (const std::vector <db::CellInstArrayWithProperties> &anotb, const db::Layout &a);
|
||||
void instances_in_b_only (const std::vector <db::CellInstArrayWithProperties> &bnota, const db::Layout &b);
|
||||
void begin_layer (const db::LayerProperties &layer, unsigned int layer_index_a, bool is_valid_a, unsigned int layer_index_b, bool is_valid_b);
|
||||
void end_layer ();
|
||||
void per_layer_bbox_differs (const db::Box &ba, const db::Box &bb);
|
||||
void begin_polygon_differences ();
|
||||
void detailed_diff (const db::PropertiesRepository &pr, const std::vector <std::pair <db::Polygon, db::properties_id_type> > &a, const std::vector <std::pair <db::Polygon, db::properties_id_type> > &b);
|
||||
void begin_path_differences ();
|
||||
void detailed_diff (const db::PropertiesRepository &pr, const std::vector <std::pair <db::Path, db::properties_id_type> > &a, const std::vector <std::pair <db::Path, db::properties_id_type> > &b);
|
||||
void begin_box_differences ();
|
||||
void detailed_diff (const db::PropertiesRepository &pr, const std::vector <std::pair <db::Box, db::properties_id_type> > &a, const std::vector <std::pair <db::Box, db::properties_id_type> > &b);
|
||||
void begin_edge_differences ();
|
||||
void detailed_diff (const db::PropertiesRepository &pr, const std::vector <std::pair <db::Edge, db::properties_id_type> > &a, const std::vector <std::pair <db::Edge, db::properties_id_type> > &b);
|
||||
void begin_text_differences ();
|
||||
void detailed_diff (const db::PropertiesRepository &pr, const std::vector <std::pair <db::Text, db::properties_id_type> > &a, const std::vector <std::pair <db::Text, db::properties_id_type> > &b);
|
||||
|
||||
private:
|
||||
const db::Layout *mp_layout_a;
|
||||
const db::Layout *mp_layout_b;
|
||||
rdb::Database *mp_rdb;
|
||||
rdb::Cell *mp_cell;
|
||||
rdb::Cell *mp_topcell;
|
||||
rdb::Category *mp_general_cat;
|
||||
rdb::Category *mp_a_only_cat;
|
||||
rdb::Category *mp_b_only_cat;
|
||||
std::vector<rdb::Category *> mp_a_only_per_layer_cat;
|
||||
std::vector<rdb::Category *> mp_b_only_per_layer_cat;
|
||||
std::map<std::pair<int, int>, rdb::Category *> mp_xor_cat;
|
||||
std::vector<db::CellInstArrayWithProperties> m_insts_a, m_insts_b;
|
||||
|
||||
std::string m_cellname;
|
||||
db::LayerProperties m_layer;
|
||||
unsigned int m_layer_index_a, m_layer_index_b;
|
||||
bool m_is_valid_layer_index_a, m_is_valid_layer_index_b;
|
||||
bool m_diffs_reported;
|
||||
bool m_with_properties;
|
||||
bool m_detailed;
|
||||
bool m_run_xor;
|
||||
db::ShapeProcessor m_ep;
|
||||
size_t m_obj_index;
|
||||
|
||||
void produce_cell_inst (const db::CellInstArrayWithProperties &ci, const db::Layout *layout, const rdb::Category *cat);
|
||||
template <class SH> void produce_diffs_for_xor (const db::PropertiesRepository &pr, const std::vector <std::pair <SH, db::properties_id_type> > &a, const std::vector <std::pair <SH, db::properties_id_type> > &b, double dbu_a, db::Shapes &shapes);
|
||||
template <class SH> void produce_diffs (const db::PropertiesRepository &pr, const std::vector <std::pair <SH, db::properties_id_type> > &a, const std::vector <std::pair <SH, db::properties_id_type> > &b, double dbu_a, const rdb::Category *cat);
|
||||
template <class SH> void shape_diffs (const db::PropertiesRepository &pr, const std::vector <std::pair <SH, db::properties_id_type> > &a, const std::vector <std::pair <SH, db::properties_id_type> > &b);
|
||||
void shape_diffs_found ();
|
||||
};
|
||||
|
||||
RdbDifferenceReceiver::RdbDifferenceReceiver (const db::Layout &layout_a, const db::Layout &layout_b, rdb::Database *rdb, bool detailed, bool with_properties, bool run_xor)
|
||||
: mp_layout_a (&layout_a),
|
||||
mp_layout_b (&layout_b),
|
||||
mp_rdb (rdb),
|
||||
mp_cell (0),
|
||||
m_cellname (),
|
||||
m_layer (),
|
||||
m_layer_index_a (0),
|
||||
m_layer_index_b (0),
|
||||
m_is_valid_layer_index_a (false),
|
||||
m_is_valid_layer_index_b (false),
|
||||
m_diffs_reported (false),
|
||||
m_with_properties (with_properties),
|
||||
m_detailed (detailed),
|
||||
m_run_xor (run_xor)
|
||||
{
|
||||
mp_topcell = rdb->create_cell ("" /*dummy*/);
|
||||
mp_general_cat = rdb->create_category ("Summary");
|
||||
mp_general_cat->set_description (tl::to_string (QObject::tr ("Summary of Differences")));
|
||||
m_obj_index = 0;
|
||||
|
||||
std::map<db::LayerProperties, std::pair<int, int>, db::LPLogicalLessFunc> layers;
|
||||
for (db::Layout::layer_iterator l = layout_a.begin_layers (); l != layout_a.end_layers (); ++l) {
|
||||
layers.insert (std::make_pair (*(*l).second, std::make_pair (-1, -1))).first->second.first = (*l).first;
|
||||
}
|
||||
for (db::Layout::layer_iterator l = layout_b.begin_layers (); l != layout_b.end_layers (); ++l) {
|
||||
layers.insert (std::make_pair (*(*l).second, std::make_pair (-1, -1))).first->second.second = (*l).first;
|
||||
}
|
||||
|
||||
if (detailed) {
|
||||
|
||||
rdb::Category *instances_cat = rdb->create_category ("Instances");
|
||||
instances_cat->set_description (tl::to_string (QObject::tr ("Differences in instances")));
|
||||
|
||||
mp_a_only_cat = rdb->create_category (instances_cat, "A");
|
||||
mp_a_only_cat->set_description (tl::to_string (QObject::tr ("Instances in A but not in B")));
|
||||
|
||||
mp_b_only_cat = rdb->create_category (instances_cat, "B");
|
||||
mp_b_only_cat->set_description (tl::to_string (QObject::tr ("Instances in B but not in A")));
|
||||
|
||||
for (std::map<db::LayerProperties, std::pair<int, int>, db::LPLogicalLessFunc>::const_iterator l = layers.begin (); l != layers.end (); ++l) {
|
||||
|
||||
while ((int) mp_a_only_per_layer_cat.size () <= l->second.first) {
|
||||
mp_a_only_per_layer_cat.push_back (0);
|
||||
}
|
||||
while ((int) mp_b_only_per_layer_cat.size () <= l->second.second) {
|
||||
mp_b_only_per_layer_cat.push_back (0);
|
||||
}
|
||||
|
||||
rdb::Category *layer_cat = rdb->create_category (l->first.to_string ());
|
||||
layer_cat->set_description (tl::to_string (QObject::tr ("Differences in layer")) + " " + l->first.to_string ());
|
||||
|
||||
if (l->second.first >= 0) {
|
||||
mp_a_only_per_layer_cat [(unsigned int) l->second.first] = rdb->create_category (layer_cat, "A");
|
||||
mp_a_only_per_layer_cat [(unsigned int) l->second.first]->set_description (tl::to_string (QObject::tr ("Shapes in A but not in B, on Layer ")) + l->first.to_string ());
|
||||
}
|
||||
|
||||
if (l->second.second >= 0) {
|
||||
mp_b_only_per_layer_cat [(unsigned int) l->second.second] = rdb->create_category (layer_cat, "B");
|
||||
mp_b_only_per_layer_cat [(unsigned int) l->second.second]->set_description (tl::to_string (QObject::tr ("Shapes in B but not in A, on Layer ")) + l->first.to_string ());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
mp_a_only_cat = 0;
|
||||
mp_b_only_cat = 0;
|
||||
}
|
||||
|
||||
if (run_xor) {
|
||||
|
||||
for (std::map<db::LayerProperties, std::pair<int, int>, db::LPLogicalLessFunc>::const_iterator l = layers.begin (); l != layers.end (); ++l) {
|
||||
|
||||
rdb::Category *cat = rdb->create_category (std::string ("XOR ") + l->first.to_string ());
|
||||
cat->set_description (tl::to_string (QObject::tr ("Geometrical differences on layer")) + " " + l->first.to_string ());
|
||||
mp_xor_cat [l->second] = cat;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
add_property_text (rdb::Item *item, const db::PropertiesRepository &pr, db::properties_id_type prop_id)
|
||||
{
|
||||
if (prop_id != 0) {
|
||||
const db::PropertiesRepository::properties_set &p = pr.properties (prop_id);
|
||||
for (db::PropertiesRepository::properties_set::const_iterator pp = p.begin (); pp != p.end (); ++pp) {
|
||||
const tl::Variant &name = pr.prop_name (pp->first);
|
||||
std::string r = std::string ("property: ") + name.to_string () + " = " + pp->second.to_string ();
|
||||
item->add_value (r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RdbDifferenceReceiver::produce_cell_inst (const db::CellInstArrayWithProperties &ci, const db::Layout *layout, const rdb::Category *cat)
|
||||
{
|
||||
db::box_convert <db::CellInstArrayWithProperties> bc (*layout);
|
||||
|
||||
rdb::Item *item = mp_rdb->create_item (mp_cell->id (), cat->id ());
|
||||
|
||||
std::string r = "item: " + tl::sprintf (tl::to_string (QObject::tr ("instance: (%s) %s")), layout->cell_name (ci.object ().cell_index ()), ci.complex_trans ().to_string ());
|
||||
|
||||
db::Vector a, b;
|
||||
unsigned long amax, bmax;
|
||||
if (ci.is_regular_array (a, b, amax, bmax)) {
|
||||
r += tl::sprintf (" [a=%s, b=%s, na=%ld, nb=%ld]", a.to_string (), b.to_string (), amax, bmax);
|
||||
}
|
||||
|
||||
item->add_value (r);
|
||||
|
||||
db::Box box = bc (ci);
|
||||
item->add_value (box * layout->dbu ());
|
||||
|
||||
if (m_with_properties) {
|
||||
add_property_text (item, layout->properties_repository (), ci.properties_id ());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RdbDifferenceReceiver::dbu_differs (double dbu_a, double dbu_b)
|
||||
{
|
||||
rdb::Item *item = mp_rdb->create_item (mp_topcell->id (), mp_general_cat->id ());
|
||||
item->add_value (tl::sprintf (tl::to_string (QObject::tr ("Database units differ %g vs. %g")), dbu_a, dbu_b));
|
||||
}
|
||||
|
||||
void
|
||||
RdbDifferenceReceiver::layer_in_a_only (const db::LayerProperties &la)
|
||||
{
|
||||
rdb::Item *item = mp_rdb->create_item (mp_topcell->id (), mp_general_cat->id ());
|
||||
item->add_value (tl::sprintf (tl::to_string (QObject::tr ("Layer %s is not present in layout B, but in A")), la.to_string ()));
|
||||
}
|
||||
|
||||
void
|
||||
RdbDifferenceReceiver::layer_in_b_only (const db::LayerProperties &lb)
|
||||
{
|
||||
rdb::Item *item = mp_rdb->create_item (mp_topcell->id (), mp_general_cat->id ());
|
||||
item->add_value (tl::sprintf (tl::to_string (QObject::tr ("Layer %s is not present in layout A, but in B")), lb.to_string ()));
|
||||
}
|
||||
|
||||
void
|
||||
RdbDifferenceReceiver::layer_name_differs (const db::LayerProperties &la, const db::LayerProperties &lb)
|
||||
{
|
||||
rdb::Item *item = mp_rdb->create_item (mp_topcell->id (), mp_general_cat->id ());
|
||||
item->add_value (tl::sprintf (tl::to_string (QObject::tr ("Layer names differ between layout A and B for layer %d/%d: %s vs. %s")), la.layer, la.datatype, la.name, lb.name));
|
||||
}
|
||||
|
||||
void
|
||||
RdbDifferenceReceiver::cell_in_a_only (const std::string &cellname, db::cell_index_type /*ci*/)
|
||||
{
|
||||
rdb::Item *item = mp_rdb->create_item (mp_topcell->id (), mp_general_cat->id ());
|
||||
item->add_value (tl::sprintf (tl::to_string (QObject::tr ("Cell %s is not present in layout B, but in A")), cellname));
|
||||
}
|
||||
|
||||
void
|
||||
RdbDifferenceReceiver::cell_in_b_only (const std::string &cellname, db::cell_index_type /*ci*/)
|
||||
{
|
||||
rdb::Item *item = mp_rdb->create_item (mp_topcell->id (), mp_general_cat->id ());
|
||||
item->add_value (tl::sprintf (tl::to_string (QObject::tr ("Cell %s is not present in layout A, but in B")), cellname));
|
||||
}
|
||||
|
||||
void
|
||||
RdbDifferenceReceiver::cell_name_differs (const std::string &cellname_a, db::cell_index_type /*cia*/, const std::string &cellname_b, db::cell_index_type /*cib*/)
|
||||
{
|
||||
rdb::Item *item = mp_rdb->create_item (mp_topcell->id (), mp_general_cat->id ());
|
||||
item->add_value (tl::sprintf (tl::to_string (QObject::tr ("Cell %s in A is renamed to %s in B")), cellname_a, cellname_b));
|
||||
}
|
||||
|
||||
void
|
||||
RdbDifferenceReceiver::begin_cell (const std::string &cellname, db::cell_index_type /*cia*/, db::cell_index_type /*cib*/)
|
||||
{
|
||||
mp_cell = mp_rdb->create_cell (cellname);
|
||||
m_diffs_reported = false;
|
||||
|
||||
m_insts_a.clear ();
|
||||
m_insts_b.clear ();
|
||||
}
|
||||
|
||||
void
|
||||
RdbDifferenceReceiver::bbox_differs (const db::Box &ba, const db::Box &bb)
|
||||
{
|
||||
rdb::Item *item = mp_rdb->create_item (mp_cell->id (), mp_general_cat->id ());
|
||||
item->add_value (tl::sprintf (tl::to_string (QObject::tr ("Bounding boxes differ: %s (A) vs. %s (B)")), ba.to_string (), bb.to_string ()));
|
||||
}
|
||||
|
||||
void
|
||||
RdbDifferenceReceiver::begin_inst_differences ()
|
||||
{
|
||||
rdb::Item *item = mp_rdb->create_item (mp_cell->id (), mp_general_cat->id ());
|
||||
item->add_value (tl::to_string (QObject::tr ("Instances differ")));
|
||||
}
|
||||
|
||||
void
|
||||
RdbDifferenceReceiver::instances_in_a (const std::vector <db::CellInstArrayWithProperties> & /*insts_a*/, const std::vector <std::string> & /*cell_names*/, const db::PropertiesRepository & /*props*/)
|
||||
{
|
||||
// .. nothing ..
|
||||
}
|
||||
|
||||
void
|
||||
RdbDifferenceReceiver::instances_in_b (const std::vector <db::CellInstArrayWithProperties> & /*insts_b*/, const std::vector <std::string> & /*cell_names*/, const db::PropertiesRepository & /*props*/)
|
||||
{
|
||||
// .. nothing ..
|
||||
}
|
||||
|
||||
void
|
||||
RdbDifferenceReceiver::instances_in_a_only (const std::vector <db::CellInstArrayWithProperties> &anotb, const db::Layout & /*a*/)
|
||||
{
|
||||
if (m_detailed) {
|
||||
for (std::vector <db::CellInstArrayWithProperties>::const_iterator s = anotb.begin (); s != anotb.end (); ++s) {
|
||||
produce_cell_inst (*s, mp_layout_a, mp_a_only_cat);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_run_xor) {
|
||||
m_insts_a.insert (m_insts_a.end (), anotb.begin (), anotb.end ());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RdbDifferenceReceiver::instances_in_b_only (const std::vector <db::CellInstArrayWithProperties> &bnota, const db::Layout & /*b*/)
|
||||
{
|
||||
if (m_detailed) {
|
||||
for (std::vector <db::CellInstArrayWithProperties>::const_iterator s = bnota.begin (); s != bnota.end (); ++s) {
|
||||
produce_cell_inst (*s, mp_layout_b, mp_b_only_cat);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_run_xor) {
|
||||
m_insts_b.insert (m_insts_b.end (), bnota.begin (), bnota.end ());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RdbDifferenceReceiver::begin_layer (const db::LayerProperties &layer, unsigned int layer_index_a, bool is_valid_a, unsigned int layer_index_b, bool is_valid_b)
|
||||
{
|
||||
m_layer = layer;
|
||||
m_diffs_reported = false;
|
||||
m_layer_index_a = layer_index_a;
|
||||
m_is_valid_layer_index_a = is_valid_a;
|
||||
m_layer_index_b = layer_index_b;
|
||||
m_is_valid_layer_index_b = is_valid_b;
|
||||
|
||||
if (m_run_xor) {
|
||||
|
||||
m_obj_index = 0;
|
||||
|
||||
if (is_valid_a) {
|
||||
for (std::vector <db::CellInstArrayWithProperties>::const_iterator i = m_insts_a.begin (); i != m_insts_a.end (); ++i) {
|
||||
for (db::RecursiveShapeIterator shapes (*mp_layout_a, mp_layout_a->cell (i->object ().cell_index ()), m_layer_index_a); ! shapes.at_end (); ++shapes) {
|
||||
for (db::CellInstArray::iterator a = i->begin (); ! a.at_end (); ++a) {
|
||||
m_ep.insert (shapes.shape (), i->complex_trans (*a) * shapes.trans (), m_obj_index * 2);
|
||||
++m_obj_index;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_valid_b) {
|
||||
for (std::vector <db::CellInstArrayWithProperties>::const_iterator i = m_insts_b.begin (); i != m_insts_b.end (); ++i) {
|
||||
for (db::RecursiveShapeIterator shapes (*mp_layout_b, mp_layout_b->cell (i->object ().cell_index ()), m_layer_index_b); ! shapes.at_end (); ++shapes) {
|
||||
for (db::CellInstArray::iterator a = i->begin (); ! a.at_end (); ++a) {
|
||||
m_ep.insert (shapes.shape (), i->complex_trans (*a) * shapes.trans (), m_obj_index * 2 + 1);
|
||||
++m_obj_index;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RdbDifferenceReceiver::end_layer ()
|
||||
{
|
||||
if (m_run_xor) {
|
||||
|
||||
std::vector <db::Polygon> out_polygons;
|
||||
db::BooleanOp op (db::BooleanOp::Xor);
|
||||
db::PolygonContainer pc (out_polygons);
|
||||
db::PolygonGenerator out (pc, false /*don't resolve holes*/, true /*min coherence*/);
|
||||
m_ep.process (out, op);
|
||||
|
||||
db::CplxTrans t (mp_layout_a->dbu ());
|
||||
|
||||
rdb::Category *cat = mp_xor_cat [std::make_pair (m_is_valid_layer_index_a ? m_layer_index_a : -1, m_is_valid_layer_index_b ? m_layer_index_b : -1)];
|
||||
if (cat) {
|
||||
for (std::vector <db::Polygon>::const_iterator x = out_polygons.begin (); x != out_polygons.end (); ++x) {
|
||||
rdb::Item *item = mp_rdb->create_item (mp_cell->id (), cat->id ());
|
||||
item->add_value (t * *x);
|
||||
}
|
||||
}
|
||||
|
||||
m_ep.clear ();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RdbDifferenceReceiver::per_layer_bbox_differs (const db::Box &ba, const db::Box &bb)
|
||||
{
|
||||
rdb::Item *item = mp_rdb->create_item (mp_cell->id (), mp_general_cat->id ());
|
||||
item->add_value (tl::sprintf (tl::to_string (QObject::tr ("Per-layer bounding boxes differ (layer %s): %s (A) vs. %s (B)")), m_layer.to_string (), ba.to_string (), bb.to_string ()));
|
||||
}
|
||||
|
||||
void
|
||||
RdbDifferenceReceiver::shape_diffs_found ()
|
||||
{
|
||||
if (! m_diffs_reported) {
|
||||
rdb::Item *item = mp_rdb->create_item (mp_cell->id (), mp_general_cat->id ());
|
||||
item->add_value (tl::sprintf (tl::to_string (QObject::tr ("Shapes differ on layer %s")), m_layer.to_string ()));
|
||||
m_diffs_reported = true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RdbDifferenceReceiver::begin_polygon_differences ()
|
||||
{
|
||||
shape_diffs_found ();
|
||||
}
|
||||
|
||||
inline std::string shape_type (const db::Polygon &)
|
||||
{
|
||||
return "polygon";
|
||||
}
|
||||
|
||||
inline std::string shape_type (const db::Path &)
|
||||
{
|
||||
return "path";
|
||||
}
|
||||
|
||||
inline std::string shape_type (const db::Edge &)
|
||||
{
|
||||
return "edge";
|
||||
}
|
||||
|
||||
inline std::string shape_type (const db::Text &)
|
||||
{
|
||||
return "text";
|
||||
}
|
||||
|
||||
inline std::string shape_type (const db::Box &)
|
||||
{
|
||||
return "box";
|
||||
}
|
||||
|
||||
template <class SH>
|
||||
void
|
||||
RdbDifferenceReceiver::produce_diffs_for_xor (const db::PropertiesRepository & /*pr*/, const std::vector <std::pair <SH, db::properties_id_type> > &a, const std::vector <std::pair <SH, db::properties_id_type> > &b, double dbu_a, db::Shapes &shapes)
|
||||
{
|
||||
db::CplxTrans t (dbu_a);
|
||||
std::vector <std::pair <SH, db::properties_id_type> > anotb;
|
||||
std::set_difference (a.begin (), a.end (), b.begin (), b.end (), std::back_inserter (anotb));
|
||||
for (typename std::vector <std::pair <SH, db::properties_id_type> >::const_iterator s = anotb.begin (); s != anotb.end (); ++s) {
|
||||
shapes.insert (s->first);
|
||||
}
|
||||
}
|
||||
|
||||
template <class SH>
|
||||
void
|
||||
RdbDifferenceReceiver::produce_diffs (const db::PropertiesRepository &pr, const std::vector <std::pair <SH, db::properties_id_type> > &a, const std::vector <std::pair <SH, db::properties_id_type> > &b, double dbu_a, const rdb::Category *cat)
|
||||
{
|
||||
db::CplxTrans t (dbu_a);
|
||||
std::vector <std::pair <SH, db::properties_id_type> > anotb;
|
||||
std::set_difference (a.begin (), a.end (), b.begin (), b.end (), std::back_inserter (anotb));
|
||||
for (typename std::vector <std::pair <SH, db::properties_id_type> >::const_iterator s = anotb.begin (); s != anotb.end (); ++s) {
|
||||
|
||||
rdb::Item *item = mp_rdb->create_item (mp_cell->id (), cat->id ());
|
||||
|
||||
if (s->second && m_with_properties) {
|
||||
item->add_value ("item: " + shape_type (s->first) + " " + tl::to_string (QObject::tr ("with properties")));
|
||||
} else {
|
||||
item->add_value ("item: " + shape_type (s->first));
|
||||
}
|
||||
|
||||
item->add_value (t * s->first);
|
||||
|
||||
if (s->second && m_with_properties) {
|
||||
add_property_text (item, pr, s->second);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
template <class SH>
|
||||
void
|
||||
RdbDifferenceReceiver::shape_diffs (const db::PropertiesRepository &pr, const std::vector <std::pair <SH, db::properties_id_type> > &a, const std::vector <std::pair <SH, db::properties_id_type> > &b)
|
||||
{
|
||||
if (m_detailed && m_is_valid_layer_index_a && mp_a_only_per_layer_cat [m_layer_index_a] != 0) {
|
||||
produce_diffs (pr, a, b, mp_layout_a->dbu (), mp_a_only_per_layer_cat [m_layer_index_a]);
|
||||
}
|
||||
|
||||
if (m_run_xor && m_is_valid_layer_index_a) {
|
||||
db::Shapes shapes;
|
||||
produce_diffs_for_xor (pr, a, b, mp_layout_a->dbu (), shapes);
|
||||
for (db::Shapes::shape_iterator s = shapes.begin (db::Shapes::shape_iterator::All); ! s.at_end (); ++s) {
|
||||
m_ep.insert (*s, m_obj_index * 2);
|
||||
++m_obj_index;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_detailed && m_is_valid_layer_index_b && mp_b_only_per_layer_cat [m_layer_index_b] != 0) {
|
||||
produce_diffs (pr, b, a, mp_layout_b->dbu (), mp_b_only_per_layer_cat [m_layer_index_b]);
|
||||
}
|
||||
|
||||
if (m_run_xor && m_is_valid_layer_index_b) {
|
||||
db::Shapes shapes;
|
||||
produce_diffs_for_xor (pr, b, a, mp_layout_b->dbu (), shapes);
|
||||
for (db::Shapes::shape_iterator s = shapes.begin (db::Shapes::shape_iterator::All); ! s.at_end (); ++s) {
|
||||
m_ep.insert (*s, m_obj_index * 2 + 1);
|
||||
++m_obj_index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RdbDifferenceReceiver::detailed_diff (const db::PropertiesRepository &pr, const std::vector <std::pair <db::Polygon, db::properties_id_type> > &a, const std::vector <std::pair <db::Polygon, db::properties_id_type> > &b)
|
||||
{
|
||||
shape_diffs (pr, a, b);
|
||||
}
|
||||
|
||||
void
|
||||
RdbDifferenceReceiver::begin_path_differences ()
|
||||
{
|
||||
shape_diffs_found ();
|
||||
}
|
||||
|
||||
void
|
||||
RdbDifferenceReceiver::detailed_diff (const db::PropertiesRepository &pr, const std::vector <std::pair <db::Path, db::properties_id_type> > &a, const std::vector <std::pair <db::Path, db::properties_id_type> > &b)
|
||||
{
|
||||
shape_diffs (pr, a, b);
|
||||
}
|
||||
|
||||
void
|
||||
RdbDifferenceReceiver::begin_box_differences ()
|
||||
{
|
||||
shape_diffs_found ();
|
||||
}
|
||||
|
||||
void
|
||||
RdbDifferenceReceiver::detailed_diff (const db::PropertiesRepository &pr, const std::vector <std::pair <db::Box, db::properties_id_type> > &a, const std::vector <std::pair <db::Box, db::properties_id_type> > &b)
|
||||
{
|
||||
shape_diffs (pr, a, b);
|
||||
}
|
||||
|
||||
void
|
||||
RdbDifferenceReceiver::begin_edge_differences ()
|
||||
{
|
||||
shape_diffs_found ();
|
||||
}
|
||||
|
||||
void
|
||||
RdbDifferenceReceiver::detailed_diff (const db::PropertiesRepository &pr, const std::vector <std::pair <db::Edge, db::properties_id_type> > &a, const std::vector <std::pair <db::Edge, db::properties_id_type> > &b)
|
||||
{
|
||||
shape_diffs (pr, a, b);
|
||||
}
|
||||
|
||||
void
|
||||
RdbDifferenceReceiver::begin_text_differences ()
|
||||
{
|
||||
shape_diffs_found ();
|
||||
}
|
||||
|
||||
void
|
||||
RdbDifferenceReceiver::detailed_diff (const db::PropertiesRepository &pr, const std::vector <std::pair <db::Text, db::properties_id_type> > &a, const std::vector <std::pair <db::Text, db::properties_id_type> > &b)
|
||||
{
|
||||
shape_diffs (pr, a, b);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// DiffToolDialog definition
|
||||
|
||||
DiffToolDialog::DiffToolDialog (QWidget *parent)
|
||||
: QDialog (parent), mp_view (0)
|
||||
{
|
||||
mp_ui = new Ui::DiffToolDialog ();
|
||||
mp_ui->setupUi (this);
|
||||
|
||||
connect (mp_ui->xor_cbx, SIGNAL (clicked ()), this, SLOT (xor_changed ()));
|
||||
}
|
||||
|
||||
DiffToolDialog::~DiffToolDialog ()
|
||||
{
|
||||
delete mp_ui;
|
||||
mp_ui = 0;
|
||||
}
|
||||
|
||||
int
|
||||
DiffToolDialog::exec_dialog (lay::LayoutView *view)
|
||||
{
|
||||
mp_view = view;
|
||||
|
||||
if (view != mp_ui->layouta->layout_view () || view != mp_ui->layoutb->layout_view ()) {
|
||||
|
||||
mp_ui->layouta->set_layout_view (view);
|
||||
mp_ui->layoutb->set_layout_view (view);
|
||||
|
||||
if (view->cellviews () >= 2) {
|
||||
mp_ui->layouta->set_current_cv_index (0);
|
||||
mp_ui->layoutb->set_current_cv_index (1);
|
||||
}
|
||||
|
||||
} else {
|
||||
// force update of the layer list
|
||||
// TODO: the controls should register a listener for the view so this activity is not necessary:
|
||||
mp_ui->layouta->set_layout_view (view);
|
||||
mp_ui->layoutb->set_layout_view (view);
|
||||
}
|
||||
|
||||
lay::PluginRoot *config_root = lay::PluginRoot::instance ();
|
||||
|
||||
bool f = false;
|
||||
if (config_root->config_get (cfg_diff_run_xor, f)) {
|
||||
mp_ui->xor_cbx->setChecked (f);
|
||||
}
|
||||
if (config_root->config_get (cfg_diff_detailed, f)) {
|
||||
mp_ui->detailed_cbx->setChecked (f);
|
||||
}
|
||||
if (config_root->config_get (cfg_diff_smart, f)) {
|
||||
mp_ui->smart_cbx->setChecked (f);
|
||||
}
|
||||
if (config_root->config_get (cfg_diff_summarize, f)) {
|
||||
mp_ui->summarize_cbx->setChecked (f);
|
||||
}
|
||||
if (config_root->config_get (cfg_diff_expand_cell_arrays, f)) {
|
||||
mp_ui->expand_cell_arrays_cbx->setChecked (f);
|
||||
}
|
||||
if (config_root->config_get (cfg_diff_exact, f)) {
|
||||
mp_ui->exact_cbx->setChecked (f);
|
||||
}
|
||||
|
||||
update ();
|
||||
|
||||
int ret = QDialog::exec ();
|
||||
|
||||
if (ret) {
|
||||
run_diff ();
|
||||
}
|
||||
|
||||
mp_view = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
DiffToolDialog::accept ()
|
||||
{
|
||||
BEGIN_PROTECTED
|
||||
|
||||
int cv_index_a = mp_ui->layouta->current_cv_index ();
|
||||
int cv_index_b = mp_ui->layoutb->current_cv_index ();
|
||||
|
||||
const lay::CellView &cva = mp_view->cellview (cv_index_a);
|
||||
const lay::CellView &cvb = mp_view->cellview (cv_index_b);
|
||||
|
||||
if (&cva->layout () == &cvb->layout () && cva.cell_index () == cvb.cell_index ()) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Trying to perform an Diff between identical layouts")));
|
||||
}
|
||||
|
||||
lay::PluginRoot *config_root = lay::PluginRoot::instance ();
|
||||
|
||||
config_root->config_set (cfg_diff_run_xor, mp_ui->xor_cbx->isChecked ());
|
||||
config_root->config_set (cfg_diff_detailed, mp_ui->detailed_cbx->isChecked ());
|
||||
config_root->config_set (cfg_diff_smart, mp_ui->smart_cbx->isChecked ());
|
||||
config_root->config_set (cfg_diff_summarize, mp_ui->summarize_cbx->isChecked ());
|
||||
config_root->config_set (cfg_diff_expand_cell_arrays, mp_ui->expand_cell_arrays_cbx->isChecked ());
|
||||
config_root->config_set (cfg_diff_exact, mp_ui->exact_cbx->isChecked ());
|
||||
config_root->config_end ();
|
||||
|
||||
QDialog::accept ();
|
||||
|
||||
END_PROTECTED
|
||||
}
|
||||
|
||||
void
|
||||
DiffToolDialog::update ()
|
||||
{
|
||||
bool xor_mode = mp_ui->xor_cbx->isChecked ();
|
||||
mp_ui->summarize_cbx->setEnabled (! xor_mode);
|
||||
mp_ui->detailed_cbx->setEnabled (! xor_mode);
|
||||
mp_ui->expand_cell_arrays_cbx->setEnabled (! xor_mode);
|
||||
mp_ui->exact_cbx->setEnabled (! xor_mode);
|
||||
}
|
||||
|
||||
void
|
||||
DiffToolDialog::run_diff ()
|
||||
{
|
||||
bool smart = mp_ui->smart_cbx->isChecked ();
|
||||
bool run_xor = mp_ui->xor_cbx->isChecked ();
|
||||
bool detailed = !run_xor && mp_ui->detailed_cbx->isChecked ();
|
||||
bool summarize = !run_xor && mp_ui->summarize_cbx->isChecked ();
|
||||
bool expand_cell_arrays = !run_xor && mp_ui->expand_cell_arrays_cbx->isChecked ();
|
||||
bool exact = !run_xor && mp_ui->exact_cbx->isChecked ();
|
||||
|
||||
int cv_index_a = mp_ui->layouta->current_cv_index ();
|
||||
int cv_index_b = mp_ui->layoutb->current_cv_index ();
|
||||
|
||||
lay::CellView cva = mp_view->cellview (cv_index_a);
|
||||
lay::CellView cvb = mp_view->cellview (cv_index_b);
|
||||
|
||||
unsigned int flags = 0;
|
||||
if (detailed || run_xor) {
|
||||
flags |= db::layout_diff::f_verbose;
|
||||
}
|
||||
if (!exact) {
|
||||
flags |= db::layout_diff::f_no_text_details;
|
||||
flags |= db::layout_diff::f_no_layer_names;
|
||||
flags |= db::layout_diff::f_no_text_orientation;
|
||||
flags |= db::layout_diff::f_no_properties;
|
||||
flags |= db::layout_diff::f_boxes_as_polygons;
|
||||
flags |= db::layout_diff::f_paths_as_polygons;
|
||||
}
|
||||
if (expand_cell_arrays) {
|
||||
flags |= db::layout_diff::f_flatten_array_insts;
|
||||
}
|
||||
if (! summarize) {
|
||||
flags |= db::layout_diff::f_dont_summarize_missing_layers;
|
||||
}
|
||||
if (smart) {
|
||||
flags |= db::layout_diff::f_smart_cell_mapping;
|
||||
}
|
||||
|
||||
// TODO: make an parameter
|
||||
db::Coord tolerance = 0;
|
||||
|
||||
// Create the report database or identify the output layout
|
||||
rdb::Database *rdb = 0;
|
||||
int rdb_index = 0;
|
||||
|
||||
rdb = new rdb::Database ();
|
||||
rdb->set_name ("Diff " + cva->name () + "/" + cvb->name ());
|
||||
rdb->set_top_cell_name (cva->layout ().cell_name (cva.cell_index ()));
|
||||
|
||||
rdb_index = mp_view->add_rdb (rdb);
|
||||
|
||||
std::string srca = cva->name () + ", Cell " + cva->layout ().cell_name (cva.cell_index ());
|
||||
std::string srcb = cvb->name () + ", Cell " + cvb->layout ().cell_name (cvb.cell_index ());
|
||||
rdb->set_description ("Diff of '" + srca + "' vs. '" + srcb + "'");
|
||||
|
||||
RdbDifferenceReceiver r (cva->layout (), cvb->layout (), rdb, detailed, exact, run_xor);
|
||||
|
||||
db::compare_layouts (cva->layout (), cva.cell_index (), cvb->layout (), cvb.cell_index (), flags, tolerance, r);
|
||||
|
||||
mp_view->open_rdb_browser (rdb_index, cv_index_a);
|
||||
mp_view->update_content ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2018 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_layDiffToolDialog
|
||||
#define HDR_layDiffToolDialog
|
||||
|
||||
#include <QDialog>
|
||||
#include <string>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class DiffToolDialog;
|
||||
}
|
||||
|
||||
namespace lay
|
||||
{
|
||||
class LayoutView;
|
||||
}
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
||||
extern std::string cfg_diff_run_xor;
|
||||
extern std::string cfg_diff_detailed;
|
||||
extern std::string cfg_diff_summarize;
|
||||
extern std::string cfg_diff_expand_cell_arrays;
|
||||
extern std::string cfg_diff_exact;
|
||||
|
||||
class DiffToolDialog
|
||||
: public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DiffToolDialog (QWidget *parent);
|
||||
~DiffToolDialog ();
|
||||
|
||||
int exec_dialog (lay::LayoutView *view);
|
||||
|
||||
protected slots:
|
||||
void xor_changed () { update (); }
|
||||
|
||||
protected:
|
||||
void accept ();
|
||||
void run_diff ();
|
||||
void update ();
|
||||
|
||||
private:
|
||||
Ui::DiffToolDialog *mp_ui;
|
||||
lay::LayoutView *mp_view;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
|
||||
TARGET = diff
|
||||
DESTDIR = $$OUT_PWD/../../../../lay_plugins
|
||||
|
||||
include($$PWD/../../../lay_plugin.pri)
|
||||
|
||||
INCLUDEPATH += $$RDB_INC $$ANT_INC
|
||||
DEPENDPATH += $$RDB_INC $$ANT_INC
|
||||
LIBS += -L$$DESTDIR/.. -lklayout_rdb -lklayout_ant
|
||||
|
||||
HEADERS = \
|
||||
layDiffToolDialog.h
|
||||
|
||||
SOURCES = \
|
||||
layDiffPlugin.cc \
|
||||
layDiffToolDialog.cc
|
||||
|
||||
FORMS = \
|
||||
DiffToolDialog.ui \
|
||||
@@ -0,0 +1,5 @@
|
||||
|
||||
TEMPLATE = subdirs
|
||||
|
||||
SUBDIRS = lay_plugin
|
||||
|
||||
@@ -0,0 +1,843 @@
|
||||
<ui version="4.0" >
|
||||
<class>StreamImportDialog</class>
|
||||
<widget class="QDialog" name="StreamImportDialog" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>754</width>
|
||||
<height>604</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="6" column="1" >
|
||||
<widget class="QPushButton" name="last_pb" >
|
||||
<property name="text" >
|
||||
<string>Back</string>
|
||||
</property>
|
||||
<property name="icon" >
|
||||
<iconset resource="layResources.qrc" >:/back.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" >
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>331</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="6" column="3" >
|
||||
<widget class="QPushButton" name="import_pb" >
|
||||
<property name="text" >
|
||||
<string>Import</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="2" >
|
||||
<widget class="QPushButton" name="next_pb" >
|
||||
<property name="text" >
|
||||
<string>Next</string>
|
||||
</property>
|
||||
<property name="icon" >
|
||||
<iconset resource="layResources.qrc" >:/forward.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="4" >
|
||||
<widget class="QPushButton" name="cancel_pb" >
|
||||
<property name="text" >
|
||||
<string>Cancel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="5" >
|
||||
<widget class="Line" name="line_4" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="5" >
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType" >
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>736</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="5" >
|
||||
<widget class="Line" name="line" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="5" >
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType" >
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>736</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="5" >
|
||||
<widget class="QFrame" name="frame_3" >
|
||||
<property name="frameShape" >
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow" >
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="section_header_lbl" >
|
||||
<property name="font" >
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>SectionHeader</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="reset_pb" >
|
||||
<property name="text" >
|
||||
<string>Reset</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="5" >
|
||||
<widget class="QStackedWidget" name="central_stack" >
|
||||
<property name="currentIndex" >
|
||||
<number>2</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="page" >
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_4" >
|
||||
<property name="title" >
|
||||
<string>Input</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="1" column="0" >
|
||||
<widget class="QLabel" name="label_7" >
|
||||
<property name="text" >
|
||||
<string>Top cell </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="2" >
|
||||
<widget class="QLineEdit" name="file_le" />
|
||||
</item>
|
||||
<item row="0" column="3" >
|
||||
<widget class="QToolButton" name="file_pb" >
|
||||
<property name="text" >
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" >
|
||||
<widget class="QLabel" name="label_6" >
|
||||
<property name="text" >
|
||||
<string>File </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2" colspan="2" >
|
||||
<widget class="QLabel" name="label_2" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy>
|
||||
<hsizetype>5</hsizetype>
|
||||
<vsizetype>5</vsizetype>
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>(leave empty for selecting the top cell automatically)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" >
|
||||
<widget class="QLineEdit" name="topcell_le" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy>
|
||||
<hsizetype>7</hsizetype>
|
||||
<vsizetype>0</vsizetype>
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="4" >
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType" >
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>10</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="4" >
|
||||
<widget class="QFrame" name="frame_2" >
|
||||
<property name="frameShape" >
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow" >
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3" >
|
||||
<property name="text" >
|
||||
<string>Stream reader options </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="edit_options_pb" >
|
||||
<property name="text" >
|
||||
<string>Edit ...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="reset_options_pb" >
|
||||
<property name="text" >
|
||||
<string>Reset</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox" >
|
||||
<property name="title" >
|
||||
<string>Import Mode</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="import_simple_rb" >
|
||||
<property name="text" >
|
||||
<string>Merge - Merge new cell into current cell and create a new cell hierarchy below</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="import_extra_rb" >
|
||||
<property name="text" >
|
||||
<string>Extra cells - Import as extra cells</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="import_instantiate_rb" >
|
||||
<property name="text" >
|
||||
<string>Instantiate - Instantiate a new cell tree below the current cell</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="import_merge_rb" >
|
||||
<property name="text" >
|
||||
<string>Merge hierarchy - Merge into current cell's hierarchy (attempt to identify corresponding cells)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType" >
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>10</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_8" >
|
||||
<property name="text" >
|
||||
<string>Note: All modes except "Extra cells" require a unique top cell for the input file. Either one must be specified or the input file must have a single top cell.</string>
|
||||
</property>
|
||||
<property name="wordWrap" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType" >
|
||||
<enum>QSizePolicy::Expanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="page_2" >
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame" >
|
||||
<property name="frameShape" >
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow" >
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<layout class="QGridLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item rowspan="5" row="0" column="0" >
|
||||
<widget class="QGroupBox" name="groupBox_2" >
|
||||
<property name="title" >
|
||||
<string>Layer mapping</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="2" column="1" colspan="2" >
|
||||
<widget class="QLabel" name="label" >
|
||||
<property name="text" >
|
||||
<string>Use "layer/datatype" notation to specify an offset to be added to layer and/or datatype.</string>
|
||||
</property>
|
||||
<property name="wordWrap" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" >
|
||||
<widget class="QLineEdit" name="offset_le" />
|
||||
</item>
|
||||
<item row="1" column="0" >
|
||||
<widget class="QRadioButton" name="offset_rb" >
|
||||
<property name="text" >
|
||||
<string>On original layers plus offset</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" >
|
||||
<widget class="QRadioButton" name="no_mapping_rb" >
|
||||
<property name="text" >
|
||||
<string>No mapping - use original layers</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2" >
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>211</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" >
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="page_6" >
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame_5" >
|
||||
<property name="frameShape" >
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow" >
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<layout class="QGridLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="3" column="5" >
|
||||
<widget class="QLineEdit" name="layout_x1_le" />
|
||||
</item>
|
||||
<item row="5" column="2" >
|
||||
<widget class="QLineEdit" name="pcb_y3_le" />
|
||||
</item>
|
||||
<item row="3" column="4" >
|
||||
<widget class="QLabel" name="label_22" >
|
||||
<property name="text" >
|
||||
<string>Point 1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="6" >
|
||||
<widget class="QLabel" name="label_24" >
|
||||
<property name="text" >
|
||||
<string>y (micron)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="3" >
|
||||
<widget class="QLabel" name="label_17" >
|
||||
<property name="text" >
|
||||
<string>Reference points coordinates on layout to import</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2" >
|
||||
<widget class="QLineEdit" name="pcb_y2_le" />
|
||||
</item>
|
||||
<item row="5" column="4" >
|
||||
<widget class="QLabel" name="Point 3" >
|
||||
<property name="text" >
|
||||
<string>Point 3</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="5" >
|
||||
<widget class="QLineEdit" name="layout_x2_le" />
|
||||
</item>
|
||||
<item row="0" column="4" colspan="3" >
|
||||
<widget class="QLabel" name="label_18" >
|
||||
<property name="text" >
|
||||
<string>Reference point coordinates in existing layout</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="5" >
|
||||
<widget class="QLineEdit" name="layout_x3_le" />
|
||||
</item>
|
||||
<item row="5" column="6" >
|
||||
<widget class="QLineEdit" name="layout_y3_le" />
|
||||
</item>
|
||||
<item row="2" column="5" >
|
||||
<widget class="QLabel" name="label_23" >
|
||||
<property name="text" >
|
||||
<string>x (micron)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="3" >
|
||||
<widget class="Line" name="line_2" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" >
|
||||
<widget class="QLabel" name="label_25" >
|
||||
<property name="text" >
|
||||
<string>Point 2</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1" >
|
||||
<widget class="QLineEdit" name="pcb_x2_le" />
|
||||
</item>
|
||||
<item row="5" column="0" >
|
||||
<widget class="QLabel" name="label_26" >
|
||||
<property name="text" >
|
||||
<string>Point 3</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" >
|
||||
<widget class="QLabel" name="label_21" >
|
||||
<property name="text" >
|
||||
<string>Point 1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1" >
|
||||
<widget class="QLineEdit" name="pcb_x3_le" />
|
||||
</item>
|
||||
<item row="3" column="2" >
|
||||
<widget class="QLineEdit" name="pcb_y1_le" />
|
||||
</item>
|
||||
<item row="1" column="4" colspan="3" >
|
||||
<widget class="Line" name="line_3" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" >
|
||||
<widget class="QLineEdit" name="pcb_x1_le" />
|
||||
</item>
|
||||
<item row="2" column="2" >
|
||||
<widget class="QLabel" name="label_20" >
|
||||
<property name="text" >
|
||||
<string>y (micron)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" >
|
||||
<widget class="QLabel" name="label_19" >
|
||||
<property name="text" >
|
||||
<string>x (micron)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="4" >
|
||||
<widget class="QLabel" name="label_27" >
|
||||
<property name="text" >
|
||||
<string>Point 2</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="6" >
|
||||
<widget class="QLineEdit" name="layout_y2_le" />
|
||||
</item>
|
||||
<item row="3" column="6" >
|
||||
<widget class="QLineEdit" name="layout_y1_le" />
|
||||
</item>
|
||||
<item rowspan="6" row="0" column="3" >
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType" >
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>16</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="7" >
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType" >
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>691</width>
|
||||
<height>8</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="8" column="0" colspan="7" >
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType" >
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>15</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="9" column="0" colspan="7" >
|
||||
<widget class="QFrame" name="frame_6" >
|
||||
<property name="frameShape" >
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow" >
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_30" >
|
||||
<property name="text" >
|
||||
<string>Explicit transformation</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="explicit_trans_le" >
|
||||
<property name="toolTip" >
|
||||
<string>Examples: "r90", "m45", "r90 (2000,-5000)"</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_31" >
|
||||
<property name="text" >
|
||||
<string>(Reference points have higher priority)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0" colspan="7" >
|
||||
<widget class="QLabel" name="label_29" >
|
||||
<property name="text" >
|
||||
<string>Leave fields empty to specify less reference points. One point is used to derive the displacement, further points are used to derive the orientation. Currently, no magnification is implied and only simple rotations are derived from the mapping points.
|
||||
|
||||
Alternatively the transformation (imported to existing layout) can be specified using the explicit transformation below. This allows to specify an arbitary transformation. Use the common notation (i.e. "*2 r90 10,-100").</string>
|
||||
</property>
|
||||
<property name="wordWrap" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>file_le</tabstop>
|
||||
<tabstop>file_pb</tabstop>
|
||||
<tabstop>topcell_le</tabstop>
|
||||
<tabstop>edit_options_pb</tabstop>
|
||||
<tabstop>reset_options_pb</tabstop>
|
||||
<tabstop>import_simple_rb</tabstop>
|
||||
<tabstop>import_extra_rb</tabstop>
|
||||
<tabstop>import_instantiate_rb</tabstop>
|
||||
<tabstop>import_merge_rb</tabstop>
|
||||
<tabstop>no_mapping_rb</tabstop>
|
||||
<tabstop>offset_rb</tabstop>
|
||||
<tabstop>offset_le</tabstop>
|
||||
<tabstop>pcb_x1_le</tabstop>
|
||||
<tabstop>pcb_y1_le</tabstop>
|
||||
<tabstop>layout_x1_le</tabstop>
|
||||
<tabstop>layout_y1_le</tabstop>
|
||||
<tabstop>pcb_x2_le</tabstop>
|
||||
<tabstop>pcb_y2_le</tabstop>
|
||||
<tabstop>layout_x2_le</tabstop>
|
||||
<tabstop>layout_y2_le</tabstop>
|
||||
<tabstop>pcb_x3_le</tabstop>
|
||||
<tabstop>pcb_y3_le</tabstop>
|
||||
<tabstop>layout_x3_le</tabstop>
|
||||
<tabstop>layout_y3_le</tabstop>
|
||||
<tabstop>explicit_trans_le</tabstop>
|
||||
<tabstop>last_pb</tabstop>
|
||||
<tabstop>next_pb</tabstop>
|
||||
<tabstop>import_pb</tabstop>
|
||||
<tabstop>cancel_pb</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="layResources.qrc" />
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>import_pb</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>StreamImportDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<x>572</x>
|
||||
<y>598</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<x>574</x>
|
||||
<y>614</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>cancel_pb</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>StreamImportDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<x>679</x>
|
||||
<y>597</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<x>683</x>
|
||||
<y>613</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -0,0 +1,173 @@
|
||||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2018 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 "layStreamImportDialog.h"
|
||||
#include "layStreamImporter.h"
|
||||
|
||||
#include "dbStream.h"
|
||||
|
||||
#include "tlExceptions.h"
|
||||
#include "layPlugin.h"
|
||||
#include "layMainWindow.h"
|
||||
#include "layFileDialog.h"
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
||||
static const std::string cfg_stream_import_spec ("stream-import-spec2");
|
||||
|
||||
class StreamImportPluginDeclaration
|
||||
: public lay::PluginDeclaration
|
||||
{
|
||||
public:
|
||||
StreamImportPluginDeclaration ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
virtual void get_options (std::vector < std::pair<std::string, std::string> > &options) const
|
||||
{
|
||||
options.push_back (std::pair<std::string, std::string> (cfg_stream_import_spec, ""));
|
||||
}
|
||||
|
||||
virtual lay::ConfigPage *config_page (QWidget * /*parent*/, std::string & /*title*/) const
|
||||
{
|
||||
// .. nothing yet ..
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void get_menu_entries (std::vector<lay::MenuEntry> &menu_entries) const
|
||||
{
|
||||
lay::PluginDeclaration::get_menu_entries (menu_entries);
|
||||
menu_entries.push_back (lay::MenuEntry ("lay::import_stream", "import_stream:edit", "file_menu.import_menu.end", tl::to_string (QObject::tr ("Other File Into Current"))));
|
||||
}
|
||||
|
||||
virtual bool configure (const std::string &name, const std::string &value)
|
||||
{
|
||||
if (name == cfg_stream_import_spec) {
|
||||
m_import_spec = value;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void config_finalize ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
virtual bool menu_activated (const std::string &symbol) const
|
||||
{
|
||||
if (symbol == "lay::import_stream") {
|
||||
|
||||
lay::LayoutView *view = lay::LayoutView::current ();
|
||||
if (! view) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("No view open to import files into")));
|
||||
}
|
||||
|
||||
StreamImportData data;
|
||||
try {
|
||||
data.from_string (m_import_spec);
|
||||
} catch (...) {
|
||||
data = StreamImportData ();
|
||||
}
|
||||
|
||||
lay::PluginRoot *config_root = lay::PluginRoot::instance ();
|
||||
|
||||
StreamImportDialog dialog (QApplication::activeWindow (), &data);
|
||||
lay::StreamImporter importer;
|
||||
|
||||
bool ok = false;
|
||||
while (! ok && dialog.exec ()) {
|
||||
|
||||
BEGIN_PROTECTED
|
||||
data.setup_importer (&importer);
|
||||
ok = true;
|
||||
END_PROTECTED
|
||||
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
|
||||
// clear selection
|
||||
lay::MainWindow::instance ()->cancel ();
|
||||
|
||||
config_root->config_set (cfg_stream_import_spec, data.to_string ());
|
||||
config_root->config_end ();
|
||||
|
||||
int cv_index = view->active_cellview_index ();
|
||||
const lay::CellView &cv = view->cellview (cv_index);
|
||||
|
||||
std::vector <unsigned int> new_layer_ids;
|
||||
importer.read (cv->layout (), cv.cell_index (), new_layer_ids);
|
||||
|
||||
// create the initial layer properties
|
||||
std::vector <lay::ParsedLayerSource> new_layers;
|
||||
new_layers.reserve (cv->layout ().layers ());
|
||||
|
||||
for (unsigned int i = 0; i < new_layer_ids.size (); ++i) {
|
||||
if (cv->layout ().is_valid_layer (new_layer_ids [i])) {
|
||||
db::LayerProperties lp (cv->layout ().get_properties (new_layer_ids [i]));
|
||||
new_layers.push_back (lay::ParsedLayerSource (lp, cv_index));
|
||||
}
|
||||
}
|
||||
|
||||
std::sort (new_layers.begin (), new_layers.end ());
|
||||
|
||||
lay::LayerPropertiesList new_props (view->get_properties ());
|
||||
|
||||
// create the layers and do a basic recoloring ..
|
||||
for (std::vector <lay::ParsedLayerSource>::const_iterator l = new_layers.begin (); l != new_layers.end (); ++l) {
|
||||
lay::LayerProperties p;
|
||||
p.set_source (*l);
|
||||
view->init_layer_properties (p);
|
||||
new_props.push_back (p);
|
||||
}
|
||||
|
||||
view->set_properties (new_props);
|
||||
|
||||
view->update_content ();
|
||||
|
||||
config_root->config_set (cfg_stream_import_spec, data.to_string ());
|
||||
config_root->config_end ();
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_import_spec;
|
||||
};
|
||||
|
||||
static tl::RegisteredClass<lay::PluginDeclaration> config_decl (new lay::StreamImportPluginDeclaration (), 1300, "lay::StreamImportPlugin");
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,491 @@
|
||||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2018 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 "ui_StreamImportDialog.h"
|
||||
#include "layStreamImporter.h"
|
||||
#include "layStreamImportDialog.h"
|
||||
|
||||
#include "tlExceptions.h"
|
||||
#include "layFileDialog.h"
|
||||
#include "layDialogs.h"
|
||||
#include "layConverters.h"
|
||||
#include "layLoadLayoutOptionsDialog.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
|
||||
#include <fstream>
|
||||
|
||||
namespace {
|
||||
|
||||
static struct {
|
||||
const char *string;
|
||||
lay::StreamImportData::mode_type value;
|
||||
} mode_strings [] = {
|
||||
{ "simple", lay::StreamImportData::Simple },
|
||||
{ "instantiate", lay::StreamImportData::Instantiate },
|
||||
{ "extra", lay::StreamImportData::Extra },
|
||||
{ "merge", lay::StreamImportData::Merge }
|
||||
};
|
||||
|
||||
struct ModeConverter
|
||||
{
|
||||
std::string to_string (lay::StreamImportData::mode_type t) const
|
||||
{
|
||||
for (unsigned int i = 0; i < sizeof (mode_strings) / sizeof (mode_strings [0]); ++i) {
|
||||
if (mode_strings [i].value == t) {
|
||||
return mode_strings [i].string;
|
||||
}
|
||||
}
|
||||
return std::string ();
|
||||
}
|
||||
|
||||
void from_string (const std::string &s, lay::StreamImportData::mode_type &t) const
|
||||
{
|
||||
for (unsigned int i = 0; i < sizeof (mode_strings) / sizeof (mode_strings [0]); ++i) {
|
||||
if (s == mode_strings [i].string) {
|
||||
t = mode_strings [i].value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
t = mode_strings [0].value;
|
||||
}
|
||||
};
|
||||
|
||||
static struct {
|
||||
const char *string;
|
||||
lay::StreamImportData::layer_mode_type value;
|
||||
} layer_mode_strings [] = {
|
||||
{ "original", lay::StreamImportData::Original },
|
||||
{ "offset", lay::StreamImportData::Offset }
|
||||
};
|
||||
|
||||
struct LayerModeConverter
|
||||
{
|
||||
std::string to_string (lay::StreamImportData::layer_mode_type t) const
|
||||
{
|
||||
for (unsigned int i = 0; i < sizeof (layer_mode_strings) / sizeof (layer_mode_strings [0]); ++i) {
|
||||
if (layer_mode_strings [i].value == t) {
|
||||
return layer_mode_strings [i].string;
|
||||
}
|
||||
}
|
||||
return std::string ();
|
||||
}
|
||||
|
||||
void from_string (const std::string &s, lay::StreamImportData::layer_mode_type &t) const
|
||||
{
|
||||
for (unsigned int i = 0; i < sizeof (layer_mode_strings) / sizeof (layer_mode_strings [0]); ++i) {
|
||||
if (s == layer_mode_strings [i].string) {
|
||||
t = layer_mode_strings [i].value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
t = layer_mode_strings [0].value;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
||||
// -----------------------------------------------------------------------------------------
|
||||
// StreamImportData implementation
|
||||
|
||||
StreamImportData::StreamImportData ()
|
||||
: mode (Simple), layer_mode (Original)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void
|
||||
StreamImportData::setup_importer (StreamImporter *importer)
|
||||
{
|
||||
importer->set_global_trans (explicit_trans);
|
||||
importer->set_reference_points (reference_points);
|
||||
importer->set_cell_mapping (mode);
|
||||
importer->set_layer_mapping (layer_mode);
|
||||
importer->set_file (file);
|
||||
importer->set_topcell (topcell);
|
||||
importer->set_layer_offset (layer_offset);
|
||||
importer->set_reader_options (options);
|
||||
}
|
||||
|
||||
static tl::XMLElementList xml_elements ()
|
||||
{
|
||||
typedef std::pair <db::DPoint, db::DPoint> ref_point;
|
||||
typedef std::vector<ref_point> ref_point_v;
|
||||
|
||||
return
|
||||
tl::make_member (&StreamImportData::file, "file") +
|
||||
tl::make_member (&StreamImportData::topcell, "cell-name") +
|
||||
tl::make_member (&StreamImportData::layer_offset, "layer-offset") +
|
||||
tl::make_member (&StreamImportData::layer_mode, "layer-mode", LayerModeConverter ()) +
|
||||
tl::make_member (&StreamImportData::mode, "import-mode", ModeConverter ()) +
|
||||
tl::make_element (&StreamImportData::reference_points, "reference-points",
|
||||
tl::make_element<ref_point, ref_point_v::const_iterator, ref_point_v> (&ref_point_v::begin, &ref_point_v::end, &ref_point_v::push_back, "reference-point",
|
||||
tl::make_member (&ref_point::first, "p1") +
|
||||
tl::make_member (&ref_point::second, "p2")
|
||||
)
|
||||
) +
|
||||
tl::make_member (&StreamImportData::explicit_trans, "explicit-trans") +
|
||||
tl::make_element (&StreamImportData::options, "options",
|
||||
db::load_options_xml_element_list ()
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
StreamImportData::from_string (const std::string &s)
|
||||
{
|
||||
*this = StreamImportData ();
|
||||
|
||||
tl::XMLStringSource source (s);
|
||||
tl::XMLStruct<StreamImportData> xml_struct ("stream-import-data", xml_elements ());
|
||||
xml_struct.parse (source, *this);
|
||||
}
|
||||
|
||||
std::string
|
||||
StreamImportData::to_string () const
|
||||
{
|
||||
tl::OutputStringStream os;
|
||||
tl::XMLStruct<StreamImportData> xml_struct ("stream-import-data", xml_elements ());
|
||||
tl::OutputStream oss (os);
|
||||
xml_struct.write (oss, *this);
|
||||
return os.string ();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------
|
||||
// StreamImportDialog implementation
|
||||
|
||||
StreamImportDialog::StreamImportDialog (QWidget *parent, StreamImportData *data)
|
||||
: QDialog (parent), mp_data (data)
|
||||
{
|
||||
mp_ui = new Ui::StreamImportDialog ();
|
||||
mp_ui->setupUi (this);
|
||||
|
||||
connect (mp_ui->last_pb, SIGNAL (clicked ()), this, SLOT (last_page ()));
|
||||
connect (mp_ui->next_pb, SIGNAL (clicked ()), this, SLOT (next_page ()));
|
||||
connect (mp_ui->file_pb, SIGNAL (clicked ()), this, SLOT (browse_filename ()));
|
||||
connect (mp_ui->edit_options_pb, SIGNAL (clicked ()), this, SLOT (edit_options ()));
|
||||
connect (mp_ui->reset_options_pb, SIGNAL (clicked ()), this, SLOT (reset_options ()));
|
||||
connect (mp_ui->reset_pb, SIGNAL (clicked ()), this, SLOT (reset ()));
|
||||
connect (mp_ui->offset_rb, SIGNAL (clicked ()), this, SLOT (mapping_changed ()));
|
||||
connect (mp_ui->no_mapping_rb, SIGNAL (clicked ()), this, SLOT (mapping_changed ()));
|
||||
}
|
||||
|
||||
StreamImportDialog::~StreamImportDialog ()
|
||||
{
|
||||
delete mp_ui;
|
||||
mp_ui = 0;
|
||||
}
|
||||
|
||||
void
|
||||
StreamImportDialog::edit_options ()
|
||||
{
|
||||
lay::LoadLayoutOptionsDialog dialog (this, tl::to_string (QObject::tr ("Import Layout Options")));
|
||||
|
||||
dialog.get_options (mp_data->options);
|
||||
}
|
||||
|
||||
void
|
||||
StreamImportDialog::reset_options ()
|
||||
{
|
||||
mp_data->options = db::LoadLayoutOptions ();
|
||||
}
|
||||
|
||||
void
|
||||
StreamImportDialog::browse_filename ()
|
||||
{
|
||||
QString file = mp_ui->file_le->text ();
|
||||
file = QFileDialog::getOpenFileName (this, QObject::tr ("File To Import"), file, QObject::tr ("All files (*)"));
|
||||
if (! file.isNull ()) {
|
||||
mp_ui->file_le->setText (file);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
StreamImportDialog::reject ()
|
||||
{
|
||||
try {
|
||||
commit_page ();
|
||||
} catch (...) {
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
QDialog::reject ();
|
||||
}
|
||||
|
||||
void
|
||||
StreamImportDialog::accept ()
|
||||
{
|
||||
BEGIN_PROTECTED
|
||||
|
||||
commit_page ();
|
||||
QDialog::accept ();
|
||||
|
||||
END_PROTECTED
|
||||
}
|
||||
|
||||
int
|
||||
StreamImportDialog::exec ()
|
||||
{
|
||||
mp_ui->central_stack->setCurrentIndex (0);
|
||||
update ();
|
||||
|
||||
return QDialog::exec ();
|
||||
}
|
||||
|
||||
/*
|
||||
* 0 - General
|
||||
* 1 - Layers
|
||||
* 2 - Reference points
|
||||
*/
|
||||
static int next_pages[] = { 1, 2, -1 };
|
||||
static int prev_pages[] = { -1, 0, 1 };
|
||||
|
||||
void
|
||||
StreamImportDialog::next_page ()
|
||||
{
|
||||
BEGIN_PROTECTED
|
||||
commit_page ();
|
||||
|
||||
int index = mp_ui->central_stack->currentIndex ();
|
||||
if (index >= 0 && index < int (sizeof (next_pages) / sizeof (next_pages [0]))) {
|
||||
index = next_pages [index];
|
||||
if (index >= 0) {
|
||||
mp_ui->central_stack->setCurrentIndex (index);
|
||||
enter_page ();
|
||||
}
|
||||
}
|
||||
|
||||
update ();
|
||||
END_PROTECTED
|
||||
}
|
||||
|
||||
void
|
||||
StreamImportDialog::last_page ()
|
||||
{
|
||||
// "safe" commit
|
||||
try {
|
||||
commit_page ();
|
||||
} catch (...) { }
|
||||
|
||||
BEGIN_PROTECTED
|
||||
|
||||
int index = mp_ui->central_stack->currentIndex ();
|
||||
if (index >= 0 && index < int (sizeof (next_pages) / sizeof (next_pages [0]))) {
|
||||
index = prev_pages [index];
|
||||
if (index >= 0) {
|
||||
mp_ui->central_stack->setCurrentIndex (index);
|
||||
}
|
||||
}
|
||||
|
||||
update ();
|
||||
END_PROTECTED
|
||||
}
|
||||
|
||||
void
|
||||
StreamImportDialog::enter_page ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void
|
||||
StreamImportDialog::commit_page ()
|
||||
{
|
||||
int page = mp_ui->central_stack->currentIndex ();
|
||||
|
||||
if (page == 0) {
|
||||
|
||||
// --- General page
|
||||
mp_data->file = tl::to_string (mp_ui->file_le->text ());
|
||||
mp_data->topcell = tl::to_string (mp_ui->topcell_le->text ());
|
||||
if (mp_ui->import_simple_rb->isChecked ()) {
|
||||
mp_data->mode = StreamImportData::Simple;
|
||||
} else if (mp_ui->import_instantiate_rb->isChecked ()) {
|
||||
mp_data->mode = StreamImportData::Instantiate;
|
||||
} else if (mp_ui->import_extra_rb->isChecked ()) {
|
||||
mp_data->mode = StreamImportData::Extra;
|
||||
} else if (mp_ui->import_merge_rb->isChecked ()) {
|
||||
mp_data->mode = StreamImportData::Merge;
|
||||
}
|
||||
|
||||
} else if (page == 1) {
|
||||
|
||||
// --- Layer mapping
|
||||
if (mp_ui->no_mapping_rb->isChecked ()) {
|
||||
mp_data->layer_mode = StreamImportData::Original;
|
||||
} else if (mp_ui->offset_rb->isChecked ()) {
|
||||
mp_data->layer_mode = StreamImportData::Offset;
|
||||
}
|
||||
|
||||
mp_data->layer_offset = db::LayerOffset ();
|
||||
std::string offset = tl::to_string (mp_ui->offset_le->text ());
|
||||
tl::Extractor ex (offset.c_str ());
|
||||
mp_data->layer_offset.read (ex);
|
||||
|
||||
} else if (page == 2) {
|
||||
|
||||
// --- Coordinate Mapping page
|
||||
QLineEdit *(coord_editors[][4]) = {
|
||||
{ mp_ui->pcb_x1_le, mp_ui->pcb_y1_le, mp_ui->layout_x1_le, mp_ui->layout_y1_le },
|
||||
{ mp_ui->pcb_x2_le, mp_ui->pcb_y2_le, mp_ui->layout_x2_le, mp_ui->layout_y2_le },
|
||||
{ mp_ui->pcb_x3_le, mp_ui->pcb_y3_le, mp_ui->layout_x3_le, mp_ui->layout_y3_le }
|
||||
};
|
||||
|
||||
mp_data->reference_points.clear ();
|
||||
for (unsigned int i = 0; i < sizeof (coord_editors) / sizeof (coord_editors [0]); ++i) {
|
||||
|
||||
std::string t_pcb_x (tl::to_string (coord_editors [i][0]->text ()));
|
||||
tl::Extractor pcb_x (t_pcb_x.c_str ());
|
||||
|
||||
std::string t_pcb_y (tl::to_string (coord_editors [i][1]->text ()));
|
||||
tl::Extractor pcb_y (t_pcb_y.c_str ());
|
||||
|
||||
std::string t_layout_x (tl::to_string (coord_editors [i][2]->text ()));
|
||||
tl::Extractor layout_x (t_layout_x.c_str ());
|
||||
|
||||
std::string t_layout_y (tl::to_string (coord_editors [i][3]->text ()));
|
||||
tl::Extractor layout_y (t_layout_y.c_str ());
|
||||
|
||||
if (pcb_x.at_end () || pcb_y.at_end () || layout_x.at_end () || layout_y.at_end ()) {
|
||||
|
||||
if (! pcb_x.at_end () || ! pcb_y.at_end () || ! layout_x.at_end () || ! layout_y.at_end ()) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("All coordinates (imported and existing layout) must be specified for a reference point")));
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
double x, y;
|
||||
|
||||
pcb_x.read (x);
|
||||
pcb_x.expect_end ();
|
||||
pcb_y.read (y);
|
||||
pcb_y.expect_end ();
|
||||
db::DPoint pcb (x, y);
|
||||
|
||||
layout_x.read (x);
|
||||
layout_x.expect_end ();
|
||||
layout_y.read (y);
|
||||
layout_y.expect_end ();
|
||||
db::DPoint layout (x, y);
|
||||
|
||||
mp_data->reference_points.push_back (std::make_pair (pcb, layout));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
std::string t (tl::to_string (mp_ui->explicit_trans_le->text ()));
|
||||
tl::Extractor ex (t.c_str ());
|
||||
mp_data->explicit_trans = db::DCplxTrans ();
|
||||
if (! ex.at_end ()) {
|
||||
ex.read (mp_data->explicit_trans);
|
||||
ex.expect_end ();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
StreamImportDialog::update ()
|
||||
{
|
||||
std::string section_headers[] = {
|
||||
tl::to_string (QObject::tr ("General")),
|
||||
tl::to_string (QObject::tr ("Layers")),
|
||||
tl::to_string (QObject::tr ("Coordinate Mapping")),
|
||||
};
|
||||
|
||||
int page = mp_ui->central_stack->currentIndex ();
|
||||
if (page < 0 || page >= int (sizeof (section_headers) / sizeof (section_headers [0]))) {
|
||||
return;
|
||||
}
|
||||
|
||||
mp_ui->last_pb->setEnabled (page > 0);
|
||||
mp_ui->next_pb->setEnabled (page < int (sizeof (section_headers) / sizeof (section_headers [0]) - 1));
|
||||
mp_ui->section_header_lbl->setText (tl::to_qstring (section_headers [page]));
|
||||
|
||||
// --- General page
|
||||
mp_ui->file_le->setText (tl::to_qstring (mp_data->file));
|
||||
mp_ui->topcell_le->setText (tl::to_qstring (mp_data->topcell));
|
||||
mp_ui->import_simple_rb->setChecked (mp_data->mode == StreamImportData::Simple);
|
||||
mp_ui->import_extra_rb->setChecked (mp_data->mode == StreamImportData::Extra);
|
||||
mp_ui->import_instantiate_rb->setChecked (mp_data->mode == StreamImportData::Instantiate);
|
||||
mp_ui->import_merge_rb->setChecked (mp_data->mode == StreamImportData::Merge);
|
||||
|
||||
// --- Layers page
|
||||
mp_ui->no_mapping_rb->setChecked (mp_data->layer_mode == StreamImportData::Original);
|
||||
mp_ui->offset_rb->setChecked (mp_data->layer_mode == StreamImportData::Offset);
|
||||
mp_ui->offset_le->setText (tl::to_qstring (mp_data->layer_offset.to_string ()));
|
||||
mapping_changed ();
|
||||
|
||||
// --- Coordinate Mapping page
|
||||
QLineEdit *(coord_editors[][4]) = {
|
||||
{ mp_ui->pcb_x1_le, mp_ui->pcb_y1_le, mp_ui->layout_x1_le, mp_ui->layout_y1_le },
|
||||
{ mp_ui->pcb_x2_le, mp_ui->pcb_y2_le, mp_ui->layout_x2_le, mp_ui->layout_y2_le },
|
||||
{ mp_ui->pcb_x3_le, mp_ui->pcb_y3_le, mp_ui->layout_x3_le, mp_ui->layout_y3_le }
|
||||
};
|
||||
|
||||
for (unsigned int i = 0; i < sizeof (coord_editors) / sizeof (coord_editors [0]); ++i) {
|
||||
if (mp_data->reference_points.size () > i) {
|
||||
coord_editors[i][0]->setText (tl::to_qstring (tl::to_string (mp_data->reference_points [i].first.x ())));
|
||||
coord_editors[i][1]->setText (tl::to_qstring (tl::to_string (mp_data->reference_points [i].first.y ())));
|
||||
coord_editors[i][2]->setText (tl::to_qstring (tl::to_string (mp_data->reference_points [i].second.x ())));
|
||||
coord_editors[i][3]->setText (tl::to_qstring (tl::to_string (mp_data->reference_points [i].second.y ())));
|
||||
} else {
|
||||
for (unsigned int j = 0; j < 4; ++j) {
|
||||
coord_editors[i][j]->setText (QString ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mp_data->explicit_trans == db::DCplxTrans ()) {
|
||||
mp_ui->explicit_trans_le->setText (QString ());
|
||||
} else {
|
||||
mp_ui->explicit_trans_le->setText (tl::to_qstring (mp_data->explicit_trans.to_string ()));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
StreamImportDialog::mapping_changed ()
|
||||
{
|
||||
mp_ui->offset_le->setEnabled (mp_ui->offset_rb->isChecked ());
|
||||
}
|
||||
|
||||
void
|
||||
StreamImportDialog::reset ()
|
||||
{
|
||||
// Commit everything that is not loaded
|
||||
try {
|
||||
commit_page ();
|
||||
} catch (...) {
|
||||
// ..
|
||||
}
|
||||
|
||||
*mp_data = StreamImportData ();
|
||||
mp_ui->central_stack->setCurrentIndex (0);
|
||||
update ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2018 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_layStreamImportDialog
|
||||
#define HDR_layStreamImportDialog
|
||||
|
||||
#include <QDialog>
|
||||
#include <QAction>
|
||||
#include <QFrame>
|
||||
#include <QComboBox>
|
||||
|
||||
#include "dbLayout.h"
|
||||
#include "dbPoint.h"
|
||||
#include "dbTrans.h"
|
||||
#include "dbLayerProperties.h"
|
||||
#include "dbLoadLayoutOptions.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
class QTreeWidgetItem;
|
||||
class QTreeWidget;
|
||||
class QToolButton;
|
||||
class QLineEdit;
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class StreamImportDialog;
|
||||
}
|
||||
|
||||
namespace tl
|
||||
{
|
||||
class InputStream;
|
||||
}
|
||||
|
||||
namespace lay
|
||||
{
|
||||
class PluginRoot;
|
||||
}
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
||||
class StreamImporter;
|
||||
|
||||
struct StreamImportData
|
||||
{
|
||||
public:
|
||||
StreamImportData ();
|
||||
|
||||
enum mode_type { Simple = 0, Instantiate = 1, Extra = 2, Merge = 3 };
|
||||
enum layer_mode_type { Original = 0, Offset = 1 };
|
||||
|
||||
mode_type mode;
|
||||
std::string file;
|
||||
std::string topcell;
|
||||
std::vector <std::pair <db::DPoint, db::DPoint> > reference_points;
|
||||
db::DCplxTrans explicit_trans;
|
||||
layer_mode_type layer_mode;
|
||||
db::LayerOffset layer_offset;
|
||||
db::LoadLayoutOptions options;
|
||||
|
||||
void setup_importer (StreamImporter *importer);
|
||||
void from_string (const std::string &s);
|
||||
std::string to_string () const;
|
||||
};
|
||||
|
||||
class StreamImportDialog
|
||||
: public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
StreamImportDialog (QWidget *parent, StreamImportData *data);
|
||||
~StreamImportDialog ();
|
||||
|
||||
int exec ();
|
||||
void accept ();
|
||||
void reject ();
|
||||
|
||||
public slots:
|
||||
void next_page ();
|
||||
void last_page ();
|
||||
void browse_filename ();
|
||||
void edit_options ();
|
||||
void reset_options ();
|
||||
void reset ();
|
||||
void mapping_changed ();
|
||||
|
||||
private:
|
||||
StreamImportData *mp_data;
|
||||
Ui::StreamImportDialog *mp_ui;
|
||||
|
||||
void update ();
|
||||
void commit_page ();
|
||||
void enter_page ();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,281 @@
|
||||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2018 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 "layStreamImporter.h"
|
||||
#include "layLayoutView.h"
|
||||
#include "tlStream.h"
|
||||
#include "tlString.h"
|
||||
#include "tlString.h"
|
||||
#include "tlLog.h"
|
||||
#include "dbEdgeProcessor.h"
|
||||
#include "dbCellMapping.h"
|
||||
#include "dbLayoutUtils.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QMessageBox>
|
||||
#include <QApplication>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
||||
// ---------------------------------------------------------------------------------------
|
||||
// Implementation of StreamImporter
|
||||
|
||||
StreamImporter::StreamImporter ()
|
||||
: m_cell_mapping (StreamImportData::Simple), m_layer_mapping (StreamImportData::Original)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void
|
||||
StreamImporter::read (db::Layout &target, db::cell_index_type target_cell_index, std::vector <unsigned int> &new_layers)
|
||||
{
|
||||
// Clear the undo buffer
|
||||
if (target.manager () && !target.manager ()->transacting ()) {
|
||||
target.manager ()->clear ();
|
||||
}
|
||||
|
||||
tl::log << tl::to_string (QObject::tr ("Importing stream data"));
|
||||
// tl::Progress m_progress (tl::to_string (QObject::tr ("Importing stream data")), m_files.size (), 1);
|
||||
|
||||
// TODO: this code should be available otherwise ...
|
||||
// derive the actual global transformation from the reference points
|
||||
db::DCplxTrans global_trans (m_global_trans);
|
||||
if (! m_reference_points.empty ()) {
|
||||
|
||||
db::DPoint p1_pcb = m_reference_points[0].first;
|
||||
db::DPoint p1_ly = m_reference_points[0].second;
|
||||
|
||||
if (m_reference_points.size () > 1) {
|
||||
|
||||
db::DPoint p2_pcb = m_reference_points[1].first;
|
||||
db::DPoint p2_ly = m_reference_points[1].second;
|
||||
|
||||
db::DVector d12_pcb = (p2_pcb - p1_pcb) * (1.0 / p2_pcb.distance (p1_pcb));
|
||||
db::DVector d12_ly = (p2_ly - p1_ly) * (1.0 / p2_ly.distance (p1_ly));
|
||||
|
||||
int ru = -1;
|
||||
int rm = -1;
|
||||
for (int f = 0; f < 8; ++f) {
|
||||
db::DVector d12 = db::DTrans (f) * d12_pcb;
|
||||
if ((d12 - d12_ly).length () < 0.1) {
|
||||
if (f < 4) {
|
||||
ru = f;
|
||||
} else {
|
||||
rm = f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ru < 0 || rm < 0) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Unable to deduce rotation from reference points p1 and p2 (imported and existing layout)")));
|
||||
}
|
||||
|
||||
if (m_reference_points.size () > 2) {
|
||||
|
||||
db::DPoint p3_pcb = m_reference_points[2].first;
|
||||
db::DPoint p3_ly = m_reference_points[2].second;
|
||||
|
||||
db::DVector d13_pcb = (p3_pcb - p1_pcb) * (1.0 / p3_pcb.distance (p1_pcb));
|
||||
db::DVector d13_ly = (p3_ly - p1_ly) * (1.0 / p3_ly.distance (p1_ly));
|
||||
|
||||
double vp_pcb = d13_pcb.x () * d12_pcb.y () - d13_pcb.y () * d12_pcb.x ();
|
||||
double vp_gds = d13_ly.x () * d12_ly.y () - d13_ly.y () * d12_ly.x ();
|
||||
|
||||
if (vp_pcb * vp_gds < 0.0) {
|
||||
global_trans = db::DCplxTrans (db::DFTrans (rm));
|
||||
} else {
|
||||
global_trans = db::DCplxTrans (db::DFTrans (ru));
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (global_trans.is_mirror ()) {
|
||||
global_trans = db::DCplxTrans (db::DFTrans (rm));
|
||||
} else {
|
||||
global_trans = db::DCplxTrans (db::DFTrans (ru));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
global_trans = db::DCplxTrans (p1_ly - (db::DPoint () + global_trans.disp ())) * global_trans * db::DCplxTrans (db::DPoint () - p1_pcb);
|
||||
|
||||
}
|
||||
|
||||
// Prepare the layout to read
|
||||
db::Layout source;
|
||||
|
||||
// Load the layout
|
||||
{
|
||||
tl::InputStream stream (m_file);
|
||||
db::Reader reader (stream);
|
||||
|
||||
tl::log << tl::to_string (QObject::tr ("Loading file: ")) << m_file;
|
||||
tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (QObject::tr ("Loading")));
|
||||
reader.read (source, m_options);
|
||||
}
|
||||
|
||||
// Locate the top cell in the source file
|
||||
db::cell_index_type source_topcell;
|
||||
std::vector <db::cell_index_type> source_cells;
|
||||
|
||||
if (m_cell_mapping != StreamImportData::Extra || !m_topcell.empty ()) {
|
||||
|
||||
if (m_topcell.empty ()) {
|
||||
|
||||
db::Layout::top_down_const_iterator t = source.begin_top_down ();
|
||||
if (t == source.end_top_down ()) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Source layout does not have a top cell")));
|
||||
}
|
||||
|
||||
source_topcell = *t;
|
||||
|
||||
++t;
|
||||
if (t != source.end_top_cells ()) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Source layout does not have a unique top cell - specify one explicitly")));
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
std::pair<bool, db::cell_index_type> t = source.cell_by_name (m_topcell.c_str ());
|
||||
if (! t.first) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Source layout does not have a cell named '%s'")), m_topcell);
|
||||
}
|
||||
|
||||
source_topcell = t.second;
|
||||
|
||||
}
|
||||
|
||||
source_cells.push_back (source_topcell);
|
||||
|
||||
} else {
|
||||
|
||||
// collect source cells
|
||||
for (db::Layout::top_down_const_iterator t = source.begin_top_down (); t != source.end_top_cells (); ++t) {
|
||||
source_cells.push_back (*t);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Issue a warning, if the transformation is not ortho etc.
|
||||
if (fabs (global_trans.mag () - floor (global_trans.mag () + 0.5)) > 1e-6 || ! global_trans.is_ortho ()) {
|
||||
|
||||
if (QMessageBox::warning (QApplication::activeWindow (),
|
||||
QObject::tr ("Complex Transformation"),
|
||||
tl::to_qstring (tl::sprintf (tl::to_string (QObject::tr ("The specified transformation (%s) is complex.\nGrid snapping to the database unit grid can occur and\neffectively alter the geometry of the layout.\nPress 'Ok' to continue.")), global_trans.to_string ())),
|
||||
QMessageBox::Ok | QMessageBox::Cancel,
|
||||
QMessageBox::Ok) != QMessageBox::Ok) {
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Create a layer map
|
||||
std::map <unsigned int, unsigned int> layer_map;
|
||||
for (db::Layout::layer_iterator l = source.begin_layers (); l != source.end_layers (); ++l) {
|
||||
|
||||
db::LayerProperties lp (*(*l).second);
|
||||
if (m_layer_mapping == StreamImportData::Offset) {
|
||||
lp = m_layer_offset.apply (lp);
|
||||
}
|
||||
|
||||
bool layer_found = false;
|
||||
for (db::Layout::layer_iterator ll = target.begin_layers (); ll != target.end_layers () && ! layer_found; ++ll) {
|
||||
if ((*ll).second->log_equal (lp)) {
|
||||
layer_map.insert (std::make_pair ((*l).first, (*ll).first));
|
||||
layer_found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (! layer_found) {
|
||||
unsigned int new_layer = target.insert_layer (lp);
|
||||
layer_map.insert (std::make_pair ((*l).first, new_layer));
|
||||
new_layers.push_back (new_layer);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Create a cell map
|
||||
std::map <db::cell_index_type, db::cell_index_type> cell_map;
|
||||
|
||||
if (m_cell_mapping == StreamImportData::Simple) {
|
||||
|
||||
cell_map.insert (std::make_pair (source_topcell, target_cell_index));
|
||||
|
||||
} else if (m_cell_mapping == StreamImportData::Extra) {
|
||||
|
||||
// create new top cells for each source top cell
|
||||
for (std::vector<db::cell_index_type>::const_iterator t = source_cells.begin (); t != source_cells.end (); ++t) {
|
||||
db::cell_index_type new_top = target.add_cell (source.cell_name (*t));
|
||||
cell_map.insert (std::make_pair (*t, new_top));
|
||||
}
|
||||
|
||||
} else if (m_cell_mapping == StreamImportData::Instantiate) {
|
||||
|
||||
// Create a new top cell for importing into and use the cell reference to produce the first part of the transformation
|
||||
|
||||
db::cell_index_type new_top = target.add_cell (source.cell_name (source_topcell));
|
||||
cell_map.insert (std::make_pair (source_topcell, new_top));
|
||||
|
||||
db::ICplxTrans gt_dbu = db::VCplxTrans (1.0 / target.dbu ()) * global_trans * db::CplxTrans (source.dbu ());
|
||||
target.cell (target_cell_index).insert (db::CellInstArray (new_top, gt_dbu * db::ICplxTrans (1.0 / global_trans.mag ())));
|
||||
|
||||
global_trans = db::DCplxTrans (global_trans.mag ());
|
||||
|
||||
} else if (m_cell_mapping == StreamImportData::Merge) {
|
||||
|
||||
// Create the cell mapping
|
||||
// TODO: Currently no merging is provided for non-unity transformations
|
||||
if (! global_trans.equal (db::DCplxTrans ())) {
|
||||
|
||||
if (QMessageBox::warning (QApplication::activeWindow (),
|
||||
QObject::tr ("Merge Mode Is Not Available"),
|
||||
tl::to_qstring (tl::sprintf (tl::to_string (QObject::tr ("Merge mode is not supported for the specified transformation (%s).\nSimple mode will be used instead.\nPress 'Ok' to continue.")), global_trans.to_string ())),
|
||||
QMessageBox::Ok | QMessageBox::Cancel,
|
||||
QMessageBox::Ok) != QMessageBox::Ok) {
|
||||
return;
|
||||
}
|
||||
|
||||
cell_map.insert (std::make_pair (source_topcell, target_cell_index));
|
||||
|
||||
} else {
|
||||
|
||||
db::CellMapping cm;
|
||||
cm.create_from_geometry (target, target_cell_index, source, source_topcell);
|
||||
cell_map.insert (cm.begin (), cm.end ());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// And actually merge
|
||||
db::merge_layouts (target, source, db::VCplxTrans (1.0 / target.dbu ()) * global_trans * db::CplxTrans (source.dbu ()), source_cells, cell_map, layer_map);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,208 @@
|
||||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2018 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_layStreamImporter
|
||||
#define HDR_layStreamImporter
|
||||
|
||||
#include "layPluginCommon.h"
|
||||
|
||||
#include "dbLayout.h"
|
||||
#include "dbTrans.h"
|
||||
#include "dbLoadLayoutOptions.h"
|
||||
#include "tlStream.h"
|
||||
#include "tlProgress.h"
|
||||
#include "layStreamImportDialog.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace db
|
||||
{
|
||||
class Manager;
|
||||
}
|
||||
|
||||
namespace lay
|
||||
{
|
||||
class LayoutView;
|
||||
}
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief The Stream importer object
|
||||
*/
|
||||
class LAY_PLUGIN_PUBLIC StreamImporter
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
*/
|
||||
StreamImporter ();
|
||||
|
||||
/**
|
||||
* @brief Read into an existing layout
|
||||
*
|
||||
* This method reads the layout specified into the given layout and cell.
|
||||
*/
|
||||
void read (db::Layout &layout, db::cell_index_type cell_index, std::vector <unsigned int> &new_layers);
|
||||
|
||||
/**
|
||||
* @brief Specifies the global transformation
|
||||
*
|
||||
* This specifies the global transformation to apply (in micron units).
|
||||
*/
|
||||
void set_global_trans (const db::DCplxTrans &trans)
|
||||
{
|
||||
m_global_trans = trans;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the global transformation
|
||||
*/
|
||||
const db::DCplxTrans &global_trans () const
|
||||
{
|
||||
return m_global_trans;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the reference points
|
||||
*/
|
||||
void set_reference_points (const std::vector<std::pair <db::DPoint, db::DPoint> > &pts)
|
||||
{
|
||||
m_reference_points = pts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set file which is read.
|
||||
*/
|
||||
void set_file (const std::string &file)
|
||||
{
|
||||
m_file = file;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the file which is read
|
||||
*/
|
||||
const std::string &file () const
|
||||
{
|
||||
return m_file;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set top cell name which is read.
|
||||
*
|
||||
* If an empty top cell name is specified, the top cell is determined automatically (it must be a unique top cell in some
|
||||
* cases).
|
||||
*/
|
||||
void set_topcell (const std::string &topcell)
|
||||
{
|
||||
m_topcell = topcell;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the top cell name.
|
||||
*/
|
||||
const std::string &topcell () const
|
||||
{
|
||||
return m_topcell;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set cell mapping mode
|
||||
*/
|
||||
void set_cell_mapping (StreamImportData::mode_type cell_mapping)
|
||||
{
|
||||
m_cell_mapping = cell_mapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the cell mapping mode
|
||||
*/
|
||||
StreamImportData::mode_type cell_mapping () const
|
||||
{
|
||||
return m_cell_mapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set layer mapping mode
|
||||
*/
|
||||
void set_layer_mapping (StreamImportData::layer_mode_type layer_mapping)
|
||||
{
|
||||
m_layer_mapping = layer_mapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the layer mapping mode
|
||||
*/
|
||||
StreamImportData::layer_mode_type layer_mapping () const
|
||||
{
|
||||
return m_layer_mapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set layer offset
|
||||
*/
|
||||
void set_layer_offset (const db::LayerOffset &layer_offset)
|
||||
{
|
||||
m_layer_offset = layer_offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the layer offset
|
||||
*/
|
||||
db::LayerOffset layer_offset () const
|
||||
{
|
||||
return m_layer_offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set reader options
|
||||
*/
|
||||
void set_reader_options (const db::LoadLayoutOptions &options)
|
||||
{
|
||||
m_options = options;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the reader options
|
||||
*/
|
||||
const db::LoadLayoutOptions &reader_options () const
|
||||
{
|
||||
return m_options;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_file;
|
||||
std::string m_topcell;
|
||||
db::DCplxTrans m_global_trans;
|
||||
std::vector <std::pair <db::DPoint, db::DPoint> > m_reference_points;
|
||||
StreamImportData::mode_type m_cell_mapping;
|
||||
StreamImportData::layer_mode_type m_layer_mapping;
|
||||
db::LayerOffset m_layer_offset;
|
||||
db::LoadLayoutOptions m_options;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
|
||||
TARGET = import
|
||||
DESTDIR = $$OUT_PWD/../../../../lay_plugins
|
||||
|
||||
include($$PWD/../../../lay_plugin.pri)
|
||||
|
||||
HEADERS = \
|
||||
layStreamImporter.h \
|
||||
layStreamImportDialog.h
|
||||
|
||||
SOURCES = \
|
||||
layStreamImporter.cc \
|
||||
layStreamImportDialog.cc \
|
||||
layStreamImport.cc
|
||||
|
||||
FORMS = \
|
||||
StreamImportDialog.ui \
|
||||
@@ -25,7 +25,7 @@
|
||||
#ifndef HDR_dbNetTracer
|
||||
#define HDR_dbNetTracer
|
||||
|
||||
#include "dbCommon.h"
|
||||
#include "dbPluginCommon.h"
|
||||
|
||||
#include "dbShapes.h"
|
||||
#include "dbShape.h"
|
||||
@@ -52,7 +52,7 @@ class NetTracerData;
|
||||
* the data and second, this guarantees that the Shape references delivered point to the same object
|
||||
* for identical shapes.
|
||||
*/
|
||||
class DB_PUBLIC NetTracerShapeHeap
|
||||
class DB_PLUGIN_PUBLIC NetTracerShapeHeap
|
||||
{
|
||||
public:
|
||||
/**
|
||||
@@ -81,7 +81,7 @@ private:
|
||||
* This class describes a shape in the hierarchy by the transformation into the top cell, the shape reference, the cell
|
||||
* index and the layer the shape resides on.
|
||||
*/
|
||||
class DB_PUBLIC NetTracerShape
|
||||
class DB_PLUGIN_PUBLIC NetTracerShape
|
||||
{
|
||||
public:
|
||||
/**
|
||||
@@ -252,7 +252,7 @@ typedef db::box_tree<db::Box, const NetTracerShape *, HitTestDataBoxConverter, 1
|
||||
/**
|
||||
* @brief Describes a boolean expression for computed layers
|
||||
*/
|
||||
class DB_PUBLIC NetTracerLayerExpression
|
||||
class DB_PLUGIN_PUBLIC NetTracerLayerExpression
|
||||
{
|
||||
public:
|
||||
/**
|
||||
@@ -397,7 +397,7 @@ private:
|
||||
* This class has three members: the index of the first conductive layer, the
|
||||
* index of the via layer and the index of the second conductive layer.
|
||||
*/
|
||||
class DB_PUBLIC NetTracerConnection
|
||||
class DB_PLUGIN_PUBLIC NetTracerConnection
|
||||
{
|
||||
public:
|
||||
/**
|
||||
@@ -474,7 +474,7 @@ private:
|
||||
/**
|
||||
* @brief Wraps the data for a net tracing
|
||||
*/
|
||||
class DB_PUBLIC NetTracerData
|
||||
class DB_PLUGIN_PUBLIC NetTracerData
|
||||
{
|
||||
public:
|
||||
/**
|
||||
@@ -582,7 +582,7 @@ private:
|
||||
* Net tracing can be performed with a given seed point and given tracing data.
|
||||
* The tracing is initiated with the "trace" method.
|
||||
*/
|
||||
class DB_PUBLIC NetTracer
|
||||
class DB_PLUGIN_PUBLIC NetTracer
|
||||
{
|
||||
public:
|
||||
typedef std::set <NetTracerShape>::const_iterator iterator;
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#ifndef HDR_dbNetTracerIO
|
||||
#define HDR_dbNetTracerIO
|
||||
|
||||
#include "dbPluginCommon.h"
|
||||
#include "dbNetTracer.h"
|
||||
#include "dbLayerProperties.h"
|
||||
#include "dbTechnology.h"
|
||||
@@ -34,7 +35,7 @@ namespace db
|
||||
|
||||
class NetTracerTechnologyComponent;
|
||||
|
||||
class DB_PUBLIC NetTracerLayerExpressionInfo
|
||||
class DB_PLUGIN_PUBLIC NetTracerLayerExpressionInfo
|
||||
{
|
||||
public:
|
||||
NetTracerLayerExpressionInfo ();
|
||||
@@ -72,7 +73,7 @@ private:
|
||||
NetTracerLayerExpression *get_expr (const db::LayerProperties &lp, const db::Layout &layout, const NetTracerTechnologyComponent &tech, const std::set<std::string> &used_symbols) const;
|
||||
};
|
||||
|
||||
class DB_PUBLIC NetTracerConnectionInfo
|
||||
class DB_PLUGIN_PUBLIC NetTracerConnectionInfo
|
||||
{
|
||||
public:
|
||||
NetTracerConnectionInfo ();
|
||||
@@ -118,7 +119,7 @@ private:
|
||||
NetTracerLayerExpressionInfo m_la, m_via, m_lb;
|
||||
};
|
||||
|
||||
class DB_PUBLIC NetTracerSymbolInfo
|
||||
class DB_PLUGIN_PUBLIC NetTracerSymbolInfo
|
||||
{
|
||||
public:
|
||||
NetTracerSymbolInfo ();
|
||||
@@ -152,7 +153,7 @@ private:
|
||||
std::string m_expression;
|
||||
};
|
||||
|
||||
class DB_PUBLIC Net
|
||||
class DB_PLUGIN_PUBLIC Net
|
||||
{
|
||||
public:
|
||||
typedef std::vector <db::NetTracerShape>::const_iterator iterator;
|
||||
@@ -355,7 +356,7 @@ private:
|
||||
void define_layer (unsigned int l, const db::LayerProperties &lp, const db::LayerProperties &lp_representative);
|
||||
};
|
||||
|
||||
class DB_PUBLIC NetTracerTechnologyComponent
|
||||
class DB_PLUGIN_PUBLIC NetTracerTechnologyComponent
|
||||
: public db::TechnologyComponent
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -8,8 +8,8 @@ include($$PWD/../../../../lib_ut.pri)
|
||||
SOURCES = \
|
||||
dbNetTracer.cc \
|
||||
|
||||
INCLUDEPATH += $$LAY_INC $$TL_INC $$DB_INC $$GSI_INC $$PWD/../db_plugin
|
||||
DEPENDPATH += $$LAY_INC $$TL_INC $$DB_INC $$GSI_INC $$PWD/../db_plugin
|
||||
INCLUDEPATH += $$LAY_INC $$TL_INC $$DB_INC $$GSI_INC $$PWD/../db_plugin $$PWD/../../../common
|
||||
DEPENDPATH += $$LAY_INC $$TL_INC $$DB_INC $$GSI_INC $$PWD/../db_plugin $$PWD/../../../common
|
||||
|
||||
LIBS += -L$$DESTDIR_UT -lklayout_db -lklayout_tl -lklayout_gsi
|
||||
|
||||
|
||||
@@ -0,0 +1,605 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>XORToolDialog</class>
|
||||
<widget class="QDialog" name="XORToolDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>576</width>
|
||||
<height>649</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>XOR Tool</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Input</string>
|
||||
</property>
|
||||
<layout class="QGridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="text">
|
||||
<string>From region</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Layout A</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Use for input </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Layout B</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="input_layers_cbx">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>All Layers (different layouts)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Visible layers (different layouts)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>10</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QComboBox" name="region_cbx">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>All</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Visible region</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Clipped to ruler</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="lay::CellViewSelectionComboBox" name="layoutb">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToContentsOnFirstShow</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="lay::CellViewSelectionComboBox" name="layouta">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToContentsOnFirstShow</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>10</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Options</string>
|
||||
</property>
|
||||
<layout class="QGridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="1" column="1" colspan="2">
|
||||
<widget class="QCheckBox" name="anotb_cb">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>A NOT B (In A but not in B)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="2">
|
||||
<widget class="QCheckBox" name="axorb_cb">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>A XOR B (differences)</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="3">
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>10</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="4" column="1" colspan="2">
|
||||
<widget class="QCheckBox" name="summarize_cb">
|
||||
<property name="text">
|
||||
<string>Summarize missing layers</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Tolerances</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Compare modes </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Tolerances (t1,t2,..) in micron</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>Threads</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Tiling</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1" colspan="2">
|
||||
<widget class="QFrame" name="frame">
|
||||
<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>
|
||||
<widget class="QLineEdit" name="tiling">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Tile size in micron</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="heal_cb">
|
||||
<property name="text">
|
||||
<string>Heal result shapes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1" colspan="2">
|
||||
<widget class="QFrame" name="frame_2">
|
||||
<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>
|
||||
<widget class="QSpinBox" name="threads">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Used for tiles and layers</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" colspan="2">
|
||||
<widget class="QCheckBox" name="bnota_cb">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>B NOT A (in B but not in A)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLineEdit" name="tolerances">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_4">
|
||||
<property name="title">
|
||||
<string>Output</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Send output to </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="output_cbx">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Marker database</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Other layout</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>New layers in layout A ...</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>New layers in layout B ...</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="layer_offset_lbl">
|
||||
<property name="text">
|
||||
<string>with offset</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="layer_offset_le">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>1000/0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>lay::CellViewSelectionComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>layWidgets.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>layouta</tabstop>
|
||||
<tabstop>layoutb</tabstop>
|
||||
<tabstop>input_layers_cbx</tabstop>
|
||||
<tabstop>region_cbx</tabstop>
|
||||
<tabstop>axorb_cb</tabstop>
|
||||
<tabstop>anotb_cb</tabstop>
|
||||
<tabstop>bnota_cb</tabstop>
|
||||
<tabstop>summarize_cb</tabstop>
|
||||
<tabstop>tolerances</tabstop>
|
||||
<tabstop>tiling</tabstop>
|
||||
<tabstop>threads</tabstop>
|
||||
<tabstop>output_cbx</tabstop>
|
||||
<tabstop>layer_offset_le</tabstop>
|
||||
<tabstop>buttonBox</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>XORToolDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>XORToolDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -0,0 +1,121 @@
|
||||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2018 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 "layXORToolDialog.h"
|
||||
|
||||
#include "layPlugin.h"
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
||||
class XORPlugin
|
||||
: public lay::Plugin
|
||||
{
|
||||
public:
|
||||
XORPlugin (Plugin *parent, lay::LayoutView *view)
|
||||
: lay::Plugin (parent), mp_view (view)
|
||||
{
|
||||
mp_dialog = new lay::XORToolDialog (0);
|
||||
}
|
||||
|
||||
~XORPlugin ()
|
||||
{
|
||||
delete mp_dialog;
|
||||
mp_dialog = 0;
|
||||
}
|
||||
|
||||
void menu_activated (const std::string &symbol)
|
||||
{
|
||||
if (symbol == "lay::xor_tool") {
|
||||
|
||||
if (mp_dialog->exec_dialog (mp_view)) {
|
||||
|
||||
// ... implementation is in layXORToolDialog.cc ...
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
lay::LayoutView *mp_view;
|
||||
lay::XORToolDialog *mp_dialog;
|
||||
};
|
||||
|
||||
class XORPluginDeclaration
|
||||
: public lay::PluginDeclaration
|
||||
{
|
||||
public:
|
||||
XORPluginDeclaration ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
virtual void get_options (std::vector < std::pair<std::string, std::string> > &options) const
|
||||
{
|
||||
options.push_back (std::pair<std::string, std::string> (cfg_xor_input_mode, "all"));
|
||||
options.push_back (std::pair<std::string, std::string> (cfg_xor_output_mode, "rdb"));
|
||||
options.push_back (std::pair<std::string, std::string> (cfg_xor_nworkers, "1"));
|
||||
options.push_back (std::pair<std::string, std::string> (cfg_xor_layer_offset, ""));
|
||||
options.push_back (std::pair<std::string, std::string> (cfg_xor_axorb, "true"));
|
||||
options.push_back (std::pair<std::string, std::string> (cfg_xor_anotb, "false"));
|
||||
options.push_back (std::pair<std::string, std::string> (cfg_xor_bnota, "false"));
|
||||
options.push_back (std::pair<std::string, std::string> (cfg_xor_summarize, "false"));
|
||||
options.push_back (std::pair<std::string, std::string> (cfg_xor_tolerances, ""));
|
||||
options.push_back (std::pair<std::string, std::string> (cfg_xor_tiling, ""));
|
||||
options.push_back (std::pair<std::string, std::string> (cfg_xor_region_mode, "all"));
|
||||
}
|
||||
|
||||
virtual lay::ConfigPage *config_page (QWidget * /*parent*/, std::string & /*title*/) const
|
||||
{
|
||||
// .. nothing yet ..
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void get_menu_entries (std::vector<lay::MenuEntry> &menu_entries) const
|
||||
{
|
||||
lay::PluginDeclaration::get_menu_entries (menu_entries);
|
||||
menu_entries.push_back (lay::MenuEntry ("lay::xor_tool", "xor_tool:edit", "tools_menu.post_verification_group", tl::to_string (QObject::tr ("XOR Tool"))));
|
||||
}
|
||||
|
||||
virtual bool configure (const std::string & /*name*/, const std::string & /*value*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void config_finalize ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
lay::Plugin *create_plugin (db::Manager *, lay::PluginRoot *root, lay::LayoutView *view) const
|
||||
{
|
||||
return new XORPlugin (root, view);
|
||||
}
|
||||
};
|
||||
|
||||
static tl::RegisteredClass<lay::PluginDeclaration> config_decl (new lay::XORPluginDeclaration (), 3000, "lay::XORPlugin");
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,414 @@
|
||||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2018 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 "layXORProgress.h"
|
||||
|
||||
#include "tlString.h"
|
||||
|
||||
#include <QWidget>
|
||||
#include <QImage>
|
||||
#include <QPainter>
|
||||
#include <QBitmap>
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
||||
static inline void merge (size_t &a, size_t b)
|
||||
{
|
||||
if (a == missing_in_a || a == missing_in_b) {
|
||||
// leave a
|
||||
} else if (b == missing_in_a || b == missing_in_b) {
|
||||
a = b;
|
||||
} else {
|
||||
a += b;
|
||||
}
|
||||
}
|
||||
|
||||
static void merge (std::vector<std::vector<size_t> > &a, const std::vector<std::vector<size_t> > &b)
|
||||
{
|
||||
if (a.size () < b.size ()) {
|
||||
a.resize (b.size (), std::vector<size_t> ());
|
||||
}
|
||||
|
||||
std::vector<std::vector<size_t> >::iterator ia = a.begin ();
|
||||
for (std::vector<std::vector<size_t> >::const_iterator ib = b.begin (); ib != b.end (); ++ib, ++ia) {
|
||||
if (ia->size () < ib->size ()) {
|
||||
ia->resize (ib->size (), 0);
|
||||
}
|
||||
std::vector<size_t>::iterator ja = ia->begin ();
|
||||
for (std::vector<size_t>::const_iterator jb = ib->begin (); jb != ib->end (); ++jb, ++ja) {
|
||||
merge (*ja, *jb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static size_t sum (const std::vector<std::vector<size_t> > &b)
|
||||
{
|
||||
size_t n = 0;
|
||||
for (std::vector<std::vector<size_t> >::const_iterator i = b.begin (); i != b.end (); ++i) {
|
||||
for (std::vector<size_t>::const_iterator j = i->begin (); j != i->end (); ++j) {
|
||||
merge (n, *j);
|
||||
}
|
||||
if (n == missing_in_a || n == missing_in_b) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------------
|
||||
// The progress widget class
|
||||
|
||||
struct CounterCompare
|
||||
{
|
||||
typedef std::pair<db::LayerProperties, size_t> value_type;
|
||||
bool operator() (const value_type &a, const value_type &b) const
|
||||
{
|
||||
bool a_special = (a.second == missing_in_a || a.second == missing_in_b);
|
||||
bool b_special = (b.second == missing_in_a || b.second == missing_in_b);
|
||||
|
||||
if (a_special != b_special) {
|
||||
return a_special < b_special;
|
||||
}
|
||||
if (a.second != b.second) {
|
||||
return a.second > b.second;
|
||||
}
|
||||
return a.first < b.first;
|
||||
}
|
||||
};
|
||||
|
||||
class XORProgressWidget
|
||||
: public QWidget
|
||||
{
|
||||
public:
|
||||
XORProgressWidget ()
|
||||
: QWidget (0)
|
||||
{
|
||||
m_pixmap_size = 24;
|
||||
m_spacing = 4;
|
||||
|
||||
QFontMetrics fm (font ());
|
||||
m_line_height = std::max (fm.height (), m_pixmap_size + 4);
|
||||
m_font_height = fm.height () * 3 / 2;
|
||||
m_first_column_width = fm.width (QString::fromUtf8 ("LAYERNAME"));
|
||||
m_column_width = m_pixmap_size + 4 + m_spacing + fm.width (QString::fromUtf8 ("1.00G "));
|
||||
}
|
||||
|
||||
QSize sizeHint () const
|
||||
{
|
||||
int w = int (m_tolerance_labels.size ()) * (m_column_width + m_spacing) + m_first_column_width;
|
||||
int col = std::max (1, width () / w);
|
||||
return QSize (w * std::min (int (m_layer_labels.size ()), col), (m_line_height + m_spacing) * ((int (m_layer_labels.size ()) + col - 1) / col) + m_font_height * 2 + m_spacing);
|
||||
}
|
||||
|
||||
void set_results (double dbu, int nx, int ny, const std::map<std::pair<db::LayerProperties, db::Coord>, std::vector<std::vector<size_t> > > &results, const std::map<db::LayerProperties, size_t> &count_per_layer, const std::vector<db::Coord> &tolerances)
|
||||
{
|
||||
m_labels.clear ();
|
||||
m_layer_labels.clear ();
|
||||
m_red_images.clear ();
|
||||
m_green_images.clear ();
|
||||
m_blue_images.clear ();
|
||||
m_yellow_images.clear ();
|
||||
m_labels.clear ();
|
||||
|
||||
QSize szh = sizeHint ();
|
||||
|
||||
m_tolerance_labels.clear ();
|
||||
for (std::vector<db::Coord>::const_iterator t = tolerances.begin (); t != tolerances.end (); ++t) {
|
||||
m_tolerance_labels << tl::to_qstring (tl::sprintf ("%.12g µm", *t * dbu));
|
||||
}
|
||||
|
||||
std::vector<std::pair<db::LayerProperties, size_t> > counters;
|
||||
counters.insert (counters.end (), count_per_layer.begin (), count_per_layer.end ());
|
||||
std::sort (counters.begin (), counters.end (), CounterCompare ());
|
||||
|
||||
for (std::vector<std::pair<db::LayerProperties, size_t> >::const_iterator c = counters.begin (); c != counters.end (); ++c) {
|
||||
|
||||
m_layer_labels << tl::to_qstring (c->first.to_string ());
|
||||
|
||||
m_labels.push_back (QStringList ());
|
||||
m_red_images.push_back (std::vector<QImage> ());
|
||||
m_green_images.push_back (std::vector<QImage> ());
|
||||
m_blue_images.push_back (std::vector<QImage> ());
|
||||
m_yellow_images.push_back (std::vector<QImage> ());
|
||||
|
||||
for (std::vector<db::Coord>::const_iterator t = tolerances.begin (); t != tolerances.end (); ++t) {
|
||||
|
||||
m_labels.back ().push_back (QString ());
|
||||
m_red_images.back ().push_back (QImage (m_pixmap_size, m_pixmap_size, QImage::Format_MonoLSB));
|
||||
m_green_images.back ().push_back (QImage (m_pixmap_size, m_pixmap_size, QImage::Format_MonoLSB));
|
||||
m_blue_images.back ().push_back (QImage (m_pixmap_size, m_pixmap_size, QImage::Format_MonoLSB));
|
||||
m_yellow_images.back ().push_back (QImage (m_pixmap_size, m_pixmap_size, QImage::Format_MonoLSB));
|
||||
|
||||
m_red_images.back ().back ().fill (Qt::black);
|
||||
m_green_images.back ().back ().fill (Qt::black);
|
||||
m_blue_images.back ().back ().fill (Qt::black);
|
||||
m_yellow_images.back ().back ().fill (Qt::black);
|
||||
|
||||
size_t tot_count = 0;
|
||||
|
||||
std::map<std::pair<db::LayerProperties, db::Coord>, std::vector<std::vector<size_t> > >::const_iterator rm = results.find (std::make_pair (c->first, *t));
|
||||
if (rm != results.end ()) {
|
||||
|
||||
const std::vector<std::vector<size_t> > &counts = rm->second;
|
||||
tot_count = sum (counts);
|
||||
|
||||
int ix = 0;
|
||||
for (std::vector<std::vector<size_t> >::const_iterator c = counts.begin (); c != counts.end (); ++c, ++ix) {
|
||||
|
||||
int iy = 0;
|
||||
for (std::vector<size_t>::const_iterator cc = c->begin (); cc != c->end (); ++cc, ++iy) {
|
||||
|
||||
QImage *img = 0;
|
||||
if (*cc == 0) {
|
||||
img = &m_green_images.back ().back ();
|
||||
} else if (*cc == missing_in_a) {
|
||||
m_blue_images.back ().back ().fill (Qt::white);
|
||||
} else if (*cc == missing_in_b) {
|
||||
m_yellow_images.back ().back ().fill (Qt::white);
|
||||
} else {
|
||||
img = &m_red_images.back ().back ();
|
||||
}
|
||||
|
||||
if (img) {
|
||||
|
||||
if (nx == 0 || ny == 0) {
|
||||
|
||||
img->fill (Qt::white);
|
||||
|
||||
} else {
|
||||
|
||||
int y2 = m_pixmap_size - 1 - (iy * m_pixmap_size + m_pixmap_size / 2) / ny;
|
||||
int y1 = m_pixmap_size - 1 - ((iy + 1) * m_pixmap_size + m_pixmap_size / 2) / ny;
|
||||
int x1 = (ix * m_pixmap_size + m_pixmap_size / 2) / nx;
|
||||
int x2 = ((ix + 1) * m_pixmap_size + m_pixmap_size / 2) / nx;
|
||||
|
||||
// "draw" the field
|
||||
for (int y = y1; y <= y2 && y >= 0 && y < m_pixmap_size; ++y) {
|
||||
*((uint32_t *) img->scanLine (y)) &= (((1 << x1) - 1) | ~((1 << (x2 + 1)) - 1));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
QString text;
|
||||
if (tot_count == missing_in_a) {
|
||||
text = QString::fromUtf8 ("B");
|
||||
} else if (tot_count == missing_in_b) {
|
||||
text = QString::fromUtf8 ("A");
|
||||
} else if (tot_count > 1000000000) {
|
||||
text = QString::fromUtf8 ("%1G").arg (tot_count * 1e-9, 0, 'f', 2);
|
||||
} else if (tot_count > 100000000) {
|
||||
text = QString::fromUtf8 ("%1M").arg (tot_count * 1e-6, 0, 'f', 0);
|
||||
} else if (tot_count > 10000000) {
|
||||
text = QString::fromUtf8 ("%1M").arg (tot_count * 1e-6, 0, 'f', 1);
|
||||
} else if (tot_count > 1000000) {
|
||||
text = QString::fromUtf8 ("%1M").arg (tot_count * 1e-6, 0, 'f', 2);
|
||||
} else if (tot_count > 100000) {
|
||||
text = QString::fromUtf8 ("%1k").arg (tot_count * 1e-3, 0, 'f', 0);
|
||||
} else if (tot_count > 10000) {
|
||||
text = QString::fromUtf8 ("%1k").arg (tot_count * 1e-3, 0, 'f', 1);
|
||||
} else if (tot_count > 1000) {
|
||||
text = QString::fromUtf8 ("%1k").arg (tot_count * 1e-3, 0, 'f', 2);
|
||||
} else {
|
||||
text = QString::fromUtf8 ("%1").arg (tot_count);
|
||||
}
|
||||
m_labels.back ().back () = text;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (szh != sizeHint ()) {
|
||||
updateGeometry ();
|
||||
}
|
||||
|
||||
update ();
|
||||
}
|
||||
|
||||
void paintEvent (QPaintEvent * /*ev*/)
|
||||
{
|
||||
QPainter painter (this);
|
||||
|
||||
QSize szh = QSize (int (m_tolerance_labels.size ()) * (m_column_width + m_spacing) + m_first_column_width, (m_line_height + m_spacing) * int (m_layer_labels.size ()) + m_font_height * 2 + m_spacing + 10);
|
||||
|
||||
bool ellipsis = false;
|
||||
|
||||
int visible_lines = std::max (1, (height () - m_font_height * 2 - m_spacing) / (m_line_height + m_spacing));
|
||||
int columns = std::min (std::max (1, width () / std::max (1, szh.width ())), int (m_layer_labels.size ()));
|
||||
|
||||
int x0 = std::max (0, (width () - szh.width () * columns) / 2);
|
||||
int visible_columns = std::max (0, (width () - m_first_column_width + 20) / (m_column_width + m_spacing));
|
||||
|
||||
for (int c = 0; c < columns; ++c) {
|
||||
|
||||
painter.drawText (QRect (QPoint (x0 + c * szh.width (), 0), QSize (m_first_column_width, m_font_height)),
|
||||
tr ("Lay/Tol."),
|
||||
QTextOption (Qt::AlignRight | Qt::AlignTop));
|
||||
|
||||
for (int t = 0; t < m_tolerance_labels.size () && t < visible_columns; ++t) {
|
||||
painter.drawText (QRect (QPoint (x0 + c * szh.width () + m_first_column_width + m_spacing + t * (m_column_width + m_spacing), 0), QSize (m_column_width, m_font_height)),
|
||||
m_tolerance_labels [t],
|
||||
QTextOption (Qt::AlignLeft | Qt::AlignTop));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int c = 0;
|
||||
int r = 0;
|
||||
|
||||
for (int l = 0; l < m_layer_labels.size (); ++l, ++c) {
|
||||
|
||||
if (c == columns) {
|
||||
c = 0;
|
||||
++r;
|
||||
if (r == visible_lines) {
|
||||
ellipsis = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
painter.drawText (QRect (QPoint (x0 + c * szh.width (), m_font_height + m_spacing + r * (m_line_height + m_spacing)), QSize (m_first_column_width, m_line_height)),
|
||||
m_layer_labels [l],
|
||||
QTextOption (Qt::AlignRight | Qt::AlignVCenter));
|
||||
|
||||
for (int t = 0; t < m_tolerance_labels.size () && t < visible_columns; ++t) {
|
||||
|
||||
int x = x0 + c * szh.width () + m_first_column_width + m_spacing + t * (m_column_width + m_spacing);
|
||||
int y = m_font_height + m_spacing + r * (m_line_height + m_spacing);
|
||||
|
||||
painter.drawText (QRect (QPoint (x + m_pixmap_size + 4 + m_spacing, y), QSize (m_column_width, m_line_height)),
|
||||
m_labels [l][t],
|
||||
QTextOption (Qt::AlignLeft | Qt::AlignVCenter));
|
||||
|
||||
painter.save ();
|
||||
|
||||
QLinearGradient grad (QPointF (0, 0), QPointF (1.0, 1.0));
|
||||
grad.setCoordinateMode (QGradient::ObjectBoundingMode);
|
||||
grad.setColorAt (0.0, QColor (248, 248, 248));
|
||||
grad.setColorAt (1.0, QColor (224, 224, 224));
|
||||
painter.setBrush (QBrush (grad));
|
||||
painter.setPen (QPen (Qt::black));
|
||||
painter.drawRect (QRect (QPoint (x, y - 2), QSize (m_pixmap_size + 3, m_pixmap_size + 3)));
|
||||
|
||||
painter.setBackgroundMode (Qt::TransparentMode);
|
||||
painter.setPen (QColor (128, 255, 128));
|
||||
painter.drawPixmap (x + 2, y, QBitmap::fromImage (m_green_images [l][t]));
|
||||
painter.setPen (QColor (255, 128, 128));
|
||||
painter.drawPixmap (x + 2, y, QBitmap::fromImage (m_red_images [l][t]));
|
||||
painter.setPen (QColor (128, 128, 255));
|
||||
painter.drawPixmap (x + 2, y, QBitmap::fromImage (m_blue_images [l][t]));
|
||||
painter.setPen (QColor (255, 255, 128));
|
||||
painter.drawPixmap (x + 2, y, QBitmap::fromImage (m_yellow_images [l][t]));
|
||||
painter.restore ();
|
||||
|
||||
}
|
||||
|
||||
if (l == 0 && int (m_tolerance_labels.size ()) > visible_columns) {
|
||||
|
||||
int x = x0 + m_first_column_width + m_spacing + visible_columns * (m_column_width + m_spacing);
|
||||
int y = m_font_height + m_spacing;
|
||||
|
||||
painter.drawText (QRect (QPoint (x - m_column_width, y), QSize (m_column_width, m_line_height)),
|
||||
QString::fromUtf8 ("..."),
|
||||
QTextOption (Qt::AlignRight | Qt::AlignVCenter));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (ellipsis) {
|
||||
painter.drawText (QRect (QPoint (x0 + c * szh.width (), m_font_height + m_spacing + r * (m_line_height + m_spacing)), QSize (m_first_column_width, m_font_height)),
|
||||
QString::fromUtf8 ("..."),
|
||||
QTextOption (Qt::AlignRight | Qt::AlignTop));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
int m_pixmap_size;
|
||||
int m_line_height;
|
||||
int m_font_height;
|
||||
int m_spacing;
|
||||
int m_column_width;
|
||||
int m_first_column_width;
|
||||
QStringList m_tolerance_labels;
|
||||
QStringList m_layer_labels;
|
||||
std::vector<QStringList> m_labels;
|
||||
std::vector<std::vector<QImage> > m_green_images;
|
||||
std::vector<std::vector<QImage> > m_red_images;
|
||||
std::vector<std::vector<QImage> > m_yellow_images;
|
||||
std::vector<std::vector<QImage> > m_blue_images;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------------------
|
||||
// XORProgress implementation
|
||||
|
||||
XORProgress::XORProgress (const std::string &title, size_t max_count, size_t yield_interval)
|
||||
: tl::RelativeProgress (title, max_count, yield_interval), m_needs_update (true), m_dbu (1.0), m_nx (0), m_ny (0)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
QWidget *XORProgress::progress_widget () const
|
||||
{
|
||||
return new XORProgressWidget ();
|
||||
}
|
||||
|
||||
void XORProgress::render_progress (QWidget *widget) const
|
||||
{
|
||||
XORProgressWidget *pw = dynamic_cast<XORProgressWidget *> (widget);
|
||||
if (pw) {
|
||||
pw->set_results (m_dbu, m_nx, m_ny, m_results, m_count_per_layer, m_tolerances);
|
||||
}
|
||||
}
|
||||
|
||||
void XORProgress::configure (double dbu, int nx, int ny, const std::vector<db::Coord> &tol)
|
||||
{
|
||||
if (m_tolerances != tol || fabs (m_dbu - dbu) > 1e-6 || m_nx != nx || m_ny != ny) {
|
||||
m_dbu = dbu;
|
||||
m_nx = nx;
|
||||
m_ny = ny;
|
||||
m_tolerances = tol;
|
||||
m_needs_update = true;
|
||||
}
|
||||
}
|
||||
|
||||
void XORProgress::merge_results (std::map<std::pair<db::LayerProperties, db::Coord>, std::vector<std::vector<size_t> > > &results)
|
||||
{
|
||||
for (std::map<std::pair<db::LayerProperties, db::Coord>, std::vector<std::vector<size_t> > >::const_iterator r = results.begin (); r != results.end (); ++r) {
|
||||
m_needs_update = true;
|
||||
merge (m_results [r->first], r->second);
|
||||
merge (m_count_per_layer [r->first.first], sum (r->second));
|
||||
}
|
||||
|
||||
results.clear ();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2018 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_layXORToolProgress
|
||||
#define HDR_layXORToolProgress
|
||||
|
||||
#include "tlProgress.h"
|
||||
|
||||
#include "dbTypes.h"
|
||||
#include "dbLayerProperties.h"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <limits>
|
||||
|
||||
class QWidget;
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
||||
const size_t missing_in_a = std::numeric_limits<size_t>::max ();
|
||||
const size_t missing_in_b = std::numeric_limits<size_t>::max () - 1;
|
||||
|
||||
/**
|
||||
* @brief A specialized progress reporter for the XOR feature
|
||||
*
|
||||
* The purpose of this class is to provide the special XOR progress widget that
|
||||
* shows the XOR progress with numbers and a map (in tiled mode).
|
||||
*/
|
||||
class XORProgress
|
||||
: public tl::RelativeProgress
|
||||
{
|
||||
public:
|
||||
XORProgress (const std::string &title, size_t max_count, size_t yield_interval);
|
||||
|
||||
virtual QWidget *progress_widget () const;
|
||||
virtual void render_progress (QWidget *widget) const;
|
||||
|
||||
void configure (double dbu, int nx, int ny, const std::vector<db::Coord> &tol);
|
||||
void merge_results (std::map<std::pair<db::LayerProperties, db::Coord>, std::vector<std::vector<size_t> > > &results);
|
||||
|
||||
private:
|
||||
std::map<std::pair<db::LayerProperties, db::Coord>, std::vector<std::vector<size_t> > > m_results;
|
||||
std::map<db::LayerProperties, size_t> m_count_per_layer;
|
||||
std::vector<db::Coord> m_tolerances;
|
||||
bool m_needs_update;
|
||||
double m_dbu;
|
||||
int m_nx, m_ny;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,82 @@
|
||||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2018 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_layXORToolDialog
|
||||
#define HDR_layXORToolDialog
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
#include "tlObject.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class XORToolDialog;
|
||||
}
|
||||
|
||||
namespace lay
|
||||
{
|
||||
class LayoutView;
|
||||
}
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
||||
extern std::string cfg_xor_input_mode;
|
||||
extern std::string cfg_xor_output_mode;
|
||||
extern std::string cfg_xor_nworkers;
|
||||
extern std::string cfg_xor_layer_offset;
|
||||
extern std::string cfg_xor_axorb;
|
||||
extern std::string cfg_xor_anotb;
|
||||
extern std::string cfg_xor_bnota;
|
||||
extern std::string cfg_xor_summarize;
|
||||
extern std::string cfg_xor_tolerances;
|
||||
extern std::string cfg_xor_tiling;
|
||||
extern std::string cfg_xor_region_mode;
|
||||
|
||||
class XORToolDialog
|
||||
: public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
XORToolDialog (QWidget *parent);
|
||||
~XORToolDialog ();
|
||||
|
||||
int exec_dialog (lay::LayoutView *view);
|
||||
|
||||
protected:
|
||||
void accept ();
|
||||
void run_xor ();
|
||||
|
||||
protected slots:
|
||||
void input_changed (int index);
|
||||
void output_changed (int index);
|
||||
|
||||
private:
|
||||
Ui::XORToolDialog *mp_ui;
|
||||
tl::weak_ptr<lay::LayoutView> mp_view;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
|
||||
TARGET = xor
|
||||
DESTDIR = $$OUT_PWD/../../../../lay_plugins
|
||||
|
||||
include($$PWD/../../../lay_plugin.pri)
|
||||
|
||||
INCLUDEPATH += $$RDB_INC $$ANT_INC
|
||||
DEPENDPATH += $$RDB_INC $$ANT_INC
|
||||
LIBS += -L$$DESTDIR/.. -lklayout_rdb -lklayout_ant
|
||||
|
||||
HEADERS = \
|
||||
layXORToolDialog.h \
|
||||
layXORProgress.h
|
||||
|
||||
SOURCES = \
|
||||
layXORToolDialog.cc \
|
||||
layXORProgress.cc \
|
||||
layXORPlugin.cc
|
||||
|
||||
FORMS = \
|
||||
XORToolDialog.ui \
|
||||
@@ -0,0 +1,5 @@
|
||||
|
||||
TEMPLATE = subdirs
|
||||
|
||||
SUBDIRS = lay_plugin
|
||||
|
||||
Reference in New Issue
Block a user