mirror of https://github.com/KLayout/klayout.git
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:
parent
430d140016
commit
6b6b45714f
|
|
@ -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 ();
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1083,7 +1083,7 @@ void MacroCollection::on_macro_changed (Macro *macro)
|
|||
}
|
||||
}
|
||||
|
||||
void MacroCollection::collect_used_nodes(std::set <Macro *> ¯os, std::set <MacroCollection *> ¯o_collections)
|
||||
void MacroCollection::collect_used_nodes (std::set <Macro *> ¯os, std::set <MacroCollection *> ¯o_collections)
|
||||
{
|
||||
for (MacroCollection::child_iterator c = begin_children (); c != end_children (); ++c) {
|
||||
macro_collections.insert (c->second);
|
||||
|
|
|
|||
|
|
@ -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 ()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
|
|
|
|||
|
|
@ -542,7 +542,7 @@ TechSetupDialog::refresh_clicked ()
|
|||
{
|
||||
BEGIN_PROTECTED
|
||||
|
||||
lay::TechnologyController::instance ()->refresh (m_technologies);
|
||||
lay::TechnologyController::instance ()->rescan (m_technologies);
|
||||
update ();
|
||||
|
||||
END_PROTECTED
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue