diff --git a/src/init.c b/src/init.c index 5c94047..56ca05e 100644 --- a/src/init.c +++ b/src/init.c @@ -60,13 +60,13 @@ __attribute__((constructor)) void nm_init() { NM_LOG("init: updating config"); - bool upd = nm_global_config_update(&err); + int rev = nm_global_config_update(&err); if (err) { NM_LOG("init: error parsing config, will show a menu item with the error: %s", err); } size_t ntmp = SIZE_MAX; - if (!upd) { + if (rev == -1) { NM_LOG("init: no config file changes detected for initial config update (it should always return an error or update), stopping (this is a bug; err should have been returned instead)"); return; } else if (!nm_global_config_items(&ntmp)) { @@ -106,7 +106,8 @@ stop: static nm_config_file_t *nm_global_menu_config_files = NULL; // updated in-place by nm_global_config_update static nm_config_t *nm_global_menu_config = NULL; // updated by nm_global_config_update, replaced by nm_global_config_replace, NULL on error static nm_menu_item_t **nm_global_menu_config_items = NULL; // updated by nm_global_config_replace to an error message or the items from nm_global_menu_config -static size_t nm_global_menu_config_n = 0; // ^ +static size_t nm_global_menu_config_n = 0; // ^ +static int nm_global_menu_config_rev = -1; // incremented by nm_global_config_update whenever the config items change for any reason nm_menu_item_t **nm_global_config_items(size_t *n_out) { if (n_out) @@ -158,8 +159,8 @@ static void nm_global_config_replace(nm_config_t *cfg, const char *err) { NM_LOG("could not allocate memory"); } -bool nm_global_config_update(char **err_out) { - #define NM_ERR_RET true +int nm_global_config_update(char **err_out) { + #define NM_ERR_RET nm_global_menu_config_rev char *err; @@ -169,6 +170,7 @@ bool nm_global_config_update(char **err_out) { NM_LOG("... error: %s", err); NM_LOG("global: freeing old config and replacing with error item"); nm_global_config_replace(NULL, err); + nm_global_menu_config_rev++; NM_RETURN_ERR("scan for config files: %s", err); } NM_LOG("global:%s changes detected", updated ? "" : " no"); @@ -180,11 +182,13 @@ bool nm_global_config_update(char **err_out) { NM_LOG("... error: %s", err); NM_LOG("global: freeing old config and replacing with error item"); nm_global_config_replace(NULL, err); + nm_global_menu_config_rev++; NM_RETURN_ERR("parse config files: %s", err); } NM_LOG("global: config updated, freeing old config and replacing with new one"); nm_global_config_replace(cfg, NULL); + nm_global_menu_config_rev++; NM_LOG("global: done swapping config"); } @@ -207,10 +211,11 @@ bool nm_global_config_update(char **err_out) { if (!nm_global_menu_config_items) NM_LOG("could not allocate memory"); + nm_global_menu_config_rev++; NM_LOG("done replacing items"); } - NM_RETURN_OK(updated || g_updated); + NM_RETURN_OK(nm_global_menu_config_rev); #undef NM_ERR_RET } diff --git a/src/init.h b/src/init.h index 15916da..cb371e9 100644 --- a/src/init.h +++ b/src/init.h @@ -7,11 +7,10 @@ extern "C" { #include #include "menu.h" -// nm_global_config_update updates and regenerates the config if needed, and -// returns true if it needed updating. If an error occurs, true is also returned -// since the menu items will be updated to a single one showing the error (see -// nm_global_config_items). -bool nm_global_config_update(char **err_out); +// nm_global_config_update updates and regenerates the config if needed. If the +// menu items changed (i.e. the old items aren't valid anymore), the revision +// will be incremented and returned (even if there was an error). +int nm_global_config_update(char **err_out); // nm_global_config_items returns an array of pointers with the current menu // items (the pointer and the items it points to will remain valid until the diff --git a/src/menu.cc b/src/menu.cc index a7f96db..ceb2dc3 100644 --- a/src/menu.cc +++ b/src/menu.cc @@ -138,15 +138,17 @@ extern "C" NM_PUBLIC MenuTextItem* _nm_menu_hook(void* _this, QMenu* menu, QStri void _nm_menu_inject(void *nmc, QMenu *menu, nm_menu_location_t loc, int at) { NM_LOG("inject %d @ %d", loc, at); - NM_LOG("checking for config updates"); - bool updated = nm_global_config_update(NULL); // if there was an error it will be returned as a menu item anyways (and updated will be true) - NM_LOG("updated = %d", updated); + int rev_o = menu->property("nm_config_rev").toInt(); + + NM_LOG("checking for config updates (current revision: %d)", rev_o); + int rev_n = nm_global_config_update(NULL); // if there was an error it will be returned as a menu item anyways (and updated will be true) + NM_LOG("new revision = %d%s", rev_n, rev_n == rev_o ? "" : " (changed)"); NM_LOG("checking for existing items added by nm"); for (auto action : menu->actions()) { if (action->property("nm_action") == true) { - if (!updated) + if (rev_o == rev_n) return; // already added items, menu is up to date menu->removeAction(action); delete action; @@ -183,7 +185,7 @@ void _nm_menu_inject(void *nmc, QMenu *menu, nm_menu_location_t loc, int at) { if (it->loc != loc) continue; - NM_LOG("adding items '%s'...", it->lbl); + NM_LOG("adding item '%s'...", it->lbl); MenuTextItem* item = AbstractNickelMenuController_createMenuTextItem_orig(nmc, menu, QString::fromUtf8(it->lbl), false, false, ""); QAction* action = AbstractNickelMenuController_createAction_before(before, loc, i == items_n-1, nmc, menu, item, true, true, true); @@ -194,6 +196,9 @@ void _nm_menu_inject(void *nmc, QMenu *menu, nm_menu_location_t loc, int at) { NM_LOG("done"); }); // note: we're capturing by value, i.e. the pointer to the global variable, rather then the stack variable, so this is safe } + + NM_LOG("updating config revision property"); + menu->setProperty("nm_config_rev", rev_n); } void nm_menu_item_do(nm_menu_item_t *it) {