diff --git a/setup.py b/setup.py index 30cdde5e9..b2c5e2748 100644 --- a/setup.py +++ b/setup.py @@ -320,7 +320,7 @@ class Config(object): """ Gets the version string """ - return "0.26.0.dev7" + return "0.26.0.dev8" config = Config() diff --git a/src/ant/ant/antPlugin.cc b/src/ant/ant/antPlugin.cc index 443cebec1..1bd0d327e 100644 --- a/src/ant/ant/antPlugin.cc +++ b/src/ant/ant/antPlugin.cc @@ -169,7 +169,7 @@ PluginDeclaration::config_finalize () } void -PluginDeclaration::initialized (lay::PluginRoot *) +PluginDeclaration::initialized (lay::PluginRoot *root) { // Check if we already have templates (initial setup) bool any_templates = false; @@ -198,8 +198,8 @@ PluginDeclaration::initialized (lay::PluginRoot *) m_templates.push_back (ant::Template (tl::to_string (QObject::tr ("Box")), "W=$(abs(X))", "H=$(abs(Y))", "", ant::Object::STY_line, ant::Object::OL_box, true, lay::AC_Global, std::string ())); - lay::PluginRoot::instance ()->config_set (cfg_ruler_templates, ant::TemplatesConverter ().to_string (m_templates)); - lay::PluginRoot::instance ()->config_end (); + root->config_set (cfg_ruler_templates, ant::TemplatesConverter ().to_string (m_templates)); + root->config_end (); } } diff --git a/src/buddies/src/bd/bdWriterOptions.cc b/src/buddies/src/bd/bdWriterOptions.cc index e7ecfd08c..2176416b4 100644 --- a/src/buddies/src/bd/bdWriterOptions.cc +++ b/src/buddies/src/bd/bdWriterOptions.cc @@ -242,7 +242,8 @@ GenericWriterOptions::add_options (tl::CommandLineOptions &cmd, const std::strin "* 0: create POLYLINE (default)\n" "* 1: create LWPOLYLINE\n" "* 2: decompose into SOLID\n" - "* 3: create HATCH" + "* 3: create HATCH\n" + "* 4: create LINE" ) ; diff --git a/src/db/db/dbEdgesToContours.cc b/src/db/db/dbEdgesToContours.cc index 4a1df24e4..832d5cb39 100644 --- a/src/db/db/dbEdgesToContours.cc +++ b/src/db/db/dbEdgesToContours.cc @@ -110,25 +110,82 @@ EdgesToContours::contour (size_t i) const } } +namespace { + +template +class point_matcher +{ +public: + + point_matcher () : m_vp_min (0.0), m_d_min (0.0), m_any (false) + { + // .. nothing yet .. + } + + /** + * @brief A search criterion for fitting next edges for a point (with attached edge) + * This search will select the edge whose starting point is closest to the + * end point of the reference edge and - if both points are coincident - forms + * the smallest angle with the reference edge. + */ + bool more (const db::point &p, const db::edge &e, const db::edge &other, bool swapped) + { + typedef db::coord_traits coord_traits; + + double d = p.double_distance (swapped ? other.p2 () : other.p1 ()); + double vp = db::vprod (other.d (), e.d ()) * (1.0 / other.d ().double_length ()); + + if (! m_any) { + + m_vp_min = vp; + m_d_min = d; + m_any = true; + return true; + + } else if (fabs (d - m_d_min) < coord_traits::prec ()) { + + double vp = db::vprod (other.d (), e.d ()) * (1.0 / other.d ().double_length ()); + if (vp < m_vp_min) { + m_vp_min = vp; + return true; + } else { + return false; + } + + } else if (d < m_d_min) { + + m_vp_min = vp; + m_d_min = d; + return true; + + } else { + return false; + } + } + +private: + double m_vp_min; + double m_d_min; + bool m_any; +}; + +} + template static EdgeRef *search_follower (const db::point &p, const EdgeRef *e, C distance, const db::box_tree, EdgeRef *, EdgeRefToBox > &t1, const db::box_tree, EdgeRef *, EdgeRefToBox > &t2) { typedef db::box box_type; - double vp_min = 0.0; EdgeRef *cand = 0; bool fwd = true; + point_matcher pm; // try in forward tree typename db::box_tree *, EdgeRefToBox >::touching_iterator f = t1.begin_touching (box_type (p, p), EdgeRefToBox (distance)); while (! f.at_end ()) { - if (*f != e && ! (*f)->connected && (*f)->swapped != 1) { - double vp = db::vprod ((*f)->iter->d (), e->iter->d ()) * (1.0 / (*f)->iter->d ().double_length ()); - if (! cand || vp < vp_min) { - vp_min = vp; - cand = *f; - } + if (*f != e && ! (*f)->connected && (*f)->swapped != 1 && pm.more (p, *e->iter, *(*f)->iter, false)) { + cand = *f; } ++f; } @@ -136,13 +193,9 @@ EdgeRef *search_follower (const db::point &p, const EdgeRef *e, C if (! t2.empty ()) { typename db::box_tree *, EdgeRefToBox >::touching_iterator f = t2.begin_touching (box_type (p, p), EdgeRefToBox (distance)); while (! f.at_end ()) { - if (*f != e && ! (*f)->connected && (*f)->swapped != -1) { - double vp = db::vprod ((*f)->iter->d (), e->iter->d ()) * (1.0 / (*f)->iter->d ().double_length ()); - if (! cand || vp < vp_min) { - vp_min = vp; - cand = *f; - fwd = false; - } + if (*f != e && ! (*f)->connected && (*f)->swapped != -1 && pm.more (p, *e->iter, *(*f)->iter, true)) { + cand = *f; + fwd = false; } ++f; } diff --git a/src/lay/lay/layApplication.cc b/src/lay/lay/layApplication.cc index 2c5a6bc02..76da61364 100644 --- a/src/lay/lay/layApplication.cc +++ b/src/lay/lay/layApplication.cc @@ -1114,7 +1114,7 @@ ApplicationBase::run () // 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 (mw); + pd->initialized (plugin_root ()); } if (! m_no_gui && m_gtf_replay.empty () && m_gtf_record.empty ()) { @@ -1280,6 +1280,7 @@ ApplicationBase::special_app_flag (const std::string &name) GuiApplication::GuiApplication (int &argc, char **argv) : QApplication (argc, argv), ApplicationBase (false), mp_mw (0), + mp_plugin_root (0), mp_recorder (0) { // install a special style proxy to overcome the issue of black-on-black tree expanders @@ -1300,6 +1301,9 @@ GuiApplication::~GuiApplication () } shutdown (); + + delete mp_plugin_root; + mp_plugin_root = 0; } bool @@ -1455,15 +1459,18 @@ GuiApplication::start_recording () lay::PluginRoot * GuiApplication::plugin_root () const { - return mp_mw; + return mp_plugin_root; } void GuiApplication::setup () { - tl_assert (mp_mw == 0); + tl_assert (mp_mw == 0 && mp_plugin_root == 0); + + mp_plugin_root = new lay::PluginRootToMainWindow (); + mp_mw = new lay::MainWindow (this, mp_plugin_root, "main_window"); + mp_plugin_root->attach_to (mp_mw); - mp_mw = new lay::MainWindow (this, "main_window"); QObject::connect (mp_mw, SIGNAL (closed ()), this, SLOT (quit ())); // create a password dialog for use with the HTTP streams diff --git a/src/lay/lay/layApplication.h b/src/lay/lay/layApplication.h index 1aa7633ba..c49e3b7b5 100644 --- a/src/lay/lay/layApplication.h +++ b/src/lay/lay/layApplication.h @@ -57,6 +57,7 @@ namespace lay { class MainWindow; +class PluginRootToMainWindow; class PluginRoot; class ProgressReporter; class ProgressBar; @@ -443,6 +444,7 @@ protected: private: MainWindow *mp_mw; + PluginRootToMainWindow *mp_plugin_root; gtf::Recorder *mp_recorder; }; diff --git a/src/lay/lay/layGenericSyntaxHighlighter.cc b/src/lay/lay/layGenericSyntaxHighlighter.cc index 80df7e962..e1324be73 100644 --- a/src/lay/lay/layGenericSyntaxHighlighter.cc +++ b/src/lay/lay/layGenericSyntaxHighlighter.cc @@ -32,7 +32,7 @@ #include -// #define DEBUG_HIGHLIGHTER +// #define DEBUG_HIGHLIGHTER /** * @brief Provide a compare operator for QList because Qt doesn't @@ -907,20 +907,31 @@ GenericSyntaxHighlighterAttributes::GenericSyntaxHighlighterAttributes (const Ge : mp_basic_attributes (basic_attributes) { if (! basic_attributes) { - add (QString::fromUtf8 ("Normal"), dsNormal, false, false, false, false, 0, 0, 0, 0); - add (QString::fromUtf8 ("Alert"), dsAlert, true, false, false, false, "#BF0303", "#9C0D0D", "#F7E7E7", 0); - add (QString::fromUtf8 ("Base-N Integer"), dsBaseN, false, false, false, false, "#B07E00", "#FFDD00", 0, 0); - add (QString::fromUtf8 ("Character"), dsChar, false, false, false, false, "#FF80E0", "#FF80E0", 0, 0); - add (QString::fromUtf8 ("Comment"), dsComment, false, true, false, false, "#888786", "#A6C2E4", 0, 0); - add (QString::fromUtf8 ("Data Type"), dsDataType, false, false, false, false, "#0057AE", "#00316E", 0, 0); - add (QString::fromUtf8 ("Decimal/Value"), dsDecVal, false, false, false, false, "#B07E00", "#FFDD00", 0, 0); - add (QString::fromUtf8 ("Error"), dsError, false, false, true, false, "#BF0303", "#9C0D0D", 0, 0); - add (QString::fromUtf8 ("Floating Point"), dsFloat, false, false, false, false, "#B07E00", "#FFDD00", 0, 0); - add (QString::fromUtf8 ("Function"), dsFunction, false, false, false, false, "#442886", "#442886", 0, 0); - add (QString::fromUtf8 ("Keyword"), dsKeyword, true, false, false, false, 0, 0, 0, 0); - add (QString::fromUtf8 ("Others"), dsOthers, false, false, false, false, "#006E26", "#80FF80", 0, 0); - add (QString::fromUtf8 ("Region Marker"), dsRegionMarker, false, false, false, false, "#0057AE", "#00316E", "#E1EAF8", 0); - add (QString::fromUtf8 ("String"), dsString, false, false, false, false, "#BF0303", "#9C0D0D", 0, 0); + add (QString::fromUtf8 ("Normal"), dsNormal, false, false, false, false, 0, 0, 0, 0); + add (QString::fromUtf8 ("Alert"), dsAlert, true, false, false, false, "#BF0303", "#9C0D0D", "#F7E7E7", 0); + add (QString::fromUtf8 ("Base-N Integer"), dsBaseN, false, false, false, false, "#B07E00", "#FFDD00", 0, 0); + add (QString::fromUtf8 ("Character"), dsChar, false, false, false, false, "#FF80E0", "#FF80E0", 0, 0); + add (QString::fromUtf8 ("Comment"), dsComment, false, true, false, false, "#888786", "#A6C2E4", 0, 0); + add (QString::fromUtf8 ("Data Type"), dsDataType, false, false, false, false, "#0057AE", "#00316E", 0, 0); + add (QString::fromUtf8 ("Decimal/Value"), dsDecVal, false, false, false, false, "#B07E00", "#FFDD00", 0, 0); + add (QString::fromUtf8 ("Error"), dsError, false, false, true, false, "#BF0303", "#9C0D0D", 0, 0); + add (QString::fromUtf8 ("Floating Point"), dsFloat, false, false, false, false, "#B07E00", "#FFDD00", 0, 0); + add (QString::fromUtf8 ("Function"), dsFunction, false, false, false, false, "#442886", "#442886", 0, 0); + add (QString::fromUtf8 ("Keyword"), dsKeyword, true, false, false, false, 0, 0, 0, 0); + add (QString::fromUtf8 ("Others"), dsOthers, false, false, false, false, "#006E26", "#80FF80", 0, 0); + add (QString::fromUtf8 ("Region Marker"), dsRegionMarker, false, false, false, false, "#0057AE", "#00316E", "#E1EAF8", 0); + add (QString::fromUtf8 ("String"), dsString, false, false, false, false, "#BF0303", "#9C0D0D", 0, 0); + add (QString::fromUtf8 ("Operator"), dsOperator, false, false, false, false, "#1F1C1B", 0, 0, 0); + add (QString::fromUtf8 ("Control Flow"), dsControlFlow, true, false, false, false, "#1F1C1B", 0, 0, 0); + add (QString::fromUtf8 ("Built-in"), dsBuiltIn, true, false, false, false, "#644A9B", "#452886", 0, 0); + add (QString::fromUtf8 ("Variable"), dsVariable, false, false, false, false, "#0057AE", "#00316e", 0, 0); + add (QString::fromUtf8 ("Extension"), dsExtension, false, false, false, false, "#0095FF", 0, 0, 0); + add (QString::fromUtf8 ("Preprocessor"), dsPreprocessor, false, false, false, false, "#006E28", "#006e28", 0, 0); + add (QString::fromUtf8 ("Import"), dsImport, false, false, false, false, "#FF5500", "#FF5500", 0, 0); + add (QString::fromUtf8 ("Verbatim String"), dsVerbatimString, false, false, false, false, "#BF0303", "#9C0E0E", 0, 0); + add (QString::fromUtf8 ("Special String"), dsSpecialString, false, false, false, false, "#FF5500", "#FF5500", 0, 0); + add (QString::fromUtf8 ("Special Character"), dsSpecialChar, false, false, false, false, "#3DAEE9", "#FCFCFC", 0, 0); + add (QString::fromUtf8 ("Attribute"), dsAttribute, false, false, false, false, "#0057AE", "#00316E", 0, 0); } } @@ -1416,7 +1427,7 @@ parse_rule (QDomElement e, GenericSyntaxHighlighterContexts &contexts, std::map< } static GenericSyntaxHighlighterContext -parse_context (QDomElement e, GenericSyntaxHighlighterContexts &contexts, std::map &lists, GenericSyntaxHighlighterAttributes &attributes) +parse_context (QDomElement e, const std::map &contexts_by_name, GenericSyntaxHighlighterContexts &contexts, std::map &lists, GenericSyntaxHighlighterAttributes &attributes) { GenericSyntaxHighlighterContext context; @@ -1424,7 +1435,11 @@ parse_context (QDomElement e, GenericSyntaxHighlighterContexts &contexts, std::m if (n.isElement()) { QDomElement ee = n.toElement(); if (ee.tagName () == QString::fromUtf8 ("IncludeRules")) { - context.include (contexts.context (ee.attributeNode (QString::fromUtf8 ("context")).value ())); + QString included_name = ee.attributeNode (QString::fromUtf8 ("context")).value (); + std::map::const_iterator c2n = contexts_by_name.find (included_name); + if (c2n != contexts_by_name.end ()) { + context.include (parse_context (c2n->second, contexts_by_name, contexts, lists, attributes)); + } } else { context.add_rule (parse_rule (ee, contexts, lists, attributes)); } @@ -1498,6 +1513,18 @@ parse_item_data (QDomElement e, GenericSyntaxHighlighterAttributes &attributes) else if (s == QString::fromUtf8 ("dsOthers")) { ds = dsOthers; } else if (s == QString::fromUtf8 ("dsRegionMarker")) { ds = dsRegionMarker; } else if (s == QString::fromUtf8 ("dsString")) { ds = dsString; } + else if (s == QString::fromUtf8 ("dsOperator")) { ds = dsOperator; } + else if (s == QString::fromUtf8 ("dsControlFlow")) { ds = dsControlFlow; } + else if (s == QString::fromUtf8 ("dsBuiltIn")) { ds = dsBuiltIn; } + else if (s == QString::fromUtf8 ("dsVariable")) { ds = dsVariable; } + else if (s == QString::fromUtf8 ("dsExtension")) { ds = dsExtension; } + else if (s == QString::fromUtf8 ("dsPreprocessor")) { ds = dsPreprocessor; } + else if (s == QString::fromUtf8 ("dsImport")) { ds = dsImport; } + else if (s == QString::fromUtf8 ("dsVerbatimString")) { ds = dsVerbatimString; } + else if (s == QString::fromUtf8 ("dsSpecialString")) { ds = dsSpecialString; } + else if (s == QString::fromUtf8 ("dsSpecialString")) { ds = dsSpecialString; } + else if (s == QString::fromUtf8 ("dsSpecialChar")) { ds = dsSpecialChar; } + else if (s == QString::fromUtf8 ("dsAttribute")) { ds = dsAttribute; } } attributes.set_styles (attribute_id, ds, format); @@ -1534,12 +1561,26 @@ GenericSyntaxHighlighter::GenericSyntaxHighlighter (QObject *parent, QIODevice & } else if (e.tagName () == QString::fromUtf8 ("contexts")) { + // first analyze the list of contexts and their dependencies + + std::map contexts_by_name; + for (QDomNode nn = e.firstChild(); !nn.isNull(); nn = nn.nextSibling()) { if (nn.isElement()) { QDomElement ee = nn.toElement (); if (ee.tagName () == QString::fromUtf8 ("context")) { QString context_name = ee.attributeNode (QString::fromUtf8 ("name")).value (); - m_contexts.insert (context_name, parse_context (ee, m_contexts, m_lists, *mp_attributes)); + contexts_by_name[context_name] = ee; + } + } + } + + for (QDomNode nn = e.firstChild(); !nn.isNull(); nn = nn.nextSibling()) { + if (nn.isElement()) { + QDomElement ee = nn.toElement (); + if (ee.tagName () == QString::fromUtf8 ("context")) { + QString context_name = ee.attributeNode (QString::fromUtf8 ("name")).value (); + m_contexts.insert (context_name, parse_context (ee, contexts_by_name, m_contexts, m_lists, *mp_attributes)); } } } diff --git a/src/lay/lay/layGenericSyntaxHighlighter.h b/src/lay/lay/layGenericSyntaxHighlighter.h index ee42704d3..2bcbefa2e 100644 --- a/src/lay/lay/layGenericSyntaxHighlighter.h +++ b/src/lay/lay/layGenericSyntaxHighlighter.h @@ -562,6 +562,17 @@ enum def_style { dsOthers, dsRegionMarker, dsString, + dsOperator, + dsControlFlow, + dsBuiltIn, + dsVariable, + dsExtension, + dsPreprocessor, + dsImport, + dsVerbatimString, + dsSpecialString, + dsSpecialChar, + dsAttribute, dsLast }; diff --git a/src/lay/lay/layMacroController.cc b/src/lay/lay/layMacroController.cc index 7bc3d8ca6..4ea5776cc 100644 --- a/src/lay/lay/layMacroController.cc +++ b/src/lay/lay/layMacroController.cc @@ -164,9 +164,9 @@ MacroController::initialized (lay::PluginRoot *root) connect (&m_temp_macros, SIGNAL (menu_needs_update ()), this, SLOT (macro_collection_changed ())); connect (&m_temp_macros, SIGNAL (macro_collection_changed (lym::MacroCollection *)), this, SLOT (macro_collection_changed ())); - mp_mw = dynamic_cast (root); + mp_mw = lay::MainWindow::instance (); if (mp_mw) { - mp_macro_editor = new lay::MacroEditorDialog (mp_mw, &lym::MacroCollection::root ()); + mp_macro_editor = new lay::MacroEditorDialog (root, &lym::MacroCollection::root ()); mp_macro_editor->setModal (false); } diff --git a/src/lay/lay/layMacroEditorDialog.cc b/src/lay/lay/layMacroEditorDialog.cc index eed7c5496..926400848 100644 --- a/src/lay/lay/layMacroEditorDialog.cc +++ b/src/lay/lay/layMacroEditorDialog.cc @@ -227,10 +227,10 @@ public: static lay::MacroEditorDialog *s_macro_editor_instance = 0; -MacroEditorDialog::MacroEditorDialog (lay::MainWindow *mw, lym::MacroCollection *root) +MacroEditorDialog::MacroEditorDialog (lay::PluginRoot *pr, lym::MacroCollection *root) : QDialog (0 /*show as individual top widget*/, Qt::Window), - lay::Plugin (mw, true), - mp_plugin_root (mw), + lay::Plugin (pr, true), + mp_plugin_root (pr), mp_root (root), m_first_show (true), m_in_processing (false), m_debugging_on (true), mp_run_macro (0), diff --git a/src/lay/lay/layMacroEditorDialog.h b/src/lay/lay/layMacroEditorDialog.h index bb492c71e..e1fea9391 100644 --- a/src/lay/lay/layMacroEditorDialog.h +++ b/src/lay/lay/layMacroEditorDialog.h @@ -98,7 +98,7 @@ public: /** * @brief Constructor */ - MacroEditorDialog (lay::MainWindow *parent, lym::MacroCollection *root); + MacroEditorDialog (lay::PluginRoot *pr, lym::MacroCollection *root); /** * @brief Destructor diff --git a/src/lay/lay/layMainWindow.cc b/src/lay/lay/layMainWindow.cc index 94d3941c3..37e55e9d5 100644 --- a/src/lay/lay/layMainWindow.cc +++ b/src/lay/lay/layMainWindow.cc @@ -443,8 +443,9 @@ MainWindow::instance () // ----------------------------------- -MainWindow::MainWindow (QApplication *app, const char *name) +MainWindow::MainWindow (QApplication *app, lay::Plugin *plugin_parent, const char *name) : QMainWindow (0), + lay::Plugin (plugin_parent), m_text_progress (this, 10 /*verbosity threshold*/), m_mode (std::numeric_limits::max ()), mp_setup_form (0), @@ -473,7 +474,7 @@ MainWindow::MainWindow (QApplication *app, const char *name) } mw_instance = this; - mp_setup_form = new SettingsForm (0, this, "setup_form"), + mp_setup_form = new SettingsForm (0, plugin_root (), "setup_form"), db::LibraryManager::instance ().changed_event.add (this, &MainWindow::libraries_changed); @@ -1082,13 +1083,13 @@ void MainWindow::dock_widget_visibility_changed (bool /*visible*/) { if (sender () == mp_lp_dock_widget) { - config_set (cfg_show_layer_panel, tl::to_string (!mp_lp_dock_widget->isHidden ())); + plugin_root ()->config_set (cfg_show_layer_panel, tl::to_string (!mp_lp_dock_widget->isHidden ())); } else if (sender () == mp_hp_dock_widget) { - config_set (cfg_show_hierarchy_panel, tl::to_string (!mp_hp_dock_widget->isHidden ())); + plugin_root ()->config_set (cfg_show_hierarchy_panel, tl::to_string (!mp_hp_dock_widget->isHidden ())); } else if (sender () == mp_navigator_dock_widget) { - config_set (cfg_show_navigator, tl::to_string (!mp_navigator_dock_widget->isHidden ())); + plugin_root ()->config_set (cfg_show_navigator, tl::to_string (!mp_navigator_dock_widget->isHidden ())); } else if (sender () == mp_layer_toolbox_dock_widget) { - config_set (cfg_show_layer_toolbox, tl::to_string (!mp_layer_toolbox_dock_widget->isHidden ())); + plugin_root ()->config_set (cfg_show_layer_toolbox, tl::to_string (!mp_layer_toolbox_dock_widget->isHidden ())); } } @@ -1283,7 +1284,7 @@ MainWindow::about_to_exec () lay::TipDialog::button_type button = lay::TipDialog::null_button; if (td.exec_dialog (button)) { if (button == lay::TipDialog::yes_button) { - config_set (cfg_full_hier_new_cell, true); + plugin_root ()->config_set (cfg_full_hier_new_cell, true); } // Don't bother the user with more dialogs. return; @@ -1734,17 +1735,6 @@ MainWindow::configure (const std::string &name, const std::string &value) apply_hidden (hidden); return true; - } else if (name == cfg_background_color) { - - if (mp_navigator) { - QColor color; - ColorConverter ().from_string (value, color); - mp_navigator->background_color (color); - } - - // do not take - let others receive the background color events as well - return false; - } else if (name == cfg_initial_technology) { m_initial_technology = value; @@ -1818,10 +1808,10 @@ MainWindow::libraries_changed () void MainWindow::read_dock_widget_state () { - config_set (cfg_show_layer_panel, tl::to_string (!mp_lp_dock_widget->isHidden ())); - config_set (cfg_show_hierarchy_panel, tl::to_string (!mp_hp_dock_widget->isHidden ())); - config_set (cfg_show_navigator, tl::to_string (!mp_navigator_dock_widget->isHidden ())); - config_set (cfg_show_layer_toolbox, tl::to_string (!mp_layer_toolbox_dock_widget->isHidden ())); + plugin_root ()->config_set (cfg_show_layer_panel, tl::to_string (!mp_lp_dock_widget->isHidden ())); + plugin_root ()->config_set (cfg_show_hierarchy_panel, tl::to_string (!mp_hp_dock_widget->isHidden ())); + plugin_root ()->config_set (cfg_show_navigator, tl::to_string (!mp_navigator_dock_widget->isHidden ())); + plugin_root ()->config_set (cfg_show_layer_toolbox, tl::to_string (!mp_layer_toolbox_dock_widget->isHidden ())); } void @@ -1934,7 +1924,7 @@ MainWindow::can_close () for (tl::Registrar::iterator cls = tl::Registrar::begin (); cls != tl::Registrar::end (); ++cls) { lay::PluginDeclaration *pd = const_cast (&*cls); - if (! pd->can_exit (this)) { + if (! pd->can_exit (plugin_root ())) { return false; } } @@ -1979,8 +1969,8 @@ MainWindow::save_state_to_config () { // save the dock widget state with all views closed (that state can be // used for staring klayout without any layout) - config_set (cfg_window_geometry, (const char *) saveGeometry ().toBase64 ().data ()); - config_set (cfg_window_state, (const char *) saveState ().toBase64 ().data ()); + plugin_root ()->config_set (cfg_window_geometry, (const char *) saveGeometry ().toBase64 ().data ()); + plugin_root ()->config_set (cfg_window_state, (const char *) saveState ().toBase64 ().data ()); } void @@ -2304,9 +2294,7 @@ MainWindow::intrinsic_mode_triggered () int mode = action->data ().toInt (); - if (lay::PluginRoot::instance ()) { - lay::PluginRoot::instance ()->select_mode (mode); - } + plugin_root ()->select_mode (mode); action->setChecked (true); @@ -3405,13 +3393,13 @@ MainWindow::cm_pull_in () void MainWindow::cm_reader_options () { - mp_layout_load_options->edit_global_options (this, db::Technologies::instance ()); + mp_layout_load_options->edit_global_options (plugin_root (), db::Technologies::instance ()); } void MainWindow::cm_writer_options () { - mp_layout_save_options->edit_global_options (this, db::Technologies::instance ()); + mp_layout_save_options->edit_global_options (plugin_root (), db::Technologies::instance ()); } void @@ -3680,7 +3668,7 @@ MainWindow::clone_current_view () } // create a new view - view = new lay::LayoutView (current_view (), &m_manager, lay::ApplicationBase::instance ()->is_editable (), this, mp_view_stack); + view = new lay::LayoutView (current_view (), &m_manager, lay::ApplicationBase::instance ()->is_editable (), plugin_root (), mp_view_stack); connect (view, SIGNAL (title_changed ()), this, SLOT (view_title_changed ())); connect (view, SIGNAL (dirty_changed ()), this, SLOT (view_title_changed ())); connect (view, SIGNAL (edits_enabled_changed ()), this, SLOT (edits_enabled_changed ())); @@ -4116,7 +4104,7 @@ MainWindow::add_mru (const std::string &fn_rel, const std::string &tech) } } - config_set (cfg_mru, config_str); + plugin_root ()->config_set (cfg_mru, config_str); } void @@ -4169,7 +4157,7 @@ MainWindow::open_recent () return; } - if (mp_layout_load_options->show_always () && !mp_layout_load_options->edit_global_options (this, db::Technologies::instance ())) { + if (mp_layout_load_options->show_always () && !mp_layout_load_options->edit_global_options (plugin_root (), db::Technologies::instance ())) { return; } @@ -4218,7 +4206,7 @@ MainWindow::open (int mode) return; } - if (mp_layout_load_options->show_always () && !mp_layout_load_options->edit_global_options (this, db::Technologies::instance ())) { + if (mp_layout_load_options->show_always () && !mp_layout_load_options->edit_global_options (plugin_root (), db::Technologies::instance ())) { return; } @@ -4289,7 +4277,7 @@ int MainWindow::do_create_view () { // create a new view - lay::LayoutView *view = new lay::LayoutView (&m_manager, lay::ApplicationBase::instance ()->is_editable (), this, mp_view_stack); + lay::LayoutView *view = new lay::LayoutView (&m_manager, lay::ApplicationBase::instance ()->is_editable (), plugin_root (), mp_view_stack); connect (view, SIGNAL (title_changed ()), this, SLOT (view_title_changed ())); connect (view, SIGNAL (dirty_changed ()), this, SLOT (view_title_changed ())); @@ -4866,8 +4854,7 @@ MainWindow::show_assistant_topic (const std::string &s, bool modal) void MainWindow::cm_show_all_tips () { - config_set (cfg_tip_window_hidden, ""); - config_finalize (); + plugin_root ()->config_set (cfg_tip_window_hidden, ""); } void @@ -4899,7 +4886,7 @@ MainWindow::action_for_slot (const char *slot) lay::Action * MainWindow::create_config_action (const std::string &title, const std::string &cname, const std::string &cvalue) { - lay::ConfigureAction *ca = new lay::ConfigureAction(this, title, cname, cvalue); + lay::ConfigureAction *ca = new lay::ConfigureAction(plugin_root (), title, cname, cvalue); m_ca_collection.push_back (ca); return ca; } @@ -4907,7 +4894,7 @@ MainWindow::create_config_action (const std::string &title, const std::string &c lay::Action * MainWindow::create_config_action (const std::string &cname, const std::string &cvalue) { - lay::ConfigureAction *ca = new lay::ConfigureAction(this, std::string (), cname, cvalue); + lay::ConfigureAction *ca = new lay::ConfigureAction(plugin_root (), std::string (), cname, cvalue); m_ca_collection.push_back (ca); return ca; } @@ -5605,11 +5592,8 @@ MainWindow::plugin_registered (lay::PluginDeclaration *cls) // recreate all plugins for (std::vector ::iterator vp = mp_views.begin (); vp != mp_views.end (); ++vp) { - (*vp)->create_plugins (this); + (*vp)->create_plugins (plugin_root ()); } - - // re-establish the configuration - config_setup (); } void @@ -5619,13 +5603,55 @@ MainWindow::plugin_removed (lay::PluginDeclaration *cls) // recreate all plugins except the one that got removed for (std::vector ::iterator vp = mp_views.begin (); vp != mp_views.end (); ++vp) { - (*vp)->create_plugins (this, cls); + (*vp)->create_plugins (plugin_root (), cls); + } +} + +// ------------------------------------------------------------ +// Implementation of the PluginRootToMainWindow bride + +PluginRootToMainWindow::PluginRootToMainWindow () + : mp_main_window (0) +{ + // .. nothing yet .. +} + +void +PluginRootToMainWindow::attach_to (lay::MainWindow *main_window) +{ + mp_main_window = main_window; +} + +void +PluginRootToMainWindow::plugin_registered (lay::PluginDeclaration *cls) +{ + if (mp_main_window.get ()) { + mp_main_window->plugin_registered (cls); } // re-establish the configuration config_setup (); } +void +PluginRootToMainWindow::plugin_removed (lay::PluginDeclaration *cls) +{ + if (mp_main_window.get ()) { + mp_main_window->plugin_removed (cls); + } + + // re-establish the configuration + config_setup (); +} + +void +PluginRootToMainWindow::select_mode (int mode) +{ + if (mp_main_window.get ()) { + mp_main_window->select_mode (mode); + } +} + // ------------------------------------------------------------ // Implementation of the "help about" dialog diff --git a/src/lay/lay/layMainWindow.h b/src/lay/lay/layMainWindow.h index 834d5d00c..55a50d340 100644 --- a/src/lay/lay/layMainWindow.h +++ b/src/lay/lay/layMainWindow.h @@ -120,8 +120,8 @@ private: class LAY_PUBLIC MainWindow : public QMainWindow, - public lay::AbstractMenuProvider, - public lay::PluginRoot + public lay::Plugin, + public lay::AbstractMenuProvider { Q_OBJECT public: @@ -134,7 +134,7 @@ public: /** * @brief Constructor */ - MainWindow (QApplication *app = 0, const char *name = "main_window"); + MainWindow (QApplication *app = 0, lay::Plugin *parent_plugin = 0, const char *name = "main_window"); /** * @brief Destructor @@ -551,7 +551,7 @@ public: void show_macro_editor (const std::string &cat = std::string (), bool add = false); /** - * @brief Reimplementation of the plugin interface: handle a generic menu request + * @brief Handles a generic menu request */ void menu_activated (const std::string &symbol); @@ -870,6 +870,8 @@ protected: void do_update_file_menu (); private: + friend class PluginRootToMainWindow; + TextProgressDelegate m_text_progress; // Main menu @@ -973,14 +975,33 @@ private: void update_dock_widget_state (); void read_dock_widget_state (); - virtual void plugin_registered (lay::PluginDeclaration *cls); - virtual void plugin_removed (lay::PluginDeclaration *cls); + void plugin_registered (lay::PluginDeclaration *cls); + void plugin_removed (lay::PluginDeclaration *cls); void libraries_changed (); void apply_key_bindings (); void apply_hidden (const std::vector > &hidden); }; +class LAY_PUBLIC PluginRootToMainWindow + : public lay::PluginRoot +{ +public: + PluginRootToMainWindow (); + + void attach_to (lay::MainWindow *main_window); + + virtual void plugin_registered (lay::PluginDeclaration *cls); + virtual void plugin_removed (lay::PluginDeclaration *cls); + virtual void select_mode (int mode); + +private: + PluginRootToMainWindow (const PluginRootToMainWindow &); + PluginRootToMainWindow &operator= (const PluginRootToMainWindow &); + + tl::weak_ptr mp_main_window; +}; + } namespace tl { diff --git a/src/lay/lay/layNavigator.cc b/src/lay/lay/layNavigator.cc index 1dd2fd521..1b4ec8119 100644 --- a/src/lay/lay/layNavigator.cc +++ b/src/lay/lay/layNavigator.cc @@ -58,7 +58,7 @@ public: mp_box (0), m_color (0) { - // .. nothing yet .. + // .. nothing yet .. } ~NavigatorService () @@ -70,6 +70,25 @@ public: drag_cancel (); } + void background_color_changed () + { + QColor c = mp_view->background_color (); + + // replace by "real" background color if required + if (! c.isValid ()) { + c = mp_view->palette ().color (QPalette::Normal, QPalette::Base); + } + + QColor contrast; + if (c.green () > 128) { + contrast = QColor (0, 0, 0); + } else { + contrast = QColor (255, 255, 255); + } + + set_colors (c, contrast); + } + bool mouse_release_event (const db::DPoint & /*p*/, unsigned int /*buttons*/, bool /*prio*/) { if (mp_box) { @@ -349,10 +368,10 @@ public: tl::Object::detach_from_all_events (); mp_source_view = source_view; + mp_source_view->viewport_changed_event.add (this, &NavigatorService::update_marker); - if (mp_source_view) { - mp_source_view->viewport_changed_event.add (this, &NavigatorService::update_marker); - } + mp_view->background_color_changed_event.add (this, &NavigatorService::background_color_changed); + background_color_changed (); update_marker (); @@ -447,11 +466,8 @@ Navigator::Navigator (MainWindow *main_window) mp_menu_bar->setFrameShape (QFrame::NoFrame); mp_menu_bar->setSizePolicy (QSizePolicy::Expanding, QSizePolicy::Preferred); - mp_view = new LayoutView (0, false, mp_main_window, this, "navigator", LayoutView::LV_Naked + LayoutView::LV_NoZoom + LayoutView::LV_NoServices + LayoutView::LV_NoGrid); - mp_view->setSizePolicy (QSizePolicy::Expanding, QSizePolicy::Expanding); - mp_view->setMinimumWidth (100); - mp_view->setMinimumHeight (100); - mp_view->hide (); + mp_view = 0; + mp_service = 0; mp_placeholder_label = new QLabel (this); mp_placeholder_label->setSizePolicy (QSizePolicy::Expanding, QSizePolicy::Expanding); @@ -461,9 +477,8 @@ Navigator::Navigator (MainWindow *main_window) QVBoxLayout *layout = new QVBoxLayout (this); layout->addWidget (mp_menu_bar); - layout->addWidget (mp_view); layout->addWidget (mp_placeholder_label); - layout->setStretchFactor (mp_view, 1); + layout->setStretchFactor (mp_placeholder_label, 1); layout->setMargin (0); layout->setSpacing (0); setLayout (layout); @@ -473,9 +488,6 @@ Navigator::Navigator (MainWindow *main_window) do_update_menu (); connect (mp_main_window->menu (), SIGNAL (changed ()), this, SLOT (menu_changed ())); - - mp_service = new NavigatorService (mp_view); - mp_view->view_object_widget ()->activate (mp_service); } Navigator::~Navigator () @@ -586,8 +598,8 @@ Navigator::showEvent (QShowEvent *) void Navigator::closeEvent (QCloseEvent *) { - mp_main_window->config_set (cfg_show_navigator, "false"); - mp_main_window->config_finalize (); + lay::PluginRoot::instance ()->config_set (cfg_show_navigator, "false"); + lay::PluginRoot::instance ()->config_end (); } void @@ -637,6 +649,14 @@ Navigator::view_closed (int index) } } +void +Navigator::resizeEvent (QResizeEvent *) +{ + if (mp_view) { + mp_view->setGeometry (mp_placeholder_label->geometry ()); + } +} + void Navigator::attach_view (LayoutView *view) { @@ -649,8 +669,24 @@ Navigator::attach_view (LayoutView *view) mp_source_view = view; + delete mp_service; + mp_service = 0; + + LayoutView *old_view = mp_view; + mp_view = 0; + if (mp_source_view) { + mp_view = new LayoutView (0, false, mp_source_view, this, "navigator", LayoutView::LV_Naked + LayoutView::LV_NoZoom + LayoutView::LV_NoServices + LayoutView::LV_NoGrid); + mp_view->setSizePolicy (QSizePolicy::Expanding, QSizePolicy::Expanding); + mp_view->setMinimumWidth (100); + mp_view->setMinimumHeight (100); + mp_view->setGeometry (mp_placeholder_label->geometry ()); + mp_view->show (); + + mp_service = new NavigatorService (mp_view); + mp_view->view_object_widget ()->activate (mp_service); + mp_source_view->cellviews_changed_event.add (this, &Navigator::content_changed); mp_source_view->cellview_changed_event.add (this, &Navigator::content_changed_with_int); mp_source_view->geom_changed_event.add (this, &Navigator::content_changed); @@ -662,60 +698,36 @@ Navigator::attach_view (LayoutView *view) image_plugin->images_changed_event.add (this, &Navigator::content_changed); } - mp_view->show (); - mp_placeholder_label->hide (); + // update the list of frozen flags per view + std::set all_views; - } else { - mp_view->hide (); - mp_placeholder_label->show (); - } - - // update the list of frozen flags per view - std::set all_views; - - for (std::map ::const_iterator f = m_frozen_list.begin (); f != m_frozen_list.end (); ++f) { - all_views.insert (f->first); - } - - for (unsigned int i = 0; i < mp_main_window->views (); ++i) { - lay::LayoutView *view = mp_main_window->view (i); - if (m_frozen_list.find (view) != m_frozen_list.end ()) { - all_views.erase (view); + for (std::map ::const_iterator f = m_frozen_list.begin (); f != m_frozen_list.end (); ++f) { + all_views.insert (f->first); } + + for (unsigned int i = 0; i < mp_main_window->views (); ++i) { + lay::LayoutView *view = mp_main_window->view (i); + if (m_frozen_list.find (view) != m_frozen_list.end ()) { + all_views.erase (view); + } + } + + for (std::set ::const_iterator v = all_views.begin (); v != all_views.end (); ++v) { + all_views.erase (*v); + } + + Action freeze_action = mp_main_window->menu ()->action (freeze_action_path); + freeze_action.set_checked (m_frozen_list.find (mp_source_view) != m_frozen_list.end ()); + + // Hint: this must happen before update () + mp_service->attach_view (mp_source_view); + + update (); + } - for (std::set ::const_iterator v = all_views.begin (); v != all_views.end (); ++v) { - all_views.erase (*v); - } + delete old_view; - Action freeze_action = mp_main_window->menu ()->action (freeze_action_path); - freeze_action.set_checked (m_frozen_list.find (mp_source_view) != m_frozen_list.end ()); - - // Hint: this must happen before update () - mp_service->attach_view (mp_source_view); - - update (); - - } -} - -void -Navigator::background_color (QColor c) -{ - // replace by "real" background color if required - if (! c.isValid ()) { - c = palette ().color (QPalette::Normal, QPalette::Base); - } - - QColor contrast; - if (c.green () > 128) { - contrast = QColor (0, 0, 0); - } else { - contrast = QColor (255, 255, 255); - } - - if (mp_service) { - mp_service->set_colors (c, contrast); } } @@ -738,16 +750,13 @@ Navigator::update_layers () void Navigator::update () { - if (! mp_source_view || m_frozen_list.find (mp_source_view) == m_frozen_list.end ()) { - - if (! mp_source_view) { - mp_view->clear_cellviews (); - mp_view->clear_layers (); - } else { - mp_view->select_cellviews (mp_source_view->cellview_list ()); - mp_view->set_properties (mp_source_view->get_properties ()); - } + if (! mp_view || ! mp_source_view) { + return; + } + if (m_frozen_list.find (mp_source_view) == m_frozen_list.end ()) { + mp_view->select_cellviews (mp_source_view->cellview_list ()); + mp_view->set_properties (mp_source_view->get_properties ()); } else { mp_view->select_cellviews (mp_source_view->cellview_list ()); mp_view->set_properties (m_frozen_list [mp_source_view].layer_properties); @@ -759,7 +768,7 @@ Navigator::update () img_target->clear_images (); if (m_show_images) { - img::Service *img_source = (mp_source_view ? mp_source_view->get_plugin () : 0); + img::Service *img_source = (mp_source_view->get_plugin ()); if (img_source) { for (img::ImageIterator i = img_source->begin_images (); ! i.at_end (); ++i) { img_target->insert_image (*i); diff --git a/src/lay/lay/layNavigator.h b/src/lay/lay/layNavigator.h index c79e55923..5582eea8b 100644 --- a/src/lay/lay/layNavigator.h +++ b/src/lay/lay/layNavigator.h @@ -83,13 +83,13 @@ public: void freeze_clicked (); void all_hier_levels (bool f); void show_images (bool f); - void background_color (QColor c); static void init_menu (AbstractMenu &menu); protected: virtual void closeEvent (QCloseEvent *event); virtual void showEvent (QShowEvent *event); + virtual void resizeEvent (QResizeEvent *event); private slots: void menu_changed (); @@ -121,6 +121,7 @@ private: void layers_changed (int); void viewport_changed (); void hier_levels_changed (); + void update_background_color (); void content_changed_with_int (int) { diff --git a/src/lay/lay/laySaltController.cc b/src/lay/lay/laySaltController.cc index 7e3030bd6..4f6b78815 100644 --- a/src/lay/lay/laySaltController.cc +++ b/src/lay/lay/laySaltController.cc @@ -36,14 +36,21 @@ namespace lay static const std::string cfg_salt_manager_window_state ("salt-manager-window-state"); SaltController::SaltController () - : mp_salt_dialog (0), mp_mw (0), m_file_watcher (0), + : mp_salt_dialog (0), mp_mw (0), mp_plugin_root (0), m_file_watcher (0), dm_sync_file_watcher (this, &SaltController::sync_file_watcher), dm_sync_files (this, &SaltController::sync_files) { } void -SaltController::initialized (lay::PluginRoot *root) +SaltController::initialize (lay::PluginRoot *root) +{ + mp_mw = lay::MainWindow::instance (); + mp_plugin_root = root; +} + +void +SaltController::initialized (lay::PluginRoot * /*root*/) { if (! m_file_watcher) { m_file_watcher = new tl::FileSystemWatcher (this); @@ -51,8 +58,6 @@ SaltController::initialized (lay::PluginRoot *root) connect (m_file_watcher, SIGNAL (fileRemoved (const QString &)), this, SLOT (file_watcher_triggered ())); } - mp_mw = dynamic_cast (root); - connect (&m_salt, SIGNAL (collections_changed ()), this, SIGNAL (salt_changed ())); } @@ -128,11 +133,9 @@ SaltController::show_editor () if (mp_salt_dialog) { - if (mp_mw) { - std::string s = mp_mw->config_get (cfg_salt_manager_window_state); - if (! s.empty ()) { - lay::restore_dialog_state (mp_salt_dialog, s); - } + std::string s = mp_plugin_root->config_get (cfg_salt_manager_window_state); + if (! s.empty ()) { + lay::restore_dialog_state (mp_salt_dialog, s); } // while running the dialog, don't watch file events - that would interfere with @@ -141,9 +144,7 @@ SaltController::show_editor () mp_salt_dialog->exec (); m_file_watcher->enable (true); - if (mp_mw) { - mp_mw->config_set (cfg_salt_manager_window_state, lay::save_dialog_state (mp_salt_dialog)); - } + mp_plugin_root->config_set (cfg_salt_manager_window_state, lay::save_dialog_state (mp_salt_dialog)); sync_file_watcher (); diff --git a/src/lay/lay/laySaltController.h b/src/lay/lay/laySaltController.h index f6ff315d0..ce8ee0e9b 100644 --- a/src/lay/lay/laySaltController.h +++ b/src/lay/lay/laySaltController.h @@ -66,6 +66,11 @@ public: */ SaltController (); + /** + * @brief Reimplementation of the PluginDeclaration interface + */ + virtual void initialize (lay::PluginRoot *root); + /** * @brief Reimplementation of the PluginDeclaration interface */ @@ -186,6 +191,7 @@ signals: private: lay::SaltManagerDialog *mp_salt_dialog; lay::MainWindow *mp_mw; + lay::PluginRoot * mp_plugin_root; std::string m_salt_mine_url; lay::Salt m_salt; tl::FileSystemWatcher *m_file_watcher; diff --git a/src/lay/lay/laySettingsForm.cc b/src/lay/lay/laySettingsForm.cc index 8d595f807..5e9649cd0 100644 --- a/src/lay/lay/laySettingsForm.cc +++ b/src/lay/lay/laySettingsForm.cc @@ -40,9 +40,9 @@ namespace lay // ------------------------------------------------------------- -SettingsForm::SettingsForm (QWidget *parent, lay::MainWindow *mw, const char *name) +SettingsForm::SettingsForm (QWidget *parent, lay::PluginRoot *plugin_root, const char *name) : QDialog (parent), Ui::SettingsForm (), - mp_main_window (mw), m_finalize_recursion (false) + mp_plugin_root (plugin_root), m_finalize_recursion (false) { setObjectName (QString::fromUtf8 (name)); @@ -237,7 +237,7 @@ SettingsForm::setup () // setup the custom config pages for (std::vector ::iterator cp = m_config_pages.begin (); cp != m_config_pages.end (); ++cp) { - (*cp)->setup (mp_main_window); + (*cp)->setup (mp_plugin_root); } } @@ -246,14 +246,14 @@ SettingsForm::commit () { // commit the custom config pages for (std::vector ::iterator cp = m_config_pages.begin (); cp != m_config_pages.end (); ++cp) { - (*cp)->commit (mp_main_window); + (*cp)->commit (mp_plugin_root); } m_finalize_recursion = true; try { // config_end will make the main window call setup on the settings form. // the recursion sentinel takes care of that. - mp_main_window->config_end (); + mp_plugin_root->config_end (); m_finalize_recursion = false; } catch (...) { m_finalize_recursion = false; diff --git a/src/lay/lay/laySettingsForm.h b/src/lay/lay/laySettingsForm.h index 92ab4497d..1295b03cb 100644 --- a/src/lay/lay/laySettingsForm.h +++ b/src/lay/lay/laySettingsForm.h @@ -37,7 +37,7 @@ namespace lay { -class MainWindow; +class PluginRoot; class ConfigPage; class SettingsForm @@ -46,7 +46,7 @@ class SettingsForm Q_OBJECT public: - SettingsForm (QWidget *parent, lay::MainWindow *lv, const char *name); + SettingsForm (QWidget *parent, lay::PluginRoot *plugin_root, const char *name); void setup (); void commit (); @@ -58,7 +58,7 @@ public slots: void item_changed (QTreeWidgetItem *, QTreeWidgetItem *); private: - lay::MainWindow *mp_main_window; + lay::PluginRoot *mp_plugin_root; std::vector m_config_pages; bool m_finalize_recursion; }; diff --git a/src/lay/lay/layTechnologyController.cc b/src/lay/lay/layTechnologyController.cc index ec056fcde..8696e4f45 100644 --- a/src/lay/lay/layTechnologyController.cc +++ b/src/lay/lay/layTechnologyController.cc @@ -50,7 +50,7 @@ std::string tech_string_from_name (const std::string &tn) } TechnologyController::TechnologyController () - : PluginDeclaration (), mp_editor (0), mp_mw (0), mp_active_technology (0) + : PluginDeclaration (), mp_editor (0), mp_mw (0), mp_plugin_root (0), mp_active_technology (0) { m_configure_enabled = true; m_current_technology_updated = false; @@ -72,7 +72,8 @@ TechnologyController::instance () void TechnologyController::initialize (lay::PluginRoot *root) { - mp_mw = dynamic_cast (root); + mp_plugin_root = root; + mp_mw = lay::MainWindow::instance (); if (mp_mw) { mp_editor = new lay::TechSetupDialog (mp_mw); mp_editor->setModal (false); @@ -192,7 +193,7 @@ TechnologyController::update_active_technology () #if 0 // Hint with this implementation, the current technology follows the current layout. // Although that's a nice way to display the current technology, it's pretty confusing - lay::PluginRoot *pr = mp_mw; + lay::PluginRoot *pr = mp_plugin_root; if (pr) { pr->config_set (cfg_initial_technology, active_tech); } @@ -203,7 +204,7 @@ void TechnologyController::technologies_changed () { // update the configuration to reflect the persisted technologies - lay::PluginRoot *pr = mp_mw; + lay::PluginRoot *pr = mp_plugin_root; if (pr) { m_configure_enabled = false; try { @@ -474,9 +475,7 @@ TechnologyController::show_editor () } - if (mp_mw) { - mp_mw->config_set (cfg_tech_editor_window_state, lay::save_dialog_state (mp_editor)); - } + mp_plugin_root->config_set (cfg_tech_editor_window_state, lay::save_dialog_state (mp_editor)); } const std::string & diff --git a/src/lay/lay/layTechnologyController.h b/src/lay/lay/layTechnologyController.h index 0ad49e21e..dc347204b 100644 --- a/src/lay/lay/layTechnologyController.h +++ b/src/lay/lay/layTechnologyController.h @@ -132,6 +132,7 @@ private: bool m_technologies_configured; lay::TechSetupDialog *mp_editor; lay::MainWindow *mp_mw; + lay::PluginRoot *mp_plugin_root; std::vector m_paths; std::vector m_temp_tech; db::Technology *mp_active_technology; diff --git a/src/lay/lay/syntax/python.xml b/src/lay/lay/syntax/python.xml index 9cbae2df1..5d03e1666 100644 --- a/src/lay/lay/syntax/python.xml +++ b/src/lay/lay/syntax/python.xml @@ -13,9 +13,10 @@ - + + - + import from as @@ -52,6 +53,8 @@ while with yield + async + await __import__ @@ -248,6 +251,11 @@ __format__ __next__ __dir__ + __await__ + __aiter__ + __anext__ + __aenter__ + __aexit__ - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + @@ -432,14 +420,14 @@ - + - + @@ -454,14 +442,14 @@ - - + + - + - + @@ -493,89 +481,176 @@ --> - + - - - - + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + - + - - + + + + + + + + + + + + + + + - + - + - + + + + + + + + + + + + + + - + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + @@ -583,8 +658,14 @@ - - + + + + + + + + diff --git a/src/laybasic/laybasic/gsiDeclLayPlugin.cc b/src/laybasic/laybasic/gsiDeclLayPlugin.cc index 131897874..b83cc3603 100644 --- a/src/laybasic/laybasic/gsiDeclLayPlugin.cc +++ b/src/laybasic/laybasic/gsiDeclLayPlugin.cc @@ -849,18 +849,28 @@ Class decl_ButtonState ("lay", "ButtonState", ); static std::vector -get_config_names (lay::PluginRoot *view) +get_config_names (lay::PluginRoot *root) { std::vector names; - view->get_config_names (names); + root->get_config_names (names); return names; } -lay::PluginRoot *config_root_instance () +static lay::PluginRoot *config_root_instance () { return lay::PluginRoot::instance (); } +static tl::Variant get_config (lay::PluginRoot *root, const std::string &name) +{ + std::string value; + if (root->config_get (name, value)) { + return tl::Variant (value); + } else { + return tl::Variant (); + } +} + /** * @brief Exposes the PluginRoot interface * @@ -868,7 +878,7 @@ lay::PluginRoot *config_root_instance () * identify the plugin root node for configuration. The Plugin nature of this interface * is somewhat artificial and may be removed later. * - * TODO: this is a duplicate of the respective methods in LayoutView and MainWindow. + * TODO: this is a duplicate of the respective methods in LayoutView and Application. * This is intentional since we don't want to spend the only derivation path on this. * Once there is a mixin concept, provide a path through that concept. */ @@ -898,13 +908,13 @@ Class decl_PluginRoot ("lay", "PluginRoot", "exist. If it does and an error occured, the error message is printed\n" "on stderr. In both cases, false is returned.\n" ) + - method ("get_config", (bool (lay::PluginRoot::*) (const std::string &, std::string &) const) &lay::PluginRoot::config_get, - "@brief Get the value of a local configuration parameter\n" + method_ext ("get_config", &get_config, + "@brief Gets the value of a local configuration parameter\n" "\n" "@args name\n" "@param name The name of the configuration parameter whose value shall be obtained (a string)\n" "\n" - "@return The value of the parameter\n" + "@return The value of the parameter or nil if there is no such parameter\n" ) + method ("set_config", (void (lay::PluginRoot::*) (const std::string &, const std::string &)) &lay::PluginRoot::config_set, "@brief Set a local configuration parameter with the given name to the given value\n" @@ -936,11 +946,16 @@ Class decl_PluginRoot ("lay", "PluginRoot", ), "@brief Root of the configuration space in the plugin context\n" "\n" - "This class provides access to the root configuration space. This object provides access to the configuration space in the context " - "of plugin programming.\n" - "Plugins are organized in a configuration tree. Configuration settings are propagated down to the individual plugins. " - "If there is a main window, the configuration root is identical with this object, so configuration settings " - "applied in the configuration root are available to all views.\n" + "This class provides access to the root configuration space in the context " + "of plugin programming. You can use this class to obtain configuration parameters " + "from the configuration tree during plugin initialization. However, the " + "preferred way of plugin configuration is through \\Plugin#configure.\n" + "\n" + "Currently, the application object provides an identical entry point for configuration modification. " + "For example, \"Application::instance.set_config\" is identical to \"PluginRoot::instance.set_config\". " + "Hence there is little motivation for the PluginRoot class currently and " + "this interface may be modified or removed in the future." + "\n" "\n" "This class has been introduced in version 0.25.\n" ); diff --git a/src/laybasic/laybasic/layLayoutView.cc b/src/laybasic/laybasic/layLayoutView.cc index 02d98642f..52d3deb34 100644 --- a/src/laybasic/laybasic/layLayoutView.cc +++ b/src/laybasic/laybasic/layLayoutView.cc @@ -247,9 +247,9 @@ const int timer_interval = 500; static LayoutView *ms_current = 0; -LayoutView::LayoutView (db::Manager *manager, bool editable, lay::PluginRoot *root, QWidget *parent, const char *name, unsigned int options) +LayoutView::LayoutView (db::Manager *manager, bool editable, lay::Plugin *plugin_parent, QWidget *parent, const char *name, unsigned int options) : QFrame (parent), - lay::Plugin (root), + lay::Plugin (plugin_parent), m_editable (editable), m_options (options), m_annotation_shapes (manager), @@ -259,7 +259,7 @@ LayoutView::LayoutView (db::Manager *manager, bool editable, lay::PluginRoot *ro tl::DeferredMethodScheduler::instance (); setObjectName (QString::fromUtf8 (name)); - init (manager, root, parent); + init (manager, plugin_root_maybe_null (), parent); } LayoutView::LayoutView (lay::LayoutView *source, db::Manager *manager, bool editable, lay::PluginRoot *root, QWidget *parent, const char *name, unsigned int options) @@ -537,7 +537,9 @@ LayoutView::init (db::Manager *mgr, lay::PluginRoot *root, QWidget * /*parent*/) connect (mp_timer, SIGNAL (timeout ()), this, SLOT (timer ())); mp_timer->start (timer_interval); - create_plugins (root); + if (root) { + create_plugins (root); + } m_new_layer_props.layer = 1; m_new_layer_props.datatype = 0; @@ -4468,6 +4470,8 @@ LayoutView::background_color (QColor c) mp_canvas->set_colors (c, contrast, mp_canvas->active_color ()); update_content (); + + background_color_changed_event (); } void diff --git a/src/laybasic/laybasic/layLayoutView.h b/src/laybasic/laybasic/layLayoutView.h index a9e3ff5aa..4d3e8b383 100644 --- a/src/laybasic/laybasic/layLayoutView.h +++ b/src/laybasic/laybasic/layLayoutView.h @@ -182,7 +182,7 @@ public: /** * @brief Constructor */ - LayoutView (db::Manager *mgr, bool editable, lay::PluginRoot *root, QWidget *parent = 0, const char *name = "view", unsigned int options = (unsigned int) LV_Normal); + LayoutView (db::Manager *mgr, bool editable, lay::Plugin *plugin_parent, QWidget *parent = 0, const char *name = "view", unsigned int options = (unsigned int) LV_Normal); /** * @brief Constructor (clone from another view) @@ -651,6 +651,11 @@ public: */ tl::Event viewport_changed_event; + /** + * @brief This event is triggered if the background color changed + */ + tl::Event background_color_changed_event; + /** * @brief An event signalling that the layer list has changed. * diff --git a/src/laybasic/laybasic/layPlugin.cc b/src/laybasic/laybasic/layPlugin.cc index 7271bccef..bb700cdb9 100644 --- a/src/laybasic/laybasic/layPlugin.cc +++ b/src/laybasic/laybasic/layPlugin.cc @@ -305,7 +305,7 @@ Plugin::config_set (const std::string &name, const std::string &value) } } - do_config_set (name, value); + do_config_set (name, value, false); // schedule a configuration finalization call (once for all config_set calls) dm_finalize_config (); @@ -363,6 +363,25 @@ Plugin::get_config_names (std::vector &names) const } } +PluginRoot * +Plugin::plugin_root () +{ + PluginRoot *pr = plugin_root_maybe_null (); + tl_assert (pr != 0); + return pr; +} + +PluginRoot * +Plugin::plugin_root_maybe_null () +{ + Plugin *p = this; + while (p->mp_parent) { + p = p->mp_parent; + } + + return dynamic_cast (p); +} + void Plugin::do_config_setup (Plugin *target) { @@ -371,7 +390,7 @@ Plugin::do_config_setup (Plugin *target) } // local configurations override the parent's configuration, i.e. are applied after the parents settings for (std::map::const_iterator p = m_repository.begin (); p != m_repository.end (); ++p) { - target->do_config_set (p->first, p->second); + target->do_config_set (p->first, p->second, false); } } @@ -385,8 +404,14 @@ Plugin::do_config_end () } bool -Plugin::do_config_set (const std::string &name, const std::string &value) +Plugin::do_config_set (const std::string &name, const std::string &value, bool for_child) { + if (for_child) { + // this is the case when we impose a configuration from the parent: in this case we + // have to remove it from the repository of local parameters. + m_repository.erase (name); + } + try { if (configure (name, value)) { // taken by us - don't propagate to the children @@ -398,7 +423,7 @@ Plugin::do_config_set (const std::string &name, const std::string &value) // propagate to all children (not only the first that takes it!) for (tl::weak_collection::iterator c = m_children.begin (); c != m_children.end (); ++c) { - c->do_config_set (name, value); + c->do_config_set (name, value, true); } return false; diff --git a/src/laybasic/laybasic/layPlugin.h b/src/laybasic/laybasic/layPlugin.h index c0c20bac5..49b79a91f 100644 --- a/src/laybasic/laybasic/layPlugin.h +++ b/src/laybasic/laybasic/layPlugin.h @@ -532,7 +532,8 @@ public: * * In order to make configuration changes effective, this method * must be called. It calls config_finalize recursively on the - * children. + * children. In GUI-enabled applications this step is optional + * and is performed automatically through a timer. */ void config_end (); @@ -632,6 +633,19 @@ public: */ void get_config_names (std::vector &names) const; + /** + * @brief Gets the plugin root (the parent plugin not having another parent) + * The returned pointer is guaranteed to be non-zero. + */ + PluginRoot *plugin_root (); + + /** + * @brief Gets the plugin root (the parent plugin not having another parent) + * This version may return null, if the plugin is instantiated without a + * root. + */ + PluginRoot *plugin_root_maybe_null (); + /** * @brief Menu command handler * @@ -761,7 +775,7 @@ private: /** * @brief Do the actual set or pass to the children if not taken */ - bool do_config_set (const std::string &name, const std::string &value); + bool do_config_set (const std::string &name, const std::string &value, bool for_child); /** * @brief Recursively call config_finalize diff --git a/src/plugins/streamers/dxf/db_plugin/dbDXFFormat.h b/src/plugins/streamers/dxf/db_plugin/dbDXFFormat.h index 35a6173d0..fd23120ff 100644 --- a/src/plugins/streamers/dxf/db_plugin/dbDXFFormat.h +++ b/src/plugins/streamers/dxf/db_plugin/dbDXFFormat.h @@ -213,6 +213,7 @@ public: * 1: create LWPOLYLINE * 2: decompose into SOLID * 3: create HATCH + * 4: create LINE: refer to 'void DXFWriter::write_polygon()' definition */ int polygon_mode; diff --git a/src/plugins/streamers/dxf/db_plugin/dbDXFWriter.cc b/src/plugins/streamers/dxf/db_plugin/dbDXFWriter.cc index 084fbaadf..8ba1df8f8 100644 --- a/src/plugins/streamers/dxf/db_plugin/dbDXFWriter.cc +++ b/src/plugins/streamers/dxf/db_plugin/dbDXFWriter.cc @@ -507,7 +507,36 @@ DXFWriter::write_polygon (const db::Polygon &polygon, double sf) } } + } else if (m_options.polygon_mode == 4) { + //-------------------------------------------------------------------------------------- + // Last modified by: Kazzz-S on October 21, 2018 (newly added) + // + // Description: When importing a DXF file comprising POLYLINEs or LWPOLYLINEs into + // Abaqus CAE, they are forcibly converted to points! + // *** This is a "specification" of Abaqus CAE. *** + // In contrast, LINEs are kept as lines, which will be then assembled into + // polygonal objects internally if required. + //-------------------------------------------------------------------------------------- + for (unsigned int c = 0; c < polygon.holes () + 1; ++c) { + + for (db::Polygon::polygon_contour_iterator p = polygon.contour (c).begin (); p != polygon.contour (c).end (); ++p) { + db::Polygon::polygon_contour_iterator q = p + 1; + + if (q == polygon.contour (c).end ()) { + q = polygon.contour (c).begin (); + } + + *this << 0 << endl << "LINE" << endl; + *this << 8 << endl; emit_layer (m_layer); + *this << 66 << endl << 1 << endl; // required by TrueView + *this << 10 << endl << (*p).x () * sf << endl; + *this << 20 << endl << (*p).y () * sf << endl; + *this << 11 << endl << (*q).x () * sf << endl; + *this << 21 << endl << (*q).y () * sf << endl; + } + } } + } void diff --git a/src/plugins/streamers/dxf/db_plugin/gsiDeclDbDXF.cc b/src/plugins/streamers/dxf/db_plugin/gsiDeclDbDXF.cc old mode 100644 new mode 100755 index 4a6a9f774..5605ae011 --- a/src/plugins/streamers/dxf/db_plugin/gsiDeclDbDXF.cc +++ b/src/plugins/streamers/dxf/db_plugin/gsiDeclDbDXF.cc @@ -361,7 +361,7 @@ gsi::ClassExt dxf_reader_options ( static void set_dxf_polygon_mode (db::SaveLayoutOptions *options, int mode) { - if (mode < 0 || mode > 3) { + if (mode < 0 || mode > 4) { throw tl::Exception (tl::to_string (tr ("Invalid polygon mode"))); } @@ -379,9 +379,9 @@ gsi::ClassExt dxf_writer_options ( gsi::method_ext ("dxf_polygon_mode=", &set_dxf_polygon_mode, "@brief Specifies how to write polygons.\n" "@args mode\n" - "The mode is 0 (write POLYLINE entities), 1 (write LWPOLYLINE entities), 2 (decompose into SOLID entities) or " - "or 3 (write HATCH entities).\n" - "\nThis property has been added in version 0.21.3.\n" + "The mode is 0 (write POLYLINE entities), 1 (write LWPOLYLINE entities), 2 (decompose into SOLID entities), " + "3 (write HATCH entities), or 4 (write LINE entities).\n" + "\nThis property has been added in version 0.21.3. '4', in version 0.25.6.\n" ) + gsi::method_ext ("dxf_polygon_mode", &get_dxf_polygon_mode, "@brief Specifies how to write polygons.\n" diff --git a/src/plugins/streamers/dxf/lay_plugin/DXFWriterOptionPage.ui b/src/plugins/streamers/dxf/lay_plugin/DXFWriterOptionPage.ui index 35ed52f0a..b3a1f217e 100644 --- a/src/plugins/streamers/dxf/lay_plugin/DXFWriterOptionPage.ui +++ b/src/plugins/streamers/dxf/lay_plugin/DXFWriterOptionPage.ui @@ -73,6 +73,11 @@ Write HATCH entity + + + Write LINE entity + + diff --git a/src/plugins/streamers/dxf/unit_tests/dbDXFReader.cc b/src/plugins/streamers/dxf/unit_tests/dbDXFReader.cc index 92ee77582..e2c709851 100644 --- a/src/plugins/streamers/dxf/unit_tests/dbDXFReader.cc +++ b/src/plugins/streamers/dxf/unit_tests/dbDXFReader.cc @@ -461,3 +461,26 @@ TEST(31) run_test (_this, "t31.dxf.gz", "t31d_au.gds.gz", opt); } +// issue #198 +TEST(32) +{ + db::DXFReaderOptions opt; + opt.layer_map = string2lm ("L11D0:1,L12D0:2"); + opt.create_other_layers = false; + opt.polyline_mode = 3; + + opt.contour_accuracy = 0.0; + run_test_public (_this, "round_path.dxf.gz", "t32a_au.gds.gz", opt); + + opt.contour_accuracy = 0.1; + run_test_public (_this, "round_path.dxf.gz", "t32b_au.gds.gz", opt); + + opt.contour_accuracy = 1.0; + run_test_public (_this, "round_path.dxf.gz", "t32c_au.gds.gz", opt); + + opt.polyline_mode = 4; + run_test_public (_this, "round_path.dxf.gz", "t32d_au.gds.gz", opt); + + opt.polyline_mode = 2; + run_test_public (_this, "round_path.dxf.gz", "t32e_au.gds.gz", opt); +} diff --git a/src/pya/pya/pya.cc b/src/pya/pya/pya.cc index cd819e7c6..f1308886f 100644 --- a/src/pya/pya/pya.cc +++ b/src/pya/pya/pya.cc @@ -168,11 +168,31 @@ init_pya_module () #endif -PythonInterpreter::PythonInterpreter () +static void reset_interpreter () +{ + delete sp_interpreter; + tl_assert (sp_interpreter == 0); +} + +PythonInterpreter::PythonInterpreter (bool embedded) : mp_current_console (0), mp_current_exec_handler (0), m_current_exec_level (0), m_in_trace (false), m_block_exceptions (false), m_ignore_next_exception (false), - mp_current_frame (NULL), mp_py3_app_name (0) + mp_current_frame (NULL), mp_py3_app_name (0), m_embedded (embedded) { + // Don't attempt any additional initialization in the standalone module case + if (! embedded) { + + sp_interpreter = this; + + // this monitor whether Python shuts down and deletes the interpreter's + // instance. + // NOTE: this assumes, the interpreter was created with new(!) + Py_AtExit (&reset_interpreter); + + return; + + } + tl::SelfTimer timer (tl::verbosity () >= 21, "Initializing Python"); std::string app_path; @@ -316,11 +336,11 @@ PythonInterpreter::PythonInterpreter () m_stderr_channel = PythonRef (PYAChannelObject::create (gsi::Console::OS_stderr)); m_stderr = PythonPtr (m_stderr_channel.get ()); + sp_interpreter = this; + m_pya_module.reset (new pya::PythonModule ()); m_pya_module->init (pya_module_name, module); m_pya_module->make_classes (); - - sp_interpreter = this; } PythonInterpreter::~PythonInterpreter () @@ -330,11 +350,15 @@ PythonInterpreter::~PythonInterpreter () m_stdout = PythonPtr (); m_stderr = PythonPtr (); - Py_Finalize (); + if (m_embedded) { + + Py_Finalize (); + + if (mp_py3_app_name) { + PyMem_Free (mp_py3_app_name); + mp_py3_app_name = 0; + } - if (mp_py3_app_name) { - PyMem_Free (mp_py3_app_name); - mp_py3_app_name = 0; } sp_interpreter = 0; diff --git a/src/pya/pya/pya.h b/src/pya/pya/pya.h index 52d3033f3..e862f2812 100644 --- a/src/pya/pya/pya.h +++ b/src/pya/pya/pya.h @@ -101,8 +101,12 @@ class PYA_PUBLIC PythonInterpreter public: /** * @brief The constructor + * + * If embedded is true, the interpreter is an embedded one. Only in this case, the + * Python interpreter is initialized. Otherwise, it is assumed the interpreter + * already exists and our application runs inside an external interpreter. */ - PythonInterpreter (); + PythonInterpreter (bool embedded = true); /** * @brief The destructor @@ -281,6 +285,7 @@ private: PyFrameObject *mp_current_frame; std::map m_file_id_map; wchar_t *mp_py3_app_name; + bool m_embedded; std::auto_ptr m_pya_module; }; diff --git a/src/pya/pya/pyaModule.cc b/src/pya/pya/pyaModule.cc index ecfb35c3c..d5864e342 100644 --- a/src/pya/pya/pyaModule.cc +++ b/src/pya/pya/pyaModule.cc @@ -2198,6 +2198,12 @@ PythonModule::take_module () void PythonModule::init (const char *mod_name, const char *description) { + // create a (standalone) Python interpreter if we don't have one yet + // NOTE: Python itself will take care to remove this instance in this case. + if (! pya::PythonInterpreter::instance ()) { + new pya::PythonInterpreter (false); + } + // do some checks before we create the module tl_assert (mod_name != 0); tl_assert (mp_module.get () == 0); diff --git a/src/pymod/__init__.py.qt4 b/src/pymod/__init__.py.qt4 index 8fee0a23c..18e5d527d 100644 --- a/src/pymod/__init__.py.qt4 +++ b/src/pymod/__init__.py.qt4 @@ -1,5 +1,5 @@ # klayout library definition file -__all__ = [ "tl", "db", "lay", "rdb", "QtCore", "QtGui", "QtXml", "QtSql", "QtNetwork", "QtDesigner" ] +__all__ = [ "tl", "db", "rdb", "QtCore", "QtGui", "QtXml", "QtSql", "QtNetwork", "QtDesigner", "lay" ] diff --git a/src/pymod/__init__.py.qt5 b/src/pymod/__init__.py.qt5 index 6e23c9122..9a943103f 100644 --- a/src/pymod/__init__.py.qt5 +++ b/src/pymod/__init__.py.qt5 @@ -1,7 +1,8 @@ # klayout library definition file -__all__ = [ "tl", "db", "lay", "rdb", +__all__ = [ "tl", "db", "rdb", "QtCore", "QtGui", "QtNetwork", "QtSql", "QtWidgets", "QtDesigner", - "QtMultimedia", "QtPrintSupport", "QtSvg", "QtXmlPatterns", "QtXml" ] + "QtMultimedia", "QtPrintSupport", "QtSvg", "QtXmlPatterns", "QtXml", + "lay" ] diff --git a/src/pymod/distutils_src/pya/__init__.py b/src/pymod/distutils_src/pya/__init__.py new file mode 100644 index 000000000..ae97d592a --- /dev/null +++ b/src/pymod/distutils_src/pya/__init__.py @@ -0,0 +1,10 @@ + +import klayout +import importlib + +__all__ = [] +for m in klayout.__all__: + mod = importlib.import_module("klayout." + m) + for mm in mod.__all__: + globals()[mm] = getattr(mod, mm) + diff --git a/src/pymod/tl/tl.pro b/src/pymod/tl/tl.pro index b3aa2e0c9..2ae8a8b1f 100644 --- a/src/pymod/tl/tl.pro +++ b/src/pymod/tl/tl.pro @@ -43,3 +43,22 @@ msvc { } INSTALLS += init_target +# And also provide the pya compatibility module here + +msvc { + QMAKE_POST_LINK += && (if not exist $$shell_path($$DESTDIR_PYMOD/../pya) $(MKDIR) $$shell_path($$DESTDIR_PYMOD/../pya)) && $(COPY) $$shell_path($$PWD/../distutils_src/pya/*.py) $$shell_path($$DESTDIR_PYMOD/../pya) +} else { + QMAKE_POST_LINK += && $(MKDIR) $$DESTDIR_PYMOD/../pya && $(COPY) $$PWD/../distutils_src/pya/*.py $$DESTDIR_PYMOD/../pya +} + +# INSTALLS needs to be inside a lib or app templates. +modpyasrc_target.path = $$PREFIX/pymod/pya +# This would be nice: +# init_target.files += $$DESTDIR_PYMOD/pya/* +# but some Qt versions need this explicitly: +msvc { + modpyasrc_target.extra = $(INSTALL_PROGRAM) $$shell_path($$DESTDIR_PYMOD/../pya/*.py) $$shell_path($(INSTALLROOT)$$PREFIX/pymod/pya) +} else { + modpyasrc_target.extra = $(INSTALL_PROGRAM) $$DESTDIR_PYMOD/../pya/*.py $(INSTALLROOT)$$PREFIX/pymod/pya +} +INSTALLS += modpyasrc_target diff --git a/src/pymod/tl/tlMain.cc b/src/pymod/tl/tlMain.cc index 42c21c630..4efb94a35 100644 --- a/src/pymod/tl/tlMain.cc +++ b/src/pymod/tl/tlMain.cc @@ -23,3 +23,4 @@ #include "../pymodHelper.h" DEFINE_PYMOD(tlcore, "tl", "KLayout core module 'tl'") + diff --git a/src/pymod/unit_tests/pymod_tests.cc b/src/pymod/unit_tests/pymod_tests.cc index bd534a4c5..5db932d67 100644 --- a/src/pymod/unit_tests/pymod_tests.cc +++ b/src/pymod/unit_tests/pymod_tests.cc @@ -109,6 +109,8 @@ PYMODTEST (import_QtXmlPatterns, "import_QtXmlPatterns.py") #endif +PYMODTEST (import_pya, "pya_tests.py") + #elif defined(HAVE_QT) PYMODTEST (import_lay, "import_lay_noqt.py") diff --git a/src/tl/tl/tlReuseVector.h b/src/tl/tl/tlReuseVector.h index 294e27254..f43698c2c 100644 --- a/src/tl/tl/tlReuseVector.h +++ b/src/tl/tl/tlReuseVector.h @@ -975,20 +975,24 @@ private: value_type *new_start = (value_type *) (new char [sizeof (value_type) * n]); - size_type l = last (); - size_type i = first (); - memcpy ((void *)(new_start + i), (void *)(mp_start + i), (l - i) * sizeof (Value)); + size_type e = 0; - size_type e = size_type (mp_finish - mp_start); + if (mp_start) { + + e = size_type (mp_finish - mp_start); + + size_type l = last (); + size_type i = first (); + memcpy ((void *)(new_start + i), (void *)(mp_start + i), (l - i) * sizeof (Value)); + + delete [] ((char *) mp_start); + + } if (mp_rdata) { mp_rdata->reserve (n); } - if (mp_start) { - delete [] ((char *) mp_start); - } - mp_start = new_start; mp_finish = mp_start + e; mp_capacity = mp_start + n; diff --git a/testdata/dxf/round_path.dxf.gz b/testdata/dxf/round_path.dxf.gz new file mode 100644 index 000000000..758978cfb Binary files /dev/null and b/testdata/dxf/round_path.dxf.gz differ diff --git a/testdata/dxf/t32a_au.gds.gz b/testdata/dxf/t32a_au.gds.gz new file mode 100644 index 000000000..573fa5a35 Binary files /dev/null and b/testdata/dxf/t32a_au.gds.gz differ diff --git a/testdata/dxf/t32b_au.gds.gz b/testdata/dxf/t32b_au.gds.gz new file mode 100644 index 000000000..6cdd643f2 Binary files /dev/null and b/testdata/dxf/t32b_au.gds.gz differ diff --git a/testdata/dxf/t32c_au.gds.gz b/testdata/dxf/t32c_au.gds.gz new file mode 100644 index 000000000..243695967 Binary files /dev/null and b/testdata/dxf/t32c_au.gds.gz differ diff --git a/testdata/dxf/t32d_au.gds.gz b/testdata/dxf/t32d_au.gds.gz new file mode 100644 index 000000000..a77b3a470 Binary files /dev/null and b/testdata/dxf/t32d_au.gds.gz differ diff --git a/testdata/dxf/t32e_au.gds.gz b/testdata/dxf/t32e_au.gds.gz new file mode 100644 index 000000000..0c4ecc775 Binary files /dev/null and b/testdata/dxf/t32e_au.gds.gz differ diff --git a/testdata/pymod/pya_tests.py b/testdata/pymod/pya_tests.py new file mode 100644 index 000000000..cf405c81a --- /dev/null +++ b/testdata/pymod/pya_tests.py @@ -0,0 +1,32 @@ + +import sys +import os +import unittest + +sys.path.append(os.path.join(os.path.dirname(__file__), "..", "python")) + +# Include all tests from testdata/python +# Missing: +# - basic.py (Test classes not available yet) +# - qtbinding (No applicable because QApplication is missing) + +import tlTest +import dbPCells +import dbLayoutTest +import dbPolygonTest +import dbReaders +import dbRegionTest +import dbTransTest + +if __name__ == '__main__': + suite = unittest.TestLoader().loadTestsFromTestCase(tlTest.TLTest) + suite = unittest.TestLoader().loadTestsFromTestCase(dbPCells.DBPCellTests) + suite = unittest.TestLoader().loadTestsFromTestCase(dbLayoutTest.DBLayoutTest) + suite = unittest.TestLoader().loadTestsFromTestCase(dbPolygonTest.DBPolygonTests) + suite = unittest.TestLoader().loadTestsFromTestCase(dbReaders.DBReadersTests) + suite = unittest.TestLoader().loadTestsFromTestCase(dbRegionTest.DBRegionTest) + suite = unittest.TestLoader().loadTestsFromTestCase(dbTransTest.DBTransTests) + + if not unittest.TextTestRunner(verbosity = 1).run(suite).wasSuccessful(): + sys.exit(1) +