mirror of
https://github.com/KLayout/klayout.git
synced 2026-09-03 16:30:20 +02:00
Fixed #353 (paths relative to .lys file for rdb-file)
This fix also includes: L2N and LVS DB files are now also included in the sessions.
This commit is contained in:
+46
-11
@@ -30,7 +30,10 @@
|
||||
#include "layStream.h"
|
||||
#include "tlXMLParser.h"
|
||||
#include "tlStream.h"
|
||||
#include "tlFileUtils.h"
|
||||
#include "tlUri.h"
|
||||
#include "dbStream.h"
|
||||
#include "dbLayoutToNetlist.h"
|
||||
#include "rdb.h"
|
||||
|
||||
#include <fstream>
|
||||
@@ -86,7 +89,16 @@ 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 (rdb->filename ());
|
||||
view_desc.rdb_filenames.push_back (tl::InputStream::absolute_path (rdb->filename ()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (unsigned int j = 0; j < view->num_l2ndbs (); ++j) {
|
||||
|
||||
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 ()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -128,6 +140,17 @@ Session::fetch (const lay::MainWindow &mw)
|
||||
|
||||
}
|
||||
|
||||
std::string
|
||||
Session::make_absolute (const std::string &fp) const
|
||||
{
|
||||
tl::URI fp_uri (fp);
|
||||
if (! m_base_dir.empty () && ! tl::is_absolute (fp_uri.path ())) {
|
||||
return tl::URI (m_base_dir).resolved (fp_uri).to_string ();
|
||||
} else {
|
||||
return fp;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Session::restore (lay::MainWindow &mw)
|
||||
{
|
||||
@@ -163,11 +186,7 @@ Session::restore (lay::MainWindow &mw)
|
||||
|
||||
std::map <std::string, const SessionLayoutDescriptor *>::const_iterator ld = ld_by_name.find (cvd->layout_name);
|
||||
|
||||
std::string fp = ld->second->file_path;
|
||||
QFileInfo fi (tl::to_qstring (fp));
|
||||
if (! m_base_dir.empty () && fi.isRelative ()) {
|
||||
fp = tl::to_string (QDir (tl::to_qstring (m_base_dir)).filePath (tl::to_qstring (ld->second->file_path)));
|
||||
}
|
||||
std::string fp = make_absolute (ld->second->file_path);
|
||||
|
||||
bool ok = false;
|
||||
if (ld != ld_by_name.end ()) {
|
||||
@@ -218,13 +237,26 @@ Session::restore (lay::MainWindow &mw)
|
||||
|
||||
for (unsigned int j = 0; j < vd.rdb_filenames.size (); ++j) {
|
||||
|
||||
rdb::Database *rdb = new rdb::Database ();
|
||||
std::auto_ptr<rdb::Database> rdb (new rdb::Database ());
|
||||
|
||||
try {
|
||||
rdb->load (vd.rdb_filenames[j]);
|
||||
view->add_rdb (rdb);
|
||||
} catch (...) {
|
||||
delete rdb;
|
||||
rdb->load (make_absolute (vd.rdb_filenames[j]));
|
||||
view->add_rdb (rdb.release ());
|
||||
} catch (tl::Exception &ex) {
|
||||
tl::error << ex.msg ();
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (unsigned int j = 0; j < vd.l2ndb_filenames.size (); ++j) {
|
||||
|
||||
try {
|
||||
db::LayoutToNetlist *l2ndb = db::LayoutToNetlist::create_from_file (make_absolute (vd.l2ndb_filenames [j]));
|
||||
view->add_l2ndb (l2ndb);
|
||||
} catch (tl::Exception &ex) {
|
||||
tl::error << ex.msg ();
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -289,6 +321,9 @@ session_structure ()
|
||||
tl::make_element<std::vector<std::string>, SessionViewDescriptor> (&SessionViewDescriptor::rdb_filenames, "rdb-files",
|
||||
tl::make_member<std::string, std::vector<std::string>::const_iterator, std::vector<std::string> > (&std::vector<std::string>::begin, &std::vector<std::string>::end, &std::vector<std::string>::push_back, "rdb-file")
|
||||
) +
|
||||
tl::make_element<std::vector<std::string>, SessionViewDescriptor> (&SessionViewDescriptor::l2ndb_filenames, "l2ndb-files",
|
||||
tl::make_member<std::string, std::vector<std::string>::const_iterator, std::vector<std::string> > (&std::vector<std::string>::begin, &std::vector<std::string>::end, &std::vector<std::string>::push_back, "l2ndb-file")
|
||||
) +
|
||||
// for backward compatibility:
|
||||
tl::make_element<lay::LayerPropertiesList, SessionViewDescriptor> (&SessionViewDescriptor::set_layer_properties, "layer-properties", lay::LayerPropertiesList::xml_format ()) +
|
||||
tl::make_member<unsigned int, SessionViewDescriptor> (&SessionViewDescriptor::current_layer_list, "current-layer-property-tab") +
|
||||
|
||||
@@ -112,6 +112,7 @@ struct SessionViewDescriptor
|
||||
std::vector<lay::LayerPropertiesList> layer_properties_lists;
|
||||
unsigned int current_layer_list;
|
||||
std::vector<std::string> rdb_filenames;
|
||||
std::vector<std::string> l2ndb_filenames;
|
||||
SessionCellViewDescriptors cellviews;
|
||||
SessionAnnotationShapes annotation_shapes;
|
||||
int active_cellview;
|
||||
@@ -174,6 +175,8 @@ private:
|
||||
std::string m_window_state;
|
||||
std::string m_window_geometry;
|
||||
std::string m_base_dir;
|
||||
|
||||
std::string make_absolute (const std::string &fp) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,171 @@
|
||||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2019 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 "laySession.h"
|
||||
#include "layMainWindow.h"
|
||||
#include "layLayoutView.h"
|
||||
#include "tlUnitTest.h"
|
||||
#include "dbLayoutToNetlist.h"
|
||||
#include "dbLayoutVsSchematic.h"
|
||||
#include "rdb.h"
|
||||
#include "antObject.h"
|
||||
#include "antService.h"
|
||||
#include "imgObject.h"
|
||||
#include "imgService.h"
|
||||
#include "tlFileUtils.h"
|
||||
|
||||
TEST (1)
|
||||
{
|
||||
lay::MainWindow *mw = lay::MainWindow::instance ();
|
||||
tl_assert (mw != 0);
|
||||
|
||||
mw->close_all ();
|
||||
|
||||
mw->load_layout (tl::testsrc () + "/testdata/sessions/test.gds");
|
||||
|
||||
lay::LayoutView *view = mw->current_view ();
|
||||
|
||||
ant::Service *ant_service = view->get_plugin <ant::Service> ();
|
||||
tl_assert (ant_service != 0);
|
||||
if (ant_service) {
|
||||
ant::Object ruler;
|
||||
ruler.fmt ("Hello, world!");
|
||||
ant_service->insert_ruler (ruler, false /*do not observe the ruler count limit*/);
|
||||
}
|
||||
|
||||
img::Service *img_service = view->get_plugin <img::Service> ();
|
||||
tl_assert (img_service != 0);
|
||||
if (img_service) {
|
||||
img::Object img;
|
||||
img.load_data (tl::testsrc () + "/testdata/sessions/test.png");
|
||||
img_service->insert_image (img);
|
||||
}
|
||||
|
||||
std::auto_ptr<rdb::Database> rdb (new rdb::Database ());
|
||||
rdb->load (tl::testsrc () + "/testdata/sessions/test.lyrdb");
|
||||
view->add_rdb (rdb.release ());
|
||||
|
||||
std::auto_ptr<db::LayoutToNetlist> l2ndb (db::LayoutToNetlist::create_from_file (tl::testsrc () + "/testdata/sessions/test.l2n"));
|
||||
view->add_l2ndb (l2ndb.release ());
|
||||
|
||||
std::auto_ptr<db::LayoutToNetlist> lvsdb (db::LayoutToNetlist::create_from_file (tl::testsrc () + "/testdata/sessions/test.lvsdb"));
|
||||
view->add_l2ndb (lvsdb.release ());
|
||||
|
||||
std::string lys_file = tmp_file ("test1.lys");
|
||||
mw->save_session (lys_file);
|
||||
|
||||
mw->close_all ();
|
||||
|
||||
EXPECT_EQ (mw->views (), (unsigned int) 0);
|
||||
mw->restore_session (lys_file);
|
||||
|
||||
EXPECT_EQ (mw->views (), (unsigned int) 1);
|
||||
|
||||
view = mw->current_view ();
|
||||
tl_assert (view != 0);
|
||||
|
||||
ant_service = view->get_plugin <ant::Service> ();
|
||||
tl_assert (ant_service != 0);
|
||||
if (ant_service) {
|
||||
ant::AnnotationIterator a = ant_service->begin_annotations ();
|
||||
EXPECT_EQ (a.at_end (), false);
|
||||
if (! a.at_end ()) {
|
||||
EXPECT_EQ (a->fmt (), "Hello, world!");
|
||||
++a;
|
||||
EXPECT_EQ (a.at_end (), true);
|
||||
}
|
||||
}
|
||||
|
||||
img_service = view->get_plugin <img::Service> ();
|
||||
tl_assert (img_service != 0);
|
||||
if (img_service) {
|
||||
img::ImageIterator i = img_service->begin_images ();
|
||||
EXPECT_EQ (i.at_end (), false);
|
||||
if (! i.at_end ()) {
|
||||
EXPECT_EQ (i->width (), (unsigned int) 256);
|
||||
EXPECT_EQ (i->height (), (unsigned int) 256);
|
||||
++i;
|
||||
EXPECT_EQ (i.at_end (), true);
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_EQ (view->num_l2ndbs (), (unsigned int) 2);
|
||||
EXPECT_EQ (tl::filename (view->get_l2ndb (0)->filename ()), "test.l2n");
|
||||
EXPECT_EQ (tl::filename (view->get_l2ndb (1)->filename ()), "test.lvsdb");
|
||||
EXPECT_EQ (dynamic_cast <db::LayoutVsSchematic *> (view->get_l2ndb (1)) != 0, true);
|
||||
|
||||
EXPECT_EQ (view->num_rdbs (), (unsigned int) 1);
|
||||
EXPECT_EQ (tl::filename (view->get_rdb (0)->filename ()), "test.lyrdb");
|
||||
}
|
||||
|
||||
// issue-353 (all paths relative to .lys file)
|
||||
TEST (2)
|
||||
{
|
||||
lay::MainWindow *mw = lay::MainWindow::instance ();
|
||||
tl_assert (mw != 0);
|
||||
|
||||
mw->close_all ();
|
||||
|
||||
mw->close_all ();
|
||||
|
||||
EXPECT_EQ (mw->views (), (unsigned int) 0);
|
||||
mw->restore_session (tl::testsrc () + "/testdata/sessions/test_with_relative_paths.lys");
|
||||
|
||||
EXPECT_EQ (mw->views (), (unsigned int) 1);
|
||||
|
||||
lay::LayoutView *view = mw->current_view ();
|
||||
tl_assert (view != 0);
|
||||
|
||||
ant::Service *ant_service = view->get_plugin <ant::Service> ();
|
||||
tl_assert (ant_service != 0);
|
||||
if (ant_service) {
|
||||
ant::AnnotationIterator a = ant_service->begin_annotations ();
|
||||
EXPECT_EQ (a.at_end (), false);
|
||||
if (! a.at_end ()) {
|
||||
EXPECT_EQ (a->fmt (), "Hello, world!");
|
||||
++a;
|
||||
EXPECT_EQ (a.at_end (), true);
|
||||
}
|
||||
}
|
||||
|
||||
img::Service *img_service = view->get_plugin <img::Service> ();
|
||||
tl_assert (img_service != 0);
|
||||
if (img_service) {
|
||||
img::ImageIterator i = img_service->begin_images ();
|
||||
EXPECT_EQ (i.at_end (), false);
|
||||
if (! i.at_end ()) {
|
||||
EXPECT_EQ (i->width (), (unsigned int) 256);
|
||||
EXPECT_EQ (i->height (), (unsigned int) 256);
|
||||
++i;
|
||||
EXPECT_EQ (i.at_end (), true);
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_EQ (view->num_l2ndbs (), (unsigned int) 2);
|
||||
EXPECT_EQ (tl::filename (view->get_l2ndb (0)->filename ()), "test.l2n");
|
||||
EXPECT_EQ (tl::filename (view->get_l2ndb (1)->filename ()), "test.lvsdb");
|
||||
EXPECT_EQ (dynamic_cast <db::LayoutVsSchematic *> (view->get_l2ndb (1)) != 0, true);
|
||||
|
||||
EXPECT_EQ (view->num_rdbs (), (unsigned int) 1);
|
||||
EXPECT_EQ (tl::filename (view->get_rdb (0)->filename ()), "test.lyrdb");
|
||||
}
|
||||
@@ -8,9 +8,10 @@ include($$PWD/../../lib_ut.pri)
|
||||
|
||||
SOURCES = \
|
||||
laySalt.cc \
|
||||
laySessionTests.cc
|
||||
|
||||
INCLUDEPATH += $$LAY_INC $$TL_INC $$LAYBASIC_INC $$DB_INC $$GSI_INC
|
||||
DEPENDPATH += $$LAY_INC $$TL_INC $$LAYBASIC_INC $$DB_INC $$GSI_INC
|
||||
INCLUDEPATH += $$LAY_INC $$TL_INC $$LAYBASIC_INC $$DB_INC $$GSI_INC $$ANT_INC $$IMG_INC $$RDB_INC
|
||||
DEPENDPATH += $$LAY_INC $$TL_INC $$LAYBASIC_INC $$DB_INC $$GSI_INC $$ANT_INC $$IMG_INC $$RDB_INC
|
||||
|
||||
LIBS += -L$$DESTDIR_UT -lklayout_lay -lklayout_laybasic -lklayout_db -lklayout_tl -lklayout_gsi
|
||||
LIBS += -L$$DESTDIR_UT -lklayout_lay -lklayout_laybasic -lklayout_db -lklayout_tl -lklayout_gsi -lklayout_ant -lklayout_img -lklayout_rdb
|
||||
|
||||
|
||||
Reference in New Issue
Block a user