diff --git a/src/lay/lay/layApplication.cc b/src/lay/lay/layApplication.cc index 1ed3c8285..60c3d572b 100644 --- a/src/lay/lay/layApplication.cc +++ b/src/lay/lay/layApplication.cc @@ -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 batch_mode_view; + if (mw) { for (std::vector > >::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::iterator cls = tl::Registrar::begin (); cls != tl::Registrar::end (); ++cls) { - lay::PluginDeclaration *pd = const_cast (&*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 > >::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 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::iterator cls = tl::Registrar::begin (); cls != tl::Registrar::end (); ++cls) { lay::PluginDeclaration *pd = const_cast (&*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 diff --git a/src/lay/lay/layApplication.h b/src/lay/lay/layApplication.h index 887fc42c5..b821cc7a0 100644 --- a/src/lay/lay/layApplication.h +++ b/src/lay/lay/layApplication.h @@ -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 scan_global_modules (); + lay::LayoutView *create_view (db::Manager &manager); enum file_type { layout_file, diff --git a/src/lay/lay/layMainWindow.cc b/src/lay/lay/layMainWindow.cc index a7e412abc..c9abd8ddc 100644 --- a/src/lay/lay/layMainWindow.cc +++ b/src/lay/lay/layMainWindow.cc @@ -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 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 cv; - for (std::vector::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")); diff --git a/src/lay/lay/layMainWindow.h b/src/lay/lay/layMainWindow.h index 8c40b7250..434edf347 100644 --- a/src/lay/lay/layMainWindow.h +++ b/src/lay/lay/layMainWindow.h @@ -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 * diff --git a/src/laybasic/laybasic/layLayoutViewBase.cc b/src/laybasic/laybasic/layLayoutViewBase.cc index 75b3fe78e..665a9f075 100644 --- a/src/laybasic/laybasic/layLayoutViewBase.cc +++ b/src/laybasic/laybasic/layLayoutViewBase.cc @@ -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 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 cv; + for (std::vector::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) { diff --git a/src/laybasic/laybasic/layLayoutViewBase.h b/src/laybasic/laybasic/layLayoutViewBase.h index 81379af57..fadf48bb2 100644 --- a/src/laybasic/laybasic/layLayoutViewBase.h +++ b/src/laybasic/laybasic/layLayoutViewBase.h @@ -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); diff --git a/src/laybasic/laybasic/layViewObject.cc b/src/laybasic/laybasic/layViewObject.cc index 3fc597c20..d782656a9 100644 --- a/src/laybasic/laybasic/layViewObject.cc +++ b/src/laybasic/laybasic/layViewObject.cc @@ -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) { diff --git a/src/laybasic/laybasic/layViewObject.h b/src/laybasic/laybasic/layViewObject.h index 242558d00..7f3e14694 100644 --- a/src/laybasic/laybasic/layViewObject.h +++ b/src/laybasic/laybasic/layViewObject.h @@ -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 */ diff --git a/src/layview/layview/layLayoutView_qt.cc b/src/layview/layview/layLayoutView_qt.cc index 4a431e518..4727fedf3 100644 --- a/src/layview/layview/layLayoutView_qt.cc +++ b/src/layview/layview/layLayoutView_qt.cc @@ -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