WIP: controllers (tech + macro)

The tech controller now is indenpendent from the
macro controller. The macro controller is responsible for
pulling it's data from the tech controller. It's initialized
after the tech controller so it can do so.

The macro controller is also responsible to building the
menus.

The tech controller issues events that the macro controller
can listen to.
This commit is contained in:
Matthias Koefferlein 2017-04-15 23:07:40 +02:00
parent 430d140016
commit 6b6b45714f
9 changed files with 260 additions and 229 deletions

View File

@ -929,37 +929,10 @@ Application::Application (int &argc, char **argv, bool non_ui_mode)
lay::MacroController *mc = lay::MacroController::instance ();
if (mc && ! m_no_macros) {
// Add the global ruby modules as the first ones.
m_load_macros.insert (m_load_macros.begin (), global_modules.begin (), global_modules.end ());
for (std::vector <std::string>::const_iterator p = m_klayout_path.begin (); p != m_klayout_path.end (); ++p) {
if (p == m_klayout_path.begin ()) {
mc->add_path (*p, tl::to_string (QObject::tr ("Local")), std::string (), false);
} else if (m_klayout_path.size () == 2) {
mc->add_path (*p, tl::to_string (QObject::tr ("Global")), std::string (), true);
} else {
mc->add_path (*p, tl::to_string (QObject::tr ("Global")) + " - " + *p, std::string (), true);
}
}
// Install the custom folders
for (std::vector <std::pair<std::string, std::string> >::const_iterator p = custom_macro_paths.begin (); p != custom_macro_paths.end (); ++p) {
mc->add_path (p->first, tl::to_string (QObject::tr ("Project")) + " - " + p->first, p->second, false);
}
// Actually load the macros
mc->load ();
}
lay::TechnologyController *tc = lay::TechnologyController::instance ();
if (tc) {
tc->enable_macros (! m_no_macros);
// auto-import technologies
for (std::vector <std::string>::const_iterator p = m_klayout_path.begin (); p != m_klayout_path.end (); ++p) {
std::string tp = tl::to_string (QDir (tl::to_qstring (*p)).filePath (QString::fromUtf8 ("tech")));
@ -987,7 +960,38 @@ Application::Application (int &argc, char **argv, bool non_ui_mode)
}
tc->refresh ();
tc->load ();
}
if (mc) {
mc->enable_implicit_macros (! m_no_macros);
if (! m_no_macros) {
// Add the global ruby modules as the first ones.
m_load_macros.insert (m_load_macros.begin (), global_modules.begin (), global_modules.end ());
for (std::vector <std::string>::const_iterator p = m_klayout_path.begin (); p != m_klayout_path.end (); ++p) {
if (p == m_klayout_path.begin ()) {
mc->add_path (*p, tl::to_string (QObject::tr ("Local")), std::string (), false);
} else if (m_klayout_path.size () == 2) {
mc->add_path (*p, tl::to_string (QObject::tr ("Global")), std::string (), true);
} else {
mc->add_path (*p, tl::to_string (QObject::tr ("Global")) + " - " + *p, std::string (), true);
}
}
// Install the custom folders
for (std::vector <std::pair<std::string, std::string> >::const_iterator p = custom_macro_paths.begin (); p != custom_macro_paths.end (); ++p) {
mc->add_path (p->first, tl::to_string (QObject::tr ("Project")) + " - " + p->first, p->second, false);
}
}
// Actually load the macros
mc->load ();
}

View File

