mirror of https://github.com/KLayout/klayout.git
commit
637660ca69
|
|
@ -1382,9 +1382,6 @@ dragging_what (const ant::Object *robj, const db::DBox &search_dbox, ant::Servic
|
|||
bool
|
||||
Service::begin_move (lay::Editable::MoveMode mode, const db::DPoint &p, lay::angle_constraint_type /*ac*/)
|
||||
{
|
||||
// cancel any pending move or drag operations, reset mp_active_ruler
|
||||
ui ()->drag_cancel (); // KLUDGE: every service does this to the same service manager
|
||||
|
||||
clear_transient_selection ();
|
||||
|
||||
// choose move mode
|
||||
|
|
|
|||
|
|
@ -1938,9 +1938,11 @@ struct SelectFilterPropertyIDs
|
|||
SelectFilterPropertyIDs (LayoutQuery *q)
|
||||
{
|
||||
data = q->register_property ("data", LQ_variant);
|
||||
expressions = q->register_property ("expressions", LQ_variant);
|
||||
}
|
||||
|
||||
unsigned int data; // data -> An array of the selected values
|
||||
unsigned int expressions; // data -> An array with the expressions
|
||||
};
|
||||
|
||||
class DB_PUBLIC SelectFilterReportingState
|
||||
|
|
@ -2037,7 +2039,16 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
virtual void reset (FilterStateBase *previous)
|
||||
void get_expressions (tl::Variant &v)
|
||||
{
|
||||
std::vector<tl::Variant> vd;
|
||||
v = tl::Variant (vd.begin (), vd.end ());
|
||||
for (std::vector<tl::Expression>::const_iterator e = m_expressions.begin (); e != m_expressions.end (); ++e) {
|
||||
v.push (e->text ());
|
||||
}
|
||||
}
|
||||
|
||||
virtual void reset (FilterStateBase *previous)
|
||||
{
|
||||
if (m_has_sorting) {
|
||||
|
||||
|
|
@ -2082,6 +2093,9 @@ public:
|
|||
if (id == m_pids.data) {
|
||||
get_data (v);
|
||||
return true;
|
||||
} else if (id == m_pids.expressions) {
|
||||
get_expressions (v);
|
||||
return true;
|
||||
} else if (m_in_data_eval) {
|
||||
return FilterStateBase::get_property (id, v);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ typedef l2n_std_format::keys<true> skeys;
|
|||
typedef l2n_std_format::keys<false> lkeys;
|
||||
|
||||
LayoutToNetlistStandardReader::LayoutToNetlistStandardReader (tl::InputStream &stream)
|
||||
: m_stream (stream), m_path (stream.absolute_path ()), m_dbu (0.0),
|
||||
: m_stream (stream), m_path (stream.absolute_file_path ()), m_dbu (0.0),
|
||||
m_progress (tl::to_string (tr ("Reading L2N database")), 1000)
|
||||
{
|
||||
m_progress.set_format (tl::to_string (tr ("%.0fk lines")));
|
||||
|
|
|
|||
|
|
@ -183,7 +183,7 @@ SpiceReaderStream::line_number () const
|
|||
std::string
|
||||
SpiceReaderStream::source () const
|
||||
{
|
||||
return mp_stream->absolute_path ();
|
||||
return mp_stream->absolute_file_path ();
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -495,7 +495,7 @@ SpiceCircuitDict::read (tl::InputStream &stream)
|
|||
m_global_net_names.clear ();
|
||||
m_global_nets.clear ();
|
||||
|
||||
m_file_id = file_id (stream.absolute_path ());
|
||||
m_file_id = file_id (stream.absolute_file_path ());
|
||||
|
||||
while (! at_end ()) {
|
||||
read_card ();
|
||||
|
|
|
|||
|
|
@ -479,10 +479,10 @@ std::string
|
|||
Technology::correct_path (const std::string &fp) const
|
||||
{
|
||||
std::string bp = base_path ();
|
||||
if (bp.empty ()) {
|
||||
if (bp.empty () || ! tl::InputStream::is_file_path (fp) || ! tl::InputStream::is_file_path (bp)) {
|
||||
return fp;
|
||||
} else {
|
||||
return tl::relative_path (bp, fp);
|
||||
return tl::relative_path (tl::InputStream::as_file_path (bp), tl::InputStream::as_file_path (fp));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -494,7 +494,11 @@ Technology::load (const std::string &fn)
|
|||
xml_struct.parse (source, *this);
|
||||
|
||||
// use the tech file's path as the default base path
|
||||
set_default_base_path (tl::absolute_path (fn));
|
||||
if (tl::InputStream::is_file_path (fn)) {
|
||||
set_default_base_path (tl::absolute_path (fn));
|
||||
} else {
|
||||
set_default_base_path (std::string ());
|
||||
}
|
||||
|
||||
set_tech_file_path (fn);
|
||||
}
|
||||
|
|
@ -515,10 +519,10 @@ Technology::build_effective_path (const std::string &p) const
|
|||
return p;
|
||||
}
|
||||
|
||||
if (tl::is_absolute (p)) {
|
||||
if (tl::InputStream::is_absolute (p)) {
|
||||
return p;
|
||||
} else {
|
||||
return tl::combine_path (bp, p);
|
||||
return tl::InputStream::combine (bp, p);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1811,7 +1811,7 @@ PartialService::mouse_move_event (const db::DPoint &p, unsigned int buttons, boo
|
|||
if (snap_details.object_snap == lay::PointSnapToObjectResult::NoObject) {
|
||||
m_current = m_start + snap_move (p - m_start);
|
||||
} else {
|
||||
m_current = snap_details.snapped_point;
|
||||
m_current = m_start + snap_move (snap_details.snapped_point - m_start);
|
||||
mouse_cursor_from_snap_details (snap_details);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -588,9 +588,6 @@ Service::mouse_move_event (const db::DPoint & /*p*/, unsigned int /*buttons*/, b
|
|||
bool
|
||||
Service::begin_move (lay::Editable::MoveMode mode, const db::DPoint &p, lay::angle_constraint_type /*ac*/)
|
||||
{
|
||||
// cancel any pending move or drag operations
|
||||
widget ()->drag_cancel (); // KLUDGE: every service does this to the same service manager
|
||||
|
||||
// compute search box
|
||||
double l = catch_distance ();
|
||||
db::DBox search_dbox = db::DBox (p, p).enlarged (db::DVector (l, l));
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ equals(HAVE_RUBY, "1") {
|
|||
|
||||
!equals(HAVE_QT, "0") {
|
||||
|
||||
# TODO: make buddies able to build without Qt
|
||||
SUBDIRS += \
|
||||
klayout_main \
|
||||
lay \
|
||||
|
|
|
|||
|
|
@ -14,74 +14,18 @@
|
|||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="6" column="0" colspan="4">
|
||||
<widget class="Line" name="line_2">
|
||||
<item row="1" column="2" colspan="2">
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="4">
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="group_le"/>
|
||||
</item>
|
||||
<item row="7" column="0" rowspan="2">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Database
|
||||
unit</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="0" colspan="4">
|
||||
<widget class="Line" name="line_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="3">
|
||||
<widget class="QToolButton" name="browse_pb">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="15" column="1" rowspan="2" colspan="3">
|
||||
<widget class="QListWidget" name="libs_lw">
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::NoSelection</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2" colspan="2">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>(Use the rename button to change this)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="desc_le"/>
|
||||
</item>
|
||||
<item row="5" column="1" colspan="3">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>The base path is used to locate auxiliary files if those are specified with a relative path. If none is specified, the default path is used. The default path is the one from which a technology was imported.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="7" column="1" colspan="3">
|
||||
<widget class="QFrame" name="frame">
|
||||
|
|
@ -124,122 +68,13 @@ unit</string>
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1" colspan="2">
|
||||
<widget class="QLineEdit" name="base_path_le"/>
|
||||
</item>
|
||||
<item row="2" column="2" colspan="2">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string>(Used for creating tech groups)</string>
|
||||
<string>Group</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0" colspan="4">
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>5</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="15" column="0">
|
||||
<widget class="QLabel" name="libs_lbl">
|
||||
<property name="text">
|
||||
<string>Technology
|
||||
specific
|
||||
libraries</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="text">
|
||||
<string>Grids</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Base path</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Description</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2" colspan="2">
|
||||
<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="10" column="1" colspan="3">
|
||||
<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" name="horizontalLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="grids_le"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="text">
|
||||
<string>µm (g1,g2,...)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="16" column="0">
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="13" column="1" colspan="3">
|
||||
<widget class="QGroupBox" name="lyp_grp">
|
||||
<property name="title">
|
||||
|
|
@ -284,10 +119,61 @@ libraries</string>
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="add_other_layers_cbx">
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="name_le">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1" colspan="3">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>The default database unit is used as database unit for freshly created layouts</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1" colspan="3">
|
||||
<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" name="horizontalLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="grids_le"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="text">
|
||||
<string>Automatically add other layers</string>
|
||||
<string>µm (g1,g2,...)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
@ -305,37 +191,79 @@ properties</string>
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<item row="5" column="1" colspan="3">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="name_le">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string>Group</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1" colspan="3">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>The default database unit is used as database unit for freshly created layouts</string>
|
||||
<string>The base path is used to locate auxiliary files if those are specified with a relative path. If none is specified, the default path is used. The default path is the one from which a technology was imported.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="1" colspan="3">
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="text">
|
||||
<string>These grids are available for selection from the "View" menu and will override the general ones. You can declare one grid as a strong default to enforce an editing grid from this list. To do so, add an exclamation mark to the grid - e.g. "0.01!,0.02,0.05".</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="16" column="0">
|
||||
<widget class="QLabel" name="libs_lbl">
|
||||
<property name="text">
|
||||
<string>Technology
|
||||
specific
|
||||
libraries</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="15" column="0" colspan="4">
|
||||
<widget class="Line" name="line_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</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="3" column="0" colspan="4">
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0" colspan="4">
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>5</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Base path</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="0" colspan="4">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
|
|
@ -352,13 +280,85 @@ properties</string>
|
|||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="11" column="1" colspan="3">
|
||||
<widget class="QLabel" name="label_15">
|
||||
<item row="7" column="0" rowspan="2">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>These grids are available for selection from the "View" menu and will override the general ones. You can declare one grid as a strong default to enforce an editing grid from this list. To do so, add an exclamation mark to the grid - e.g. "0.01!,0.02,0.05".</string>
|
||||
<string>Database
|
||||
unit</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="17" column="0">
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="16" column="1" rowspan="2" colspan="3">
|
||||
<widget class="QListWidget" name="libs_lw">
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::NoSelection</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2" colspan="2">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="text">
|
||||
<string>(Used for creating tech groups)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="3">
|
||||
<widget class="QToolButton" name="browse_pb">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="text">
|
||||
<string>Grids</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Description</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="desc_le"/>
|
||||
</item>
|
||||
<item row="0" column="2" colspan="2">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>(Use the rename button to change this)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1" colspan="2">
|
||||
<widget class="QLineEdit" name="base_path_le"/>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="group_le"/>
|
||||
</item>
|
||||
<item row="14" column="1" colspan="3">
|
||||
<widget class="QCheckBox" name="add_other_layers_cbx">
|
||||
<property name="text">
|
||||
<string>Initialize other layers with default properties</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
|||
|
|
@ -2981,7 +2981,7 @@ void
|
|||
MainWindow::add_mru (const std::string &fn_rel, const std::string &tech)
|
||||
{
|
||||
std::vector <std::pair<std::string, std::string> > new_mru;
|
||||
std::string fn (tl::InputStream::absolute_path (fn_rel));
|
||||
std::string fn (tl::InputStream::absolute_file_path (fn_rel));
|
||||
|
||||
for (auto mru = m_mru.begin (); mru != m_mru.end (); ++mru) {
|
||||
if (mru->first != fn /* delete non-existing files: && tl::is_readable (mru->first) */) {
|
||||
|
|
@ -3025,7 +3025,7 @@ MainWindow::add_to_other_mru (const std::string &fn_rel, const std::string &cfg)
|
|||
}
|
||||
|
||||
std::vector <std::string> new_mru;
|
||||
std::string fn (tl::InputStream::absolute_path (fn_rel));
|
||||
std::string fn (tl::InputStream::absolute_file_path (fn_rel));
|
||||
|
||||
for (auto mru = mru_ptr->begin (); mru != mru_ptr->end (); ++mru) {
|
||||
if (*mru != fn /* delete non-existing files: && tl::is_readable (*mru) */) {
|
||||
|
|
|
|||
|
|
@ -44,6 +44,8 @@
|
|||
#include <QInputDialog>
|
||||
#include <QHeaderView>
|
||||
#include <QRegExp>
|
||||
#include <QClipboard>
|
||||
#include <QMimeData>
|
||||
|
||||
#include <fstream>
|
||||
|
||||
|
|
@ -76,6 +78,15 @@ SearchReplaceResults::clear ()
|
|||
m_has_more = false;
|
||||
}
|
||||
|
||||
void
|
||||
SearchReplaceResults::set_data_column_headers (const tl::Variant &v)
|
||||
{
|
||||
m_data_column_headers = v;
|
||||
if (v.is_list ()) {
|
||||
m_data_columns = std::max (v.get_list ().size (), m_data_columns);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SearchReplaceResults::push_back (const tl::Variant &v)
|
||||
{
|
||||
|
|
@ -166,7 +177,13 @@ SearchReplaceResults::headerData (int section, Qt::Orientation /*orientation*/,
|
|||
{
|
||||
if (role == Qt::DisplayRole) {
|
||||
if (! m_data_result.empty ()) {
|
||||
if (section == 0) {
|
||||
if (m_data_column_headers.is_list ()) {
|
||||
if (section < int (m_data_column_headers.get_list ().size ())) {
|
||||
return QVariant (m_data_column_headers.get_list () [section].to_string ());
|
||||
} else {
|
||||
return QVariant (QString ());
|
||||
}
|
||||
} else if (section == 0) {
|
||||
return QVariant (QObject::tr ("Value"));
|
||||
} else {
|
||||
return QVariant (QString ());
|
||||
|
|
@ -522,11 +539,37 @@ SearchReplaceResults::select_items (lay::LayoutViewBase *view, int cv_index, con
|
|||
edt::set_object_selection (view, sel);
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
SearchReplaceResults::export_csv_to_clipboard (const std::set<int> *rows)
|
||||
{
|
||||
tl::OutputMemoryStream buffer;
|
||||
|
||||
{
|
||||
tl::OutputStream os (buffer, true /* as text */);
|
||||
export_csv (os, rows);
|
||||
}
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
QClipboard *clipboard = QGuiApplication::clipboard();
|
||||
#else
|
||||
QClipboard *clipboard = QApplication::clipboard();
|
||||
#endif
|
||||
QMimeData *data = new QMimeData ();
|
||||
data->setData (QString::fromUtf8 ("text/csv"), QByteArray (buffer.data (), buffer.size ()));
|
||||
data->setText (QString::fromUtf8 (buffer.data (), buffer.size ()));
|
||||
clipboard->setMimeData (data);
|
||||
}
|
||||
|
||||
void
|
||||
SearchReplaceResults::export_csv (const std::string &file, const std::set<int> *rows)
|
||||
{
|
||||
std::ofstream output (file.c_str ());
|
||||
tl::OutputStream os (file, tl::OutputStream::OM_Auto, true /* as text */);
|
||||
export_csv (os, rows);
|
||||
}
|
||||
|
||||
void
|
||||
SearchReplaceResults::export_csv (tl::OutputStream &os, const std::set<int> *rows)
|
||||
{
|
||||
QModelIndex parent;
|
||||
|
||||
size_t n_columns = columnCount (parent);
|
||||
|
|
@ -534,11 +577,11 @@ SearchReplaceResults::export_csv (const std::string &file, const std::set<int> *
|
|||
|
||||
for (size_t c = 0; c < n_columns; ++c) {
|
||||
if (c) {
|
||||
output << ",";
|
||||
os << ",";
|
||||
}
|
||||
output << escape_csv (tl::to_string (headerData (int (c), Qt::Horizontal, Qt::DisplayRole).toString ()));
|
||||
os << escape_csv (tl::to_string (headerData (int (c), Qt::Horizontal, Qt::DisplayRole).toString ()));
|
||||
}
|
||||
output << std::endl;
|
||||
os << "\n";
|
||||
|
||||
for (size_t r = 0; r < n_rows; ++r) {
|
||||
|
||||
|
|
@ -546,13 +589,13 @@ SearchReplaceResults::export_csv (const std::string &file, const std::set<int> *
|
|||
|
||||
for (size_t c = 0; c < n_columns; ++c) {
|
||||
if (c) {
|
||||
output << ",";
|
||||
os << ",";
|
||||
}
|
||||
// TODO: optimize
|
||||
output << escape_csv (tl::to_string (data (index (int (r), int (c), parent), Qt::DisplayRole).toString ()));
|
||||
os << escape_csv (tl::to_string (data (index (int (r), int (c), parent), Qt::DisplayRole).toString ()));
|
||||
}
|
||||
|
||||
output << std::endl;
|
||||
os << "\n";
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -843,6 +886,7 @@ SearchReplaceDialog::SearchReplaceDialog (lay::Dispatcher *root, LayoutViewBase
|
|||
connect (results->header (), SIGNAL (sectionCountChanged (int, int)), this, SLOT (header_columns_changed (int, int)));
|
||||
|
||||
QMenu *menu = new QMenu (this);
|
||||
menu->addAction (QObject::tr ("Copy to clipboard"), this, SLOT (export_csv_to_clipboard ()));
|
||||
menu->addAction (QObject::tr ("To CSV file"), this, SLOT (export_csv ()));
|
||||
menu->addAction (QObject::tr ("To report database"), this, SLOT (export_rdb ()));
|
||||
menu->addAction (QObject::tr ("To layout"), this, SLOT (export_layout ()));
|
||||
|
|
@ -851,6 +895,10 @@ SearchReplaceDialog::SearchReplaceDialog (lay::Dispatcher *root, LayoutViewBase
|
|||
|
||||
QAction *action;
|
||||
|
||||
action = new QAction (QObject::tr ("Copy to clipboard"), results);
|
||||
connect (action, SIGNAL (triggered ()), this, SLOT (sel_export_csv_to_clipboard ()));
|
||||
results->addAction (action);
|
||||
|
||||
action = new QAction (QObject::tr ("Export to CSV file"), results);
|
||||
connect (action, SIGNAL (triggered ()), this, SLOT (sel_export_csv ()));
|
||||
results->addAction (action);
|
||||
|
|
@ -1165,6 +1213,54 @@ BEGIN_PROTECTED
|
|||
END_PROTECTED
|
||||
}
|
||||
|
||||
void
|
||||
SearchReplaceDialog::sel_export_csv_to_clipboard ()
|
||||
{
|
||||
BEGIN_PROTECTED
|
||||
|
||||
std::set<int> rows;
|
||||
QModelIndexList sel = results->selectionModel ()->selectedRows (0);
|
||||
for (auto s = sel.begin (); s != sel.end (); ++s) {
|
||||
rows.insert (s->row ());
|
||||
}
|
||||
|
||||
m_model.export_csv_to_clipboard (&rows);
|
||||
|
||||
END_PROTECTED
|
||||
}
|
||||
|
||||
void
|
||||
SearchReplaceDialog::export_csv_to_clipboard ()
|
||||
{
|
||||
BEGIN_PROTECTED
|
||||
|
||||
int cv_index = m_last_query_cv_index;
|
||||
const lay::CellView &cv = mp_view->cellview (cv_index);
|
||||
if (! cv.is_valid ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
db::LayoutQuery lq (m_last_query);
|
||||
|
||||
tl::AbsoluteProgress progress (tl::to_string (QObject::tr ("Running query")));
|
||||
progress.set_unit (100000);
|
||||
progress.set_format ("Processing ..");
|
||||
|
||||
db::LayoutQueryIterator iq (lq, &cv->layout (), 0, &progress);
|
||||
|
||||
if (tl::verbosity () >= 10) {
|
||||
tl::log << tl::to_string (QObject::tr ("Running query: ")) << m_last_query;
|
||||
}
|
||||
|
||||
SearchReplaceResults model;
|
||||
model.begin_changes (& cv->layout ());
|
||||
query_to_model (model, lq, iq, std::numeric_limits<size_t>::max (), true);
|
||||
model.end_changes ();
|
||||
model.export_csv_to_clipboard ();
|
||||
|
||||
END_PROTECTED
|
||||
}
|
||||
|
||||
void
|
||||
SearchReplaceDialog::sel_export_rdb ()
|
||||
{
|
||||
|
|
@ -1697,6 +1793,7 @@ SearchReplaceDialog::query_to_model (SearchReplaceResults &model, const db::Layo
|
|||
bool res = false;
|
||||
|
||||
int data_prop_id = lq.has_property ("data") ? int (lq.property_by_name ("data")) : -1;
|
||||
int expressions_prop_id = lq.has_property ("expressions") ? int (lq.property_by_name ("expressions")) : -1;
|
||||
int shape_prop_id = lq.has_property ("shape") ? int (lq.property_by_name ("shape")) : -1;
|
||||
int layer_index_prop_id = lq.has_property ("layer_index") ? int (lq.property_by_name ("layer_index")) : -1;
|
||||
int instance_prop_id = lq.has_property ("inst") ? int (lq.property_by_name ("inst")) : -1;
|
||||
|
|
@ -1707,6 +1804,11 @@ SearchReplaceDialog::query_to_model (SearchReplaceResults &model, const db::Layo
|
|||
int parent_cell_index_prop_id = lq.has_property ("parent_cell_index") ? int (lq.property_by_name ("parent_cell_index")) : -1;
|
||||
int initial_cell_index_prop_id = lq.has_property ("initial_cell_index") ? int (lq.property_by_name ("initial_cell_index")) : -1;
|
||||
|
||||
tl::Variant ve;
|
||||
if (expressions_prop_id >= 0 && iq.get (expressions_prop_id, ve)) {
|
||||
model.set_data_column_headers (ve);
|
||||
}
|
||||
|
||||
while (! iq.at_end ()) {
|
||||
|
||||
if (++n > max_item_count) {
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ public:
|
|||
SearchReplaceResults ();
|
||||
|
||||
void clear ();
|
||||
void set_data_column_headers (const tl::Variant &v);
|
||||
void push_back (const tl::Variant &v);
|
||||
void push_back (const QueryShapeResult &v);
|
||||
void push_back (const QueryInstResult &v);
|
||||
|
|
@ -157,6 +158,8 @@ public:
|
|||
void has_more (bool hm);
|
||||
|
||||
void export_csv (const std::string &file, const std::set<int> *rows = 0);
|
||||
void export_csv_to_clipboard (const std::set<int> *rows = 0);
|
||||
void export_csv (tl::OutputStream &os, const std::set<int> *rows = 0);
|
||||
void export_layout (db::Layout &layout, const std::set<int> *rows = 0);
|
||||
void export_rdb (rdb::Database &rdb, double dbu, const std::set<int> *rows = 0);
|
||||
void select_items (LayoutViewBase *view, int cv_index, const std::set<int> *rows = 0);
|
||||
|
|
@ -167,6 +170,7 @@ private:
|
|||
std::vector<QueryInstResult> m_inst_result;
|
||||
std::vector<QueryCellResult> m_cell_result;
|
||||
size_t m_data_columns;
|
||||
tl::Variant m_data_column_headers;
|
||||
mutable int m_last_column_count;
|
||||
std::map<db::cell_index_type, std::string> m_cellname_map;
|
||||
std::map<unsigned int, db::LayerProperties> m_lp_map;
|
||||
|
|
@ -239,10 +243,12 @@ private slots:
|
|||
void cancel_exec ();
|
||||
void select_items ();
|
||||
void export_csv ();
|
||||
void export_csv_to_clipboard ();
|
||||
void export_rdb ();
|
||||
void export_layout ();
|
||||
void sel_select_items ();
|
||||
void sel_export_csv ();
|
||||
void sel_export_csv_to_clipboard ();
|
||||
void sel_export_rdb ();
|
||||
void sel_export_layout ();
|
||||
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ Session::fetch (const lay::MainWindow &mw)
|
|||
if (lh) {
|
||||
m_layouts.push_back (SessionLayoutDescriptor ());
|
||||
m_layouts.back ().name = *l;
|
||||
m_layouts.back ().file_path = tl::InputStream::absolute_path (lh->filename ());
|
||||
m_layouts.back ().file_path = tl::InputStream::absolute_file_path (lh->filename ());
|
||||
m_layouts.back ().load_options = lh->load_options ();
|
||||
m_layouts.back ().save_options = lh->save_options ();
|
||||
m_layouts.back ().save_options_valid = lh->save_options_valid ();
|
||||
|
|
@ -89,7 +89,7 @@ Session::fetch (const lay::MainWindow &mw)
|
|||
|
||||
const rdb::Database *rdb = view->get_rdb (j);
|
||||
if (rdb && ! rdb->filename ().empty ()) {
|
||||
view_desc.rdb_filenames.push_back (tl::InputStream::absolute_path (rdb->filename ()));
|
||||
view_desc.rdb_filenames.push_back (tl::InputStream::absolute_file_path (rdb->filename ()));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -98,7 +98,7 @@ Session::fetch (const lay::MainWindow &mw)
|
|||
|
||||
const db::LayoutToNetlist *l2ndb = view->get_l2ndb (j);
|
||||
if (l2ndb && ! l2ndb->filename ().empty ()) {
|
||||
view_desc.l2ndb_filenames.push_back (tl::InputStream::absolute_path (l2ndb->filename ()));
|
||||
view_desc.l2ndb_filenames.push_back (tl::InputStream::absolute_file_path (l2ndb->filename ()));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -173,11 +173,10 @@ TechBaseEditorPage::commit ()
|
|||
|
||||
if (! mp_ui->lyp_grp->isChecked ()) {
|
||||
tech ()->set_layer_properties_file (std::string ());
|
||||
tech ()->set_add_other_layers (true);
|
||||
} else {
|
||||
tech ()->set_layer_properties_file (tl::to_string (mp_ui->lyp_le->text ()));
|
||||
tech ()->set_add_other_layers (mp_ui->add_other_layers_cbx->isChecked ());
|
||||
}
|
||||
tech ()->set_add_other_layers (mp_ui->add_other_layers_cbx->isChecked ());
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -76,15 +76,16 @@ std::vector<std::pair<std::string, std::string> >
|
|||
unpack_key_binding (const std::string &packed)
|
||||
{
|
||||
tl::Extractor ex (packed.c_str ());
|
||||
ex.test(";"); // backward compatibiliy
|
||||
|
||||
std::vector<std::pair<std::string, std::string> > key_bindings;
|
||||
|
||||
while (! ex.at_end ()) {
|
||||
ex.test(";");
|
||||
key_bindings.push_back (std::make_pair (std::string (), std::string ()));
|
||||
ex.read_word_or_quoted (key_bindings.back ().first);
|
||||
ex.test(":");
|
||||
ex.read_word_or_quoted (key_bindings.back ().second);
|
||||
ex.test(";");
|
||||
}
|
||||
|
||||
return key_bindings;
|
||||
|
|
@ -93,17 +94,26 @@ unpack_key_binding (const std::string &packed)
|
|||
std::string
|
||||
pack_key_binding (const std::vector<std::pair<std::string, std::string> > &unpacked)
|
||||
{
|
||||
std::string packed;
|
||||
std::string packed = "\n";
|
||||
bool first = true;
|
||||
|
||||
for (std::vector<std::pair<std::string, std::string> >::const_iterator p = unpacked.begin (); p != unpacked.end (); ++p) {
|
||||
if (! packed.empty ()) {
|
||||
packed += ";";
|
||||
// for easier editing we separate the entries into non-empty and empty ones and put each of them on a new line
|
||||
for (int pass = 0; pass < 2; ++pass) {
|
||||
for (std::vector<std::pair<std::string, std::string> >::const_iterator p = unpacked.begin (); p != unpacked.end (); ++p) {
|
||||
if ((pass == 0) == p->second.empty ()) {
|
||||
continue;
|
||||
}
|
||||
if (! first) {
|
||||
packed += ";\n";
|
||||
}
|
||||
first = false;
|
||||
packed += tl::to_word_or_quoted_string (p->first);
|
||||
packed += ":";
|
||||
packed += tl::to_word_or_quoted_string (p->second);
|
||||
}
|
||||
packed += tl::to_word_or_quoted_string (p->first);
|
||||
packed += ":";
|
||||
packed += tl::to_word_or_quoted_string (p->second);
|
||||
}
|
||||
|
||||
packed += "\n";
|
||||
return packed;
|
||||
}
|
||||
|
||||
|
|
@ -111,15 +121,16 @@ std::vector<std::pair<std::string, bool> >
|
|||
unpack_menu_items_hidden (const std::string &packed)
|
||||
{
|
||||
tl::Extractor ex (packed.c_str ());
|
||||
ex.test(";"); // backward compatibiliy
|
||||
|
||||
std::vector<std::pair<std::string, bool> > hidden;
|
||||
|
||||
while (! ex.at_end ()) {
|
||||
ex.test(";");
|
||||
hidden.push_back (std::make_pair (std::string (), false));
|
||||
ex.read_word_or_quoted (hidden.back ().first);
|
||||
ex.test(":");
|
||||
ex.read (hidden.back ().second);
|
||||
ex.test(";");
|
||||
}
|
||||
|
||||
return hidden;
|
||||
|
|
@ -128,17 +139,26 @@ unpack_menu_items_hidden (const std::string &packed)
|
|||
std::string
|
||||
pack_menu_items_hidden (const std::vector<std::pair<std::string, bool> > &unpacked)
|
||||
{
|
||||
std::string packed;
|
||||
std::string packed = "\n";
|
||||
bool first = true;
|
||||
|
||||
for (std::vector<std::pair<std::string, bool> >::const_iterator p = unpacked.begin (); p != unpacked.end (); ++p) {
|
||||
if (! packed.empty ()) {
|
||||
packed += ";";
|
||||
// for easier editing we separate the entries into true and false ones and put each of them on a new line
|
||||
for (int pass = 0; pass < 2; ++pass) {
|
||||
for (std::vector<std::pair<std::string, bool> >::const_iterator p = unpacked.begin (); p != unpacked.end (); ++p) {
|
||||
if ((pass == 0) != p->second) {
|
||||
continue;
|
||||
}
|
||||
if (! first) {
|
||||
packed += ";\n";
|
||||
}
|
||||
first = false;
|
||||
packed += tl::to_word_or_quoted_string (p->first);
|
||||
packed += ":";
|
||||
packed += tl::to_string (p->second);
|
||||
}
|
||||
packed += tl::to_word_or_quoted_string (p->first);
|
||||
packed += ":";
|
||||
packed += tl::to_string (p->second);
|
||||
}
|
||||
|
||||
packed += "\n";
|
||||
return packed;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -165,9 +165,9 @@ Editables::selection_catch_bbox ()
|
|||
}
|
||||
|
||||
void
|
||||
Editables::transform (const db::DCplxTrans &t, db::Transaction *transaction)
|
||||
Editables::transform (const db::DCplxTrans &t)
|
||||
{
|
||||
std::unique_ptr<db::Transaction> trans_holder (transaction ? transaction : new db::Transaction (manager (), tl::to_string (tr ("Transform"))));
|
||||
std::unique_ptr<db::Transaction> trans_holder (new db::Transaction (manager (), tl::to_string (tr ("Transform"))));
|
||||
|
||||
if (has_selection ()) {
|
||||
|
||||
|
|
@ -639,15 +639,31 @@ Editables::edit_cancel ()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
Editables::edit_finish ()
|
||||
{
|
||||
clear_previous_selection ();
|
||||
for (iterator e = begin (); e != end (); ++e) {
|
||||
e->edit_finish ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Editables::cancel_edits ()
|
||||
{
|
||||
// cancel any edit operations
|
||||
for (iterator e = begin (); e != end (); ++e) {
|
||||
e->edit_cancel ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Editables::finish_edits ()
|
||||
{
|
||||
for (iterator e = begin (); e != end (); ++e) {
|
||||
e->edit_finish ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Editables::show_properties ()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -332,6 +332,20 @@ public:
|
|||
// .. by default, nothing is implemented ..
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Finishes any pending operations
|
||||
*
|
||||
* This event is sent whenever a pending operation such as
|
||||
* a move operation should be finished.
|
||||
* In contrast to "edit_cancel", this version is supposed
|
||||
* not to rollback, for example if transactions are involved.
|
||||
*/
|
||||
virtual void edit_finish ()
|
||||
{
|
||||
// by default maps to edit_cancel
|
||||
edit_cancel ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Indicates if any objects are selected
|
||||
*/
|
||||
|
|
@ -457,14 +471,11 @@ public:
|
|||
db::DBox selection_bbox ();
|
||||
|
||||
/**
|
||||
* @brief transform the selection
|
||||
* @brief Transforms the selection
|
||||
*
|
||||
* The transformation is given in micron units.
|
||||
*
|
||||
* If a transaction is given, the operation will be appended to this pending transaction.
|
||||
* The Editables object takes ownership over the Transaction object.
|
||||
*/
|
||||
void transform (const db::DCplxTrans &tr, db::Transaction *transaction = 0);
|
||||
virtual void transform (const db::DCplxTrans &tr);
|
||||
|
||||
/**
|
||||
* @brief Enable or disable a certain editable
|
||||
|
|
@ -565,9 +576,18 @@ public:
|
|||
|
||||
/**
|
||||
* @brief Cancel any pending operations
|
||||
*
|
||||
* This method calls "edit_cancel" on all services and resets selection tracking.
|
||||
*/
|
||||
void edit_cancel ();
|
||||
|
||||
/**
|
||||
* @brief Finishes any pending operations
|
||||
*
|
||||
* This method calls "edit_finish" on all services and resets selection tracking.
|
||||
*/
|
||||
void edit_finish ();
|
||||
|
||||
/**
|
||||
* @brief Editable iterator: begin
|
||||
*/
|
||||
|
|
@ -633,11 +653,21 @@ protected:
|
|||
* @brief Cancel all edit operations
|
||||
*
|
||||
* This method can be overridden in order to implement special behaviour on cancel
|
||||
* of edits (i.e. release the mouse).
|
||||
* of edits (e.g. clean up markers).
|
||||
* Make sure, the base implementation is called as well.
|
||||
*/
|
||||
virtual void cancel_edits ();
|
||||
|
||||
/**
|
||||
* @brief Finishes all edit operations
|
||||
*
|
||||
* This method can be overridden in order to implement special behaviour on finishing
|
||||
* of edits (e.g. clean up markers). In contrast to "cancel_edits", this method
|
||||
* is expected not to rollback any operations - i.e. undo transactions.
|
||||
* Make sure, the base implementation is called as well.
|
||||
*/
|
||||
virtual void finish_edits ();
|
||||
|
||||
private:
|
||||
friend class Editable;
|
||||
|
||||
|
|
|
|||
|
|
@ -235,6 +235,8 @@ Finder::do_find (const db::Cell &cell, int level, const db::DCplxTrans &vp, cons
|
|||
|
||||
m_path.push_back (db::InstElement (*inst, p));
|
||||
|
||||
checkpoint ();
|
||||
|
||||
do_find (mp_layout->cell (cell_inst.object ().cell_index ()),
|
||||
level + 1,
|
||||
vp,
|
||||
|
|
@ -772,6 +774,14 @@ InstFinder::find_internal (LayoutViewBase *view, unsigned int cv_index, const db
|
|||
return ! m_founds.empty ();
|
||||
}
|
||||
|
||||
void
|
||||
InstFinder::checkpoint ()
|
||||
{
|
||||
if (--m_tries < 0) {
|
||||
throw StopException ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
InstFinder::visit_cell (const db::Cell &cell, const db::Box &search_box, const db::Box & /*scan_box*/, const db::DCplxTrans & /*vp*/, const db::ICplxTrans &t, int level)
|
||||
{
|
||||
|
|
@ -854,17 +864,13 @@ InstFinder::visit_cell (const db::Cell &cell, const db::Box &search_box, const d
|
|||
|
||||
} else {
|
||||
|
||||
if (--m_tries < 0) {
|
||||
throw StopException ();
|
||||
}
|
||||
checkpoint ();
|
||||
|
||||
// look for instances to check here ..
|
||||
db::Cell::touching_iterator inst = cell.begin_touching (search_box);
|
||||
while (! inst.at_end ()) {
|
||||
|
||||
if (--m_tries < 0) {
|
||||
throw StopException ();
|
||||
}
|
||||
checkpoint ();
|
||||
|
||||
const db::CellInstArray &cell_inst = inst->cell_inst ();
|
||||
const db::Cell &inst_cell = layout ().cell (cell_inst.object ().cell_index ());
|
||||
|
|
@ -877,9 +883,7 @@ InstFinder::visit_cell (const db::Cell &cell, const db::Box &search_box, const d
|
|||
db::box_convert <db::CellInst, false> bc (layout ());
|
||||
for (db::CellInstArray::iterator p = cell_inst.begin_touching (search_box, bc); ! p.at_end (); ++p) {
|
||||
|
||||
if (--m_tries < 0) {
|
||||
throw StopException ();
|
||||
}
|
||||
checkpoint ();
|
||||
|
||||
bool match = false;
|
||||
double d = std::numeric_limits<double>::max ();
|
||||
|
|
|
|||
|
|
@ -189,6 +189,11 @@ protected:
|
|||
*/
|
||||
void test_edge (const db::ICplxTrans &trans, const db::Edge &edge, double &distance, bool &match);
|
||||
|
||||
/**
|
||||
* @brief Is called "frequently", so the finder can stop after a number of tries and not waste time
|
||||
*/
|
||||
virtual void checkpoint () = 0;
|
||||
|
||||
private:
|
||||
void do_find (const db::Cell &cell, int level, const db::DCplxTrans &vp, const db::ICplxTrans &t);
|
||||
|
||||
|
|
@ -282,7 +287,7 @@ protected:
|
|||
m_tries = n;
|
||||
}
|
||||
|
||||
void checkpoint ();
|
||||
virtual void checkpoint ();
|
||||
|
||||
private:
|
||||
virtual void visit_cell (const db::Cell &cell, const db::Box &hit_box, const db::Box &scan_box, const db::DCplxTrans &vp, const db::ICplxTrans &t, int level);
|
||||
|
|
@ -339,6 +344,8 @@ public:
|
|||
return m_founds.end ();
|
||||
}
|
||||
|
||||
virtual void checkpoint ();
|
||||
|
||||
private:
|
||||
virtual void visit_cell (const db::Cell &cell, const db::Box &hit_box, const db::Box &scan_box, const db::DCplxTrans &vp, const db::ICplxTrans &t, int level);
|
||||
|
||||
|
|
|
|||
|
|
@ -2522,7 +2522,7 @@ LayoutViewBase::signal_apply_technology (lay::LayoutHandle *layout_handle)
|
|||
lyp_file = tech->eff_layer_properties_file ();
|
||||
}
|
||||
|
||||
if (! lyp_file.empty ()) {
|
||||
if (! lyp_file.empty () || tech->add_other_layers ()) {
|
||||
|
||||
// interpolate the layout properties file name
|
||||
tl::Eval expr;
|
||||
|
|
@ -3983,12 +3983,44 @@ LayoutViewBase::redraw ()
|
|||
mp_canvas->redraw_new (layers);
|
||||
}
|
||||
|
||||
void
|
||||
LayoutViewBase::transform (const db::DCplxTrans &tr)
|
||||
{
|
||||
// NOTE: we call "finish_edits" rather than "cancel_edits" because
|
||||
// "move by" while "duplicate interactive" relies on keeping the
|
||||
// pasted shapes from the previous transaction. So we must not roll back.
|
||||
finish_edits ();
|
||||
lay::Editables::transform (tr);
|
||||
}
|
||||
|
||||
void
|
||||
LayoutViewBase::cancel_edits ()
|
||||
{
|
||||
// the move service takes a special role here as it manages the
|
||||
// transaction for the collective move operation.
|
||||
mp_move_service->cancel ();
|
||||
|
||||
// cancel all drag and pending edit operations such as move operations.
|
||||
mp_canvas->drag_cancel ();
|
||||
lay::Editables::cancel_edits ();
|
||||
|
||||
// re-enable edit mode
|
||||
enable_edits (true);
|
||||
}
|
||||
|
||||
void
|
||||
LayoutViewBase::finish_edits ()
|
||||
{
|
||||
// the move service takes a special role here as it manages the
|
||||
// transaction for the collective move operation.
|
||||
mp_move_service->finish ();
|
||||
|
||||
// cancel all drag operations
|
||||
mp_canvas->drag_cancel ();
|
||||
lay::Editables::finish_edits ();
|
||||
|
||||
// re-enable edit mode
|
||||
enable_edits (true);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -3996,8 +4028,6 @@ LayoutViewBase::cancel ()
|
|||
{
|
||||
// cancel all drags and pending edit operations such as move operations.
|
||||
cancel_edits ();
|
||||
// re-enable edit mode
|
||||
enable_edits (true);
|
||||
// and clear the selection
|
||||
clear_selection ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2666,6 +2666,13 @@ public:
|
|||
*/
|
||||
void cancel_edits ();
|
||||
|
||||
/**
|
||||
* @brief Finishes all edit operations and maintains selection
|
||||
*
|
||||
* In contrast to "cancel_edits" there is no rollback of operations applied already.
|
||||
*/
|
||||
void finish_edits ();
|
||||
|
||||
/**
|
||||
* @brief Select all levels of hierarchy available
|
||||
*/
|
||||
|
|
@ -2696,7 +2703,14 @@ public:
|
|||
*/
|
||||
void ensure_selection_visible ();
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Transforms the selection
|
||||
*
|
||||
* The transformation is given in micron units.
|
||||
*/
|
||||
virtual void transform (const db::DCplxTrans &tr);
|
||||
|
||||
/**
|
||||
* @brief Select a cell by index for a certain cell view
|
||||
*
|
||||
* This will be forwarded to select_cell or select_cell_fit depending
|
||||
|
|
|
|||
|
|
@ -302,6 +302,7 @@ MoveService::handle_click (const db::DPoint &p, unsigned int buttons, bool drag_
|
|||
if (! m_dragging) {
|
||||
|
||||
mp_transaction.reset (trans_holder.release ());
|
||||
ui ()->drag_cancel ();
|
||||
|
||||
if (mp_editables->begin_move (p, ac_from_buttons (buttons))) {
|
||||
|
||||
|
|
@ -337,21 +338,31 @@ MoveService::handle_click (const db::DPoint &p, unsigned int buttons, bool drag_
|
|||
}
|
||||
|
||||
void
|
||||
MoveService::drag_cancel ()
|
||||
{
|
||||
MoveService::drag_cancel ()
|
||||
{
|
||||
m_shift = db::DPoint ();
|
||||
if (m_dragging) {
|
||||
|
||||
mp_editables->edit_cancel ();
|
||||
ui ()->ungrab_mouse (this);
|
||||
|
||||
m_dragging = false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MoveService::cancel ()
|
||||
{
|
||||
if (m_dragging) {
|
||||
if (mp_transaction.get ()) {
|
||||
mp_transaction->cancel ();
|
||||
}
|
||||
mp_transaction.reset (0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MoveService::finish ()
|
||||
{
|
||||
if (m_dragging) {
|
||||
mp_transaction.reset (0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -43,6 +43,8 @@ public:
|
|||
|
||||
bool configure (const std::string &name, const std::string &value);
|
||||
bool begin_move (db::Transaction *transaction = 0, bool transient_selection = false);
|
||||
void finish ();
|
||||
void cancel ();
|
||||
|
||||
private:
|
||||
virtual bool mouse_press_event (const db::DPoint &p, unsigned int buttons, bool prio);
|
||||
|
|
|
|||
|
|
@ -276,7 +276,7 @@ public:
|
|||
virtual void set_colors (tl::Color /*background*/, tl::Color /*text*/) { }
|
||||
|
||||
/**
|
||||
* @brief This method is called when a drag operation should be cancelled
|
||||
* @brief This method is called when a mouse tracking operation should be cancelled
|
||||
*/
|
||||
virtual void drag_cancel () { }
|
||||
|
||||
|
|
|
|||
|
|
@ -89,8 +89,8 @@
|
|||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>:/back_16.png</normaloff>:/back_16.png</iconset>
|
||||
<iconset resource="../../icons/icons.qrc">
|
||||
<normaloff>:/back_16px.png</normaloff>:/back_16px.png</iconset>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
|
|
@ -103,8 +103,8 @@
|
|||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>:/forward_16.png</normaloff>:/forward_16.png</iconset>
|
||||
<iconset resource="../../icons/icons.qrc">
|
||||
<normaloff>:/forward_16px.png</normaloff>:/forward_16px.png</iconset>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
|
|
|
|||
|
|
@ -1199,8 +1199,7 @@ LayoutViewFunctions::do_cm_duplicate (bool interactive)
|
|||
try {
|
||||
bool transient_mode = ! view ()->has_selection ();
|
||||
view ()->copy_view_objects ();
|
||||
view ()->clear_selection ();
|
||||
view ()->cancel ();
|
||||
view ()->cancel_edits ();
|
||||
if (interactive) {
|
||||
view ()->paste_interactive (transient_mode);
|
||||
} else {
|
||||
|
|
@ -1217,8 +1216,7 @@ void
|
|||
LayoutViewFunctions::do_cm_paste (bool interactive)
|
||||
{
|
||||
if (! db::Clipboard::instance ().empty ()) {
|
||||
view ()->cancel ();
|
||||
view ()->clear_selection ();
|
||||
view ()->cancel_edits ();
|
||||
if (interactive) {
|
||||
view ()->paste_interactive ();
|
||||
} else {
|
||||
|
|
@ -1330,9 +1328,7 @@ LayoutViewFunctions::cm_reload ()
|
|||
void
|
||||
LayoutViewFunctions::do_transform (const db::DCplxTrans &tr)
|
||||
{
|
||||
// end move operations, cancel edit operations
|
||||
view ()->cancel_edits ();
|
||||
view ()->lay::Editables::transform (tr);
|
||||
view ()->transform (tr);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1545,6 +1541,7 @@ LayoutViewFunctions::cm_sel_scale ()
|
|||
void
|
||||
LayoutViewFunctions::cm_sel_move_interactive ()
|
||||
{
|
||||
view ()->cancel_edits ();
|
||||
if (view ()->move_service ()->begin_move ()) {
|
||||
view ()->switch_mode (-1); // move mode
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1439,6 +1439,17 @@ LayoutView::cancel_edits ()
|
|||
LayoutViewBase::cancel_edits ();
|
||||
}
|
||||
|
||||
void
|
||||
LayoutView::finish_edits ()
|
||||
{
|
||||
// closes the property dialog
|
||||
if (mp_properties_dialog) {
|
||||
mp_properties_dialog->hide ();
|
||||
}
|
||||
|
||||
LayoutViewBase::finish_edits ();
|
||||
}
|
||||
|
||||
void
|
||||
LayoutView::activate ()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -459,6 +459,11 @@ public:
|
|||
*/
|
||||
void cancel_edits ();
|
||||
|
||||
/**
|
||||
* @brief Finishes all edit operations and maintains selection
|
||||
*/
|
||||
void finish_edits ();
|
||||
|
||||
/**
|
||||
* @brief Select all levels of hierarchy available
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1084,7 +1084,7 @@ LEFDEFReaderState::read_single_map_file (const std::string &path, std::map<std::
|
|||
tl::InputStream file_stream (file);
|
||||
tl::TextInputStream ts (file_stream);
|
||||
|
||||
tl::log << tl::to_string (tr ("Reading LEF/DEF map file")) << " " << file_stream.absolute_path ();
|
||||
tl::log << tl::to_string (tr ("Reading LEF/DEF map file")) << " " << file_stream.absolute_file_path ();
|
||||
|
||||
// Purpose name to purpose code
|
||||
std::map<std::string, LayerPurpose> purpose_translation;
|
||||
|
|
@ -2011,7 +2011,7 @@ LEFDEFImporter::get_mask (long m)
|
|||
void
|
||||
LEFDEFImporter::read (tl::InputStream &stream, db::Layout &layout, LEFDEFReaderState &state)
|
||||
{
|
||||
tl::log << tl::to_string (tr ("Reading LEF/DEF file")) << " " << stream.absolute_path ();
|
||||
tl::log << tl::to_string (tr ("Reading LEF/DEF file")) << " " << stream.absolute_file_path ();
|
||||
|
||||
m_fn = stream.filename ();
|
||||
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ LEFDEFReader::read_lefdef (db::Layout &layout, const db::LoadLayoutOptions &opti
|
|||
|
||||
std::string base_path;
|
||||
if (! effective_options.paths_relative_to_cwd ()) {
|
||||
base_path = tl::dirname (m_stream.absolute_path ());
|
||||
base_path = tl::dirname (m_stream.absolute_file_path ());
|
||||
}
|
||||
|
||||
db::LEFDEFReaderState state (&effective_options, layout, base_path);
|
||||
|
|
@ -179,7 +179,7 @@ LEFDEFReader::read_lefdef (db::Layout &layout, const db::LoadLayoutOptions &opti
|
|||
|
||||
if (effective_options.read_lef_with_def ()) {
|
||||
|
||||
std::string input_dir = tl::absolute_path (m_stream.absolute_path ());
|
||||
std::string input_dir = tl::absolute_path (m_stream.absolute_file_path ());
|
||||
|
||||
if (tl::file_exists (input_dir)) {
|
||||
|
||||
|
|
|
|||
|
|
@ -1798,7 +1798,7 @@ Database::load (std::string fn)
|
|||
reader.read (*this);
|
||||
}
|
||||
|
||||
set_filename (stream.absolute_path ());
|
||||
set_filename (stream.absolute_file_path ());
|
||||
set_name (stream.filename ());
|
||||
|
||||
reset_modified ();
|
||||
|
|
|
|||
|
|
@ -4059,7 +4059,6 @@ Eval::parse (Expression &expr, const std::string &s, bool top)
|
|||
expr = Expression (this, s);
|
||||
|
||||
tl::Extractor ex (s.c_str ());
|
||||
tl::Extractor ex0 = ex;
|
||||
ExpressionParserContext context (&expr, ex);
|
||||
|
||||
if (top) {
|
||||
|
|
@ -4074,6 +4073,8 @@ Eval::parse (Expression &expr, const std::string &s, bool top)
|
|||
void
|
||||
Eval::parse (Expression &expr, tl::Extractor &ex, bool top)
|
||||
{
|
||||
ex.skip ();
|
||||
|
||||
expr = Expression (this, ex.get ());
|
||||
|
||||
tl::Extractor ex0 = ex;
|
||||
|
|
@ -4093,6 +4094,8 @@ Eval::parse (Expression &expr, tl::Extractor &ex, bool top)
|
|||
std::string
|
||||
Eval::parse_expr (tl::Extractor &ex, bool top)
|
||||
{
|
||||
ex.skip ();
|
||||
|
||||
tl::Eval eval (0, true);
|
||||
Expression expr (&eval, ex.get ());
|
||||
|
||||
|
|
|
|||
|
|
@ -254,7 +254,6 @@ static std::vector<std::string> split_filename (const std::string &fn)
|
|||
const char *cp0 = cp;
|
||||
++cp;
|
||||
while (*cp && *cp != '.') {
|
||||
// backslash escaping (ineffective on Windows because that is a path separator)
|
||||
if (*cp == '\\' && cp[1]) {
|
||||
++cp;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -425,32 +425,124 @@ InputStream::~InputStream ()
|
|||
}
|
||||
}
|
||||
|
||||
std::string InputStream::absolute_path (const std::string &abstract_path)
|
||||
std::string InputStream::absolute_file_path (const std::string &abstract_path)
|
||||
{
|
||||
// TODO: align this implementation with InputStream ctor
|
||||
|
||||
tl::Extractor ex (abstract_path.c_str ());
|
||||
#if defined(HAVE_QT)
|
||||
if (ex.test (":")) {
|
||||
return abstract_path;
|
||||
} else
|
||||
#endif
|
||||
#if defined(HAVE_CURL) || defined(HAVE_QT)
|
||||
if (ex.test ("http:") || ex.test ("https:")) {
|
||||
return abstract_path;
|
||||
} else
|
||||
#endif
|
||||
if (ex.test ("pipe:")) {
|
||||
} else if (ex.test ("http:") || ex.test ("https:") || ex.test ("pipe:") || ex.test ("data:")) {
|
||||
return abstract_path;
|
||||
} else if (ex.test ("file:")) {
|
||||
tl::URI uri (abstract_path);
|
||||
return tl::absolute_path (uri.path ());
|
||||
return tl::absolute_file_path (uri.path ());
|
||||
} else {
|
||||
return tl::absolute_file_path (abstract_path);
|
||||
}
|
||||
}
|
||||
|
||||
const char *
|
||||
bool InputStream::is_absolute (const std::string &abstract_path)
|
||||
{
|
||||
// TODO: align this implementation with InputStream ctor
|
||||
|
||||
tl::Extractor ex (abstract_path.c_str ());
|
||||
if (ex.test (":")) {
|
||||
return true;
|
||||
} else if (ex.test ("http:") || ex.test ("https:") || ex.test ("pipe:") || ex.test ("data:")) {
|
||||
return true;
|
||||
} else if (ex.test ("file:")) {
|
||||
tl::URI uri (abstract_path);
|
||||
return tl::is_absolute (uri.path ());
|
||||
} else {
|
||||
return tl::is_absolute (abstract_path);
|
||||
}
|
||||
}
|
||||
|
||||
bool InputStream::is_file_path (const std::string &abstract_path)
|
||||
{
|
||||
tl::Extractor ex (abstract_path.c_str ());
|
||||
if (ex.test (":")) {
|
||||
return false;
|
||||
} else if (ex.test ("http:") || ex.test ("https:") || ex.test ("pipe:") || ex.test ("data:")) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
std::string InputStream::as_file_path (const std::string &abstract_path)
|
||||
{
|
||||
tl::Extractor ex (abstract_path.c_str ());
|
||||
if (ex.test (":")) {
|
||||
return std::string ();
|
||||
} else if (ex.test ("http:") || ex.test ("https:") || ex.test ("pipe:") || ex.test ("data:")) {
|
||||
return std::string ();
|
||||
} else if (ex.test ("file:")) {
|
||||
tl::URI uri (abstract_path);
|
||||
return uri.path ();
|
||||
} else {
|
||||
return abstract_path;
|
||||
}
|
||||
}
|
||||
|
||||
std::string InputStream::combine (const std::string &path1, const std::string &path2)
|
||||
{
|
||||
if (is_absolute (path2)) {
|
||||
return path2;
|
||||
}
|
||||
|
||||
tl::Extractor ex (path1);
|
||||
if (ex.test (":")) {
|
||||
return path1 + "/" + path2;
|
||||
} else if (ex.test ("pipe:") || ex.test ("data:")) {
|
||||
// ignore un-combinable first parts
|
||||
return path2;
|
||||
}
|
||||
|
||||
tl::URI uri1 (path1);
|
||||
tl::URI uri2 (path2);
|
||||
|
||||
if (uri1.scheme ().empty ()) {
|
||||
if (uri2.scheme ().empty ()) {
|
||||
return tl::combine_path (path1, path2);
|
||||
} else {
|
||||
return tl::combine_path (path1, uri2.path ());
|
||||
}
|
||||
} else {
|
||||
if (uri2.scheme ().empty ()) {
|
||||
uri1.set_path (uri1.path () + "/" + tl::replaced (path2, "\\", "/"));
|
||||
} else {
|
||||
uri1.set_path (uri1.path () + "/" + uri2.path ());
|
||||
}
|
||||
return uri1.to_abstract_path ();
|
||||
}
|
||||
}
|
||||
|
||||
std::string InputStream::relative_path (const std::string &path1, const std::string &path2)
|
||||
{
|
||||
// TODO: align this implementation with InputStream ctor
|
||||
|
||||
tl::Extractor ex (path2);
|
||||
if (ex.test (":")) {
|
||||
return path2;
|
||||
} else if (ex.test ("pipe:") || ex.test ("data:")) {
|
||||
return path2;
|
||||
}
|
||||
|
||||
tl::URI uri1 (path1);
|
||||
tl::URI uri2 (path2);
|
||||
|
||||
// NOTE: only file schemes are supported as of now
|
||||
if ((uri1.scheme ().empty () || uri1.scheme () == "file") &&
|
||||
(uri2.scheme ().empty () || uri2.scheme () == "file")) {
|
||||
return tl::relative_path (uri1.path (), uri2.path ());
|
||||
}
|
||||
|
||||
return path2;
|
||||
}
|
||||
|
||||
const char *
|
||||
InputStream::get (size_t n, bool bypass_inflate)
|
||||
{
|
||||
// if deflating, employ the deflate filter to get the data
|
||||
|
|
|
|||
|
|
@ -531,7 +531,7 @@ public:
|
|||
*
|
||||
* Returns an empty string if no absolute path is available.
|
||||
*/
|
||||
std::string absolute_path () const
|
||||
std::string absolute_file_path () const
|
||||
{
|
||||
return mp_delegate->absolute_path ();
|
||||
}
|
||||
|
|
@ -549,9 +549,34 @@ public:
|
|||
void close ();
|
||||
|
||||
/**
|
||||
* @brief Gets the absolute path for a given URL
|
||||
* @brief Gets the absolute, abstract path for a given abstract path
|
||||
*/
|
||||
static std::string absolute_path (const std::string &path);
|
||||
static std::string absolute_file_path (const std::string &apath);
|
||||
|
||||
/**
|
||||
* @brief Gets the absolute path for a given abstract path
|
||||
*/
|
||||
static bool is_absolute (const std::string &apath);
|
||||
|
||||
/**
|
||||
* @brief Gets a value indicating whether the path is a file path
|
||||
*/
|
||||
static bool is_file_path (const std::string &apath);
|
||||
|
||||
/**
|
||||
* @brief Gets the file path (no scheme) if it applies to the given abstract path
|
||||
*/
|
||||
static std::string as_file_path (const std::string &apath);
|
||||
|
||||
/**
|
||||
* @brief Combines two abstract paths
|
||||
*/
|
||||
static std::string combine (const std::string &apath1, const std::string &apath2);
|
||||
|
||||
/**
|
||||
* @brief Returns the relative abstract path of path2 vs. path1
|
||||
*/
|
||||
static std::string relative_path (const std::string &apath1, const std::string &apath2);
|
||||
|
||||
/**
|
||||
* @brief Gets the base reader (delegate)
|
||||
|
|
@ -621,7 +646,7 @@ public:
|
|||
|
||||
virtual std::string absolute_path () const
|
||||
{
|
||||
return m_inflating_stream.absolute_path ();
|
||||
return m_inflating_stream.absolute_file_path ();
|
||||
}
|
||||
|
||||
virtual std::string filename () const
|
||||
|
|
|
|||
|
|
@ -479,3 +479,112 @@ TEST(RefuseToWrite)
|
|||
}
|
||||
}
|
||||
|
||||
TEST(AbstractPathFunctions)
|
||||
{
|
||||
EXPECT_EQ (tl::InputStream::absolute_file_path (""), tl::absolute_file_path ("."));
|
||||
EXPECT_EQ (tl::InputStream::absolute_file_path ("."), tl::absolute_file_path ("."));
|
||||
EXPECT_EQ (tl::InputStream::absolute_file_path ("pipe:xyz"), "pipe:xyz");
|
||||
EXPECT_EQ (tl::InputStream::absolute_file_path ("data:xyz"), "data:xyz");
|
||||
EXPECT_EQ (tl::InputStream::absolute_file_path ("https:xyz"), "https:xyz");
|
||||
EXPECT_EQ (tl::InputStream::absolute_file_path ("http:xyz"), "http:xyz");
|
||||
EXPECT_EQ (tl::InputStream::absolute_file_path (":xyz"), ":xyz");
|
||||
EXPECT_EQ (tl::InputStream::absolute_file_path ("file:xyz"), tl::absolute_file_path ("xyz"));
|
||||
EXPECT_EQ (tl::InputStream::absolute_file_path ("xyz"), tl::absolute_file_path ("xyz"));
|
||||
EXPECT_EQ (tl::InputStream::absolute_file_path ("xyz/uvw"), tl::absolute_file_path ("xyz/uvw"));
|
||||
EXPECT_EQ (tl::InputStream::absolute_file_path ("/xyz/uvw"), tl::absolute_file_path ("/xyz/uvw"));
|
||||
tl::file_utils_force_windows ();
|
||||
EXPECT_EQ (tl::InputStream::absolute_file_path ("xyz\\uvw"), tl::absolute_file_path ("xyz\\uvw"));
|
||||
EXPECT_EQ (tl::InputStream::absolute_file_path ("\\\\server\\xyz\\uvw"), "\\\\server\\xyz\\uvw");
|
||||
EXPECT_EQ (tl::InputStream::absolute_file_path ("C:\\xyz\\uvw"), "C:\\xyz\\uvw");
|
||||
tl::file_utils_force_reset ();
|
||||
|
||||
EXPECT_EQ (tl::InputStream::is_absolute (""), false);
|
||||
EXPECT_EQ (tl::InputStream::is_absolute ("."), false);
|
||||
EXPECT_EQ (tl::InputStream::is_absolute ("pipe:xyz"), true);
|
||||
EXPECT_EQ (tl::InputStream::is_absolute ("data:xyz"), true);
|
||||
EXPECT_EQ (tl::InputStream::is_absolute ("https:xyz"), true);
|
||||
EXPECT_EQ (tl::InputStream::is_absolute ("http:xyz"), true);
|
||||
EXPECT_EQ (tl::InputStream::is_absolute (":xyz"), true);
|
||||
EXPECT_EQ (tl::InputStream::is_absolute ("file:xyz"), false);
|
||||
EXPECT_EQ (tl::InputStream::is_absolute ("xyz"), false);
|
||||
EXPECT_EQ (tl::InputStream::is_absolute ("xyz/uvw"), false);
|
||||
tl::file_utils_force_linux ();
|
||||
EXPECT_EQ (tl::InputStream::is_absolute ("/xyz/uvw"), true);
|
||||
tl::file_utils_force_windows ();
|
||||
EXPECT_EQ (tl::InputStream::is_absolute ("xyz\\uvw"), false);
|
||||
EXPECT_EQ (tl::InputStream::is_absolute ("\\\\server\\xyz\\uvw"), true);
|
||||
EXPECT_EQ (tl::InputStream::is_absolute ("c:\\xyz\\uvw"), true);
|
||||
tl::file_utils_force_reset ();
|
||||
|
||||
tl::file_utils_force_windows ();
|
||||
EXPECT_EQ (tl::InputStream::combine ("a", ""), "a");
|
||||
EXPECT_EQ (tl::InputStream::combine ("", "b"), "\\b");
|
||||
EXPECT_EQ (tl::InputStream::combine ("a", "b"), "a\\b");
|
||||
EXPECT_EQ (tl::InputStream::combine ("a", "b/c"), "a\\b/c");
|
||||
EXPECT_EQ (tl::InputStream::combine ("a", "b\\c"), "a\\b\\c");
|
||||
EXPECT_EQ (tl::InputStream::combine ("a", "data:abc"), "data:abc");
|
||||
EXPECT_EQ (tl::InputStream::combine ("data:a", "b"), "b");
|
||||
EXPECT_EQ (tl::InputStream::combine ("pipe:a", "b"), "b");
|
||||
EXPECT_EQ (tl::InputStream::combine (":a", "b"), ":a/b");
|
||||
EXPECT_EQ (tl::InputStream::combine ("https://a", "b"), "https://a/b");
|
||||
EXPECT_EQ (tl::InputStream::combine ("https://a", "https:b"), "https:b");
|
||||
EXPECT_EQ (tl::InputStream::combine ("a", "https:b"), "https:b");
|
||||
EXPECT_EQ (tl::InputStream::combine ("a", "file:b"), "a\\b");
|
||||
EXPECT_EQ (tl::InputStream::combine ("a", "file:\\b"), "file:\\b");
|
||||
EXPECT_EQ (tl::InputStream::combine ("file:a", "file:b"), "file:a/b");
|
||||
EXPECT_EQ (tl::InputStream::combine ("file:a", "file:b/c"), "file:a/b/c");
|
||||
EXPECT_EQ (tl::InputStream::combine ("file:a", "b\\c"), "file:a/b/c");
|
||||
tl::file_utils_force_linux ();
|
||||
EXPECT_EQ (tl::InputStream::combine ("a", "b"), "a/b");
|
||||
EXPECT_EQ (tl::InputStream::combine ("", "b"), "/b");
|
||||
EXPECT_EQ (tl::InputStream::combine ("a", "b/c"), "a/b/c");
|
||||
EXPECT_EQ (tl::InputStream::combine ("a", "data:abc"), "data:abc");
|
||||
EXPECT_EQ (tl::InputStream::combine ("data:a", "b"), "b");
|
||||
EXPECT_EQ (tl::InputStream::combine ("pipe:a", "b"), "b");
|
||||
EXPECT_EQ (tl::InputStream::combine (":a", "b"), ":a/b");
|
||||
EXPECT_EQ (tl::InputStream::combine ("https://a", "b"), "https://a/b");
|
||||
EXPECT_EQ (tl::InputStream::combine ("https://a", "https:b"), "https:b");
|
||||
EXPECT_EQ (tl::InputStream::combine ("a", "https:b"), "https:b");
|
||||
EXPECT_EQ (tl::InputStream::combine ("a", "file:b"), "a/b");
|
||||
EXPECT_EQ (tl::InputStream::combine ("a", "file:/b"), "file:/b");
|
||||
EXPECT_EQ (tl::InputStream::combine ("file:a", "file:b"), "file:a/b");
|
||||
EXPECT_EQ (tl::InputStream::combine ("file:a", "file:b/c"), "file:a/b/c");
|
||||
EXPECT_EQ (tl::InputStream::combine ("file:a", "b/c"), "file:a/b/c");
|
||||
tl::file_utils_force_reset ();
|
||||
|
||||
tl::file_utils_force_linux ();
|
||||
EXPECT_EQ (tl::InputStream::relative_path ("", "file:/a/b/c"), "/a/b/c");
|
||||
EXPECT_EQ (tl::InputStream::relative_path (".", "file:/a/b/c"), "/a/b/c");
|
||||
EXPECT_EQ (tl::InputStream::relative_path ("https://x", "a/b/c"), "a/b/c");
|
||||
EXPECT_EQ (tl::InputStream::relative_path ("file:/a/b", "file:/a/b/c"), "c");
|
||||
EXPECT_EQ (tl::InputStream::relative_path ("/a/b", "/a/b/c"), "c");
|
||||
EXPECT_EQ (tl::InputStream::relative_path ("/a/b", "/x/b/c"), "/x/b/c");
|
||||
EXPECT_EQ (tl::InputStream::relative_path ("file:/a/b", "file:/a/b/c"), "c");
|
||||
EXPECT_EQ (tl::InputStream::relative_path ("/a/b", "/a/b/c"), "c");
|
||||
tl::file_utils_force_windows ();
|
||||
EXPECT_EQ (tl::InputStream::relative_path ("/a/b", "/a/b/c"), "c");
|
||||
EXPECT_EQ (tl::InputStream::relative_path ("/a/b", "\\a\\b\\c\\d"), "c\\d");
|
||||
tl::file_utils_force_reset ();
|
||||
|
||||
EXPECT_EQ (tl::InputStream::is_file_path (""), true);
|
||||
EXPECT_EQ (tl::InputStream::is_file_path (":abc"), false);
|
||||
EXPECT_EQ (tl::InputStream::is_file_path ("pipe:abc"), false);
|
||||
EXPECT_EQ (tl::InputStream::is_file_path ("data:abc"), false);
|
||||
EXPECT_EQ (tl::InputStream::is_file_path ("http:abc"), false);
|
||||
EXPECT_EQ (tl::InputStream::is_file_path ("file:abc"), true);
|
||||
EXPECT_EQ (tl::InputStream::is_file_path ("a/b/c"), true);
|
||||
tl::file_utils_force_windows ();
|
||||
EXPECT_EQ (tl::InputStream::is_file_path ("a\\b\\c"), true);
|
||||
tl::file_utils_force_reset ();
|
||||
|
||||
EXPECT_EQ (tl::InputStream::as_file_path (""), std::string ());
|
||||
EXPECT_EQ (tl::InputStream::as_file_path (":abc"), std::string ());
|
||||
EXPECT_EQ (tl::InputStream::as_file_path ("pipe:abc"), std::string ());
|
||||
EXPECT_EQ (tl::InputStream::as_file_path ("data:abc"), std::string ());
|
||||
EXPECT_EQ (tl::InputStream::as_file_path ("http:abc"), std::string ());
|
||||
EXPECT_EQ (tl::InputStream::as_file_path ("file:abc"), "abc");
|
||||
EXPECT_EQ (tl::InputStream::as_file_path ("a/b/c"), "a/b/c");
|
||||
tl::file_utils_force_windows ();
|
||||
EXPECT_EQ (tl::InputStream::as_file_path ("a\\b\\c"), "a\\b\\c");
|
||||
tl::file_utils_force_reset ();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue