Macro editor now acts on more file changes

- Adding/removing folders to packages now will
  make them appear/disappear automatically in the macro
  editor.
- Adding and removing files from folders will make
  them appear/disappear in the macro tree.
This commit is contained in:
Matthias Koefferlein 2017-04-18 01:07:10 +02:00
parent b3abb276a4
commit 4460819a6c
8 changed files with 321 additions and 178 deletions

View File

@ -1173,7 +1173,7 @@ MacroCollection::make_readonly (bool f)
}
MacroCollection *
MacroCollection::add_folder (const std::string &description, const std::string &path, const std::string &cat, bool readonly)
MacroCollection::add_folder (const std::string &description, const std::string &path, const std::string &cat, bool readonly, bool force_create)
{
if (! path.empty () && path[0] == ':') {
readonly = true;
@ -1183,15 +1183,25 @@ MacroCollection::add_folder (const std::string &description, const std::string &
if (! file_info.exists ()) {
// Try to create the folder since it does not exist yet
if (tl::verbosity () >= 20) {
tl::log << "Folder does not exist yet - trying to create it: " << path;
}
if (! QDir::root ().mkpath (file_info.absoluteFilePath ())) {
if (tl::verbosity () >= 10) {
tl::error << "Unable to create folder path: " << path;
// Try to create the folder since it does not exist yet or skip that one
if (! force_create) {
if (tl::verbosity () >= 20) {
tl::log << "Folder does not exist - skipping: " << path;
}
return 0;
} else {
if (tl::verbosity () >= 20) {
tl::log << "Folder does not exist yet - trying to create it: " << path;
}
if (! QDir::root ().mkpath (file_info.absoluteFilePath ())) {
if (tl::verbosity () >= 10) {
tl::error << "Unable to create folder path: " << path;
}
return 0;
}
}
file_info.refresh ();
@ -1666,6 +1676,91 @@ MacroCollection &MacroCollection::root ()
return ms_root;
}
static bool sync_macros (lay::MacroCollection *current, lay::MacroCollection *actual)
{
bool ret = false;
if (actual) {
current->make_readonly (actual->is_readonly ());
}
std::vector<lay::MacroCollection *> folders_to_delete;
for (lay::MacroCollection::child_iterator m = current->begin_children (); m != current->end_children (); ++m) {
lay::MacroCollection *cm = actual ? actual->folder_by_name (m->first) : 0;
if (! cm) {
folders_to_delete.push_back (m->second);
}
}
if (actual) {
for (lay::MacroCollection::child_iterator m = actual->begin_children (); m != actual->end_children (); ++m) {
lay::MacroCollection *cm = current->folder_by_name (m->first);
if (! cm) {
cm = current->create_folder (m->first.c_str (), false);
ret = true;
}
if (sync_macros(cm, m->second)) {
ret = true;
}
}
}
// delete folders which do no longer exist
for (std::vector<lay::MacroCollection *>::iterator m = folders_to_delete.begin (); m != folders_to_delete.end (); ++m) {
ret = true;
sync_macros (*m, 0);
current->erase (*m);
}
std::vector<lay::Macro *> macros_to_delete;
for (lay::MacroCollection::iterator m = current->begin (); m != current->end (); ++m) {
lay::Macro *cm = actual ? actual->macro_by_name (m->first, m->second->format ()) : 0;
if (! cm) {
macros_to_delete.push_back (m->second);
}
}
if (actual) {
for (lay::MacroCollection::iterator m = actual->begin (); m != actual->end (); ++m) {
lay::Macro *cm = current->macro_by_name (m->first, m->second->format ());
if (cm) {
if (*cm != *m->second) {
cm->assign (*m->second);
}
cm->set_readonly (m->second->is_readonly ());
} else {
cm = current->create (m->first.c_str (), m->second->format ());
cm->assign (*m->second);
cm->set_readonly (m->second->is_readonly ());
ret = true;
}
}
}
// erase macros from collection which are no longer used
for (std::vector<lay::Macro *>::const_iterator m = macros_to_delete.begin (); m != macros_to_delete.end (); ++m) {
current->erase (*m);
ret = true;
}
return ret;
}
void MacroCollection::reload ()
{
// create a new collection and synchronize
lay::MacroCollection new_collection;
for (lay::MacroCollection::child_iterator c = begin_children (); c != end_children (); ++c) {
new_collection.add_folder (c->second->description (), c->second->path (), c->second->category (), c->second->is_readonly (), false /* don't force to create */);
}
// and synchronize current with the actual one
sync_macros (this, &new_collection);
}
static bool has_autorun_for (const lay::MacroCollection &collection, bool early)
{
for (lay::MacroCollection::const_child_iterator c = collection.begin_children (); c != collection.end_children (); ++c) {

View File

@ -666,8 +666,11 @@ public:
* @brief Add a folder (will also scan the folder)
*
* @return A pointer to the new collection if successful
*
* If force_create is true (the default), the folder will be created if it does not
* exist yet. On error, 0 is returned.
*/
MacroCollection *add_folder (const std::string &description, const std::string &path, const std::string &category, bool readonly);
MacroCollection *add_folder (const std::string &description, const std::string &path, const std::string &category, bool readonly, bool force_create = true);
/**
* @brief Gets the category tag of the collection
@ -998,6 +1001,13 @@ public:
*/
void rescan ();
/**
* @brief Reloads the macro collection
*
* This method is similar to rescan, but it will also remove folders and macros.
*/
void reload ();
/**
* @brief Gets the root of the macro hierarchy corresponding to the configuration space
*/

View File

@ -38,11 +38,13 @@ namespace lay
{
MacroController::MacroController ()
: 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)
: mp_macro_editor (0), mp_mw (0), m_no_implicit_macros (false), m_file_watcher (0),
dm_do_update_menu_with_macros (this, &MacroController::do_update_menu_with_macros),
dm_sync_file_watcher (this, &MacroController::sync_file_watcher),
dm_sync_files (this, &MacroController::sync_files)
{
connect (&m_temp_macros, SIGNAL (menu_needs_update ()), this, SLOT (update_menu_with_macros ()));
connect (&m_temp_macros, SIGNAL (macro_collection_changed (MacroCollection *)), this, SLOT (update_menu_with_macros ()));
connect (&m_temp_macros, SIGNAL (menu_needs_update ()), this, SLOT (macro_collection_changed ()));
connect (&m_temp_macros, SIGNAL (macro_collection_changed (MacroCollection *)), this, SLOT (macro_collection_changed ()));
}
void
@ -70,8 +72,6 @@ MacroController::load ()
}
}
sync_implicit_macros (false);
}
void
@ -83,32 +83,48 @@ MacroController::initialized (lay::PluginRoot *root)
mp_macro_editor->setModal (false);
}
connect (&lay::MacroCollection::root (), SIGNAL (menu_needs_update ()), this, SLOT (update_menu_with_macros ()));
connect (&lay::MacroCollection::root (), SIGNAL (macro_collection_changed (MacroCollection *)), this, SLOT (update_menu_with_macros ()));
if (! m_file_watcher) {
m_file_watcher = new tl::FileSystemWatcher (this);
connect (m_file_watcher, SIGNAL (fileChanged (const QString &)), this, SLOT (file_watcher_triggered ()));
connect (m_file_watcher, SIGNAL (fileRemoved (const QString &)), this, SLOT (file_watcher_triggered ()));
}
connect (&lay::MacroCollection::root (), SIGNAL (menu_needs_update ()), this, SLOT (macro_collection_changed ()));
connect (&lay::MacroCollection::root (), SIGNAL (macro_collection_changed (MacroCollection *)), this, SLOT (macro_collection_changed ()));
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 (technologies_edited ()));
connect (lay::TechnologyController::instance (), SIGNAL (active_technology_changed ()), this, SLOT (macro_collection_changed ()));
connect (lay::TechnologyController::instance (), SIGNAL (technologies_edited ()), this, SLOT (sync_with_external_sources ()));
}
if (lay::SaltController::instance ()) {
connect (lay::SaltController::instance (), SIGNAL (salt_changed ()), this, SLOT (salt_changed ()));
connect (lay::SaltController::instance (), SIGNAL (salt_changed ()), this, SLOT (sync_with_external_sources ()));
}
// synchronize the macro collection with all external sources
sync_implicit_macros (false);
// update the menus with the macro menu bindings as late as possible (now we
// can be sure that the menus are created propertly)
do_update_menu_with_macros ();
macro_collection_changed ();
}
void
MacroController::uninitialize (lay::PluginRoot * /*root*/)
{
disconnect (&lay::MacroCollection::root (), SIGNAL (menu_needs_update ()), this, SLOT (update_menu_with_macros ()));
disconnect (&lay::MacroCollection::root (), SIGNAL (macro_collection_changed (MacroCollection *)), this, SLOT (update_menu_with_macros ()));
disconnect (&lay::MacroCollection::root (), SIGNAL (menu_needs_update ()), this, SLOT (macro_collection_changed ()));
disconnect (&lay::MacroCollection::root (), SIGNAL (macro_collection_changed (MacroCollection *)), this, SLOT (macro_collection_changed ()));
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 (technologies_edited ()));
disconnect (lay::TechnologyController::instance (), SIGNAL (active_technology_changed ()), this, SLOT (macro_collection_changed ()));
disconnect (lay::TechnologyController::instance (), SIGNAL (technologies_edited ()), this, SLOT (sync_with_external_sources ()));
}
if (lay::SaltController::instance ()) {
disconnect (lay::SaltController::instance (), SIGNAL (salt_changed ()), this, SLOT (salt_changed ()));
disconnect (lay::SaltController::instance (), SIGNAL (salt_changed ()), this, SLOT (sync_with_external_sources ()));
}
if (m_file_watcher) {
disconnect (m_file_watcher, SIGNAL (fileChanged (const QString &)), this, SLOT (file_watcher_triggered ()));
disconnect (m_file_watcher, SIGNAL (fileRemoved (const QString &)), this, SLOT (file_watcher_triggered ()));
delete m_file_watcher;
m_file_watcher = 0;
}
delete mp_macro_editor;
@ -238,9 +254,6 @@ MacroController::drop_url (const std::string &path_or_url)
macro->save ();
// refresh macro editor to show new macro plus to install the menus
refresh ();
}
} else {
@ -350,10 +363,16 @@ MacroController::sync_implicit_macros (bool check_autorun)
std::vector<lay::MacroCollection *> folders_to_delete;
// determine the paths that will be in use
std::map<std::string, const ExternalPathDescriptor *> new_folders_by_path;
for (std::vector<ExternalPathDescriptor>::const_iterator p = external_paths.begin (); p != external_paths.end (); ++p) {
new_folders_by_path.insert (std::make_pair (p->path, p.operator-> ()));
}
// determine the paths currently in use
std::map<std::string, const ExternalPathDescriptor *> used_folders_by_path;
std::map<std::string, const ExternalPathDescriptor *> prev_folders_by_path;
for (std::vector<ExternalPathDescriptor>::const_iterator p = m_external_paths.begin (); p != m_external_paths.end (); ++p) {
used_folders_by_path.insert (std::make_pair (p->path, p.operator-> ()));
prev_folders_by_path.insert (std::make_pair (p->path, p.operator-> ()));
}
lay::MacroCollection *root = &lay::MacroCollection::root ();
@ -361,8 +380,8 @@ MacroController::sync_implicit_macros (bool check_autorun)
for (lay::MacroCollection::child_iterator m = root->begin_children (); m != root->end_children (); ++m) {
if (m->second->virtual_mode () == lay::MacroCollection::TechFolder ||
m->second->virtual_mode () == lay::MacroCollection::SaltFolder) {
std::map<std::string, const ExternalPathDescriptor *>::const_iterator u = used_folders_by_path.find (m->second->path ());
if (u == used_folders_by_path.end ()) {
std::map<std::string, const ExternalPathDescriptor *>::const_iterator u = new_folders_by_path.find (m->second->path ());
if (u == new_folders_by_path.end ()) {
// no longer used
folders_to_delete.push_back (m->second);
} else {
@ -387,7 +406,7 @@ MacroController::sync_implicit_macros (bool check_autorun)
for (std::vector<ExternalPathDescriptor>::const_iterator p = m_external_paths.begin (); p != m_external_paths.end (); ++p) {
if (used_folders_by_path.find (p->path) != used_folders_by_path.end ()) {
if (prev_folders_by_path.find (p->path) != prev_folders_by_path.end ()) {
continue;
}
@ -424,14 +443,6 @@ MacroController::sync_implicit_macros (bool check_autorun)
}
}
void
MacroController::refresh ()
{
if (mp_macro_editor) {
mp_macro_editor->refresh ();
}
}
void
MacroController::add_path (const std::string &path, const std::string &description, const std::string &category, bool readonly)
{
@ -530,27 +541,22 @@ MacroController::add_macro_items_to_menu (lay::MacroCollection &collection, int
}
void
MacroController::salt_changed ()
MacroController::sync_with_external_sources ()
{
sync_implicit_macros (true);
refresh ();
update_menu_with_macros ();
try {
sync_implicit_macros (true);
} catch (tl::Exception &ex) {
tl::error << ex.msg ();
}
}
void
MacroController::technologies_edited ()
{
sync_implicit_macros (true);
refresh ();
update_menu_with_macros ();
}
void
MacroController::update_menu_with_macros ()
MacroController::macro_collection_changed ()
{
// empty action to macro table now we know it's invalid
m_action_to_macro.clear ();
dm_do_update_menu_with_macros ();
dm_sync_file_watcher ();
}
void
@ -597,6 +603,39 @@ MacroController::do_update_menu_with_macros ()
}
}
void
MacroController::file_watcher_triggered ()
{
dm_sync_files ();
}
static void
add_collections_to_file_watcher (const lay::MacroCollection &collection, tl::FileSystemWatcher *watcher)
{
for (lay::MacroCollection::const_child_iterator c = collection.begin_children (); c != collection.end_children (); ++c) {
if (! c->second->path ().empty () && c->second->path ()[0] != ':') {
watcher->add_file (c->second->path ());
add_collections_to_file_watcher (*c->second, watcher);
}
}
}
void
MacroController::sync_file_watcher ()
{
m_file_watcher->clear ();
m_file_watcher->enable (false);
add_collections_to_file_watcher (lay::MacroCollection::root (), m_file_watcher);
m_file_watcher->enable (true);
}
void
MacroController::sync_files ()
{
tl::log << tl::to_string (tr ("Detected file system change in macro folders - updating"));
lay::MacroCollection::root ().reload ();
}
MacroController *
MacroController::instance ()
{

View File

@ -29,6 +29,7 @@
#include "layMacro.h"
#include "tlObject.h"
#include "tlDeferredExecution.h"
#include "tlFileSystemWatcher.h"
#include <string>
#include <map>
@ -120,11 +121,6 @@ public:
*/
void show_editor (const std::string &cat = std::string (), bool force_add = false);
/**
* @brief Reloads all macros from the paths registered
*/
void refresh ();
/**
* @brief Adds a search path to the macros
* After adding the paths, "load" needs to be called to actually load the macros.
@ -163,19 +159,20 @@ public:
public slots:
/**
* @brief Update the menu with macros bound to a menu
* @brief Updates the menu with macros bound to a menu
*/
void update_menu_with_macros ();
void macro_collection_changed ();
/**
* @brief Called when the technologies got changed
* @brief Called when the technologies or the salt got changed
*/
void technologies_edited ();
void sync_with_external_sources ();
private slots:
/**
* @brief Called when the salt (packages) got changed
* @brief Called when the file watcher detects a change in the file system
*/
void salt_changed ();
void file_watcher_triggered ();
private:
/**
@ -215,17 +212,22 @@ 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::string> > m_macro_categories;
std::vector<InternalPathDescriptor> m_internal_paths;
std::vector<ExternalPathDescriptor> m_external_paths;
tl::FileSystemWatcher *m_file_watcher;
tl::DeferredMethod<MacroController> dm_do_update_menu_with_macros;
tl::DeferredMethod<MacroController> dm_sync_file_watcher;
tl::DeferredMethod<MacroController> dm_sync_files;
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 ();
void sync_file_watcher ();
void sync_files ();
};
}

View File

@ -253,7 +253,8 @@ MacroEditorDialog::MacroEditorDialog (QWidget * /*parent*/, lay::MacroCollection
m_font_size (0),
m_edit_trace_index (-1),
m_add_edit_trace_enabled (true),
dm_refresh_file_watcher (this, &MacroEditorDialog::do_refresh_file_watcher)
dm_refresh_file_watcher (this, &MacroEditorDialog::do_refresh_file_watcher),
dm_update_ui_to_run_mode (this, &MacroEditorDialog::do_update_ui_to_run_mode)
{
// Makes this dialog receive events while progress bars are on - this way we can set breakpoints
// during execution of a macro even if anything lengthy is running.
@ -264,6 +265,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 *)));
connect (mp_root, SIGNAL (macro_collection_changed (MacroCollection *)), this, SLOT (macro_collection_changed (MacroCollection *)));
m_categories = lay::MacroController::instance ()->macro_categories ();
@ -391,7 +393,6 @@ MacroEditorDialog::MacroEditorDialog (QWidget * /*parent*/, lay::MacroCollection
watchList->addAction (actionDeleteWatches);
watchList->addAction (actionClearWatches);
connect (actionAddWatch, SIGNAL (triggered ()), this, SLOT (add_watch ()));
connect (actionAddWatch, SIGNAL (triggered ()), this, SLOT (add_watch ()));
connect (actionEditWatch, SIGNAL (triggered ()), this, SLOT (edit_watch ()));
connect (actionDeleteWatches, SIGNAL (triggered ()), this, SLOT (del_watches ()));
@ -1025,7 +1026,7 @@ MacroEditorDialog::add_edit_trace (bool compress)
}
MacroEditorPage *page = dynamic_cast<MacroEditorPage *> (tabWidget->currentWidget ());
if (! page) {
if (! page || ! page->macro ()) {
return;
}
@ -1551,17 +1552,16 @@ MacroEditorDialog::macro_collection_deleted (lay::MacroCollection *collection)
std::map <Macro *, MacroEditorPage *>::iterator p = m_tab_widgets.find (*mc);
if (p != m_tab_widgets.end ()) {
// disable the macro on the page - we'll ask for updates when the file
// watcher becomes active. So long, the macro is "zombie".
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 ();
update_ui_to_run_mode ();
}
void
@ -1573,15 +1573,20 @@ MacroEditorDialog::macro_deleted (lay::Macro *macro)
std::map <Macro *, MacroEditorPage *>::iterator page = m_tab_widgets.find (macro);
if (page != m_tab_widgets.end ()) {
// disable the macro on the page - we'll ask for updates when the file
// watcher becomes active. So long, the macro is "zombie".
page->second->connect_macro (0);
tabWidget->blockSignals (true); // blockSignals prevents a reentrant call into set_current of the tree
tabWidget->removeTab (tabWidget->indexOf (page->second));
tabWidget->blockSignals (false);
delete page->second;
m_tab_widgets.erase (page);
}
refresh_file_watcher ();
update_ui_to_run_mode ();
}
void
MacroEditorDialog::macro_collection_changed (lay::MacroCollection * /*collection*/)
{
refresh_file_watcher ();
}
void
@ -1624,7 +1629,7 @@ MacroEditorDialog::current_tab_changed (int index)
update_ui_to_run_mode ();
}
lay::Macro *MacroEditorDialog::create_macro_here(const char *prefix)
lay::Macro *MacroEditorDialog::create_macro_here (const char *prefix)
{
lay::MacroEditorTree *mt = current_macro_tree ();
MacroCollection *collection = mt->current_macro_collection ();
@ -1954,11 +1959,14 @@ MacroEditorDialog::setup_button_clicked ()
m_save_all_on_run = data.save_all_on_run;
for (std::map<Macro *, MacroEditorPage *>::const_iterator f = m_tab_widgets.begin (); f != m_tab_widgets.end (); ++f) {
f->second->set_ntab (m_ntab);
f->second->set_nindent (m_nindent);
f->second->apply_attributes ();
f->second->set_font (m_font_family, m_font_size);
for (int i = 0; i < tabWidget->count (); ++i) {
MacroEditorPage *page = dynamic_cast<MacroEditorPage *> (tabWidget->widget (i));
if (page) {
page->set_ntab (m_ntab);
page->set_nindent (m_nindent);
page->apply_attributes ();
page->set_font (m_font_family, m_font_size);
}
}
// write configuration
@ -2090,14 +2098,16 @@ BEGIN_PROTECTED
}
MacroEditorPage *page = dynamic_cast<MacroEditorPage *> (tabWidget->widget (index));
if (! page || ! page->macro ()) {
if (! page) {
delete tabWidget->currentWidget ();
return;
}
std::map <Macro *, MacroEditorPage *>::iterator p = m_tab_widgets.find (page->macro ());
if (p != m_tab_widgets.end ()) {
m_tab_widgets.erase (p);
for (std::map <Macro *, MacroEditorPage *>::iterator p = m_tab_widgets.begin (); p != m_tab_widgets.end (); ++p) {
if (p->second == page) {
m_tab_widgets.erase (p);
break;
}
}
page->connect_macro (0);
@ -2374,7 +2384,7 @@ MacroEditorDialog::file_changed (const QString &path)
{
m_changed_files.push_back (path);
// Wait a little to let more to allow for more reload requests to collect
// Wait a little to allow for more reload requests to collect
m_file_changed_timer->setInterval (300);
m_file_changed_timer->start ();
}
@ -2419,79 +2429,6 @@ MacroEditorDialog::sync_file_watcher (lay::MacroCollection * /*collection*/)
#endif
}
bool
MacroEditorDialog::sync_macros (lay::MacroCollection *current, lay::MacroCollection *actual)
{
bool ret = false;
if (actual) {
current->make_readonly (actual->is_readonly ());
}
std::vector<lay::MacroCollection *> folders_to_delete;
for (lay::MacroCollection::child_iterator m = current->begin_children (); m != current->end_children (); ++m) {
lay::MacroCollection *cm = actual ? actual->folder_by_name (m->first) : 0;
if (! cm) {
folders_to_delete.push_back (m->second);
}
}
if (actual) {
for (lay::MacroCollection::child_iterator m = actual->begin_children (); m != actual->end_children (); ++m) {
lay::MacroCollection *cm = current->folder_by_name (m->first);
if (! cm) {
cm = current->create_folder (m->first.c_str (), false);
ret = true;
}
if (sync_macros(cm, m->second)) {
ret = true;
}
}
}
// delete folders which do no longer exist
for (std::vector<lay::MacroCollection *>::iterator m = folders_to_delete.begin (); m != folders_to_delete.end (); ++m) {
ret = true;
sync_macros (*m, 0);
current->erase (*m);
}
std::vector<lay::Macro *> macros_to_delete;
for (lay::MacroCollection::iterator m = current->begin (); m != current->end (); ++m) {
lay::Macro *cm = actual ? actual->macro_by_name (m->first, m->second->format ()) : 0;
if (! cm) {
macros_to_delete.push_back (m->second);
}
}
if (actual) {
for (lay::MacroCollection::iterator m = actual->begin (); m != actual->end (); ++m) {
lay::Macro *cm = current->macro_by_name (m->first, m->second->format ());
if (cm) {
if (*cm != *m->second) {
cm->assign (*m->second);
}
cm->set_readonly (m->second->is_readonly ());
} else {
cm = current->create (m->first.c_str (), m->second->format ());
cm->assign (*m->second);
cm->set_readonly (m->second->is_readonly ());
ret = true;
}
}
}
// erase macros from collection which are no longer used
for (std::vector<lay::Macro *>::const_iterator m = macros_to_delete.begin (); m != macros_to_delete.end (); ++m) {
current->erase (*m);
ret = true;
}
return ret;
}
void
MacroEditorDialog::refresh_file_watcher ()
{
@ -2519,18 +2456,13 @@ void
MacroEditorDialog::reload_macros ()
{
m_file_watcher->clear ();
lay::MacroCollection new_root;
// create a new root
for (lay::MacroCollection::child_iterator c = mp_root->begin_children (); c != mp_root->end_children (); ++c) {
new_root.add_folder (c->second->description (), c->second->path (), c->second->category (), c->second->is_readonly ());
try {
mp_root->reload ();
refresh_file_watcher ();
} catch (...) {
refresh_file_watcher ();
throw;
}
// and synchronize current with the actual one
sync_macros (mp_root, &new_root);
refresh_file_watcher ();
}
void
@ -3058,18 +2990,26 @@ MacroEditorDialog::leave_breakpoint_mode ()
void
MacroEditorDialog::update_ui_to_run_mode ()
{
dm_update_ui_to_run_mode ();
}
void
MacroEditorDialog::do_update_ui_to_run_mode ()
{
double alpha = 0.95;
MacroEditorPage *page = dynamic_cast<MacroEditorPage *> (tabWidget->currentWidget ());
dbgOn->setEnabled (! m_in_exec);
runButton->setEnabled ((! m_in_exec && (mp_run_macro || (page && page->macro ()->interpreter () != lay::Macro::None))) || m_in_breakpoint);
runThisButton->setEnabled ((! m_in_exec && page && page->macro ()->interpreter () != lay::Macro::None) || m_in_breakpoint);
runButton->setEnabled ((! m_in_exec && (mp_run_macro || (page && page->macro () && page->macro ()->interpreter () != lay::Macro::None))) || m_in_breakpoint);
runThisButton->setEnabled ((! m_in_exec && page && page->macro () && page->macro ()->interpreter () != lay::Macro::None) || m_in_breakpoint);
singleStepButton->setEnabled (! m_in_exec || m_in_breakpoint);
nextStepButton->setEnabled (! m_in_exec || m_in_breakpoint);
stopButton->setEnabled (m_in_exec);
pauseButton->setEnabled (m_in_exec && ! m_in_breakpoint);
breakpointButton->setEnabled (page && page->macro ());
clearBreakpointsButton->setEnabled (page && page->macro ());
for (std::vector<lay::MacroEditorTree *>::const_iterator mt = m_macro_trees.begin (); mt != m_macro_trees.end (); ++mt) {
(*mt)->setEditTriggers (m_in_exec ? QAbstractItemView::NoEditTriggers : QAbstractItemView::SelectedClicked);

View File

@ -193,6 +193,7 @@ private slots:
void macro_changed (Macro *macro);
void macro_deleted (Macro *macro);
void macro_collection_deleted (MacroCollection *collection);
void macro_collection_changed (MacroCollection *collection);
void add_watch ();
void edit_watch ();
void del_watches ();
@ -249,10 +250,10 @@ private:
void run (int stop_stack_depth, lay::Macro *macro);
lay::Macro *current_run_macro ();
void update_ui_to_run_mode ();
void do_update_ui_to_run_mode ();
void set_run_macro (lay::Macro *m);
void apply_search (bool if_needed);
void process_events (QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents);
bool sync_macros (lay::MacroCollection *current, lay::MacroCollection *actual);
void sync_file_watcher (lay::MacroCollection *current);
void do_refresh_file_watcher ();
void refresh_file_watcher ();
@ -310,6 +311,7 @@ private:
QTimer *m_file_changed_timer;
std::vector<QString> m_changed_files, m_removed_files;
tl::DeferredMethod<MacroEditorDialog> dm_refresh_file_watcher;
tl::DeferredMethod<MacroEditorDialog> dm_update_ui_to_run_mode;
};
}

View File

@ -33,14 +33,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)
: mp_salt_dialog (0), mp_mw (0), m_file_watcher (0),
dm_sync_file_watcher (this, &SaltController::sync_file_watcher),
dm_sync_files (this, &SaltController::sync_files)
{
// .. nothing yet ..
}
void
SaltController::initialized (lay::PluginRoot *root)
{
if (! m_file_watcher) {
m_file_watcher = new tl::FileSystemWatcher (this);
connect (m_file_watcher, SIGNAL (fileChanged (const QString &)), this, SLOT (file_watcher_triggered ()));
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 ()));
@ -51,6 +58,13 @@ SaltController::uninitialize (lay::PluginRoot * /*root*/)
{
disconnect (&m_salt, SIGNAL (collections_changed ()), this, SIGNAL (salt_changed ()));
if (m_file_watcher) {
disconnect (m_file_watcher, SIGNAL (fileChanged (const QString &)), this, SLOT (file_watcher_triggered ()));
disconnect (m_file_watcher, SIGNAL (fileRemoved (const QString &)), this, SLOT (file_watcher_triggered ()));
delete m_file_watcher;
m_file_watcher = 0;
}
delete mp_salt_dialog;
mp_salt_dialog = 0;
mp_mw = 0;
@ -133,20 +147,47 @@ SaltController::show_editor ()
mp_mw->config_set (cfg_salt_manager_window_state, lay::save_dialog_state (mp_salt_dialog));
}
sync_file_watcher ();
}
}
void
SaltController::sync_file_watcher ()
{
m_file_watcher->clear ();
m_file_watcher->enable (false);
for (lay::Salt::flat_iterator g = m_salt.begin_flat (); g != m_salt.end_flat (); ++g) {
m_file_watcher->add_file ((*g)->path ());
}
m_file_watcher->enable (true);
}
void
SaltController::sync_files ()
{
tl::log << tl::to_string (tr ("Detected file system change in packages - updating"));
emit salt_changed ();
}
void
SaltController::add_path (const std::string &path)
{
try {
tl::log << tl::to_string (tr ("Scanning %1 for packages").arg (tl::to_qstring (path)));
m_salt.add_location (path);
dm_sync_file_watcher ();
} catch (tl::Exception &ex) {
tl::error << ex.msg ();
}
}
void
SaltController::file_watcher_triggered ()
{
dm_sync_files ();
}
void
SaltController::set_salt_mine_url (const std::string &url)
{

View File

@ -27,6 +27,8 @@
#include "layCommon.h"
#include "layPlugin.h"
#include "laySalt.h"
#include "tlFileSystemWatcher.h"
#include "tlDeferredExecution.h"
#include <vector>
#include <string>
@ -145,6 +147,12 @@ public:
*/
static SaltController *instance ();
private slots:
/**
* @brief Called when the file watcher detects a change in the file system
*/
void file_watcher_triggered ();
signals:
/**
* @brief This signal is emitted if the salt changed
@ -156,6 +164,12 @@ private:
lay::MainWindow *mp_mw;
std::string m_salt_mine_url;
lay::Salt m_salt, m_salt_mine;
tl::FileSystemWatcher *m_file_watcher;
tl::DeferredMethod<SaltController> dm_sync_file_watcher;
tl::DeferredMethod<SaltController> dm_sync_files;
void sync_file_watcher ();
void sync_files ();
};
}