@ -1083,7 +1083,7 @@ void MacroCollection::on_macro_changed (Macro *macro)
}
}
void MacroCollection::collect_used_nodes(std::set <Macro *> &macros, std::set <MacroCollection *> &macro_collections)
void MacroCollection::collect_used_nodes (std::set <Macro *> &macros, std::set <MacroCollection *> &macro_collections)
{
for (MacroCollection::child_iterator c = begin_children (); c != end_children (); ++c) {
macro_collections.insert (c->second);

View File

@ -37,7 +37,7 @@ namespace lay
{
MacroController::MacroController ()
: mp_macro_editor (0), mp_mw (0),
: mp_macro_editor (0), mp_mw (0), m_no_implicit_macros (false),
dm_do_update_menu_with_macros (this, &MacroController::do_update_menu_with_macros)
{
connect (&m_temp_macros, SIGNAL (menu_needs_update ()), this, SLOT (update_menu_with_macros ()));
@ -74,6 +74,8 @@ MacroController::load ()
}
}
sync_implicit_macros (false);
}
void
@ -89,7 +91,7 @@ MacroController::initialized (lay::PluginRoot *root)
connect (&lay::MacroCollection::root (), SIGNAL (macro_collection_changed (MacroCollection *)), this, SLOT (update_menu_with_macros ()));
if (lay::TechnologyController::instance ()) {
connect (lay::TechnologyController::instance (), SIGNAL (active_technology_changed ()), this, SLOT (update_menu_with_macros ()));
connect (lay::TechnologyController::instance (), SIGNAL (technologies_edited ()), this, SLOT (update_menu_with_macros ()));
connect (lay::TechnologyController::instance (), SIGNAL (technologies_edited ()), this, SLOT (technologies_edited ()));
}
// update the menus with the macro menu bindings as late as possible (now we
@ -104,7 +106,7 @@ MacroController::uninitialize (lay::PluginRoot * /*root*/)
disconnect (&lay::MacroCollection::root (), SIGNAL (macro_collection_changed (MacroCollection *)), this, SLOT (update_menu_with_macros ()));
if (lay::TechnologyController::instance ()) {
disconnect (lay::TechnologyController::instance (), SIGNAL (active_technology_changed ()), this, SLOT (update_menu_with_macros ()));
disconnect (lay::TechnologyController::instance (), SIGNAL (technologies_edited ()), this, SLOT (update_menu_with_macros ()));
disconnect (lay::TechnologyController::instance (), SIGNAL (technologies_edited ()), this, SLOT (technologies_edited ()));
}
delete mp_macro_editor;
@ -264,6 +266,136 @@ MacroController::show_editor (const std::string &cat, bool force_add)
}
}
void
MacroController::enable_implicit_macros (bool enable)
{
m_no_implicit_macros = !enable;
}
void
MacroController::sync_implicit_macros (bool check_autorun)
{
if (m_no_implicit_macros) {
return;
}
std::set<std::pair<std::string, std::string> > tech_macro_paths;
std::map<std::pair<std::string, std::string>, std::string> tech_names_by_path;
// Add additional places where the technologies define some macros
for (lay::Technologies::const_iterator t = lay::Technologies::instance ()->begin (); t != lay::Technologies::instance ()->end (); ++t) {
if (t->base_path ().empty ()) {
continue;
}
for (size_t c = 0; c < macro_categories ().size (); ++c) {
QDir base_dir (tl::to_qstring (t->base_path ()));
if (base_dir.exists ()) {
QDir macro_dir (base_dir.filePath (tl::to_qstring (macro_categories () [c].first)));
if (macro_dir.exists ()) {
std::string mp = tl::to_string (macro_dir.path ());
std::pair<std::string, std::string> cp (macro_categories () [c].first, mp);
tech_macro_paths.insert (cp);
std::string &tn = tech_names_by_path [cp];
if (! tn.empty ()) {
tn += ",";
}
tn += t->name ();
}
}
}
}
// delete macro collections which are no longer required or update description
std::vector<lay::MacroCollection *> folders_to_delete;
std::string desc_prefix = tl::to_string (QObject::tr ("Technology")) + " - ";
lay::MacroCollection *root = &lay::MacroCollection::root ();
for (lay::MacroCollection::child_iterator m = root->begin_children (); m != root->end_children (); ++m) {
std::pair<std::string, std::string> cp (m->second->category (), m->second->path ());
if (m->second->virtual_mode () == lay::MacroCollection::TechFolder && m_tech_macro_paths.find (cp) != m_tech_macro_paths.end ()) {
if (tech_macro_paths.find (cp) == tech_macro_paths.end ()) {
// no longer used
folders_to_delete.push_back (m->second);
} else {
// used: update description if required
std::string desc = desc_prefix + tech_names_by_path [cp];
m->second->set_description (desc);
}
}
}
for (std::vector<lay::MacroCollection *>::iterator m = folders_to_delete.begin (); m != folders_to_delete.end (); ++m) {
if (tl::verbosity () >= 20) {
tl::info << "Removing macro folder " << (*m)->path () << ", category '" << (*m)->category () << "' because no longer in use";
}
root->erase (*m);
}
// store new paths
m_tech_macro_paths = tech_macro_paths;
// add new folders
for (lay::MacroCollection::child_iterator m = root->begin_children (); m != root->end_children (); ++m) {
if (m->second->virtual_mode () == lay::MacroCollection::TechFolder) {
std::pair<std::string, std::string> cp (m->second->category (), m->second->path ());
tech_macro_paths.erase (cp);
}
}
std::vector<lay::MacroCollection *> new_folders;
for (std::set<std::pair<std::string, std::string> >::const_iterator p = tech_macro_paths.begin (); p != tech_macro_paths.end (); ++p) {
const std::string &tn = tech_names_by_path [*p];
// TODO: is it wise to make it writeable?
if (tl::verbosity () >= 20) {
tl::info << "Adding macro folder " << p->second << ", category '" << p->first << "' for technologies " << tn;
}
// Add the folder. Note: it may happen that a macro folder for the tech specific macros already exists in
// a non-tech context.
// In that case, the add_folder method will return 0.
lay::MacroCollection *mc = lay::MacroCollection::root ().add_folder (desc_prefix + tn, p->second, p->first, false);
if (mc) {
mc->set_virtual_mode (lay::MacroCollection::TechFolder);
new_folders.push_back (mc);
}
}
if (check_autorun) {
bool has_autorun = false;
for (std::vector<lay::MacroCollection *>::const_iterator m = new_folders.begin (); m != new_folders.end () && ! has_autorun; ++m) {
has_autorun = (*m)->has_autorun ();
}
if (has_autorun && QMessageBox::question (mp_mw, QObject::tr ("Run Macros"), QObject::tr ("Some macros associated with new items are configured to run automatically.\n\nChoose 'Yes' to run these macros now. Choose 'No' to not run them."), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
for (std::vector<lay::MacroCollection *>::const_iterator m = new_folders.begin (); m != new_folders.end (); ++m) {
(*m)->autorun ();
}
}
}
}
void
MacroController::refresh ()
{
@ -369,6 +501,14 @@ MacroController::add_macro_items_to_menu (lay::MacroCollection &collection, int
}
}
void
MacroController::technologies_edited ()
{
sync_implicit_macros (true);
refresh ();
update_menu_with_macros ();
}
void
MacroController::update_menu_with_macros ()
{

View File

@ -103,6 +103,14 @@ public:
*/
virtual void drop_url (const std::string &path_or_url);
/**
* @brief Enables or disables implicit macros
* If implicit macros are enabled, the macro tree contains the macros defined within the technologies
* and other implicit sources.
* This flag needs to be set initially and before the technology tree is updated.
*/
void enable_implicit_macros (bool enable);
/**
* @brief Shows the macro editor
*
@ -159,16 +167,24 @@ public slots:
*/
void update_menu_with_macros ();
/**
* @brief Called when the technologies got changed
*/
void technologies_edited ();
private:
lay::MacroEditorDialog *mp_macro_editor;
lay::MainWindow *mp_mw;
bool m_no_implicit_macros;
tl::DeferredMethod<MacroController> dm_do_update_menu_with_macros;
std::vector<lay::Action> m_macro_actions;
std::map<QAction *, lay::Macro *> m_action_to_macro;
lay::MacroCollection m_temp_macros;
std::vector< std::pair<std::string, std::pair<std::string, std::pair<std::string, bool> > > > m_paths;
std::vector< std::pair<std::string, std::string> > m_macro_categories;
std::set<std::pair<std::string, std::string> > m_tech_macro_paths;
void sync_implicit_macros (bool check_autorun);
void add_macro_items_to_menu (lay::MacroCollection &collection, int &n, std::set<std::string> &groups, const lay::Technology *tech, std::vector<std::pair<std::string, std::string> > *key_bindings);
void do_update_menu_with_macros ();
};

View File

@ -263,6 +263,7 @@ MacroEditorDialog::MacroEditorDialog (QWidget * /*parent*/, lay::MacroCollection
connect (mp_root, SIGNAL (macro_changed (Macro *)), this, SLOT (macro_changed (Macro *)));
connect (mp_root, SIGNAL (macro_deleted (Macro *)), this, SLOT (macro_deleted (Macro *)));
connect (mp_root, SIGNAL (macro_collection_deleted (MacroCollection *)), this, SLOT (macro_collection_deleted (MacroCollection *)));
m_categories = lay::MacroController::instance ()->macro_categories ();
@ -1534,6 +1535,35 @@ MacroEditorDialog::commit ()
}
}
void
MacroEditorDialog::macro_collection_deleted (lay::MacroCollection *collection)
{
// close the tab pages related to the collection we want to delete
std::set <lay::Macro *> used_macros;
std::set <lay::MacroCollection *> used_collections;
collection->collect_used_nodes (used_macros, used_collections);
for (std::set <lay::Macro *>::iterator mc = used_macros.begin (); mc != used_macros.end (); ++mc) {
if (mp_run_macro == *mc) {
mp_run_macro = 0;
}
std::map <Macro *, MacroEditorPage *>::iterator p = m_tab_widgets.find (*mc);
if (p != m_tab_widgets.end ()) {
p->second->connect_macro (0);
tabWidget->blockSignals (true); // blockSignals prevents a reentrant call into set_current of the tree
tabWidget->removeTab (tabWidget->indexOf (p->second));
tabWidget->blockSignals (false);
delete p->second;
m_tab_widgets.erase (p);
}
}
refresh_file_watcher ();
}
void
MacroEditorDialog::macro_deleted (lay::Macro *macro)
{
@ -2594,30 +2624,13 @@ BEGIN_PROTECTED
throw tl::Exception (tl::to_string (QObject::tr ("Unable to remove that location")));
}
// close the tab pages related to the collection we want to delete
std::set <lay::Macro *> used_macros;
std::set <lay::MacroCollection *> used_collections;
collection->collect_used_nodes (used_macros, used_collections);
for (std::set <lay::Macro *>::iterator mc = used_macros.begin (); mc != used_macros.end (); ++mc) {
std::map <Macro *, MacroEditorPage *>::iterator p = m_tab_widgets.find (*mc);
if (p != m_tab_widgets.end ()) {
p->second->connect_macro (0);
delete p->second;
m_tab_widgets.erase (p);
}
}
// actually remove the collection
// actually remove the collection (update is done through the
// macro_collection_deleted signal handler).
mp_root->erase (collection);
// save the new paths
set_custom_paths (paths);
refresh_file_watcher ();
END_PROTECTED
}

