diff --git a/src/klayout_main/klayout_main/klayout.cc b/src/klayout_main/klayout_main/klayout.cc index bb3c31d21..d1f3b8589 100644 --- a/src/klayout_main/klayout_main/klayout.cc +++ b/src/klayout_main/klayout_main/klayout.cc @@ -234,9 +234,11 @@ klayout_main_cont (int &argc, char **argv) app.reset (new lay::GuiApplication (argc, argv)); } - QString locale = QLocale::system ().name (); + app->parse_cmd (argc, argv); + app->init_app (); /* TODO: this kills valgrind + QString locale = QLocale::system ().name (); QTranslator translator; if (app->qapp () && translator.load (QString::fromUtf8 ("klayout_") + locale)) { app->qapp ()->installTranslator (&translator); diff --git a/src/lay/lay/layApplication.cc b/src/lay/lay/layApplication.cc index ac26af7fe..56a3651ca 100644 --- a/src/lay/lay/layApplication.cc +++ b/src/lay/lay/layApplication.cc @@ -218,11 +218,12 @@ static PluginDescriptor load_plugin (const std::string &pp) // -------------------------------------------------------------------------------- // ApplicationBase implementation -ApplicationBase::ApplicationBase () +ApplicationBase::ApplicationBase (bool non_ui_mode) : gsi::ObjectBase (), m_lyp_map_all_cvs (true), m_lyp_add_default (false), - m_write_config_file (true), + m_packages_with_dep (false), + m_write_config_file (false), m_gtf_replay_rate (0), m_gtf_replay_stop (-1), m_gtf_record (), @@ -230,52 +231,26 @@ ApplicationBase::ApplicationBase () m_no_macros (false), m_same_view (false), m_sync_mode (false), - m_no_gui (false), + m_no_gui (non_ui_mode), m_vo_mode (false), m_editable (false), + m_editable_set (false), m_enable_undo (true), mp_ruby_interpreter (0), mp_python_interpreter (0) { - // nothing yet - see init -} - -void -ApplicationBase::init_app (int &argc, char **argv, bool non_ui_mode) -{ - m_no_gui = non_ui_mode; - - gsi::make_application_decl (non_ui_mode); - // TODO: offer a strict mode for exception handling where this takes place: // lay::ApplicationBase::instance ()->exit (1); - if (! non_ui_mode) { + if (! m_no_gui) { tl::set_ui_exception_handlers (ui_exception_handler_tl, ui_exception_handler_std, ui_exception_handler_def); } + gsi::make_application_decl (m_no_gui); + // initialize the system codecs (Hint: this must be done after the QApplication is initialized because // it will call setlocale) tl::initialize_codecs (); - // transscribe the arguments to UTF8 - std::vector args; - args.reserve (argc); - for (int i = 0; i < argc; ++i) { - args.push_back (argv [i]); - } - -#if defined(KLAYOUT_VIEWER_ONLY) - // viewer-only mode compiled in - m_vo_mode = true; -#else - // determine viewer-only mode from executable name. "klayout_vo*" will enable - // viewer-only mode - std::string vo_exe_name (std::string (lay::Version::exe_name ()) + "_vo"); - if (! args.empty () && std::string (tl::to_string (QFileInfo (tl::to_qstring (args.front ())).fileName ()), 0, vo_exe_name.size ()) == vo_exe_name) { - m_vo_mode = true; - } -#endif - tl_assert (ms_instance == 0); ms_instance = this; @@ -284,11 +259,18 @@ ApplicationBase::init_app (int &argc, char **argv, bool non_ui_mode) // get the installation path m_inst_path = lay::get_inst_path (); +} +void +ApplicationBase::parse_cmd (int &argc, char **argv) +{ // get the KLayout path m_klayout_path = lay::get_klayout_path (); - if (! non_ui_mode) { + // by default write the configuration + m_write_config_file = true; + + if (! m_no_gui) { // create the configuration files paths and collect the initialization config files // (the ones used for reset) into m_initial_config_files. @@ -319,100 +301,32 @@ ApplicationBase::init_app (int &argc, char **argv, bool non_ui_mode) } - // Try to locate the native plugins: - // Native plugins are DLL's or SO's disguised as "*.klp" files. - // The are installed either - // - directly in one of the KLAYOUT_PATH directories - // - in a folder named by the architecture (i.e. "i686-win32-mingw" or "x86_64-linux-gcc") below - // one of these folders - // - in one of the Salt packages - // - in one of the Salt packages, in a folder named after the architecture - - std::string version = lay::Version::version (); - std::vector vv = tl::split (version, "."); - - std::string arch_string = tl::arch_string (); - std::vector as = tl::split (arch_string, "-"); - if (as.size () > 2) { - as.resize (2); - } - std::string short_arch_string = tl::join (as, "-"); - - for (std::vector ::const_iterator p = m_klayout_path.begin (); p != m_klayout_path.end (); ++p) { - - std::set modules; - - std::vector klp_paths; - klp_paths.push_back (tl::to_qstring (*p)); - klp_paths.push_back (QDir (klp_paths.back ()).filePath (tl::to_qstring (tl::arch_string ()))); - - lay::Salt salt; - salt.add_location (tl::to_string (QDir (tl::to_qstring (*p)).filePath (QString::fromUtf8 ("salt")))); - - // Build the search path for the *.klp files. The search priority is for example: - // salt/mypackage/x86_64-linux-gcc-0.25.1 - // salt/mypackage/x86_64-linux-gcc-0.25 - // salt/mypackage/x86_64-linux-gcc-0 - // salt/mypackage/x86_64-linux-gcc - // salt/mypackage/x86_64-linux - // salt/mypackage - - for (lay::Salt::flat_iterator g = salt.begin_flat (); g != salt.end_flat (); ++g) { - QDir dir = QDir (tl::to_qstring ((*g)->path ())); - klp_paths.push_back (dir.filePath (tl::to_qstring (arch_string + "-" + lay::Version::version()))); - if (vv.size () >= 2) { - klp_paths.push_back (dir.filePath (tl::to_qstring (arch_string + "-" + vv[0] + "." + vv[1]))); - } - if (vv.size () >= 1) { - klp_paths.push_back (dir.filePath (tl::to_qstring (arch_string + "-" + vv[0]))); - } - klp_paths.push_back (dir.filePath (tl::to_qstring (arch_string + "-" + tl::to_string (lay::Version::version ())))); - klp_paths.push_back (dir.filePath (tl::to_qstring (arch_string))); - klp_paths.push_back (dir.filePath (tl::to_qstring (short_arch_string))); - klp_paths.push_back (tl::to_qstring ((*g)->path ())); - } - - QStringList name_filters; - name_filters << QString::fromUtf8 ("*.klp"); - - for (std::vector::const_iterator p = klp_paths.begin (); p != klp_paths.end (); ++p) { - - QStringList inst_modules = QDir (*p).entryList (name_filters); - inst_modules.sort (); - - for (QStringList::const_iterator im = inst_modules.begin (); im != inst_modules.end (); ++im) { - QFileInfo klp_file (*p, *im); - if (klp_file.exists () && klp_file.isReadable ()) { - std::string m = tl::to_string (klp_file.absoluteFilePath ()); - std::string mn = tl::to_string (klp_file.fileName ()); - if (modules.find (mn) == modules.end ()) { - try { - m_native_plugins.push_back (load_plugin (m)); - modules.insert (mn); - } catch (tl::Exception &ex) { - tl::error << tl::to_string (QObject::tr ("Unable to load plugin %1: %2").arg (tl::to_qstring (m)).arg (tl::to_qstring (ex.msg ()))); - } - } - } - } - - } - + // transscribe the arguments to UTF8 + std::vector args; + args.reserve (argc); + for (int i = 0; i < argc; ++i) { + args.push_back (argv [i]); } - std::vector > custom_macro_paths; +#if defined(KLAYOUT_VIEWER_ONLY) + // viewer-only mode compiled in + m_vo_mode = true; +#else + // determine viewer-only mode from executable name. "klayout_vo*" will enable + // viewer-only mode + std::string vo_exe_name (std::string (lay::Version::exe_name ()) + "_vo"); + if (! args.empty () && std::string (tl::to_string (QFileInfo (tl::to_qstring (args.front ())).fileName ()), 0, vo_exe_name.size ()) == vo_exe_name) { + m_vo_mode = true; + } +#endif + m_no_macros = false; // currently: technology is always set to make "default" technology the default - bool tech_set = true; + bool tech_set = true; std::string tech; std::string tech_file; - std::vector package_inst; - bool packages_with_dep = false; - - bool editable_set = false; - for (int i = 1; i < argc; ++i) { const std::string &a = args [i]; @@ -538,46 +452,46 @@ ApplicationBase::init_app (int &argc, char **argv, bool non_ui_mode) } else if (a == "-s") { m_same_view = true; - + } else if (a == "-e") { m_editable = ! m_vo_mode; - editable_set = true; - + m_editable_set = true; + } else if (a == "-ne") { m_editable = false; - editable_set = true; - + m_editable_set = true; + } else if (a == "-i") { m_enable_undo = false; - + } else if (a == "-ni") { m_enable_undo = true; - + } else if (a == "-j" && (i + 1) < argc) { - custom_macro_paths.push_back (std::pair (args [++i], std::string ())); - + m_custom_macro_paths.push_back (std::pair (args [++i], std::string ())); + } else if (a == "-nt") { m_write_config_file = true; - + } else if (a == "-t") { m_write_config_file = false; - + } else if (a == "-z") { m_no_gui = true; - + } else if (a == "-zz") { m_no_gui = true; // other consequences have been dealt with before - + } else if (a == "-b") { // -nc: @@ -598,17 +512,17 @@ ApplicationBase::init_app (int &argc, char **argv, bool non_ui_mode) } else if (a == "-y" && (i + 1) < argc) { - package_inst.push_back (args [++i]); + m_package_inst.push_back (args [++i]); } else if (a == "-yd") { - packages_with_dep = true; + m_packages_with_dep = true; } else if (a == "-v") { tl::info << lay::Version::name () << " " << lay::Version::version (); exit (0); - + } else if (a == "-h") { tl::info << usage () << tl::noendl; @@ -639,6 +553,91 @@ ApplicationBase::init_app (int &argc, char **argv, bool non_ui_mode) } } +} + +void +ApplicationBase::init_app () +{ + // Try to locate the native plugins: + // Native plugins are DLL's or SO's disguised as "*.klp" files. + // The are installed either + // - directly in one of the KLAYOUT_PATH directories + // - in a folder named by the architecture (i.e. "i686-win32-mingw" or "x86_64-linux-gcc") below + // one of these folders + // - in one of the Salt packages + // - in one of the Salt packages, in a folder named after the architecture + + std::string version = lay::Version::version (); + std::vector vv = tl::split (version, "."); + + std::string arch_string = tl::arch_string (); + std::vector as = tl::split (arch_string, "-"); + if (as.size () > 2) { + as.resize (2); + } + std::string short_arch_string = tl::join (as, "-"); + + for (std::vector ::const_iterator p = m_klayout_path.begin (); p != m_klayout_path.end (); ++p) { + + std::set modules; + + std::vector klp_paths; + klp_paths.push_back (tl::to_qstring (*p)); + klp_paths.push_back (QDir (klp_paths.back ()).filePath (tl::to_qstring (tl::arch_string ()))); + + lay::Salt salt; + salt.add_location (tl::to_string (QDir (tl::to_qstring (*p)).filePath (QString::fromUtf8 ("salt")))); + + // Build the search path for the *.klp files. The search priority is for example: + // salt/mypackage/x86_64-linux-gcc-0.25.1 + // salt/mypackage/x86_64-linux-gcc-0.25 + // salt/mypackage/x86_64-linux-gcc-0 + // salt/mypackage/x86_64-linux-gcc + // salt/mypackage/x86_64-linux + // salt/mypackage + + for (lay::Salt::flat_iterator g = salt.begin_flat (); g != salt.end_flat (); ++g) { + QDir dir = QDir (tl::to_qstring ((*g)->path ())); + klp_paths.push_back (dir.filePath (tl::to_qstring (arch_string + "-" + lay::Version::version()))); + if (vv.size () >= 2) { + klp_paths.push_back (dir.filePath (tl::to_qstring (arch_string + "-" + vv[0] + "." + vv[1]))); + } + if (vv.size () >= 1) { + klp_paths.push_back (dir.filePath (tl::to_qstring (arch_string + "-" + vv[0]))); + } + klp_paths.push_back (dir.filePath (tl::to_qstring (arch_string + "-" + tl::to_string (lay::Version::version ())))); + klp_paths.push_back (dir.filePath (tl::to_qstring (arch_string))); + klp_paths.push_back (dir.filePath (tl::to_qstring (short_arch_string))); + klp_paths.push_back (tl::to_qstring ((*g)->path ())); + } + + QStringList name_filters; + name_filters << QString::fromUtf8 ("*.klp"); + + for (std::vector::const_iterator p = klp_paths.begin (); p != klp_paths.end (); ++p) { + + QStringList inst_modules = QDir (*p).entryList (name_filters); + inst_modules.sort (); + + for (QStringList::const_iterator im = inst_modules.begin (); im != inst_modules.end (); ++im) { + QFileInfo klp_file (*p, *im); + if (klp_file.exists () && klp_file.isReadable ()) { + std::string m = tl::to_string (klp_file.absoluteFilePath ()); + std::string mn = tl::to_string (klp_file.fileName ()); + if (modules.find (mn) == modules.end ()) { + try { + m_native_plugins.push_back (load_plugin (m)); + modules.insert (mn); + } catch (tl::Exception &ex) { + tl::error << tl::to_string (QObject::tr ("Unable to load plugin %1: %2").arg (tl::to_qstring (m)).arg (tl::to_qstring (ex.msg ()))); + } + } + } + } + + } + + } // initialize the GSI class system (Variant binding, Expression support) // We have to do this now since plugins may register GSI classes and before the @@ -677,9 +676,9 @@ ApplicationBase::init_app (int &argc, char **argv, bool non_ui_mode) while (! ex.at_end ()) { std::string p; ex.read_word_or_quoted (p); - custom_macro_paths.push_back (std::pair (p, std::string ())); + m_custom_macro_paths.push_back (std::pair (p, std::string ())); if (ex.test (":")) { - ex.read_word (custom_macro_paths.back ().second); + ex.read_word (m_custom_macro_paths.back ().second); } ex.test (";"); } @@ -705,8 +704,8 @@ ApplicationBase::init_app (int &argc, char **argv, bool non_ui_mode) sc->set_salt_mine_url (lay::salt_mine_url ()); // Do package installation if requested. - if (!package_inst.empty ()) { - if (! sc->install_packages (package_inst, packages_with_dep)) { + if (!m_package_inst.empty ()) { + if (! sc->install_packages (m_package_inst, m_packages_with_dep)) { exit (1); } else { exit (0); @@ -767,7 +766,7 @@ ApplicationBase::init_app (int &argc, char **argv, bool non_ui_mode) } // Install the custom folders - for (std::vector >::const_iterator p = custom_macro_paths.begin (); p != custom_macro_paths.end (); ++p) { + for (std::vector >::const_iterator p = m_custom_macro_paths.begin (); p != m_custom_macro_paths.end (); ++p) { mc->add_path (p->first, tl::to_string (QObject::tr ("Project")) + " - " + p->first, p->second, false); } @@ -779,7 +778,7 @@ ApplicationBase::init_app (int &argc, char **argv, bool non_ui_mode) // If the editable flag was not set, use it from the // configuration. Since it is too early now, we cannot use the // configuration once it is read - if (! editable_set && ! m_vo_mode) { + if (! m_editable_set && ! m_vo_mode) { m_editable = editable_from_config; } @@ -1336,7 +1335,7 @@ ApplicationBase::special_app_flag (const std::string &name) // GuiApplication implementation GuiApplication::GuiApplication (int &argc, char **argv) - : QApplication (argc, argv), ApplicationBase (), + : QApplication (argc, argv), ApplicationBase (false), mp_mw (0), mp_recorder (0) { @@ -1351,8 +1350,6 @@ GuiApplication::GuiApplication (int &argc, char **argv) // only a GUI-enabled application runs an event loop and can have a deferred // method scheduler therefore. mp_dm_scheduler.reset (new tl::DeferredMethodScheduler ()); - - init_app (argc, argv, false); } GuiApplication::~GuiApplication () @@ -1557,12 +1554,12 @@ GuiApplication::process_events_impl (QEventLoop::ProcessEventsFlags flags, bool // NonGuiApplication implementation NonGuiApplication::NonGuiApplication (int &argc, char **argv) - : QCoreApplication (argc, argv), ApplicationBase (), + : QCoreApplication (argc, argv), ApplicationBase (true), mp_pr (0), mp_pb (0), mp_plugin_root (0) { - init_app (argc, argv, true); + // .. nothing yet .. } NonGuiApplication::~NonGuiApplication () diff --git a/src/lay/lay/layApplication.h b/src/lay/lay/layApplication.h index e82681e2f..f02aae551 100644 --- a/src/lay/lay/layApplication.h +++ b/src/lay/lay/layApplication.h @@ -101,7 +101,7 @@ public: * @param argc The number of external command-line arguments passed. * @param argv The external command-line arguments. */ - ApplicationBase (); + ApplicationBase (bool non_ui_mode); /** * @brief Destructor @@ -329,6 +329,17 @@ public: return m_native_plugins; } + /** + * @brief Parses the given command line arguments and configures the application object accordingly. + */ + void parse_cmd (int &argc, char **argv); + + /** + * @brief Initializes the application + * This method needs to be called after "parse_cmd" and before the application is used. + */ + void init_app (); + /** * @brief Gets the QApplication object * This method will return non-null only if a GUI-enabled application is present. @@ -336,7 +347,6 @@ public: virtual QApplication *qapp_gui () { return 0; } protected: - void init_app (int &argc, char **argv, bool non_ui_mode); virtual void setup () = 0; virtual void shutdown (); virtual void prepare_recording (const std::string >f_record, bool gtf_record_incremental); @@ -361,7 +371,10 @@ private: bool m_lyp_map_all_cvs, m_lyp_add_default; std::string m_session_file; std::string m_run_macro; + std::vector > m_custom_macro_paths; std::vector m_load_macros; + std::vector m_package_inst; + bool m_packages_with_dep; std::string m_gtf_replay; std::vector m_config_files; std::vector m_initial_config_files; @@ -381,6 +394,7 @@ private: bool m_no_gui; bool m_vo_mode; bool m_editable; + bool m_editable_set; bool m_enable_undo; // HINT: the ruby interpreter must be destroyed before MainWindow // in order to maintain a valid MainWindow reference for ruby scripts and Ruby's GC all the time. diff --git a/src/unit_tests/unit_test_main.cc b/src/unit_tests/unit_test_main.cc index 3047d7b66..1c90f2f68 100644 --- a/src/unit_tests/unit_test_main.cc +++ b/src/unit_tests/unit_test_main.cc @@ -396,16 +396,10 @@ main_cont (int &argc, char **argv) throw tl::Exception ("No test libraries found - make sure, the *.ut files are next to the ut_runner executable."); } - // No side effects - lay::set_klayout_path (std::vector ()); - - static char av0[] = "unit_test"; - static char av1[] = "-z"; // don't show main window - static char av2[] = "-nc"; // No configuration file - static char av3[] = "-rx"; // No mplicit macros - char *av[] = { av0, av1, av2, av3, 0 }; - int ac = sizeof (av) / sizeof (av[0]) - 1; - lay::GuiApplication app (ac, av); + // NOTE: we need an application object, but we don't call parse_cmd. This makes the object + // behave neutral as far as possible. + lay::GuiApplication app (argc, argv); + app.init_app (); app.ruby_interpreter ().push_console (&console); app.python_interpreter ().push_console (&console);