Merge remote-tracking branch 'remotes/origin/pymod' into net-extract

This commit is contained in:
Matthias Koefferlein 2018-11-25 23:16:56 +01:00
commit 5c7cd02af3
49 changed files with 839 additions and 354 deletions

View File

@ -320,7 +320,7 @@ class Config(object):
"""
Gets the version string
"""
return "0.26.0.dev7"
return "0.26.0.dev8"
config = Config()

View File

@ -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 ();
}
}

View File

@ -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"
)
;

View File

@ -110,25 +110,82 @@ EdgesToContours::contour (size_t i) const
}
}
namespace {
template <class C>
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<C> &p, const db::edge<C> &e, const db::edge<C> &other, bool swapped)
{
typedef db::coord_traits<C> 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 <class Iter, class C> static
EdgeRef<Iter> *search_follower (const db::point<C> &p, const EdgeRef<Iter> *e, C distance, const db::box_tree<db::box<C>, EdgeRef<Iter> *, EdgeRefToBox<Iter, false> > &t1, const db::box_tree<db::box<C>, EdgeRef<Iter> *, EdgeRefToBox<Iter, true> > &t2)
{
typedef db::box<C> box_type;
double vp_min = 0.0;
EdgeRef<Iter> *cand = 0;
bool fwd = true;
point_matcher<C> pm;
// try in forward tree
typename db::box_tree<box_type, EdgeRef<Iter> *, EdgeRefToBox<Iter, false> >::touching_iterator f = t1.begin_touching (box_type (p, p), EdgeRefToBox <Iter, false> (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<Iter> *search_follower (const db::point<C> &p, const EdgeRef<Iter> *e, C
if (! t2.empty ()) {
typename db::box_tree<box_type, EdgeRef<Iter> *, EdgeRefToBox<Iter, true> >::touching_iterator f = t2.begin_touching (box_type (p, p), EdgeRefToBox <Iter, true> (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;
}

View File

@ -1114,7 +1114,7 @@ ApplicationBase::run ()
// Give the plugins a change to do some last-minute initialisation and checks
for (tl::Registrar<lay::PluginDeclaration>::iterator cls = tl::Registrar<lay::PluginDeclaration>::begin (); cls != tl::Registrar<lay::PluginDeclaration>::end (); ++cls) {
lay::PluginDeclaration *pd = const_cast<lay::PluginDeclaration *> (&*cls);
pd->initialized (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

View File

@ -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;
};

View File

@ -32,7 +32,7 @@
#include <QDomDocument>
// #define DEBUG_HIGHLIGHTER
// #define DEBUG_HIGHLIGHTER
/**
* @brief Provide a compare operator for QList<QString> 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<QString, GenericSyntaxHighlighterRuleStringList> &lists, GenericSyntaxHighlighterAttributes &attributes)
parse_context (QDomElement e, const std::map<QString, QDomElement> &contexts_by_name, GenericSyntaxHighlighterContexts &contexts, std::map<QString, GenericSyntaxHighlighterRuleStringList> &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<QString, QDomElement>::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<QString, QDomElement> 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));
}
}
}

View File

@ -562,6 +562,17 @@ enum def_style {
dsOthers,
dsRegionMarker,
dsString,
dsOperator,
dsControlFlow,
dsBuiltIn,
dsVariable,
dsExtension,
dsPreprocessor,
dsImport,
dsVerbatimString,
dsSpecialString,
dsSpecialChar,
dsAttribute,
dsLast
};

View File

@ -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 <lay::MainWindow *> (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);
}

View File

@ -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),

View File

@ -98,7 +98,7 @@ public:
/**
* @brief Constructor
*/
MacroEditorDialog (lay::MainWindow *parent, lym::MacroCollection *root);
MacroEditorDialog (lay::PluginRoot *pr, lym::MacroCollection *root);
/**
* @brief Destructor

View File

@ -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<unsigned int>::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<lay::PluginDeclaration>::iterator cls = tl::Registrar<lay::PluginDeclaration>::begin (); cls != tl::Registrar<lay::PluginDeclaration>::end (); ++cls) {
lay::PluginDeclaration *pd = const_cast<lay::PluginDeclaration *> (&*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 <lay::LayoutView *>::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 <lay::LayoutView *>::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

View File

@ -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<std::pair <std::string, bool> > &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<MainWindow> mp_main_window;
};
}
namespace tl {

View File

@ -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 <lay::LayoutView *> all_views;
} else {
mp_view->hide ();
mp_placeholder_label->show ();
}
// update the list of frozen flags per view
std::set <lay::LayoutView *> all_views;
for (std::map <lay::LayoutView *, NavigatorFrozenViewInfo>::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 <lay::LayoutView *, NavigatorFrozenViewInfo>::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 <lay::LayoutView *>::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 <lay::LayoutView *>::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<img::Service> () : 0);
img::Service *img_source = (mp_source_view->get_plugin<img::Service> ());
if (img_source) {
for (img::ImageIterator i = img_source->begin_images (); ! i.at_end (); ++i) {
img_target->insert_image (*i);

View File

@ -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)
{

View File

@ -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 <lay::MainWindow *> (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 ();

View File

@ -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;

View File

@ -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 <lay::ConfigPage *>::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 <lay::ConfigPage *>::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;

View File

@ -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 <lay::ConfigPage *> m_config_pages;
bool m_finalize_recursion;
};

View File

@ -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 <lay::MainWindow *> (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 &

View File

@ -132,6 +132,7 @@ private:
bool m_technologies_configured;
lay::TechSetupDialog *mp_editor;
lay::MainWindow *mp_mw;
lay::PluginRoot *mp_plugin_root;
std::vector<std::string> m_paths;
std::vector<db::Technology> m_temp_tech;
db::Technology *mp_active_technology;

View File

@ -13,9 +13,10 @@
<!-- v2.06 decorator names can (and often do) contain periods -->
<!-- v2.07 add support for %prog and co, see bug 142832 -->
<!-- v2.08 add missing overloaders, new Python 3 statements, builtins, and keywords -->
<language name="Python" version="2.22" style="python" kateversion="2.4" section="Scripts" extensions="*.py;*.pyw;SConstruct;SConscript" mimetype="application/x-python;text/x-python" casesensitive="1" author="Michael Bueker" license="">
<!-- v2.29 recognize escape sequenzes correctly -->
<language name="Python" version="4" style="python" kateversion="5.0" section="Scripts" extensions="*.py;*.pyw;SConstruct;SConscript" mimetype="application/x-python;text/x-python" casesensitive="1" author="Michael Bueker" license="">
<highlighting>
<list name="prep">
<list name="import">
<item> import </item>
<item> from </item>
<item> as </item>
@ -52,6 +53,8 @@
<item> while </item>
<item> with </item>
<item> yield </item>
<item> async </item>
<item> await </item>
</list>
<list name="builtinfuncs">
<item> __import__ </item>
@ -248,6 +251,11 @@
<item>__format__</item>
<item>__next__</item>
<item>__dir__</item>
<item>__await__</item>
<item>__aiter__</item>
<item>__anext__</item>
<item>__aenter__</item>
<item>__aexit__</item>
</list>
<list name="exceptions">
<!--
@ -323,17 +331,17 @@
</list>
<contexts>
<context name="Normal" attribute="Normal Text" lineEndContext="#stay">
<keyword attribute="Preprocessor" String="prep" context="#stay"/>
<keyword attribute="Import" String="import" context="#stay"/>
<keyword attribute="Definition Keyword" String="defs" context="#stay"/>
<keyword attribute="Operator" String="operators" context="#stay"/>
<keyword attribute="Command Keyword" String="commands" context="#stay"/>
<keyword attribute="Operator Keyword" String="operators" context="#stay"/>
<keyword attribute="Flow Control Keyword" String="flow" context="#stay"/>
<keyword attribute="Builtin Function" String="builtinfuncs" context="#stay"/>
<keyword attribute="Special Variable" String="specialvars" context="#stay"/>
<keyword attribute="Extensions" String="bindings" context="#stay"/>
<keyword attribute="Exceptions" String="exceptions" context="#stay"/>
<keyword attribute="Overloaders" String="overloaders" context="#stay"/>
<RegExpr attribute="Normal" String="[a-zA-Z_][a-zA-Z_0-9]{2,}" context="#stay"/>
<RegExpr attribute="ClassNames" String="[A-Z][a-zA-Z_0-9]+" context="#stay"/>
<RegExpr attribute="Normal Text" String="[a-z_][a-zA-Z_][a-zA-Z_0-9]+" context="#stay"/>
<RegExpr attribute="Complex" String=" ((([0-9]*\.[0-9]+|[0-9]+\.)|([0-9]+|([0-9]*\.[0-9]+|[0-9]+\.))[eE](\+|-)?[0-9]+)|[0-9]+)[jJ]" context="#stay"/>
<Float attribute="Float" context="#stay" />
@ -353,15 +361,15 @@
<IncludeRules context="StringVariants" />
<AnyChar attribute="Operator" String="+*/%\|=;\!&lt;&gt;!^&amp;~-" context="#stay"/>
<RegExpr attribute="Decorator" String="@[_a-zA-Z][\._a-zA-Z0-9]*" firstNonSpace="true"/>
<AnyChar attribute="Operator" String="+*/%\|=;\!&lt;&gt;!^&amp;~-@" context="#stay"/>
</context>
<context name="#CheckForString" attribute="Normal Text" lineEndContext="#pop" fallthrough="true" fallthroughContext="#pop">
<DetectSpaces/>
<LineContinue attribute="Normal Text" context="CheckForStringNext"/>
</context>
<context name="CheckForStringNext" attribute="Normal Text" lineEndContext="#pop" fallthrough="true" fallthroughContext="#pop">
<DetectSpaces/>
<LineContinue attribute="Normal Text" context="CheckForStringNext"/>
@ -370,60 +378,40 @@
<context name="StringVariants" attribute="Normal Text" lineEndContext="#stay">
<DetectSpaces/>
<!-- ''' -->
<StringDetect attribute="String" String="'''" context="Tripple A-string" beginRegion="Tripple A-region"/>
<StringDetect attribute="String" String="u'''" insensitive="true" context="Tripple A-string" beginRegion="Tripple A-region"/>
<!-- """ -->
<StringDetect attribute="String" String="&quot;&quot;&quot;" context="Tripple Q-string" beginRegion="Tripple Q-region"/>
<StringDetect attribute="String" String="u&quot;&quot;&quot;" insensitive="true" context="Tripple Q-string" beginRegion="Tripple Q-region"/>
<!-- ' -->
<DetectChar attribute="String" char="'" context="Single A-string"/>
<Detect2Chars attribute="String" char="u" char1="'" insensitive="true" context="Single A-string"/>
<!-- " -->
<DetectChar attribute="String" char="&quot;" context="Single Q-string"/>
<Detect2Chars attribute="String" char="u" char1="&quot;" insensitive="true" context="Single Q-string"/>
<!-- ''' -->
<StringDetect attribute="Raw String" String="r'''" insensitive="true" context="Raw Tripple A-string" beginRegion="Tripple A-region"/>
<StringDetect attribute="Raw String" String="ur'''" insensitive="true" context="Raw Tripple A-string" beginRegion="Tripple A-region"/>
<!-- """ -->
<StringDetect attribute="Raw String" String="r&quot;&quot;&quot;" insensitive="true" context="Raw Tripple Q-string" beginRegion="Tripple Q-region"/>
<StringDetect attribute="Raw String" String="ur&quot;&quot;&quot;" insensitive="true" context="Raw Tripple Q-string" beginRegion="Tripple Q-region"/>
<!-- ' -->
<StringDetect attribute="Raw String" String="r'" insensitive="true" context="Raw A-string"/>
<StringDetect attribute="Raw String" String="ur'" insensitive="true" context="Raw A-string"/>
<!-- " -->
<StringDetect attribute="Raw String" String="r&quot;" insensitive="true" context="Raw Q-string"/>
<StringDetect attribute="Raw String" String="ur&quot;" insensitive="true" context="Raw Q-string"/>
<RegExpr attribute="String" String="u?'''" insensitive="true" context="Triple A-string" beginRegion="Triple A-region"/>
<RegExpr attribute="String" String="u?&quot;&quot;&quot;" insensitive="true" context="Triple Q-string" beginRegion="Triple Q-region"/>
<RegExpr attribute="String" String="u?'" insensitive="true" context="Single A-string"/>
<RegExpr attribute="String" String="u?&quot;" insensitive="true" context="Single Q-string"/>
<RegExpr attribute="Raw String" String="(u?r|ru)'''" insensitive="true" context="Raw Triple A-string" beginRegion="Triple A-region"/>
<RegExpr attribute="Raw String" String="(u?r|ru)&quot;&quot;&quot;" insensitive="true" context="Raw Triple Q-string" beginRegion="Triple Q-region"/>
<RegExpr attribute="Raw String" String="(u?r|ru)'" insensitive="true" context="Raw A-string"/>
<RegExpr attribute="Raw String" String="(u?r|ru)&quot;" insensitive="true" context="Raw Q-string"/>
<StringDetect attribute="F-String" String="f'''" insensitive="true" context="Triple A-F-String" beginRegion="Triple A-region"/>
<StringDetect attribute="F-String" String="f&quot;&quot;&quot;" insensitive="true" context="Triple Q-F-String" beginRegion="Triple Q-region"/>
<StringDetect attribute="F-String" String="f'" insensitive="true" context="Single A-F-String"/>
<StringDetect attribute="F-String" String="f&quot;" insensitive="true" context="Single Q-F-String"/>
<RegExpr attribute="Raw F-String" String="(fr|rf)'''" insensitive="true" context="Raw Triple A-F-String" beginRegion="Triple A-region"/>
<RegExpr attribute="Raw F-String" String="(fr|rf)&quot;&quot;&quot;" insensitive="true" context="Raw Triple Q-F-String" beginRegion="Triple Q-region"/>
<RegExpr attribute="Raw F-String" String="(fr|rf)'" insensitive="true" context="Raw A-F-String"/>
<RegExpr attribute="Raw F-String" String="(fr|rf)&quot;" insensitive="true" context="Raw Q-F-String"/>
</context>
<context name="CommentVariants" attribute="Normal Text" lineEndContext="#stay">
<DetectSpaces/>
<!-- ''' -->
<StringDetect attribute="Comment" String="'''" firstNonSpace="true" context="Tripple A-comment" beginRegion="Tripple A-region"/>
<StringDetect attribute="Comment" String="u'''" insensitive="true" firstNonSpace="true" context="Tripple A-comment" beginRegion="Tripple A-region"/>
<!-- """ -->
<StringDetect attribute="Comment" String="&quot;&quot;&quot;" firstNonSpace="true" context="Tripple Q-comment" beginRegion="Tripple Q-region"/>
<StringDetect attribute="Comment" String="u&quot;&quot;&quot;" insensitive="true" firstNonSpace="true" context="Tripple Q-comment" beginRegion="Tripple Q-region"/>
<!-- ' -->
<DetectChar attribute="Comment" char="'" firstNonSpace="true" context="Single A-comment"/>
<Detect2Chars attribute="Comment" char="u" char1="'" insensitive="true" firstNonSpace="true" context="Single A-comment"/>
<!-- " -->
<DetectChar attribute="Comment" char="&quot;" firstNonSpace="true" context="Single Q-comment"/>
<Detect2Chars attribute="Comment" char="u" char1="&quot;" insensitive="true" firstNonSpace="true" context="Single Q-comment"/>
<!-- ''' -->
<StringDetect attribute="Comment" String="r'''" insensitive="true" firstNonSpace="true" context="Tripple A-comment" beginRegion="Tripple A-region"/>
<StringDetect attribute="Comment" String="ur'''" insensitive="true" firstNonSpace="true" context="Tripple A-comment" beginRegion="Tripple A-region"/>
<!-- """ -->
<StringDetect attribute="Comment" String="r&quot;&quot;&quot;" insensitive="true" firstNonSpace="true" context="Tripple Q-comment" beginRegion="Tripple Q-region"/>
<StringDetect attribute="Comment" String="ur&quot;&quot;&quot;" insensitive="true" firstNonSpace="true" context="Tripple Q-comment" beginRegion="Tripple Q-region"/>
<!-- ' -->
<StringDetect attribute="Comment" String="r'" insensitive="true" firstNonSpace="true" context="Single A-comment"/>
<StringDetect attribute="Comment" String="ur'" insensitive="true" firstNonSpace="true" context="Single A-comment"/>
<!-- " -->
<StringDetect attribute="Comment" String="r&quot;" insensitive="true" firstNonSpace="true" context="Single Q-comment"/>
<StringDetect attribute="Comment" String="ur&quot;" insensitive="true" firstNonSpace="true" context="Single Q-comment"/>
<RegExpr attribute="Comment" String="u?'''" insensitive="true" firstNonSpace="true" context="Triple A-comment" beginRegion="Triple A-region"/>
<RegExpr attribute="Comment" String="u?&quot;&quot;&quot;" insensitive="true" firstNonSpace="true" context="Triple Q-comment" beginRegion="Triple Q-region"/>
<RegExpr attribute="Comment" String="u?'" insensitive="true" firstNonSpace="true" context="Single A-comment"/>
<RegExpr attribute="Comment" String="u?&quot;" insensitive="true" firstNonSpace="true" context="Single Q-comment"/>
<RegExpr attribute="Comment" String="(u?r|ru)'''" insensitive="true" firstNonSpace="true" context="Triple A-comment" beginRegion="Triple A-region"/>
<RegExpr attribute="Comment" String="(u?r|ru)&quot;&quot;&quot;" insensitive="true" firstNonSpace="true" context="Triple Q-comment" beginRegion="Triple Q-region"/>
<RegExpr attribute="Comment" String="(u?r|ru)'" insensitive="true" firstNonSpace="true" context="Single A-comment"/>
<RegExpr attribute="Comment" String="(u?r|ru)&quot;" insensitive="true" firstNonSpace="true" context="Single Q-comment"/>
</context>
<context name="Dictionary" attribute="Normal Text" lineEndContext="#stay" noIndentationBasedFolding="true">
@ -432,14 +420,14 @@
<IncludeRules context="StringVariants" />
<IncludeRules context="Normal" />
</context>
<context name="List" attribute="Normal Text" lineEndContext="#stay" noIndentationBasedFolding="true">
<DetectSpaces/>
<DetectChar attribute="Normal Text" char="]" context="#pop" endRegion="List"/>
<IncludeRules context="StringVariants" />
<IncludeRules context="Normal" />
</context>
<context name="Tuple" attribute="Normal Text" lineEndContext="#stay" noIndentationBasedFolding="true">
<DetectSpaces/>
<DetectChar attribute="Normal Text" char=")" context="#pop" endRegion="Tuple"/>
@ -454,14 +442,14 @@
<IncludeRules context="##Modelines" />
</context>
<context name="Tripple A-comment" attribute="Comment" lineEndContext="#stay" noIndentationBasedFolding="true">
<StringDetect attribute="Comment" String="'''" context="#pop" endRegion="Tripple A-region"/>
<context name="Triple A-comment" attribute="Comment" lineEndContext="#stay" noIndentationBasedFolding="true">
<StringDetect attribute="Comment" String="'''" context="#pop" endRegion="Triple A-region"/>
<IncludeRules context="##Alerts_indent" />
</context>
<context name="Tripple Q-comment" attribute="Comment" lineEndContext="#stay" noIndentationBasedFolding="true">
<context name="Triple Q-comment" attribute="Comment" lineEndContext="#stay" noIndentationBasedFolding="true">
<HlCChar attribute="Comment" context="#stay"/>
<StringDetect attribute="Comment" String="&quot;&quot;&quot;" context="#pop" endRegion="Tripple Q-region"/>
<StringDetect attribute="Comment" String="&quot;&quot;&quot;" context="#pop" endRegion="Triple Q-region"/>
<IncludeRules context="##Alerts_indent" />
</context>
@ -493,89 +481,176 @@
-->
<RegExpr attribute="String Substitution" String="%((\([a-zA-Z0-9_]+\))?[#0\- +]?([1-9][0-9]*|\*)?(\.([1-9][0-9]*|\*))?[hlL]?[crsdiouxXeEfFgG%]|prog|default)" context="#stay"/>
<!-- http://docs.python.org/2/library/string.html#format-string-syntax:
replacement_field ::= "{" field_name ["!" conversion] [":" format_spec] "}"
field_name ::= (identifier | integer) ("." attribute_name | "[" element_index "]")*
attribute_name ::= identifier
element_index ::= integer | index_string
index_string ::= <any source character except "]"> +
conversion ::= "r" | "s"
format_spec ::= [[fill]align][sign][#][0][width][.precision][type]
fill ::= <a character other than '}'>
align ::= "<" | ">" | "=" | "^"
sign ::= "+" | "-" | " "
width ::= integer
precision ::= integer
type ::= "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%"
replacement_field ::= "{" [field_name] ["!" conversion] [":" format_spec] "}"
field_name ::= arg_name ("." attribute_name | "[" element_index "]")*
arg_name ::= [identifier | integer]
attribute_name ::= identifier
element_index ::= integer | index_string
index_string ::= <any source character except "]"> +
conversion ::= "r" | "s"
format_spec ::= [[fill]align][sign][#][0][width][,][.precision][type]
fill ::= <any character>
align ::= "<" | ">" | "=" | "^"
sign ::= "+" | "-" | " "
width ::= integer
precision ::= integer
type ::= "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%"
-->
<RegExpr attribute="String Substitution" String="\{([a-zA-Z0-9_]+|[0-9]+)(\.[a-zA-Z0-9_]+|\[[^ \]]+\])*(![rs])?(:([^}]?[&lt;&gt;=^])?[ +-]?#?0?[0-9]*(\.[0-9]+)?[bcdeEfFgGnosxX%]?)?\}" context="#stay"/>
<RegExpr attribute="String Substitution" String="\{(([a-zA-Z0-9_]+|[0-9]+)(\.[a-zA-Z0-9_]+|\[[^ \]]+\])*)?(![rs])?(:([^}]?[&lt;&gt;=^])?[ +-]?#?0?[0-9]*(\.[0-9]+)?[bcdeEfFgGnosxX%]?)?\}" context="#stay"/>
<Detect2Chars attribute="String Substitution" char="{" char1="{" context="#stay" />
<Detect2Chars attribute="String Substitution" char="}" char1="}" context="#stay" />
</context>
<context name="Tripple A-string" attribute="String" lineEndContext="#stay" noIndentationBasedFolding="true">
<HlCStringChar attribute="String Char" context="#stay"/>
<IncludeRules context="stringformat"/>
<StringDetect attribute="String" String="'''" context="#pop#CheckForString" endRegion="Tripple A-region"/>
<!-- escape characters -->
<context name="stringescape" attribute="String Char" lineEndContext="#stay">
<!-- As this highlighting style is for both, Python 2 and 3,
we do not know if a normal string is “unicode” or not. So we
-->
<RegExpr attribute="String Char" String="\\[\\'&quot;abfnrtv]" context="#stay"/>
<RegExpr attribute="String Char" String="\\[0-7]{1,3}" context="#stay"/>
<RegExpr attribute="String Char" String="\\x[0-9A-Fa-f]{2}" context="#stay"/>
<RegExpr attribute="String Char" String="\\u[0-9A-Fa-f]{4}" context="#stay"/>
<RegExpr attribute="String Char" String="\\U[0-9A-Fa-f]{8}" context="#stay"/>
<RegExpr attribute="String Char" String="\\N\{[a-zA-Z0-9\- ]+\}" context="#stay"/>
</context>
<context name="Raw Tripple A-string" attribute="Raw String" lineEndContext="#stay" noIndentationBasedFolding="true">
<!-- f-literals -->
<context name="stringinterpolation" attribute="F-String" lineEndContext="#stay">
<Detect2Chars attribute="String Char" char="{" char1="{" context="#stay"/>
<DetectChar attribute="String Substitution" char="{" context="String Interpolation"/>
</context>
<context name="String Interpolation" attribute="String Substitution" lineEndContext="#stay">
<DetectChar attribute="Error" char="\" context="#pop"/>
<RegExpr attribute="String Substitution" String="(![rs])?(:([^}]?[&lt;&gt;=^])?[ +-]?#?0?[0-9]*(\.[0-9]+)?[bcdeEfFgGnosxX%]?)?\}" context="#pop"/>
<IncludeRules context="Normal"/> <!-- TODO: create expression context instead -->
</context>
<!--
It follows a Binary tree of string kinds (not even touching byte literals).
The levels are:
1. triple- vs. single-quoted
2. apostrophe vs. quotation mark
3. static vs. interpolated (f-literal)
4. escaped vs. raw
Adding byte literals wouldnt make the current 2⁴ into 2⁵ contexts, as there are no byte f-literals
-->
<!-- Triple-quoted A-strings -->
<context name="Triple A-string" attribute="String" lineEndContext="#stay" noIndentationBasedFolding="true">
<IncludeRules context="stringescape"/>
<IncludeRules context="stringformat"/>
<StringDetect attribute="String" String="'''" context="#pop#CheckForString" endRegion="Triple A-region"/>
</context>
<context name="Raw Triple A-string" attribute="Raw String" lineEndContext="#stay" noIndentationBasedFolding="true">
<HlCStringChar attribute="Raw String" context="#stay"/>
<IncludeRules context="stringformat"/>
<StringDetect attribute="String" String="'''" context="#pop#CheckForString" endRegion="Tripple A-region"/>
<StringDetect attribute="Raw String" String="'''" context="#pop#CheckForString" endRegion="Triple A-region"/>
</context>
<context name="Tripple Q-string" attribute="String" lineEndContext="#stay" noIndentationBasedFolding="true">
<HlCStringChar attribute="String Char" context="#stay"/>
<context name="Triple A-F-String" attribute="F-String" lineEndContext="#stay" noIndentationBasedFolding="true">
<IncludeRules context="stringescape"/>
<IncludeRules context="stringinterpolation"/>
<StringDetect attribute="F-String" String="'''" context="#pop#CheckForString" endRegion="Triple A-region"/>
</context>
<context name="Raw Triple A-F-String" attribute="Raw F-String" lineEndContext="#stay" noIndentationBasedFolding="true">
<HlCStringChar attribute="Raw F-String" context="#stay"/>
<IncludeRules context="stringinterpolation"/>
<StringDetect attribute="Raw F-String" String="'''" context="#pop#CheckForString" endRegion="Triple A-region"/>
</context>
<!-- Triple-quoted Q-strings -->
<context name="Triple Q-string" attribute="String" lineEndContext="#stay" noIndentationBasedFolding="true">
<IncludeRules context="stringescape"/>
<IncludeRules context="stringformat"/>
<StringDetect attribute="String" String="&quot;&quot;&quot;" context="#pop#CheckForString" endRegion="Tripple Q-region"/>
<StringDetect attribute="String" String="&quot;&quot;&quot;" context="#pop#CheckForString" endRegion="Triple Q-region"/>
</context>
<context name="Raw Tripple Q-string" attribute="Raw String" lineEndContext="#stay" noIndentationBasedFolding="true">
<context name="Raw Triple Q-string" attribute="Raw String" lineEndContext="#stay" noIndentationBasedFolding="true">
<HlCStringChar attribute="Raw String" context="#stay"/>
<IncludeRules context="stringformat"/>
<StringDetect attribute="String" String="&quot;&quot;&quot;" context="#pop#CheckForString" endRegion="Tripple Q-region"/>
<StringDetect attribute="Raw String" String="&quot;&quot;&quot;" context="#pop#CheckForString" endRegion="Triple Q-region"/>
</context>
<context name="Triple Q-F-String" attribute="F-String" lineEndContext="#stay" noIndentationBasedFolding="true">
<IncludeRules context="stringescape"/>
<IncludeRules context="stringinterpolation"/>
<StringDetect attribute="F-String" String="&quot;&quot;&quot;" context="#pop#CheckForString" endRegion="Triple Q-region"/>
</context>
<context name="Raw Triple Q-F-String" attribute="Raw F-String" lineEndContext="#stay" noIndentationBasedFolding="true">
<HlCStringChar attribute="Raw F-String" context="#stay"/>
<IncludeRules context="stringinterpolation"/>
<StringDetect attribute="Raw F-String" String="&quot;&quot;&quot;" context="#pop#CheckForString" endRegion="Triple Q-region"/>
</context>
<!-- Single-quoted A-strings -->
<context name="Single A-string" attribute="String" lineEndContext="#stay">
<HlCStringChar attribute="String Char" context="#stay"/>
<IncludeRules context="stringescape"/>
<IncludeRules context="stringformat"/>
<DetectChar attribute="String" char="'" context="#pop#CheckForString"/>
</context>
<context name="Single Q-string" attribute="String" lineEndContext="#stay">
<HlCStringChar attribute="String Char" context="#stay"/>
<IncludeRules context="stringformat"/>
<DetectChar attribute="String" char="&quot;" context="#pop#CheckForString"/>
</context>
<context name="Raw A-string" attribute="Raw String" lineEndContext="#stay">
<HlCStringChar attribute="Raw String" context="#stay"/>
<IncludeRules context="stringformat"/>
<DetectChar attribute="Raw String" char="'" context="#pop#CheckForString"/>
</context>
<context name="Single A-F-String" attribute="F-String" lineEndContext="#stay">
<IncludeRules context="stringescape"/>
<IncludeRules context="stringinterpolation"/>
<DetectChar attribute="F-String" char="'" context="#pop#CheckForString"/>
</context>
<context name="Raw A-F-String" attribute="Raw F-String" lineEndContext="#stay">
<HlCStringChar attribute="Raw F-String" context="#stay"/>
<IncludeRules context="stringinterpolation"/>
<DetectChar attribute="Raw F-String" char="'" context="#pop#CheckForString"/>
</context>
<!-- Single-quoted Q-strings -->
<context name="Single Q-string" attribute="String" lineEndContext="#stay">
<IncludeRules context="stringescape"/>
<IncludeRules context="stringformat"/>
<DetectChar attribute="String" char="&quot;" context="#pop#CheckForString"/>
</context>
<context name="Raw Q-string" attribute="Raw String" lineEndContext="#stay">
<HlCStringChar attribute="Raw String" context="#stay"/>
<IncludeRules context="stringformat"/>
<DetectChar attribute="Raw String" char="&quot;" context="#pop#CheckForString"/>
</context>
<context name="Single Q-F-String" attribute="F-String" lineEndContext="#stay">
<IncludeRules context="stringescape"/>
<IncludeRules context="stringinterpolation"/>
<DetectChar attribute="F-String" char="&quot;" context="#pop#CheckForString"/>
</context>
<context name="Raw Q-F-String" attribute="Raw F-String" lineEndContext="#stay">
<HlCStringChar attribute="Raw F-String" context="#stay"/>
<IncludeRules context="stringinterpolation"/>
<DetectChar attribute="Raw F-String" char="&quot;" context="#pop#CheckForString"/>
</context>
</contexts>
<itemDatas>
<itemData name="Normal Text" defStyleNum="dsNormal" spellChecking="false"/>
<itemData name="Definition Keyword" defStyleNum="dsKeyword" spellChecking="false"/>
<itemData name="Operator" defStyleNum="dsNormal" bold="1" spellChecking="false"/>
<itemData name="String Substitution" defStyleNum="dsOthers" color="#0057ae" selColor="#0057ae" spellChecking="false"/>
<itemData name="Command Keyword" defStyleNum="dsKeyword" spellChecking="false"/>
<itemData name="Flow Control Keyword" defStyleNum="dsKeyword" spellChecking="false"/>
<itemData name="Builtin Function" defStyleNum="dsDataType" spellChecking="false"/>
<itemData name="Special Variable" defStyleNum="dsOthers" spellChecking="false"/>
<itemData name="Extensions" defStyleNum="dsOthers" color="#0095ff" selColor="#0095ff" bold="1" italic="0" spellChecking="false"/>
<itemData name="Exceptions" defStyleNum="dsOthers" color="#054d00" selColor="#054d00" bold="1" italic="0" spellChecking="false"/>
<itemData name="Overloaders" defStyleNum="dsOthers" color="#000e52" selColor="#000e52" bold="1" italic="0" spellChecking="false"/>
<itemData name="Preprocessor" defStyleNum="dsChar" spellChecking="false"/>
<itemData name="String Char" defStyleNum="dsChar" spellChecking="false"/>
<itemData name="Operator" defStyleNum="dsOperator" spellChecking="false"/>
<itemData name="Operator Keyword" defStyleNum="dsKeyword" spellChecking="false"/>
<itemData name="Flow Control Keyword" defStyleNum="dsControlFlow" spellChecking="false"/>
<itemData name="Builtin Function" defStyleNum="dsBuiltIn" spellChecking="false"/>
<itemData name="Special Variable" defStyleNum="dsVariable" spellChecking="false"/>
<itemData name="Extensions" defStyleNum="dsExtension" spellChecking="false"/>
<itemData name="Exceptions" defStyleNum="dsPreprocessor" spellChecking="false"/>
<itemData name="Overloaders" defStyleNum="dsFunction" spellChecking="false"/>
<itemData name="Import" defStyleNum="dsImport" spellChecking="false"/>
<itemData name="Float" defStyleNum="dsFloat" spellChecking="false"/>
<itemData name="Int" defStyleNum="dsDecVal" spellChecking="false"/>
<itemData name="Hex" defStyleNum="dsBaseN" spellChecking="false"/>
@ -583,8 +658,14 @@
<itemData name="Complex" defStyleNum="dsOthers" spellChecking="false"/>
<itemData name="Comment" defStyleNum="dsComment"/>
<itemData name="String" defStyleNum="dsString"/>
<itemData name="Raw String" defStyleNum="dsString"/>
<itemData name="Decorator" defStyleNum="dsOthers" color="#8f6b32" selColor="#8f6b32" italic="0" spellChecking="false"/>
<itemData name="ClassNames" defStyleNum="dsOthers" color="#FCAD3D" selColor="#ffffff" bold="1" italic="0" spellChecking="false"/>
<itemData name="Raw String" defStyleNum="dsVerbatimString"/>
<itemData name="F-String" defStyleNum="dsSpecialString"/>
<itemData name="Raw F-String" defStyleNum="dsVerbatimString"/>
<itemData name="String Char" defStyleNum="dsChar" spellChecking="false"/>
<itemData name="String Substitution" defStyleNum="dsSpecialChar" spellChecking="false"/>
<itemData name="Decorator" defStyleNum="dsAttribute" spellChecking="false"/>
<itemData name="Error" defStyleNum="dsError"/>
</itemDatas>
</highlighting>
<general>

View File

@ -849,18 +849,28 @@ Class<gsi::ButtonStateNamespace> decl_ButtonState ("lay", "ButtonState",
);
static std::vector<std::string>
get_config_names (lay::PluginRoot *view)
get_config_names (lay::PluginRoot *root)
{
std::vector<std::string> 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<lay::PluginRoot> 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<lay::PluginRoot> 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"
);

View File

@ -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

View File

@ -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.
*

View File

@ -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<std::string> &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<PluginRoot *> (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<std::string, std::string>::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<Plugin>::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;

View File

@ -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<std::string> &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

View File

@ -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;

View File

@ -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

8
src/plugins/streamers/dxf/db_plugin/gsiDeclDbDXF.cc Normal file → Executable file
View File

@ -361,7 +361,7 @@ gsi::ClassExt<db::LoadLayoutOptions> 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<db::SaveLayoutOptions> 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"

View File

@ -73,6 +73,11 @@
<string>Write HATCH entity</string>
</property>
</item>
<item>
<property name="text" >
<string>Write LINE entity</string>
</property>
</item>
</widget>
</item>
</layout>

View File

@ -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);
}

View File

@ -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;

View File

@ -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<PyObject *, size_t> m_file_id_map;
wchar_t *mp_py3_app_name;
bool m_embedded;
std::auto_ptr<pya::PythonModule> m_pya_module;
};

View File

@ -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);

View File

@ -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" ]

View File

@ -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" ]

View File

@ -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)

View File

@ -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

View File

@ -23,3 +23,4 @@
#include "../pymodHelper.h"
DEFINE_PYMOD(tlcore, "tl", "KLayout core module 'tl'")

View File

@ -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")

View File

@ -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;

BIN
testdata/dxf/round_path.dxf.gz vendored Normal file

Binary file not shown.

BIN
testdata/dxf/t32a_au.gds.gz vendored Normal file

Binary file not shown.

BIN
testdata/dxf/t32b_au.gds.gz vendored Normal file

Binary file not shown.

BIN
testdata/dxf/t32c_au.gds.gz vendored Normal file

Binary file not shown.

BIN
testdata/dxf/t32d_au.gds.gz vendored Normal file

Binary file not shown.

BIN
testdata/dxf/t32e_au.gds.gz vendored Normal file

Binary file not shown.

32
testdata/pymod/pya_tests.py vendored Normal file
View File

@ -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)