View File

@ -192,6 +192,7 @@ private slots:
void help_requested (const QString &s);
void macro_changed (Macro *macro);
void macro_deleted (Macro *macro);
void macro_collection_deleted (MacroCollection *collection);
void add_watch ();
void edit_watch ();
void del_watches ();

View File

@ -542,7 +542,7 @@ TechSetupDialog::refresh_clicked ()
{
BEGIN_PROTECTED
lay::TechnologyController::instance ()->refresh (m_technologies);
lay::TechnologyController::instance ()->rescan (m_technologies);
update ();
END_PROTECTED

View File

@ -24,7 +24,6 @@
#include "layTechnologyController.h"
#include "layTechSetupDialog.h"
#include "layMainWindow.h"
#include "layMacroController.h"
#include "layApplication.h"
#include "layConfig.h"
#include "laybasicConfig.h"
@ -47,18 +46,12 @@ std::string tech_string_from_name (const std::string &tn)
}
TechnologyController::TechnologyController ()
: PluginDeclaration (), mp_editor (0), mp_mw (0), m_no_macros (false), mp_active_technology (0)
: PluginDeclaration (), mp_editor (0), mp_mw (0), mp_active_technology (0)
{
m_current_technology_updated = false;
m_technologies_configured = false;
}
void
TechnologyController::enable_macros (bool enable)
{
m_no_macros = !enable;
}
TechnologyController *
TechnologyController::instance ()
{
@ -80,8 +73,6 @@ TechnologyController::initialize (lay::PluginRoot * /*root*/)
void
TechnologyController::initialized (lay::PluginRoot *root)
{
sync_tech_macro_locations ();
mp_mw = dynamic_cast <lay::MainWindow *> (root);
if (mp_mw) {
mp_editor = new lay::TechSetupDialog (mp_mw);
@ -223,16 +214,13 @@ TechnologyController::configure (const std::string &name, const std::string &val
if (! value.empty ()) {
// sync the non-persisted technologies with the configuration
lay::Technologies::instance ()->begin_updates ();
try {
lay::Technologies::instance ()->load_from_xml (value);
lay::Technologies new_tech = *lay::Technologies::instance ();
new_tech.load_from_xml (value);
replace_technologies (new_tech);
m_technologies_configured = true;
} catch (...) {
}
lay::Technologies::instance ()->end_updates_no_event ();
// explicitly handle changes -> no recursion
m_technologies_configured = true;
}
@ -351,6 +339,24 @@ TechnologyController::update_menu ()
update_active_technology ();
}
void
TechnologyController::replace_technologies (const lay::Technologies &technologies)
{
bool has_active_tech = (mp_active_technology != 0);
std::string active_tech_name;
if (mp_active_technology) {
active_tech_name = mp_active_technology->name ();
}
lay::Technologies ().instance ()->begin_updates ();
*lay::Technologies ().instance () = technologies;
lay::Technologies ().instance ()->end_updates_no_event ();
if (has_active_tech) {
mp_active_technology = lay::Technologies::instance ()->technology_by_name (active_tech_name);
}
}
void
TechnologyController::show_editor ()
{
@ -374,9 +380,7 @@ TechnologyController::show_editor ()
}
}
lay::Technologies ().instance ()->begin_updates ();
*lay::Technologies ().instance () = new_tech;
lay::Technologies ().instance ()->end_updates_no_event ();
replace_technologies (new_tech);
// save the technologies that need to be saved
// TODO: save only the ones that really need saving
@ -424,19 +428,6 @@ TechnologyController::show_editor ()
QMessageBox::Ok);
}
std::vector<lay::MacroCollection *> nm = sync_tech_macro_locations ();
bool has_autorun = false;
for (std::vector<lay::MacroCollection *>::const_iterator m = nm.begin (); m != nm.end () && ! has_autorun; ++m) {
has_autorun = (*m)->has_autorun ();
}
if (has_autorun && QMessageBox::question (mp_mw, QObject::tr ("Run Macros"), QObject::tr ("Some macros associated with technologies now are configured to run automatically.\n\nChoose 'Yes' to run these macros now. Choose 'No' to not run them."), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
for (std::vector<lay::MacroCollection *>::const_iterator m = nm.begin (); m != nm.end (); ++m) {
(*m)->autorun ();
}
}
update_menu ();
emit technologies_edited ();
@ -451,25 +442,13 @@ TechnologyController::default_root ()
}
void
TechnologyController::refresh ()
TechnologyController::load ()
{
try {
lay::Technologies::instance ()->begin_updates ();
refresh (*lay::Technologies::instance ());
lay::Technologies::instance ()->end_updates_no_event ();
update_menu ();
emit technologies_edited ();
} catch (...) {
lay::Technologies::instance ()->end_updates_no_event ();
throw;
}
rescan (*lay::Technologies::instance ());
}
void
TechnologyController::refresh (lay::Technologies &technologies)
TechnologyController::rescan (lay::Technologies &technologies)
{
lay::Technologies current = technologies;
@ -545,119 +524,6 @@ TechnologyController::add_path (const std::string &p)
m_paths.push_back (p);
}
std::vector<lay::MacroCollection *>
TechnologyController::sync_tech_macro_locations ()
{
lay::MacroController *mc = lay::MacroController::instance ();
if (! mc || m_no_macros) {
return std::vector<lay::MacroCollection *> ();
}
std::set<std::pair<std::string, std::string> > tech_macro_paths;
std::map<std::pair<std::string, std::string>, std::string> tech_names_by_path;
// Add additional places where the technologies define some macros
for (lay::Technologies::const_iterator t = lay::Technologies::instance ()->begin (); t != lay::Technologies::instance ()->end (); ++t) {
if (t->base_path ().empty ()) {
continue;
}
for (size_t c = 0; c < mc->macro_categories ().size (); ++c) {
QDir base_dir (tl::to_qstring (t->base_path ()));
if (base_dir.exists ()) {
QDir macro_dir (base_dir.filePath (tl::to_qstring (mc->macro_categories () [c].first)));
if (macro_dir.exists ()) {
std::string mp = tl::to_string (macro_dir.path ());
std::pair<std::string, std::string> cp (mc->macro_categories () [c].first, mp);
tech_macro_paths.insert (cp);
std::string &tn = tech_names_by_path [cp];
if (! tn.empty ()) {
tn += ",";
}
tn += t->name ();
}
}
}
}
// delete macro collections which are no longer required or update description
std::vector<lay::MacroCollection *> folders_to_delete;
std::string desc_prefix = tl::to_string (QObject::tr ("Technology")) + " - ";
lay::MacroCollection *root = &lay::MacroCollection::root ();
for (lay::MacroCollection::child_iterator m = root->begin_children (); m != root->end_children (); ++m) {
std::pair<std::string, std::string> cp (m->second->category (), m->second->path ());
if (m->second->virtual_mode () == lay::MacroCollection::TechFolder && m_tech_macro_paths.find (cp) != m_tech_macro_paths.end ()) {
if (tech_macro_paths.find (cp) == tech_macro_paths.end ()) {
// no longer used
folders_to_delete.push_back (m->second);
} else {
// used: update description if required
std::string desc = desc_prefix + tech_names_by_path [cp];
m->second->set_description (desc);
}
}
}
for (std::vector<lay::MacroCollection *>::iterator m = folders_to_delete.begin (); m != folders_to_delete.end (); ++m) {
if (tl::verbosity () >= 20) {
tl::info << "Removing macro folder " << (*m)->path () << ", category '" << (*m)->category () << "' because no longer in use";
}
root->erase (*m);
}
// store new paths
m_tech_macro_paths = tech_macro_paths;
// add new folders
for (lay::MacroCollection::child_iterator m = root->begin_children (); m != root->end_children (); ++m) {
if (m->second->virtual_mode () == lay::MacroCollection::TechFolder) {
std::pair<std::string, std::string> cp (m->second->category (), m->second->path ());
tech_macro_paths.erase (cp);
}
}
std::vector<lay::MacroCollection *> new_folders;
for (std::set<std::pair<std::string, std::string> >::const_iterator p = tech_macro_paths.begin (); p != tech_macro_paths.end (); ++p) {
const std::string &tn = tech_names_by_path [*p];
// TODO: is it wise to make it writeable?
if (tl::verbosity () >= 20) {
tl::info << "Adding macro folder " << p->second << ", category '" << p->first << "' for technologies " << tn;
}
// Add the folder. Note: it may happen that a macro folder for the tech specific macros already exists in
// a non-tech context.
// In that case, the add_folder method will return 0.
lay::MacroCollection *mc = lay::MacroCollection::root ().add_folder (desc_prefix + tn, p->second, p->first, false);
if (mc) {
mc->set_virtual_mode (lay::MacroCollection::TechFolder);
new_folders.push_back (mc);
}
}
return new_folders;
}
static tl::RegisteredClass<lay::PluginDeclaration> config_decl (new TechnologyController (), 110, "TechnologyController");
}

