[gnote] Load only enabled addins on startup



commit dda314e9014adbb3271f5132d61012ced3d1f711
Author: Aurimas Černius <aurisc4 gmail com>
Date:   Sun Apr 14 15:48:20 2013 +0300

    Load only enabled addins on startup
    
    Redesign addin support so that meta information is provided by .desktop
    files. Only load addin modules, when addin is enabled.

 src/Makefile.am               |   1 +
 src/abstractaddin.hpp         |  10 +-
 src/addininfo.cpp             |  96 +++++++++++++++++
 src/addininfo.hpp             |  97 ++++++++++++++++++
 src/addinmanager.cpp          | 232 ++++++++++++++++++++++++++----------------
 src/addinmanager.hpp          |  24 +++--
 src/preferencesdialog.cpp     | 128 +++++++++++++----------
 src/preferencesdialog.hpp     |   3 +-
 src/sharp/addinstreemodel.cpp |  51 +++++-----
 src/sharp/addinstreemodel.hpp |  14 ++-
 src/sharp/dynamicmodule.cpp   |   6 +-
 src/sharp/dynamicmodule.hpp   |   9 +-
 src/sharp/modulemanager.cpp   |  95 ++++++++---------
 src/sharp/modulemanager.hpp   |  19 ++--
 14 files changed, 522 insertions(+), 263 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 78d4777..f70f2e7 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -97,6 +97,7 @@ libgnote_la_SOURCES = \
        sharp/xsltargumentlist.hpp sharp/xsltargumentlist.cpp \
        sharp/xsltransform.hpp sharp/xsltransform.cpp \
        abstractaddin.hpp abstractaddin.cpp \
+       addininfo.hpp addininfo.cpp \
        addinmanager.hpp addinmanager.cpp \
        addinpreferencefactory.hpp addinpreferencefactory.cpp \
        applicationaddin.hpp \
