Enabling input files in batch mode, fixed a segfault during tests

This commit is contained in:
Matthias Koefferlein 2022-05-29 14:16:44 +02:00
parent e231f2b987
commit 40eb3aaebe
9 changed files with 184 additions and 74 deletions

View File

@ -1091,6 +1091,10 @@ ApplicationBase::run ()
// Run plugin and macro specific initializations
autorun ();
// Some objects we need during batch mode view generation
db::Manager batch_mode_manager;
tl::shared_ptr<LayoutView> batch_mode_view;
if (mw) {
for (std::vector <std::pair<file_type, std::pair<std::string, std::string> > >::const_iterator f = m_files.begin (); f != m_files.end (); ++f) {
@ -1141,11 +1145,7 @@ ApplicationBase::run ()
if (! m_layer_props_file.empty ()) {
if (m_lyp_map_all_cvs && mw->is_single_cv_layer_properties_file (m_layer_props_file)) {
mw->load_layer_properties (m_layer_props_file, -1, true /*all views*/, m_lyp_add_default);
} else {
mw->load_layer_properties (m_layer_props_file, true /*all views*/, m_lyp_add_default);
}
mw->load_layer_properties (m_layer_props_file, true /*all views*/, m_lyp_add_default);
tl::log << "Layer properties loaded '" << m_layer_props_file << "'";
@ -1165,25 +1165,79 @@ ApplicationBase::run ()
player.replay (m_gtf_replay_rate, m_gtf_replay_stop);
}
// Give the plugins a change to do some last-minute initialisation and checks
for (tl::Registrar<lay::PluginDeclaration>::iterator cls = tl::Registrar<lay::PluginDeclaration>::begin (); cls != tl::Registrar<lay::PluginDeclaration>::end (); ++cls) {
lay::PluginDeclaration *pd = const_cast<lay::PluginDeclaration *> (&*cls);
pd->initialized (dispatcher ());
}
if (! m_no_gui && m_gtf_replay.empty () && m_gtf_record.empty ()) {
// Show initial tip window if required
mw->about_to_exec ();
}
} else if (dispatcher ()) {
// Give the plugins a change to do some last-minute initialisation and checks
} else {
// in batch mode create at least one
for (std::vector <std::pair<file_type, std::pair<std::string, std::string> > >::const_iterator f = m_files.begin (); f != m_files.end (); ++f) {
if (f->first == layout_file || f->first == layout_file_with_tech) {
std::string filename = f->second.first;
if (batch_mode_view.get () != 0 && ! m_same_view) {
tl::warn << tl::sprintf (tl::to_string (tr ("Ignoring additional views in batch mode (file %s)")), filename);
continue;
}
if (! batch_mode_view) {
batch_mode_view.reset (create_view (batch_mode_manager));
}
if (f->first != layout_file_with_tech) {
batch_mode_view->load_layout (f->second.first, true);
} else {
batch_mode_view->load_layout (f->second.first, f->second.second, true);
}
// Make the first one loaded the active one.
batch_mode_view->set_active_cellview_index (0);
} else if (f->first == rdb_file) {
if (! batch_mode_view) {
batch_mode_view.reset (create_view (batch_mode_manager));
}
std::unique_ptr <rdb::Database> db (new rdb::Database ());
db->load (f->second.first);
batch_mode_view->add_rdb (db.release ());
} else if (f->first == l2ndb_file) {
if (! batch_mode_view) {
batch_mode_view.reset (create_view (batch_mode_manager));
}
batch_mode_view->add_l2ndb (db::LayoutToNetlist::create_from_file (f->second.first));
}
}
if (! m_layer_props_file.empty () && batch_mode_view.get ()) {
batch_mode_view->load_layer_props (m_layer_props_file, m_lyp_add_default);
tl::log << "Layer properties loaded '" << m_layer_props_file << "'";
// because the layer may carry transformations, we need to refit the cellviews.
batch_mode_view->zoom_fit ();
}
}
// Give the plugins a change to do some last-minute initialisation and checks
if (dispatcher ()) {
for (tl::Registrar<lay::PluginDeclaration>::iterator cls = tl::Registrar<lay::PluginDeclaration>::begin (); cls != tl::Registrar<lay::PluginDeclaration>::end (); ++cls) {
lay::PluginDeclaration *pd = const_cast<lay::PluginDeclaration *> (&*cls);
pd->initialized (dispatcher ());
}
}
if (mw && ! m_no_gui && m_gtf_replay.empty () && m_gtf_record.empty ()) {
// Show initial tip window if required
mw->about_to_exec ();
}
if (! m_run_macro.empty ()) {
@ -1200,9 +1254,29 @@ ApplicationBase::run ()
finish ();
batch_mode_view.reset (0);
return result;
}
lay::LayoutView *
ApplicationBase::create_view (db::Manager &manager)
{
// create a new view
lay::LayoutView *view = new lay::LayoutView (&manager, lay::ApplicationBase::instance ()->is_editable (), dispatcher (), 0 /*parent*/);
// set initial attributes
view->set_synchronous (m_sync_mode);
int tl = 0;
dispatcher ()->config_get (cfg_initial_hier_depth, tl);
view->set_hier_levels (std::make_pair (0, tl));
view->set_current ();
return view;
}
void
ApplicationBase::autorun ()
{
@ -1250,7 +1324,8 @@ dump_children (QObject *obj, int level = 0)
void
ApplicationBase::process_events_impl (QEventLoop::ProcessEventsFlags /*flags*/, bool /*silent*/)
{
// The base class implementation does nothing ..
// in the non-UI case there are no events, but we can at least schedule deferred method calls.
tl::DeferredMethodScheduler::execute ();
}
bool

View File

@ -54,6 +54,11 @@ namespace lym
class MacroCollection;
}
namespace db
{
class Manager;
}
namespace lay
{
@ -61,6 +66,7 @@ class MainWindow;
class Dispatcher;
class ProgressReporter;
class ProgressBar;
class LayoutView;
/**
* @brief The application base class
@ -324,6 +330,7 @@ protected:
private:
std::vector<std::string> scan_global_modules ();
lay::LayoutView *create_view (db::Manager &manager);
enum file_type {
layout_file,

View File

@ -1985,38 +1985,6 @@ MainWindow::load_layer_properties (const std::string &fn, int cv_index, bool all
}
}
bool
MainWindow::is_single_cv_layer_properties_file (const std::string &fn)
{
// If the file contains information for a single layout but we have multiple ones,
// show the dialog to determine what layout to apply the information to.
std::vector<lay::LayerPropertiesList> props;
try {
tl::XMLFileSource in (fn);
props.push_back (lay::LayerPropertiesList ());
props.back ().load (in);
} catch (...) {
props.clear ();
tl::XMLFileSource in (fn);
lay::LayerPropertiesList::load (in, props);
}
// Collect all cv indices in the layer properties
std::set <int> cv;
for (std::vector<lay::LayerPropertiesList>::const_iterator p = props.begin (); p != props.end (); ++p) {
for (lay::LayerPropertiesConstIterator lp = p->begin_const_recursive (); ! lp.at_end (); ++lp) {
if (! lp->has_children ()) {
cv.insert (lp->source (true).cv_index ());
if (cv.size () >= 2) {
break;
}
}
}
}
return (cv.size () == 1);
}
void
MainWindow::cm_save_layer_props ()
{
@ -2054,7 +2022,7 @@ MainWindow::load_layer_props_from_file (const std::string &fn)
int target_cv_index = -2;
if (current_view ()->cellviews () > 1 && is_single_cv_layer_properties_file (fn)) {
if (current_view ()->cellviews () > 1 && lay::LayoutView::is_single_cv_layer_properties_file (fn)) {
QStringList items;
items << QString (QObject::tr ("Take it as it is"));

View File

@ -239,13 +239,6 @@ public:
*/
void clone_current_view ();
/**
* @brief Determine whether a given layer properties file is a single-layout file
*
* @return True, if the file contains definitions of a single layout only.
*/
bool is_single_cv_layer_properties_file (const std::string &fn);
/**
* @brief Load a layer definition file
*

View File

@ -408,7 +408,8 @@ LayoutViewBase::init (db::Manager *mgr)
create_plugins ();
}
LayoutViewBase::~LayoutViewBase ()
void
LayoutViewBase::shutdown ()
{
// detach all observers
// This is to prevent signals to partially destroyed observers that own a LayoutViewBase
@ -457,10 +458,15 @@ LayoutViewBase::~LayoutViewBase ()
delete *p;
}
// detach from the manager, so we can safely delete the manager
// detach from the manager, so we can safely delete the manager
manager (0);
stop ();
}
LayoutViewBase::~LayoutViewBase ()
{
shutdown ();
// because LayoutViewBase and LayoutCanvas both control lifetimes of
// ruler objects for example, it is safer to explicitly delete the
@ -2287,6 +2293,38 @@ LayoutViewBase::bookmark_view (const std::string &name)
bookmarks_changed ();
}
bool
LayoutViewBase::is_single_cv_layer_properties_file (const std::string &fn)
{
// If the file contains information for a single layout but we have multiple ones,
// show the dialog to determine what layout to apply the information to.
std::vector<lay::LayerPropertiesList> props;
try {
tl::XMLFileSource in (fn);
props.push_back (lay::LayerPropertiesList ());
props.back ().load (in);
} catch (...) {
props.clear ();
tl::XMLFileSource in (fn);
lay::LayerPropertiesList::load (in, props);
}
// Collect all cv indices in the layer properties
std::set <int> cv;
for (std::vector<lay::LayerPropertiesList>::const_iterator p = props.begin (); p != props.end (); ++p) {
for (lay::LayerPropertiesConstIterator lp = p->begin_const_recursive (); ! lp.at_end (); ++lp) {
if (! lp->has_children ()) {
cv.insert (lp->source (true).cv_index ());
if (cv.size () >= 2) {
break;
}
}
}
}
return (cv.size () == 1);
}
void
LayoutViewBase::load_layer_props (const std::string &fn)
{

View File

@ -799,6 +799,13 @@ public:
*/
void load_layer_props (const std::string &fn, int cv_index, bool add_default);
/**
* @brief Determine whether a given layer properties file is a single-layout file
*
* @return True, if the file contains definitions of a single layout only.
*/
static bool is_single_cv_layer_properties_file (const std::string &fn);
/**
* @brief Bookmark the current view under the given name
*/
@ -2836,6 +2843,7 @@ protected:
virtual void create_plugins (const lay::PluginDeclaration *except_this = 0);
void free_resources ();
void shutdown ();
virtual lay::Color default_background_color ();
virtual void do_set_background_color (lay::Color color, lay::Color contrast);

View File

@ -488,7 +488,8 @@ private:
// ViewObjectWidget implementation
ViewObjectUI::ViewObjectUI ()
: m_view_objects_dismissed (false),
: mp_widget (0),
m_view_objects_dismissed (false),
m_needs_update_static (false),
m_needs_update_bg (false),
mp_active_service (0),
@ -502,16 +503,6 @@ ViewObjectUI::ViewObjectUI ()
m_widget_height (0),
m_image_updated (false)
{
#if defined(HAVE_QT)
if (lay::has_gui ()) {
mp_widget = new ViewObjectQWidget (this);
mp_widget->setMouseTracking (true);
mp_widget->setAcceptDrops (true);
} else {
mp_widget = 0;
}
#endif
m_objects.changed ().add (this, &ViewObjectUI::objects_changed);
}
@ -527,6 +518,20 @@ ViewObjectUI::~ViewObjectUI ()
}
}
#if defined(HAVE_QT)
void
ViewObjectUI::init_ui (QWidget *parent)
{
// we rely on the parent to delete the UI widget
tl_assert (parent != 0);
tl_assert (mp_widget == 0);
mp_widget = new ViewObjectQWidget (this);
mp_widget->setMouseTracking (true);
mp_widget->setAcceptDrops (true);
}
#endif
void
ViewObjectUI::register_service (lay::ViewService *svc)
{

View File

@ -589,6 +589,13 @@ public:
*/
~ViewObjectUI ();
#if defined(HAVE_QT)
/**
* @brief Initializes the UI components
*/
void init_ui (QWidget *parent);
#endif
/**
* @brief Cancel all drag operations
*/

View File

@ -289,7 +289,8 @@ LayoutView::init_ui (QWidget *parent, const char *name)
mp_widget = new LayoutViewFrame (parent, this);
mp_widget->setObjectName (QString::fromUtf8 (name));
canvas ()->widget ()->setParent (mp_widget);
canvas ()->init_ui (mp_widget);
mp_connector = new LayoutViewSignalConnector (mp_widget, this);
@ -415,6 +416,9 @@ LayoutView::~LayoutView ()
ms_current = 0;
}
// release all components and plugins before we delete the user interface
shutdown ();
if (mp_control_frame) {
delete mp_control_frame;
}
@ -443,6 +447,11 @@ LayoutView::~LayoutView ()
}
mp_bookmarks_frame = 0;
mp_bookmarks_view = 0;
if (mp_widget) {
delete mp_widget;
mp_widget = 0;
}
}
void