View File

@ -70,16 +70,9 @@ public:
*/
lay::Technology *active_technology () const;
/**
* @brief Enables or disables macros
* If macros are enabled, the macro tree contains the macros defined within the technologies.
* This flag needs to be set initially and before the technology tree is updated.
*/
void enable_macros (bool enable);
/**
* @brief Adds a path as a search path for technologies
* "refresh" needs to be called after search paths have been added.
* "load" needs to be called after search paths have been added.
*/
void add_path (const std::string &path);
@ -87,19 +80,19 @@ public:
* @brief Adds a temporary technology
* Temporary technologies are additional technologies which are added to the list of technologies
* but are not persisted or editable.
* "refresh" needs to be called after temp technologies have been added.
* "load" needs to be called after temp technologies have been added.
*/
void add_temp_tech (const lay::Technology &t);
/**
* @brief Updates the given technology collection with the technologies from the search path and teh temp technologies
* @brief Updates the given technology collection with the technologies from the search path and the temp technologies
*/
void refresh (lay::Technologies &technologies);
void rescan (lay::Technologies &technologies);
/**
* @brief Refreshes the global list of technologies
* @brief Loads the global list of technologies
*/
void refresh ();
void load ();
/**
* @brief Gets the default root folder
@ -133,10 +126,8 @@ private:
bool m_technologies_configured;
lay::TechSetupDialog *mp_editor;
lay::MainWindow *mp_mw;
bool m_no_macros;
std::vector<std::string> m_paths;
std::vector<lay::Technology> m_temp_tech;
std::set<std::pair<std::string, std::string> > m_tech_macro_paths;
lay::Technology *mp_active_technology;
void update_active_technology ();
@ -148,7 +139,7 @@ private:
bool menu_activated (const std::string &symbol) const;
void update_current_technology ();
void update_menu ();
std::vector<lay::MacroCollection *> sync_tech_macro_locations ();
void replace_technologies (const lay::Technologies &technologies);
};
}