diff --git a/src/abstractaddin.hpp b/src/abstractaddin.hpp
index 581c48b..fbd0794 100644
--- a/src/abstractaddin.hpp
+++ b/src/abstractaddin.hpp
@@ -1,7 +1,7 @@
 /*
  * gnote
  *
- * Copyright (C) 2010,2012 Aurimas Cernius
+ * Copyright (C) 2010,2012-2013 Aurimas Cernius
  * Copyright (C) 2009 Hubert Figuiere
  *
  * This program is free software: you can redistribute it and/or modify
@@ -30,14 +30,6 @@
 
 namespace gnote {
 
-enum {
-  ADDIN_CATEGORY_UNKNOWN,
-  ADDIN_CATEGORY_TOOLS,
-  ADDIN_CATEGORY_FORMATTING,
-  ADDIN_CATEGORY_DESKTOP_INTEGRATION,
-  ADDIN_CATEGORY_SYNCHRONIZATION
-};
-
 class AbstractAddin
   : public sharp::IInterface
   , public sigc::trackable
diff --git a/src/addininfo.cpp b/src/addininfo.cpp
new file mode 100644
index 0000000..e5339c5
--- /dev/null
+++ b/src/addininfo.cpp
@@ -0,0 +1,96 @@
+/*
+ * gnote
+ *
+ * Copyright (C) 2013 Aurimas Cernius
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdexcept>
+
+#include <glibmm/i18n.h>
+#include <glibmm/keyfile.h>
+
+#include "addininfo.hpp"
+#include "debug.hpp"
+
+
+namespace gnote {
+
+  namespace {
+
+    const char * ADDIN_INFO = "AddinInfo";
+
+    AddinCategory resolve_addin_category(const std::string & cat)
+    {
+      if(cat == "Tools") {
+        return ADDIN_CATEGORY_TOOLS;
+      }
+      if(cat == "Formatting") {
+        return ADDIN_CATEGORY_FORMATTING;
+      }
+      if(cat == "DesktopIntegration") {
+        return ADDIN_CATEGORY_DESKTOP_INTEGRATION;
+      }
+      if(cat == "Synchronization") {
+        return ADDIN_CATEGORY_SYNCHRONIZATION;
+      }
+
+      return ADDIN_CATEGORY_UNKNOWN;
+    }
+
+  }
+
+
+
+AddinInfo::AddinInfo(const std::string & info_file)
+  : m_category(ADDIN_CATEGORY_UNKNOWN)
+  , m_default_enabled(false)
+{
+  load_from_file(info_file);
+}
+
+void AddinInfo::load_from_file(const std::string & info_file)
+{
+  try {
+    Glib::KeyFile addin_info;
+    if(!addin_info.load_from_file(info_file)) {
+      throw std::runtime_error(_("Failed to load add-in information!"));
+    }
+    m_id = addin_info.get_string(ADDIN_INFO, "Id");
+    m_name = addin_info.get_locale_string(ADDIN_INFO, "Name");
+    m_description = addin_info.get_locale_string(ADDIN_INFO, "Description");
+    m_authors = addin_info.get_locale_string(ADDIN_INFO, "Authors");
+    m_category = resolve_addin_category(addin_info.get_string(ADDIN_INFO, "Category"));
+    m_version = addin_info.get_string(ADDIN_INFO, "Version");
+    try {
+      m_copyright = addin_info.get_locale_string(ADDIN_INFO, "Copyright");
+    }
+    catch(Glib::KeyFileError & e) {
+      DBG_OUT("Can't read copyright, using none: %s", e.what().c_str());
+    }
+    try {
+      m_default_enabled = addin_info.get_boolean(ADDIN_INFO, "DefaultEnabled");
+    }
+    catch(Glib::KeyFileError & e) {
+      DBG_OUT("Can't read default enabled status, assuming default: %s", e.what().c_str());
+    }
+    m_addin_module = addin_info.get_string(ADDIN_INFO, "Module");
+  }
+  catch(Glib::Error & e) {
+    throw std::runtime_error(e.what());
+  }
+}
+
+}
diff --git a/src/addininfo.hpp b/src/addininfo.hpp
new file mode 100644
index 0000000..4dc9c88
--- /dev/null
+++ b/src/addininfo.hpp
@@ -0,0 +1,97 @@
+/*
+ * gnote
+ *
+ * Copyright (C) 2013 Aurimas Cernius
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _ADDININFO_HPP_
+#define _ADDININFO_HPP_
+
+#include <string>
+
+namespace gnote {
+
+enum AddinCategory {
+  ADDIN_CATEGORY_UNKNOWN,
+  ADDIN_CATEGORY_TOOLS,
+  ADDIN_CATEGORY_FORMATTING,
+  ADDIN_CATEGORY_DESKTOP_INTEGRATION,
+  ADDIN_CATEGORY_SYNCHRONIZATION
+};
+
+
+class AddinInfo
+{
+public:
+  AddinInfo(){}
+  explicit AddinInfo(const std::string & info_file);
+  void load_from_file(const std::string & info_file);
+
+  const std::string & id() const
+    {
+      return m_id;
+    }
+  const std::string & name() const
+    {
+      return m_name;
+    }
+  const std::string & description() const
+    {
+      return m_description;
+    }
+  const std::string & authors() const
+    {
+      return m_authors;
+    }
+  AddinCategory category() const
+    {
+      return m_category;
+    }
+  const std::string & version() const
+    {
+      return m_version;
+    }
+  const std::string & copyright() const
+    {
+      return m_copyright;
+    }
+  bool default_enabled() const
+    {
+      return m_default_enabled;
+    }
+  const std::string & addin_module() const
+    {
+      return m_addin_module;
+    }
+  void addin_module(const std::string & module)
+    {
+      m_addin_module = module;
+    }
+private:
+  std::string m_id;
+  std::string m_name;
+  std::string m_description;
+  std::string m_authors;
+  AddinCategory m_category;
+  std::string m_version;
+  std::string m_copyright;
+  bool m_default_enabled;
+  std::string m_addin_module;
+};
+
+}
+
+#endif
diff --git a/src/addinmanager.cpp b/src/addinmanager.cpp
index 5beee03..f7ae871 100644
--- a/src/addinmanager.cpp
+++ b/src/addinmanager.cpp
@@ -26,10 +26,12 @@
 #include <boost/checked_delete.hpp>
 
 #include <glib.h>
+#include <glibmm/i18n.h>
 
 #include "sharp/map.hpp"
 #include "sharp/directory.hpp"
 #include "sharp/dynamicmodule.hpp"
+#include "sharp/files.hpp"
 
 #include "addinmanager.hpp"
 #include "addinpreferencefactory.hpp"
@@ -64,19 +66,10 @@ namespace gnote {
 
     const bool is_first_run
                  = !sharp::directory_exists(m_addins_prefs_dir);
-    const std::string old_addins_dir
-                        = Glib::build_filename(IGnote::old_note_dir(),
-                                               "addins");
-    const bool migration_needed
-                 = is_first_run
-                   && sharp::directory_exists(old_addins_dir);
 
     if (is_first_run)
       g_mkdir_with_parents(m_addins_prefs_dir.c_str(), S_IRWXU);
 
-    if (migration_needed)
-      migrate_addins(old_addins_dir);
-
     initialize_sharp_addins();
   }
 
@@ -95,16 +88,14 @@ namespace gnote {
     }
   }
 
-  void AddinManager::add_note_addin_info(
-                       const sharp::DynamicModule * dmod)
+  void AddinManager::add_note_addin_info(const std::string & id,
+                                         const sharp::DynamicModule * dmod)
   {
-    const char * const id = dmod->id();
-
     {
       const IdInfoMap::const_iterator iter
                                         = m_note_addin_infos.find(id);
       if (m_note_addin_infos.end() != iter) {
-        ERR_OUT("NoteAddin info %s already present", id);
+        ERR_OUT(_("Note add-in info %s already present"), id.c_str());
         return;
       }
     }
@@ -112,11 +103,11 @@ namespace gnote {
     sharp::IfaceFactoryBase * const f = dmod->query_interface(
                                           NoteAddin::IFACE_NAME);
     if(!f) {
-      ERR_OUT("does not implement %s", NoteAddin::IFACE_NAME);
+      ERR_OUT(_("%s does not implement %s"), id.c_str(), NoteAddin::IFACE_NAME);
       return;
     }
 
-    m_note_addin_infos.insert(std::make_pair(std::string(id), f));
+    m_note_addin_infos.insert(std::make_pair(id, f));
 
     {
       for(NoteAddinMap::iterator iter = m_note_addins.begin();
@@ -124,7 +115,7 @@ namespace gnote {
         IdAddinMap & id_addin_map = iter->second;
         IdAddinMap::const_iterator it = id_addin_map.find(id);
         if (id_addin_map.end() != it) {
-          ERR_OUT("NoteAddin %s already present", id);
+          ERR_OUT(_("Note add-in %s already present"), id.c_str());
           continue;
         }
 
@@ -138,15 +129,12 @@ namespace gnote {
     }
   }
 
-  void AddinManager::erase_note_addin_info(
-                       const sharp::DynamicModule * dmod)
+  void AddinManager::erase_note_addin_info(const std::string & id)
   {
-    const char * const id = dmod->id();
-
     {
       const IdInfoMap::iterator iter = m_note_addin_infos.find(id);
       if (m_note_addin_infos.end() == iter) {
-        ERR_OUT("NoteAddin info %s absent", id);
+        ERR_OUT(_("Note add-in info %s is absent"), id.c_str());
         return;
       }
 
@@ -159,7 +147,7 @@ namespace gnote {
         IdAddinMap & id_addin_map = iter->second;
         IdAddinMap::iterator it = id_addin_map.find(id);
         if (id_addin_map.end() == it) {
-          ERR_OUT("NoteAddin %s absent", id);
+          ERR_OUT(_("Note add-in %s is absent"), id.c_str());
           continue;
         }
 
@@ -172,6 +160,57 @@ namespace gnote {
     }
   }
 
+  void AddinManager::load_addin_infos(const std::string & global_path,
+                                      const std::string & local_path)
+  {
+    load_addin_infos(global_path);
+    load_addin_infos(local_path);
+  }
+
+  void AddinManager::load_addin_infos(const std::string & path)
+  {
+    std::list<std::string> files;
+    sharp::directory_get_files_with_ext(path, ".desktop", files);
+    for(std::list<std::string>::iterator iter = files.begin(); iter != files.end(); ++iter) {
+      try {
+        AddinInfo addin_info(*iter);
+        std::string module = Glib::build_filename(path, addin_info.addin_module());
+        if(sharp::file_exists(module + "." + G_MODULE_SUFFIX)) {
+          addin_info.addin_module(module);
+          m_addin_infos[addin_info.id()] = addin_info;
+        }
+        else {
+          ERR_OUT(_("Failed to find module %s for addin %s"), addin_info.id().c_str(), module.c_str());
+        }
+      }
+      catch(std::exception & e) {
+        ERR_OUT(_("Failed to load addin info for %s: %s"), iter->c_str(), e.what());
+      }
+    }
+  }
+
+  void AddinManager::get_enabled_addins(std::list<std::string> & addins) const
+  {
+    bool global_addins_prefs_loaded = true;
+    Glib::KeyFile global_addins_prefs;
+    try {
+      global_addins_prefs.load_from_file(m_addins_prefs_file);
+    }
+    catch(Glib::Error & not_loaded) {
+      global_addins_prefs_loaded = false;
+    }
+
+    for(AddinInfoMap::const_iterator iter = m_addin_infos.begin(); iter != m_addin_infos.end(); ++iter) {
+      if(global_addins_prefs_loaded && global_addins_prefs.has_key("Enabled", iter->first)
+         && global_addins_prefs.get_boolean("Enabled", iter->first)) {
+          addins.push_back(iter->second.addin_module());
+      }
+      else if(iter->second.default_enabled()) {
+          addins.push_back(iter->second.addin_module());
+      }
+    }
+  }
+
   void AddinManager::initialize_sharp_addins()
   {
     if (!sharp::directory_exists (m_addins_prefs_dir))
@@ -190,62 +229,70 @@ namespace gnote {
    
     REGISTER_APP_ADDIN(notebooks::NotebookApplicationAddin);
 
-    m_module_manager.add_path(LIBDIR"/"PACKAGE_NAME"/addins/"PACKAGE_VERSION);
-    m_module_manager.add_path(m_gnote_conf_dir + "/addins");
+    std::string global_path = LIBDIR"/"PACKAGE_NAME"/addins/"PACKAGE_VERSION;
+    std::string local_path = m_gnote_conf_dir + "/addins";
 
-    m_module_manager.load_modules();
+    load_addin_infos(global_path, local_path);
+    std::list<std::string> enabled_addins;
+    get_enabled_addins(enabled_addins);
+    m_module_manager.load_modules(enabled_addins);
 
-    bool global_addins_prefs_loaded = true;
-    Glib::KeyFile global_addins_prefs;
-    try {
-      global_addins_prefs.load_from_file(m_addins_prefs_file);
-    }
-    catch (Glib::Error & not_loaded) {
-      global_addins_prefs_loaded = false;
-    }
+    const sharp::ModuleMap & modules = m_module_manager.get_modules();
+    for(sharp::ModuleMap::const_iterator iter = modules.begin();
+        iter != modules.end(); ++iter) {
 
-    const sharp::ModuleList & list = m_module_manager.get_modules();
-    for(sharp::ModuleList::const_iterator iter = list.begin();
-        iter != list.end(); ++iter) {
-
-      sharp::DynamicModule* dmod = *iter;
+      const std::string & mod_id = get_info_for_module(iter->first).id();
+      sharp::DynamicModule* dmod = iter->second;
       if(!dmod) {
         continue;
       }
 
-      if(global_addins_prefs_loaded &&
-         global_addins_prefs.has_key("Enabled", dmod->id())) {
-        dmod->enabled(global_addins_prefs.get_boolean("Enabled", dmod->id()));
-      }
+      dmod->enabled(true); // enable all loaded modules on startup
+      add_module_addins(mod_id, dmod);
+    }
+  }
 
-      sharp::IfaceFactoryBase * f = dmod->query_interface(NoteAddin::IFACE_NAME);
-      if(f && dmod->is_enabled()) {
-        m_note_addin_infos.insert(std::make_pair(dmod->id(), f));
-      }
+  void AddinManager::add_module_addins(const std::string & mod_id, sharp::DynamicModule * dmod)
+  {
+    sharp::IfaceFactoryBase * f = dmod->query_interface(NoteAddin::IFACE_NAME);
+    if(f && dmod->is_enabled()) {
+      m_note_addin_infos.insert(std::make_pair(mod_id, f));
+    }
 
-      f = dmod->query_interface(AddinPreferenceFactoryBase::IFACE_NAME);
-      if(f) {
-        AddinPreferenceFactoryBase * factory = dynamic_cast<AddinPreferenceFactoryBase*>((*f)());
-        m_addin_prefs.insert(std::make_pair(dmod->id(), factory));
-      }
+    f = dmod->query_interface(AddinPreferenceFactoryBase::IFACE_NAME);
+    if(f) {
+      AddinPreferenceFactoryBase * factory = dynamic_cast<AddinPreferenceFactoryBase*>((*f)());
+      m_addin_prefs.insert(std::make_pair(mod_id, factory));
+    }
 
-      f = dmod->query_interface(ImportAddin::IFACE_NAME);
-      if(f) {
-        ImportAddin * addin = dynamic_cast<ImportAddin*>((*f)());
-        m_import_addins.insert(std::make_pair(dmod->id(), addin));
-      }
+    f = dmod->query_interface(ImportAddin::IFACE_NAME);
+    if(f) {
+      ImportAddin * addin = dynamic_cast<ImportAddin*>((*f)());
+      m_import_addins.insert(std::make_pair(mod_id, addin));
+    }
 
-      f = dmod->query_interface(ApplicationAddin::IFACE_NAME);
-      if(f) {
-        ApplicationAddin * addin = dynamic_cast<ApplicationAddin*>((*f)());
-        m_app_addins.insert(std::make_pair(dmod->id(), addin));
-      }
-      f = dmod->query_interface(sync::SyncServiceAddin::IFACE_NAME);
-      if(f) {
-        sync::SyncServiceAddin * addin = dynamic_cast<sync::SyncServiceAddin*>((*f)());
-        m_sync_service_addins.insert(std::make_pair(dmod->id(), addin));
+    f = dmod->query_interface(ApplicationAddin::IFACE_NAME);
+    if(f) {
+      ApplicationAddin * addin = dynamic_cast<ApplicationAddin*>((*f)());
+      addin->note_manager(m_note_manager);
+      m_app_addins.insert(std::make_pair(mod_id, addin));
+    }
+    f = dmod->query_interface(sync::SyncServiceAddin::IFACE_NAME);
+    if(f) {
+      sync::SyncServiceAddin * addin = dynamic_cast<sync::SyncServiceAddin*>((*f)());
+      m_sync_service_addins.insert(std::make_pair(mod_id, addin));
+    }
+  }
+
+  AddinInfo AddinManager::get_info_for_module(const std::string & module) const
+  {
+    for(AddinInfoMap::const_iterator iter = m_addin_infos.begin();
+        iter != m_addin_infos.end(); ++iter) {
+      if(iter->second.addin_module() == module) {
+        return iter->second;
       }
     }
+    return AddinInfo();
   }
 
   void AddinManager::load_addins_for_note(const Note::Ptr & note)
@@ -382,12 +429,12 @@ namespace gnote {
     catch (Glib::Error & not_loaded_ignored) {
     }
 
-    const sharp::ModuleList & list = m_module_manager.get_modules();
-    for(sharp::ModuleList::const_iterator iter = list.begin();
-        iter != list.end(); ++iter) {
-      const sharp::DynamicModule* dmod = *iter;
-      global_addins_prefs.set_boolean("Enabled", dmod->id(),
-                                      dmod->is_enabled());
+    const sharp::ModuleMap & modules = m_module_manager.get_modules();
+    for(sharp::ModuleMap::const_iterator iter = modules.begin();
+        iter != modules.end(); ++iter) {
+      const std::string & mod_id = iter->first;
+      const sharp::DynamicModule* dmod = iter->second;
+      global_addins_prefs.set_boolean("Enabled", mod_id, dmod->is_enabled());
     }
 
     Glib::RefPtr<Gio::File> prefs_file = Gio::File::create_for_path(
@@ -398,27 +445,40 @@ namespace gnote {
     prefs_file_stream->write(global_addins_prefs.to_data());
   }
 
-  Gtk::Widget * AddinManager::create_addin_preference_widget(const std::string & id)
+  AddinInfo AddinManager::get_addin_info(const std::string & id) const
   {
-    IdAddinPrefsMap::const_iterator iter = m_addin_prefs.find(id);
-    if(iter != m_addin_prefs.end()) {
-      return iter->second->create_preference_widget(m_note_manager);
+    AddinInfoMap::const_iterator iter = m_addin_infos.find(id);
+    if(iter != m_addin_infos.end()) {
+      return iter->second;
     }
-    return NULL;
+    return AddinInfo();
   }
 
-  void AddinManager::migrate_addins(const std::string & old_addins_dir)
+  bool AddinManager::is_module_loaded(const std::string & id) const
   {
-    const Glib::RefPtr<Gio::File> src
-      = Gio::File::create_for_path(old_addins_dir);
-    const Glib::RefPtr<Gio::File> dest
-      = Gio::File::create_for_path(m_gnote_conf_dir);
+    AddinInfo info = get_addin_info(id);
+    return m_module_manager.get_module(info.addin_module());
+  }
 
-    try {
-      sharp::directory_copy(src, dest);
+  sharp::DynamicModule *AddinManager::get_module(const std::string & id)
+  {
+    AddinInfo info = get_addin_info(id);
+    sharp::DynamicModule *module = m_module_manager.get_module(info.addin_module());
+    if(!module) {
+      module = m_module_manager.load_module(info.addin_module());
+      if(module) {
+        add_module_addins(id, module);
+      }
     }
-    catch (const Gio::Error & e) {
-      DBG_OUT("AddinManager: migrating addins: %s", e.what().c_str());
+    return module;
+  }
+
+  Gtk::Widget * AddinManager::create_addin_preference_widget(const std::string & id)
+  {
+    IdAddinPrefsMap::const_iterator iter = m_addin_prefs.find(id);
+    if(iter != m_addin_prefs.end()) {
+      return iter->second->create_preference_widget(m_note_manager);
     }
+    return NULL;
   }
 }
diff --git a/src/addinmanager.hpp b/src/addinmanager.hpp
index 1b69b6e..fce604a 100644
--- a/src/addinmanager.hpp
+++ b/src/addinmanager.hpp
@@ -30,6 +30,7 @@
 #include <sigc++/signal.h>
 
 #include "sharp/modulemanager.hpp"
+#include "addininfo.hpp"
 #include "note.hpp"
 #include "noteaddin.hpp"
 #include "importaddin.hpp"
@@ -45,6 +46,8 @@ namespace sync {
 class SyncServiceAddin;
 }
 
+typedef std::map<std::string, AddinInfo> AddinInfoMap;
+
 
 class AddinManager
 {
@@ -52,8 +55,8 @@ public:
   AddinManager(NoteManager & note_manager, const std::string & conf_dir);
   ~AddinManager();
 
-  void add_note_addin_info(const sharp::DynamicModule * dmod);
-  void erase_note_addin_info(const sharp::DynamicModule * dmod);
+  void add_note_addin_info(const std::string & id, const sharp::DynamicModule * dmod);
+  void erase_note_addin_info(const std::string & id);
 
   std::string & get_prefs_dir()
     {
@@ -71,16 +74,22 @@ public:
   void shutdown_application_addins() const;
   void save_addins_prefs() const;
 
-  const sharp::ModuleList & get_modules() const
-    { 
-      return m_module_manager.get_modules(); 
+  const AddinInfoMap & get_addin_infos() const
+    {
+      return m_addin_infos;
     }
+  AddinInfo get_addin_info(const std::string & id) const;
+  bool is_module_loaded(const std::string & id) const;
+  sharp::DynamicModule *get_module(const std::string & id);
 
   Gtk::Widget * create_addin_preference_widget(const std::string & id);
 private:
-
+  void load_addin_infos(const std::string & global_path, const std::string & local_path);
+  void load_addin_infos(const std::string & path);
+  void get_enabled_addins(std::list<std::string> & addins) const;
   void initialize_sharp_addins();
-  void migrate_addins(const std::string & old_addins_dir);
+  void add_module_addins(const std::string & mod_id, sharp::DynamicModule * dmod);
+  AddinInfo get_info_for_module(const std::string & module) const;
     
   NoteManager & m_note_manager;
   const std::string m_gnote_conf_dir;
@@ -88,6 +97,7 @@ private:
   std::string m_addins_prefs_file;
   sharp::ModuleManager m_module_manager;
   std::list<sharp::IfaceFactoryBase*> m_builtin_ifaces;
+  AddinInfoMap m_addin_infos;
   /// Key = TypeExtensionNode.Id
   typedef std::map<std::string, ApplicationAddin*> AppAddinMap;
   AppAddinMap                               m_app_addins;
diff --git a/src/preferencesdialog.cpp b/src/preferencesdialog.cpp
index bdcafb6..397c5f6 100644
--- a/src/preferencesdialog.cpp
+++ b/src/preferencesdialog.cpp
@@ -74,14 +74,14 @@ namespace gnote {
     : public Gtk::Dialog
   {
   public:
-    AddinInfoDialog(const sharp::DynamicModule * module, Gtk::Dialog &parent);
+    AddinInfoDialog(const AddinInfo & module, Gtk::Dialog &parent);
     void set_addin_id(const std::string & id)
       { m_id = id; }
     const std::string & get_addin_id() const
       { return m_id; }
   private:
     void fill(Gtk::Label &);
-    const sharp::DynamicModule *m_module;
+    AddinInfo m_addin_info;
     std::string m_id;
   };
 
@@ -177,19 +177,22 @@ namespace gnote {
 
   void PreferencesDialog::enable_addin(bool enable)
   {
-    sharp::DynamicModule * const module = get_selected_addin();
-    if (!module)
+    std::string id = get_selected_addin();
+    sharp::DynamicModule * const module = m_addin_manager.get_module(id);
+    if(!module) {
       return;
+    }
+    else {
+      set_module_for_selected_addin(module);
+    }
 
     if (module->has_interface(NoteAddin::IFACE_NAME)) {
       if (enable)
-        m_addin_manager.add_note_addin_info(module);
+        m_addin_manager.add_note_addin_info(id, module);
       else
-        m_addin_manager.erase_note_addin_info(module);
+        m_addin_manager.erase_note_addin_info(id);
     }
     else {
-      const char * const id = module->id();
-
       ApplicationAddin * const addin = m_addin_manager.get_application_addin(id);
       if(addin) {
         enable_addin(addin, enable);
@@ -200,7 +203,7 @@ namespace gnote {
           enable_addin(sync_addin, enable);
         }
         else {
-          ERR_OUT("Addin %s absent", id);
+          ERR_OUT(_("Add-in %s is absent"), id.c_str());
           return;
         }
       }
@@ -746,16 +749,26 @@ namespace gnote {
   }
 
 
-  sharp::DynamicModule * PreferencesDialog::get_selected_addin()
+  std::string PreferencesDialog::get_selected_addin()
   {
     /// TODO really set
     Glib::RefPtr<Gtk::TreeSelection> select = m_addin_tree->get_selection();
     Gtk::TreeIter iter = select->get_selected();
-    sharp::DynamicModule * module = NULL;
+    std::string module_id;
+    if(iter) {
+      module_id = m_addin_tree_model->get_module_id(iter);
+    }
+    return module_id;
+  }
+
+
+  void PreferencesDialog::set_module_for_selected_addin(sharp::DynamicModule * module)
+  {
+    Glib::RefPtr<Gtk::TreeSelection> select = m_addin_tree->get_selection();
+    Gtk::TreeIter iter = select->get_selected();
     if(iter) {
-      module = m_addin_tree_model->get_module(iter);
+      m_addin_tree_model->set_module(iter, module);
     }
-    return module;
   }
 
 
@@ -768,12 +781,21 @@ namespace gnote {
   /// Set the sensitivity of the buttons based on what is selected
   void PreferencesDialog::update_addin_buttons()
   {
-    const sharp::DynamicModule * module = get_selected_addin();
-    if(module) {
-      enable_addin_button->set_sensitive(!module->is_enabled());
-      disable_addin_button->set_sensitive(module->is_enabled());
-      addin_prefs_button->set_sensitive(
-        module->has_interface(AddinPreferenceFactoryBase::IFACE_NAME));
+    std::string id = get_selected_addin();
+    if(id != "") {
+      bool loaded = m_addin_manager.is_module_loaded(id);
+      bool enabled = false;
+      if(loaded) {
+        const sharp::DynamicModule *module = m_addin_manager.get_module(id);
+        enabled = module->is_enabled();
+        addin_prefs_button->set_sensitive(
+          module->has_interface(AddinPreferenceFactoryBase::IFACE_NAME));
+      }
+      else {
+        addin_prefs_button->set_sensitive(false);
+      }
+      enable_addin_button->set_sensitive(!enabled);
+      disable_addin_button->set_sensitive(enabled);
       addin_info_button->set_sensitive(true);
     }
     else {
@@ -788,11 +810,14 @@ namespace gnote {
   void PreferencesDialog::load_addins()
   {
     ///// TODO populate
-    const sharp::ModuleList & list(m_addin_manager.get_modules());
-    for(sharp::ModuleList::const_iterator iter = list.begin();
-        iter != list.end(); ++iter) {
-
-      m_addin_tree_model->append(*iter);
+    const AddinInfoMap & addins(m_addin_manager.get_addin_infos());
+    for(AddinInfoMap::const_iterator iter = addins.begin();
+        iter != addins.end(); ++iter) {
+      sharp::DynamicModule *module = NULL;
+      if(m_addin_manager.is_module_loaded(iter->first)) {
+        module = m_addin_manager.get_module(iter->first);
+      }
+      m_addin_tree_model->append(iter->second, module);
     }
 
     update_addin_buttons();
@@ -816,7 +841,9 @@ namespace gnote {
 
   void PreferencesDialog::on_addin_prefs_button()
   {
-    const sharp::DynamicModule * module = get_selected_addin();
+    std::string id = get_selected_addin();
+    AddinInfo addin_info = m_addin_manager.get_addin_info(id);
+    const sharp::DynamicModule *module = m_addin_manager.get_module(id);
     Gtk::Dialog *dialog;
 
     if (!module) {
@@ -824,7 +851,7 @@ namespace gnote {
     }
 
     std::map<std::string, Gtk::Dialog* >::iterator iter;
-    iter = addin_prefs_dialogs.find(module->id());
+    iter = addin_prefs_dialogs.find(id);
     if (iter == addin_prefs_dialogs.end()) {
       // A preference dialog isn't open already so create a new one
       Gtk::Image *icon =
@@ -832,13 +859,13 @@ namespace gnote {
       Gtk::Label *caption = manage(new Gtk::Label());
       caption->set_markup(
         str(boost::format("<span size='large' weight='bold'>%1% %2%</span>") 
-            % module->name() % module->version()));
+            % addin_info.name() % addin_info.version()));
       caption->property_xalign() = 0;
       caption->set_use_markup(true);
       caption->set_use_underline(false);
 
       Gtk::Widget * pref_widget =
-        m_addin_manager.create_addin_preference_widget (module->id());
+        m_addin_manager.create_addin_preference_widget(id);
 
       if (pref_widget == NULL) {
         pref_widget = manage(new Gtk::Label (_("Not Implemented")));
@@ -855,7 +882,7 @@ namespace gnote {
       vbox->show_all ();
 
       dialog = new Gtk::Dialog(
-        str(boost::format(_("%1% Preferences")) % module->name()),
+        str(boost::format(_("%1% Preferences")) % addin_info.name()),
         *this, false);
       dialog->property_destroy_with_parent() = true;
       dialog->add_button(Gtk::Stock::CLOSE, Gtk::RESPONSE_CLOSE);
@@ -874,7 +901,7 @@ namespace gnote {
       // presented again if the user clicks on the preferences button
       // again before closing the preferences dialog.
 //      dialog->set_data(Glib::Quark("AddinId"), module->id());
-      addin_prefs_dialogs [module->id()] = dialog;
+      addin_prefs_dialogs[id] = dialog;
     } 
     else {
       // It's already opened so just present it again
@@ -903,15 +930,12 @@ namespace gnote {
 
   void PreferencesDialog::on_addin_info_button()
   {
-    const sharp::DynamicModule * addin = get_selected_addin();
-
-    if (addin == NULL) {
-      return;
-    }
+    std::string id = get_selected_addin();
+    AddinInfo addin = m_addin_manager.get_addin_info(id);
 
     Gtk::Dialog* dialog;
     std::map<std::string, Gtk::Dialog* >::iterator iter;
-    iter = addin_info_dialogs.find(addin->id());
+    iter = addin_info_dialogs.find(addin.id());
     if (iter == addin_info_dialogs.end()) {
       dialog = new AddinInfoDialog (addin, *this);
       dialog->signal_delete_event().connect(
@@ -926,8 +950,8 @@ namespace gnote {
       // Store this dialog off in a dictionary so it can be presented
       // again if the user clicks on the Info button before closing
       // the original dialog.
-      static_cast<AddinInfoDialog*>(dialog)->set_addin_id(addin->id());
-      addin_info_dialogs [addin->id()] = dialog;
+      static_cast<AddinInfoDialog*>(dialog)->set_addin_id(id);
+      addin_info_dialogs[id] = dialog;
     } 
     else {
       // It's already opened so just present it again
@@ -1336,10 +1360,10 @@ DBG_OUT("no addin");
   }
 
 
-  AddinInfoDialog::AddinInfoDialog(const sharp::DynamicModule * module,
+  AddinInfoDialog::AddinInfoDialog(const AddinInfo & addin_info,
                                    Gtk::Dialog &parent)
-    : Gtk::Dialog(module->name(), parent, false)
-    , m_module(module)
+    : Gtk::Dialog(addin_info.name(), parent, false)
+    , m_addin_info(addin_info)
   {
     property_destroy_with_parent() = true;
     add_button(Gtk::Stock::CLOSE, Gtk::RESPONSE_CLOSE);
@@ -1375,25 +1399,17 @@ DBG_OUT("no addin");
 
        void AddinInfoDialog::fill(Gtk::Label & info_label)
   {
-    std::string sb("<b><big>");
-    sb += std::string(m_module->name()) + "</big></b>\n\n";
-
-    const char * s = m_module->description();
-    if (s && *s) {
-      sb += std::string(s) + "\n\n";
-    }
+    std::string sb = "<b><big>" + m_addin_info.name() + "</big></b>\n\n";
+    sb += m_addin_info.description() + "\n\n";
 
     sb += str(boost::format("<small><b>%1%</b>\n%2%\n\n")
-              % _("Version:") % m_module->version());
+              % _("Version:") % m_addin_info.version());
 
-    s = m_module->authors();
-    if (s && *s) {
-      sb += str(boost::format("<b>%1%</b>\n%2%\n\n")
-                % _("Author:") % s);
-    }
+    sb += str(boost::format("<b>%1%</b>\n%2%\n\n")
+              % _("Author:") % m_addin_info.authors());
     
-    s = m_module->copyright();
-    if (s && *s) {
+    std::string s = m_addin_info.copyright();
+    if(s != "") {
       sb += str(boost::format("<b>%1%</b>\n%2%\n\n") 
                 % _("Copyright:") % s);
     }
diff --git a/src/preferencesdialog.hpp b/src/preferencesdialog.hpp
index cb8908c..e00f68c 100644
--- a/src/preferencesdialog.hpp
+++ b/src/preferencesdialog.hpp
@@ -74,7 +74,8 @@ private:
   void on_preferences_setting_changed(const Glib::ustring & key);
   void on_rename_behavior_changed();
 
-  sharp::DynamicModule * get_selected_addin();
+  std::string get_selected_addin();
+  void set_module_for_selected_addin(sharp::DynamicModule * module);
   void on_addin_tree_selection_changed();
   void update_addin_buttons();
   void load_addins();
diff --git a/src/sharp/addinstreemodel.cpp b/src/sharp/addinstreemodel.cpp
index b0cf79b..f989672 100644
--- a/src/sharp/addinstreemodel.cpp
+++ b/src/sharp/addinstreemodel.cpp
@@ -1,7 +1,7 @@
 /*
  * gnote
  *
- * Copyright (C) 2010,2012 Aurimas Cernius
+ * Copyright (C) 2010,2012-2013 Aurimas Cernius
  * Copyright (C) 2009 Hubert Figuiere
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -51,6 +51,15 @@ namespace sharp {
     set_column_types(m_columns);
   }
 
+  std::string AddinsTreeModel::get_module_id(const Gtk::TreeIter & iter)
+  {
+    std::string id;
+    if(iter) {
+      iter->get_value(4, id);
+    }
+    return id;
+  }
+
   sharp::DynamicModule * AddinsTreeModel::get_module(const Gtk::TreeIter & iter)
   {
     sharp::DynamicModule * module = NULL;
@@ -60,6 +69,13 @@ namespace sharp {
     return module;
   }
 
+  void AddinsTreeModel::set_module(const Gtk::TreeIter & iter, const sharp::DynamicModule * dmod)
+  {
+    if(iter) {
+      iter->set_value(2, dmod);
+    }
+  }
+
   void AddinsTreeModel::name_cell_data_func(Gtk::CellRenderer * renderer,
                                             const Gtk::TreeIter & iter)
   {
@@ -68,7 +84,7 @@ namespace sharp {
     iter->get_value(0, value);
     text_renderer->property_text() = value;
     const sharp::DynamicModule *module = get_module(iter);
-    if(!module || module->is_enabled()) {
+    if(get_module_id(iter) == "" || (module && module->is_enabled())) {
       text_renderer->property_foreground() = "black";
     }
     else {
@@ -81,7 +97,7 @@ namespace sharp {
   {
     Gtk::CellRendererPixbuf *icon_renderer = dynamic_cast<Gtk::CellRendererPixbuf*>(renderer);
     Glib::RefPtr<Gdk::Pixbuf> icon;
-    if(get_module(iter)) {
+    if(get_module_id(iter) != "") {
       icon = gnote::IconManager::obj().get_icon(gnote::IconManager::EMBLEM_PACKAGE, 22);
     }
     icon_renderer->property_pixbuf() = icon;
@@ -106,12 +122,13 @@ namespace sharp {
   }
 
 
-  Gtk::TreeIter AddinsTreeModel::append(const sharp::DynamicModule *module)
+  Gtk::TreeIter AddinsTreeModel::append(const gnote::AddinInfo & module_info,
+                                        const sharp::DynamicModule *module)
   {
-    int category = module->category();
+    gnote::AddinCategory category = module_info.category();
     Gtk::TreeIter iter = children().begin();
     while(iter != children().end()) {
-      int row_value;
+      gnote::AddinCategory row_value;
       iter->get_value(3, row_value);
       if(row_value == category)
         break;
@@ -119,18 +136,18 @@ namespace sharp {
     }
     if(iter == children().end()) {
       iter = Gtk::TreeStore::append();
-      category = ensure_valid_addin_category(category);
       iter->set_value(0, get_addin_category_name(category));
       iter->set_value(3, category);
     }
     iter = Gtk::TreeStore::append(iter->children());
-    iter->set_value(0, std::string(module->name()));
-    iter->set_value(1, std::string(module->version()));
+    iter->set_value(0, std::string(module_info.name()));
+    iter->set_value(1, std::string(module_info.version()));
     iter->set_value(2, module);
+    iter->set_value(4, module_info.id());
     return iter;
   }
 
-  std::string AddinsTreeModel::get_addin_category_name(int category)
+  std::string AddinsTreeModel::get_addin_category_name(gnote::AddinCategory category)
   {
     switch(category) {
       case gnote::ADDIN_CATEGORY_FORMATTING:
@@ -152,18 +169,4 @@ namespace sharp {
     }
   }
 
-  int AddinsTreeModel::ensure_valid_addin_category(int category)
-  {
-    switch(category) {
-      case gnote::ADDIN_CATEGORY_FORMATTING:
-      case gnote::ADDIN_CATEGORY_DESKTOP_INTEGRATION:
-      case gnote::ADDIN_CATEGORY_TOOLS:
-      case gnote::ADDIN_CATEGORY_SYNCHRONIZATION:
-        return category;
-      case gnote::ADDIN_CATEGORY_UNKNOWN:
-      default:
-        return gnote::ADDIN_CATEGORY_UNKNOWN;
-    }
-  }
-
 }
diff --git a/src/sharp/addinstreemodel.hpp b/src/sharp/addinstreemodel.hpp
index e9d9b84..bcf8289 100644
--- a/src/sharp/addinstreemodel.hpp
+++ b/src/sharp/addinstreemodel.hpp
@@ -1,7 +1,7 @@
 /*
  * gnote
  *
- * Copyright (C) 2010,2012 Aurimas Cernius
+ * Copyright (C) 2010,2012-2013 Aurimas Cernius
  * Copyright (C) 2009 Hubert Figuiere
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -32,6 +32,7 @@
 #include <gtkmm/treestore.h>
 #include <gtkmm/treeview.h>
 
+#include "addininfo.hpp"
 #include "sharp/dynamicmodule.hpp"
 
 namespace sharp {
@@ -43,9 +44,11 @@ public:
   typedef Glib::RefPtr<AddinsTreeModel> Ptr;
   static Ptr create(Gtk::TreeView * treeview);
 
+  std::string get_module_id(const Gtk::TreeIter &);
   sharp::DynamicModule * get_module(const Gtk::TreeIter &);
+  void set_module(const Gtk::TreeIter &, const sharp::DynamicModule *);
 
-  Gtk::TreeIter append(const sharp::DynamicModule *);
+  Gtk::TreeIter append(const gnote::AddinInfo &, const sharp::DynamicModule *);
   class AddinsColumns
     : public Gtk::TreeModelColumnRecord
   {
@@ -56,17 +59,18 @@ public:
         add(version);
         add(addin);
         add(category);
+        add(id);
       }
 
     Gtk::TreeModelColumn<std::string>          name;
     Gtk::TreeModelColumn<std::string>          version;
     Gtk::TreeModelColumn<const sharp::DynamicModule *> addin;
-    Gtk::TreeModelColumn<int>                  category;
+    Gtk::TreeModelColumn<gnote::AddinCategory> category;
+    Gtk::TreeModelColumn<std::string>          id;
   };
   AddinsColumns m_columns;
 
-  static std::string get_addin_category_name(int category);
-  static int ensure_valid_addin_category(int category);
+  static std::string get_addin_category_name(gnote::AddinCategory category);
 protected:
   AddinsTreeModel();
   void set_columns(Gtk::TreeView *v);
diff --git a/src/sharp/dynamicmodule.cpp b/src/sharp/dynamicmodule.cpp
index d916f3a..bf97faa 100644
--- a/src/sharp/dynamicmodule.cpp
+++ b/src/sharp/dynamicmodule.cpp
@@ -1,6 +1,7 @@
 /*
  * gnote
  *
+ * Copyright (C) 2013 Aurimas Cernius
  * Copyright (C) 2009 Hubert Figuiere
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -42,11 +43,6 @@ namespace sharp {
     sharp::map_delete_all_second(m_interfaces);
   }
 
-  const char * DynamicModule::copyright() const
-  {
-    return "";
-  }
-
   
   void DynamicModule::enabled(bool enable)
   {
diff --git a/src/sharp/dynamicmodule.hpp b/src/sharp/dynamicmodule.hpp
index 0bf2287..c8c8c6b 100644
--- a/src/sharp/dynamicmodule.hpp
+++ b/src/sharp/dynamicmodule.hpp
@@ -1,7 +1,7 @@
 /*
  * gnote
  *
- * Copyright (C) 2010 Aurimas Cernius
+ * Copyright (C) 2010,2013 Aurimas Cernius
  * Copyright (C) 2009 Hubert Figuiere
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -56,13 +56,6 @@ public:
 
   virtual ~DynamicModule();
 
-  virtual const char * id() const = 0;
-  virtual const char * name() const = 0;
-  virtual const char * description() const = 0;
-  virtual const char * authors() const = 0;
-  virtual int          category() const = 0;
-  virtual const char * version() const = 0;
-  virtual const char * copyright() const;
   bool is_enabled() const
     {
       return m_enabled;
diff --git a/src/sharp/modulemanager.cpp b/src/sharp/modulemanager.cpp
index bb37670..8acd9a0 100644
--- a/src/sharp/modulemanager.cpp
+++ b/src/sharp/modulemanager.cpp
@@ -1,6 +1,7 @@
 /*
  * gnote
  *
+ * Copyright (C) 2013 Aurimas Cernius
  * Copyright (C) 2009 Hubert Figuiere
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -27,6 +28,7 @@
 #include <dlfcn.h>
 
 #include <gmodule.h>
+#include <glibmm/i18n.h>
 #include <glibmm/module.h>
 
 #include "sharp/directory.hpp"
@@ -41,68 +43,59 @@ namespace sharp {
 
   ModuleManager::~ModuleManager()
   {
-    for(ModuleList::const_iterator mod_iter = m_modules.begin();
+    for(ModuleMap::const_iterator mod_iter = m_modules.begin();
         mod_iter != m_modules.end(); ++mod_iter) {
-      delete *mod_iter;
+      delete mod_iter->second;
     }
   }
 
-
-  void ModuleManager::add_path(const std::string & dir)
+  DynamicModule *ModuleManager::load_module(const std::string & mod)
   {
-    m_dirs.insert(dir);
-    DBG_OUT("add path %s", dir.c_str());
-  }
+    DynamicModule *dmod = get_module(mod);
+    if(dmod) {
+      return dmod;
+    }
 
+    Glib::Module module(mod, Glib::MODULE_BIND_LOCAL);
+    DBG_OUT("load module %s", file_basename(mod).c_str());
+    if(!module) {
+      ERR_OUT(_("Error loading %s"), Glib::Module::get_last_error().c_str());
+      return dmod;
+    }
 
-  void ModuleManager::load_modules()
-  {
-    std::string ext = std::string(".") + G_MODULE_SUFFIX;
-
-    for(std::set<std::string>::const_iterator iter = m_dirs.begin();
-        iter != m_dirs.end(); ++iter) {
-
-      std::list<std::string> l;
-      directory_get_files_with_ext(*iter, ext, l);
-      
-      for(std::list<std::string>::const_iterator mod_iter = l.begin();
-          mod_iter != l.end(); ++mod_iter) {
-
-        Glib::Module module(*iter + "/" + file_basename(*mod_iter), 
-                            Glib::MODULE_BIND_LOCAL);
-        DBG_OUT("load module %s", file_basename(*mod_iter).c_str());
-
-        if(!module) {
-          DBG_OUT("error loading %s", Glib::Module::get_last_error().c_str());
-          continue;
-        }
-        void * func = NULL;
-        bool found = module.get_symbol("dynamic_module_instanciate", func);
-
-        if(!found) {
-          DBG_OUT("error getting symbol %s", Glib::Module::get_last_error().c_str());
-          continue;
-        }
-        instanciate_func_t real_func = (instanciate_func_t)func;
-        DynamicModule * dmod = (*real_func)();
-
-        if(dmod) {
-          m_modules.push_back(dmod);
-          module.make_resident();
-        }
-      }
+    void *func = NULL;
+    bool found = module.get_symbol("dynamic_module_instanciate", func);
+    if(!found) {
+      DBG_OUT(_("Error getting symbol dynamic_module_instanciate: %s"),
+              Glib::Module::get_last_error().c_str());
+      return dmod;
+    }
+
+    instanciate_func_t real_func = (instanciate_func_t)func;
+    dmod = (*real_func)();
+    if(dmod) {
+      m_modules[mod] = dmod;
+      module.make_resident();
+    }
+
+    return dmod;
+  }
 
+  void ModuleManager::load_modules(const std::list<std::string> & modules)
+  {
+    for(std::list<std::string>::const_iterator mod_iter = modules.begin();
+        mod_iter != modules.end(); ++mod_iter) {
+      load_module(*mod_iter);
     }
   }
 
-const DynamicModule * ModuleManager::get_module(const std::string & id) const
-{
-  for(ModuleList::const_iterator iter = m_modules.begin();
-      iter != m_modules.end(); ++iter) {
-    if (id == (*iter)->id())
-      return *iter;
+  DynamicModule * ModuleManager::get_module(const std::string & module) const
+  {
+    ModuleMap::const_iterator iter = m_modules.find(module);
+    if(iter != m_modules.end()) {
+      return iter->second;
+    }
+    return 0;
   }
-  return 0;
-}
 
 }
diff --git a/src/sharp/modulemanager.hpp b/src/sharp/modulemanager.hpp
index 30ce8d1..ade87f0 100644
--- a/src/sharp/modulemanager.hpp
+++ b/src/sharp/modulemanager.hpp
@@ -1,6 +1,7 @@
 /*
  * gnote
  *
+ * Copyright (C) 2013 Aurimas Cernius
  * Copyright (C) 2009 Hubert Figuiere
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -27,32 +28,28 @@
 #ifndef __SHARP_MODULEMANAGER_HPP_
 #define __SHARP_MODULEMANAGER_HPP_
 
-#include <list>
-#include <set>
+#include <map>
 #include <string>
 
 namespace sharp {
 
 class DynamicModule;
 
-typedef std::list<DynamicModule *> ModuleList;
+typedef std::map<std::string, DynamicModule*> ModuleMap;
 
 class ModuleManager 
 {
 public:
   ~ModuleManager();
 
-  /** add path to list the modules */
-  void add_path(const std::string & dir);
-  void load_modules();
+  DynamicModule *load_module(const std::string & module);
+  void load_modules(const std::list<std::string> & modules);
   
-  const ModuleList & get_modules() const
+  const ModuleMap & get_modules() const
     { return m_modules; }
-  const DynamicModule * get_module(const std::string & id) const;
+  DynamicModule *get_module(const std::string & module) const;
 private:
-  std::set<std::string> m_dirs;
-
-  ModuleList m_modules;
+  ModuleMap m_modules;
 };
 
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]