[gnote] support addins.



commit 169166ea8e370c35936dfdfaa92b223fd5447ca7
Author: Hubert Figuiere <hub figuiere net>
Date:   Mon Apr 20 17:58:20 2009 -0400

    support addins.
    Ported fixedwidth adding
    (Bug #578980)
---
 .gitignore                                    |    1 +
 NEWS                                          |    7 ++-
 configure.ac                                  |    2 +
 po/POTFILES.in                                |    2 +
 src/Makefile.am                               |   11 +++-
 src/abstractaddin.hpp                         |    5 +-
 src/addinmanager.cpp                          |   63 +++++++++++----
 src/addinmanager.hpp                          |   26 +++----
 src/addins/Makefile.am                        |    4 +
 src/addins/fixedwidth/Makefile.am             |   18 +++++
 src/addins/fixedwidth/fixedwidthmenuitem.cpp  |   61 +++++++++++++++
 src/addins/fixedwidth/fixedwidthmenuitem.hpp  |   56 ++++++++++++++
 src/addins/fixedwidth/fixedwidthnoteaddin.cpp |  100 +++++++++++++++++++++++++
 src/addins/fixedwidth/fixedwidthnoteaddin.hpp |   76 +++++++++++++++++++
 src/addins/fixedwidth/fixedwidthtag.hpp       |   50 ++++++++++++
 src/gnote.cpp                                 |    5 +-
 src/noteaddin.cpp                             |    2 +
 src/noteaddin.hpp                             |    1 +
 src/notewindow.hpp                            |    3 +-
 src/preferencesdialog.cpp                     |   28 +++++--
 src/preferencesdialog.hpp                     |    6 +-
 src/preferencetabaddin.hpp                    |   67 +++++++++++++++++
 src/sharp/directory.cpp                       |    3 +
 src/sharp/dynamicmodule.cpp                   |   72 ++++++++++++++++++
 src/sharp/dynamicmodule.hpp                   |   81 ++++++++++++++++++++
 src/sharp/modulefactory.hpp                   |   74 ++++++++++++++++++
 src/sharp/modulemanager.cpp                   |   98 ++++++++++++++++++++++++
 src/sharp/modulemanager.hpp                   |   61 +++++++++++++++
 28 files changed, 932 insertions(+), 51 deletions(-)

diff --git a/.gitignore b/.gitignore
index 02273b9..9118a77 100644
--- a/.gitignore
+++ b/.gitignore
@@ -35,6 +35,7 @@ src/stringtest
 src/notetest
 src/dttest
 src/libgnote.a
+src/addins/fixedwidth/fixedwidth.so
 m4/intltool.m4
 m4/libtool.m4
 m4/ltoptions.m4
diff --git a/NEWS b/NEWS
index a5b0ac9..d1dafe0 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,9 @@
-0.1.3
+0.2.0
+
+New features
+
+  * Now support addins:
+    - Fixed Width (Bug #578980)
 
 Fixes:
 
diff --git a/configure.ac b/configure.ac
index 25eafe7..b22bb48 100644
--- a/configure.ac
+++ b/configure.ac
@@ -184,6 +184,8 @@ data/Makefile
 data/icons/Makefile
 libtomboy/Makefile
 src/Makefile
+src/addins/Makefile
+src/addins/fixedwidth/Makefile
 po/Makefile.in
 po/Makefile
 help/Makefile
diff --git a/po/POTFILES.in b/po/POTFILES.in
index f2e5de2..4b67a9d 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -19,3 +19,5 @@ src/notebooks/notebookmanager.cpp
 src/notebooks/notebooknewnotemenuitem.cpp
 src/notebooks/notebookmenuitem.cpp
 src/notebooks/notebooknoteaddin.cpp
+src/addins/fixedwidth/fixedwidthmenuitem.cpp
+src/addins/fixedwidth/fixedwidthnoteaddin.cpp
diff --git a/src/Makefile.am b/src/Makefile.am
index 2c31943..a94442e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,12 +1,16 @@
 
 
+SUBDIRS = addins
+
 
 INCLUDES = -I$(top_srcdir)
 AM_CPPFLAGS= LIBGTKMM_CFLAGS@ @LIBGLIBMM_CFLAGS@ \
 	@LIBXMLPP_CFLAGS@ @GCONF_CFLAGS@ @GTK_CFLAGS@ \
 	@GTKSPELL_CFLAGS@ \
 	-DGNOTE_LOCALEDIR=\"@GNOTE_LOCALEDIR \" \
-	-DDATADIR=\"$(datadir)\"
+	-DDATADIR=\"$(datadir)\" -DLIBDIR=\"$(libdir)\"
+
+AM_LDFLAGS=-Wl,--export-dynamic
 
 GNOTE_LIBS = @LIBGLIBMM_LIBS@ @LIBGTKMM_LIBS@ @LIBXMLPP_LIBS@ \
 	@GCONF_LIBS@ @BOOST_FILESYSTEM_LIBS@ @BOOST_REGEX_LIBS@ \
@@ -39,9 +43,13 @@ gnote_SOURCES = main.cpp
 libgnote_a_SOURCES = \
 	base/singleton.hpp \
 	sharp/datetime.hpp sharp/datetime.cpp \
+	sharp/dynamicmodule.hpp sharp/dynamicmodule.cpp \
 	sharp/directory.hpp sharp/directory.cpp \
 	sharp/exception.hpp sharp/exception.cpp \
 	sharp/files.hpp sharp/files.cpp \
+	sharp/map.hpp \
+	sharp/modulefactory.hpp \
+	sharp/modulemanager.hpp sharp/modulemanager.cpp \
 	sharp/propertyeditor.hpp sharp/propertyeditor.cpp \
 	sharp/string.hpp sharp/string.cpp \
 	sharp/uri.hpp sharp/uri.cpp \
@@ -65,6 +73,7 @@ libgnote_a_SOURCES = \
 	notewindow.hpp notewindow.cpp \
 	preferences.hpp preferences.cpp \
 	preferencesdialog.hpp preferencesdialog.cpp \
+	preferencetabaddin.hpp \
 	prefskeybinder.hpp prefskeybinder.cpp \
 	recenttreeview.hpp \
 	recentchanges.hpp recentchanges.cpp \
diff --git a/src/abstractaddin.hpp b/src/abstractaddin.hpp
index f9588f4..16909fa 100644
--- a/src/abstractaddin.hpp
+++ b/src/abstractaddin.hpp
@@ -25,10 +25,13 @@
 
 #include <sigc++/trackable.h>
 
+#include "sharp/modulefactory.hpp"
+
 namespace gnote {
 
 class AbstractAddin
-  : public sigc::trackable
+  : public sharp::IInterface
+  , public sigc::trackable
 {
 public:
   AbstractAddin();
diff --git a/src/addinmanager.cpp b/src/addinmanager.cpp
index 78b8ea4..4bce85a 100644
--- a/src/addinmanager.cpp
+++ b/src/addinmanager.cpp
@@ -18,10 +18,15 @@
  */
 
 
+#include <config.h>
 
 #include <boost/bind.hpp>
 
+#include "sharp/map.hpp"
+#include "sharp/dynamicmodule.hpp"
+
 #include "addinmanager.hpp"
+#include "debug.hpp"
 #include "watchers.hpp"
 #include "notebooks/notebookapplicationaddin.hpp"
 #include "notebooks/notebooknoteaddin.hpp"
@@ -30,7 +35,7 @@ namespace gnote {
 
 #define REGISTER_NOTE_ADDIN(klass) \
   m_note_addin_infos.insert(std::make_pair(typeid(klass).name(),        \
-  new NoteAddinInfo(sigc::ptr_fun(&klass::create), typeid(klass).name())))
+                                           new sharp::IfaceFactory<klass>))
 
 #define REGISTER_APP_ADDIN(klass) \
   m_app_addins.insert(std::make_pair(typeid(klass).name(),        \
@@ -44,19 +49,12 @@ namespace gnote {
 
   AddinManager::~AddinManager()
   {
-    for(AppAddinMap::const_iterator iter = m_app_addins.begin();
-        iter != m_app_addins.end(); ++iter) {
-      delete iter->second;
-    }
+    sharp::map_delete_all_second(m_app_addins);
     for(NoteAddinMap::const_iterator iter = m_note_addins.begin();
         iter != m_note_addins.end(); ++iter) {
       std::for_each(iter->second.begin(), iter->second.end(), 
                     boost::bind(&boost::checked_delete<NoteAddin>, _1));
     }
-    for(IdInfoMap::const_iterator iter = m_note_addin_infos.begin();
-        iter != m_note_addin_infos.end(); ++iter) {
-      delete iter->second;
-    }
   }
 
   void AddinManager::initialize_sharp_addins()
@@ -73,6 +71,28 @@ namespace gnote {
     REGISTER_NOTE_ADDIN(notebooks::NotebookNoteAddin);
    
     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);
+
+    m_module_manager.load_modules();
+
+    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;
+      if(!dmod) {
+        continue;
+      }
+
+      sharp::IfaceFactoryBase * f = dmod->query_interface(NoteAddin::IFACE_NAME);
+      if(f) {
+        m_note_addin_infos.insert(std::make_pair(typeid(*f).name(), f));
+      }
+
+      
+    }
   }
 
   void AddinManager::load_addins_for_note(const Note::Ptr & note)
@@ -84,20 +104,29 @@ namespace gnote {
     for(IdInfoMap::const_iterator iter = m_note_addin_infos.begin();
         iter != m_note_addin_infos.end(); ++iter) {
 
-      const IdInfoMap::value_type & addin_info(*iter);
-      NoteAddin * addin = addin_info.second->factory();
-      addin->initialize(note);
-      loaded.push_back(addin);
+      const IdInfoMap::value_type & addin_info(*iter); 
+      sharp::IInterface* iface = (*addin_info.second)();
+      NoteAddin * addin = dynamic_cast<NoteAddin *>(iface);
+      if(addin) {
+        addin->initialize(note);
+        loaded.push_back(addin);
+      }
+      else {
+        DBG_OUT("wrong type for the interface: %s", typeid(*iface).name());
+        delete iface;
+      }
     }
   }
 
 
   void AddinManager::get_application_addins(std::list<ApplicationAddin*> & l) const
   {
-    for(AppAddinMap::const_iterator iter = m_app_addins.begin();
-        iter != m_app_addins.end(); ++iter) {
-      l.push_back(iter->second);
-    }
+    sharp::map_get_values(m_app_addins, l);
   }
 
+
+  void AddinManager::get_preference_tab_addins(std::list<PreferenceTabAddin *> &l) const
+  {
+    sharp::map_get_values(m_pref_tab_addins, l);
+  }
 }
diff --git a/src/addinmanager.hpp b/src/addinmanager.hpp
index 328f2f5..2312dc9 100644
--- a/src/addinmanager.hpp
+++ b/src/addinmanager.hpp
@@ -29,27 +29,16 @@
 
 #include <sigc++/signal.h>
 
+#include "sharp/modulemanager.hpp"
 #include "note.hpp"
 #include "noteaddin.hpp"
 
 namespace gnote {
 
-  class ApplicationAddin;
+class ApplicationAddin;
+class PreferenceTabAddin;
 
 
-class NoteAddinInfo
-{
-public:
-  NoteAddinInfo(const sigc::slot<NoteAddin*> & f,
-                const char * id)
-    : addin_id(id)
-    {
-      factory.connect(f);
-    }
-  sigc::signal<NoteAddin*> factory;
-  std::string              addin_id;
-};
-
 class AddinManager
 {
 public:
@@ -58,7 +47,7 @@ public:
 
   void load_addins_for_note(const Note::Ptr &);
   void get_application_addins(std::list<ApplicationAddin*> &) const;
-  /// get_preference_tab_addins();
+  void get_preference_tab_addins(std::list<PreferenceTabAddin *> &) const;
 
   sigc::signal<void> & signal_application_addin_list_changed();
 private:
@@ -66,14 +55,19 @@ private:
   void initialize_sharp_addins();
     
   const std::string m_gnote_conf_dir;
+  sharp::ModuleManager m_module_manager;
   /// Key = TypeExtensionNode.Id
   typedef std::map<std::string, ApplicationAddin*> AppAddinMap;
   AppAddinMap                               m_app_addins;
   typedef std::map<Note::Ptr, std::list<NoteAddin*> > NoteAddinMap;
   NoteAddinMap                              m_note_addins;
   /// Key = TypeExtensionNode.Id
-  typedef std::map<std::string, NoteAddinInfo*> IdInfoMap;
+  /// the iface factory is not owned by the manager.
+  /// TODO: make sure it is removed if the dynamic module is unloaded.
+  typedef std::map<std::string, sharp::IfaceFactoryBase*> IdInfoMap;
   IdInfoMap                                m_note_addin_infos;
+  typedef std::map<std::string, PreferenceTabAddin*> IdPrefTabAddinMap;
+  IdPrefTabAddinMap                         m_pref_tab_addins;
   sigc::signal<void>         m_application_addin_list_changed;
 };
 
diff --git a/src/addins/Makefile.am b/src/addins/Makefile.am
new file mode 100644
index 0000000..dc00cef
--- /dev/null
+++ b/src/addins/Makefile.am
@@ -0,0 +1,4 @@
+
+
+
+SUBDIRS = fixedwidth
\ No newline at end of file
diff --git a/src/addins/fixedwidth/Makefile.am b/src/addins/fixedwidth/Makefile.am
new file mode 100644
index 0000000..b40e258
--- /dev/null
+++ b/src/addins/fixedwidth/Makefile.am
@@ -0,0 +1,18 @@
+
+
+
+INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src
+AM_CPPFLAGS= LIBGTKMM_CFLAGS@ @LIBGLIBMM_CFLAGS@ \
+	@GCONF_CFLAGS@ \
+	-DDATADIR=\"$(datadir)\" -DLIBDIR=\"$(libdir)\"
+
+AM_LDFLAGS = -avoid-version -module -Wl,--export-dynamic
+
+addinsdir = @libdir@/@PACKAGE_NAME@/addins/@VERSION@
+addins_LTLIBRARIES = fixedwidth.la
+
+
+fixedwidth_la_SOURCES = fixedwidthnoteaddin.hpp fixedwidthnoteaddin.cpp \
+	fixedwidthtag.hpp \
+	fixedwidthmenuitem.hpp fixedwidthmenuitem.cpp \
+	$(NULL)
diff --git a/src/addins/fixedwidth/fixedwidthmenuitem.cpp b/src/addins/fixedwidth/fixedwidthmenuitem.cpp
new file mode 100644
index 0000000..81ca48b
--- /dev/null
+++ b/src/addins/fixedwidth/fixedwidthmenuitem.cpp
@@ -0,0 +1,61 @@
+/*
+ * gnote
+ *
+ * Copyright (C) 2009 Hubert Figuiere
+ *
+ * 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 <glibmm/i18n.h>
+
+#include "noteaddin.hpp"
+#include "notewindow.hpp"
+
+#include "fixedwidthmenuitem.hpp"
+
+
+namespace fixedwidth {
+
+  FixedWidthMenuItem::FixedWidthMenuItem(gnote::NoteAddin *addin)
+    : Gtk::CheckMenuItem(Glib::ustring("<span font_family=\"monospace\">")
+                         + _("_Fixed Width") + "</span>", true)
+    , m_note_addin(addin)
+    , m_event_freeze(false)
+  {
+    gnote::NoteTextMenu::markup_label(*this);
+    m_note_addin->get_window()->text_menu()->signal_show().connect(
+      sigc::mem_fun(*this, &FixedWidthMenuItem::menu_shown));
+
+    show_all();
+  }
+
+
+  void FixedWidthMenuItem::on_activate()
+  {
+    if (!m_event_freeze)
+				m_note_addin->get_buffer()->toggle_active_tag ("monospace");
+  }
+
+
+  void FixedWidthMenuItem::menu_shown()
+  {
+    m_event_freeze = true;
+    set_active(m_note_addin->get_buffer()->is_active_tag ("monospace"));
+    m_event_freeze = false;
+  }
+
+
+}
diff --git a/src/addins/fixedwidth/fixedwidthmenuitem.hpp b/src/addins/fixedwidth/fixedwidthmenuitem.hpp
new file mode 100644
index 0000000..620f69a
--- /dev/null
+++ b/src/addins/fixedwidth/fixedwidthmenuitem.hpp
@@ -0,0 +1,56 @@
+/*
+ * gnote
+ *
+ * Copyright (C) 2009 Hubert Figuiere
+ *
+ * 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 __FIXED_WIDTH_MENUITEM_HPP_
+#define __FIXED_WIDTH_MENUITEM_HPP_
+
+#include <gtkmm/checkmenuitem.h>
+
+namespace gnote {
+  class NoteAddin;
+}
+
+
+namespace fixedwidth {
+
+
+class FixedWidthMenuItem
+  : public Gtk::CheckMenuItem
+{
+public:
+  FixedWidthMenuItem(gnote::NoteAddin *);
+  
+protected:
+  virtual void on_activate();
+
+private:
+  void menu_shown();
+
+  gnote::NoteAddin * m_note_addin;
+  bool m_event_freeze;
+};
+
+
+
+}
+
+
+#endif
diff --git a/src/addins/fixedwidth/fixedwidthnoteaddin.cpp b/src/addins/fixedwidth/fixedwidthnoteaddin.cpp
new file mode 100644
index 0000000..c822c1c
--- /dev/null
+++ b/src/addins/fixedwidth/fixedwidthnoteaddin.cpp
@@ -0,0 +1,100 @@
+/*
+ * gnote
+ *
+ * Copyright (C) 2009 Hubert Figuiere
+ * Original C# file
+ * (C) 2006 Ryan Lortie <desrt desrt ca>
+ *
+ * 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/>.
+ */
+
+
+// Translated from FixedWidthNoteAddin.cs:
+// Add a 'fixed width' item to the font styles menu.
+
+#include <glibmm/i18n.h>
+
+#include "sharp/modulefactory.hpp"
+#include "fixedwidthmenuitem.hpp"
+#include "fixedwidthnoteaddin.hpp"
+#include "fixedwidthtag.hpp"
+
+
+namespace fixedwidth {
+
+  FixedWidthModule::FixedWidthModule()
+  {
+    add(gnote::NoteAddin::IFACE_NAME, 
+        new sharp::IfaceFactory<FixedWidthNoteAddin>);
+  }
+
+  const char * FixedWidthModule::id() const
+  {
+    return "FixedWidthAddin";
+  }
+  const char * FixedWidthModule::name() const
+  {
+    // this is the name of the plugin.
+    return _("Fixed Width");
+  }
+  const char * FixedWidthModule::description() const
+  {
+    return _("Adds fixed-width font style.");
+  }
+  const char * FixedWidthModule::authors() const
+  {
+    return "";
+  }
+  const char * FixedWidthModule::category() const
+  {
+    return "Formatting";
+  }
+  const char * FixedWidthModule::version() const
+  {
+    return "0.1";
+  }
+
+
+
+  void FixedWidthNoteAddin::initialize ()
+  {
+    // If a tag of this name already exists, don't install.
+    if (!get_note()->get_tag_table()->lookup ("monospace")) {
+      m_tag = Glib::RefPtr<Gtk::TextTag>(new FixedWidthTag ());
+				get_note()->get_tag_table()->add (m_tag);
+			}
+
+  }
+
+
+  void FixedWidthNoteAddin::shutdown ()
+  {
+	// Remove the tag only if we installed it.
+    if (m_tag) {
+      get_note()->get_tag_table()->remove (m_tag);
+    }
+  }
+
+
+  void FixedWidthNoteAddin::on_note_opened ()
+  {
+    // Add here instead of in Initialize to avoid creating unopened
+    // notes' windows/buffers.
+    add_text_menu_item (new FixedWidthMenuItem (this));
+  }
+
+
+
+}
+
diff --git a/src/addins/fixedwidth/fixedwidthnoteaddin.hpp b/src/addins/fixedwidth/fixedwidthnoteaddin.hpp
new file mode 100644
index 0000000..6d583bf
--- /dev/null
+++ b/src/addins/fixedwidth/fixedwidthnoteaddin.hpp
@@ -0,0 +1,76 @@
+/*
+ * gnote
+ *
+ * Copyright (C) 2009 Hubert Figuiere
+ * Original C# file
+ * (C) 2006 Ryan Lortie <desrt desrt ca>
+ *
+ * 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/>.
+ */
+
+
+
+
+// Translated from FixedWidthNoteAddin.cs:
+
+// Add a 'fixed width' item to the font styles menu.
+
+
+#ifndef __ADDIN_FIXEDWIDTHNOTEADDIN_H_
+#define __ADDIN_FIXEDWIDTHNOTEADDIN_H_
+
+#include <gtkmm/texttag.h>
+
+#include "sharp/dynamicmodule.hpp"
+#include "noteaddin.hpp"
+
+namespace fixedwidth {
+
+  class FixedWidthModule
+    : public sharp::DynamicModule
+  {
+  public:
+    FixedWidthModule();
+    virtual const char * id() const;
+    virtual const char * name() const;
+    virtual const char * description() const;
+    virtual const char * authors() const;
+    virtual const char * category() const;
+    virtual const char * version() const;
+  };
+
+
+  DECLARE_MODULE(FixedWidthModule);
+
+  class FixedWidthNoteAddin
+    : public gnote::NoteAddin
+  {
+  public:
+    static FixedWidthNoteAddin* create()
+      { 
+        return new FixedWidthNoteAddin();
+      }
+    virtual void initialize ();
+    virtual void shutdown ();
+    virtual void on_note_opened ();
+  private:
+    Glib::RefPtr<Gtk::TextTag> m_tag;
+  };
+
+
+}
+
+
+#endif
+
diff --git a/src/addins/fixedwidth/fixedwidthtag.hpp b/src/addins/fixedwidth/fixedwidthtag.hpp
new file mode 100644
index 0000000..09bd501
--- /dev/null
+++ b/src/addins/fixedwidth/fixedwidthtag.hpp
@@ -0,0 +1,50 @@
+/*
+ * gnote
+ *
+ * Copyright (C) 2009 Hubert Figuiere
+ *
+ * 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 __ADDIN_FIXED_WIDTH_TAG_HPP_
+#define __ADDIN_FIXED_WIDTH_TAG_HPP_
+
+#include <string>
+
+#include "notetag.hpp"
+
+
+namespace fixedwidth {
+
+
+class FixedWidthTag
+  : public gnote::NoteTag
+{
+public:
+  FixedWidthTag()
+    : gnote::NoteTag("monospace", CAN_GROW | CAN_UNDO)
+    {
+      property_family() = "monospace";
+    }
+};
+
+
+
+}
+
+#endif
diff --git a/src/gnote.cpp b/src/gnote.cpp
index 55a83ab..454ae3d 100644
--- a/src/gnote.cpp
+++ b/src/gnote.cpp
@@ -223,8 +223,9 @@ namespace gnote {
   void Gnote::on_show_preferences_action()
   {
     if(!m_prefsdlg) {
-      m_prefsdlg = new PreferencesDialog(/*addin manager*/);
-      m_prefsdlg->signal_response().connect(sigc::mem_fun(*this, &Gnote::on_preferences_response));
+      m_prefsdlg = new PreferencesDialog(m_manager->get_addin_manager());
+      m_prefsdlg->signal_response().connect(
+        sigc::mem_fun(*this, &Gnote::on_preferences_response));
     }
     m_prefsdlg->present();
   }
diff --git a/src/noteaddin.cpp b/src/noteaddin.cpp
index 1313d0b..35d46e4 100644
--- a/src/noteaddin.cpp
+++ b/src/noteaddin.cpp
@@ -26,6 +26,8 @@
 
 namespace gnote {
 
+  const char * NoteAddin::IFACE_NAME = "gnote::NoteAddin";
+
   void NoteAddin::initialize(const Note::Ptr & note)
   {
     m_note = note;
diff --git a/src/noteaddin.hpp b/src/noteaddin.hpp
index 5e5b3e4..8f94094 100644
--- a/src/noteaddin.hpp
+++ b/src/noteaddin.hpp
@@ -49,6 +49,7 @@ class NoteAddin
   : public AbstractAddin
 {
 public:
+  static const char * IFACE_NAME;
   /// factory method
 //  static NoteAddin *create() { return NULL; }
   void initialize(const Note::Ptr & note);
diff --git a/src/notewindow.hpp b/src/notewindow.hpp
index 69346d4..71e0fac 100644
--- a/src/notewindow.hpp
+++ b/src/notewindow.hpp
@@ -47,12 +47,13 @@ class NoteTextMenu
 public:
   NoteTextMenu(const Glib::RefPtr<Gtk::AccelGroup>&, 
                const Glib::RefPtr<NoteBuffer> & buffer, UndoManager& undo_manager);
+
+  static void markup_label (Gtk::MenuItem & item);
   
 protected:
   virtual void on_show();
 
 private:
-  void markup_label (Gtk::MenuItem & item);
   void refresh_sizing_state();
   void refresh_state();
   void font_style_clicked(Gtk::CheckMenuItem * item);
diff --git a/src/preferencesdialog.cpp b/src/preferencesdialog.cpp
index ad78c00..51a9a94 100644
--- a/src/preferencesdialog.cpp
+++ b/src/preferencesdialog.cpp
@@ -38,23 +38,27 @@
 #include <gtkmm/table.h>
 
 #include "sharp/propertyeditor.hpp"
+#include "addinmanager.hpp"
+#include "debug.hpp"
 #include "gnote.hpp"
 #include "notemanager.hpp"
 #include "notewindow.hpp"
 #include "preferencesdialog.hpp"
 #include "preferences.hpp"
+#include "preferencetabaddin.hpp"
 #include "utils.hpp"
 #include "watchers.hpp"
 
 namespace gnote {
 
-  PreferencesDialog::PreferencesDialog()
+  PreferencesDialog::PreferencesDialog(AddinManager & addinmanager)
     : Gtk::Dialog()
     , syncAddinCombo(NULL)
     , syncAddinPrefsContainer(NULL)
     , syncAddinPrefsWidget(NULL)
     , resetSyncAddinButton(NULL)
     , saveSyncAddinButton(NULL)
+    , m_addin_manager(addinmanager)
   {
 //    set_icon(utils::get_icon("gnote"));
     set_has_separator(false);
@@ -88,20 +92,26 @@ namespace gnote {
                            _("Add-ins"));
 
       // TODO: Figure out a way to have these be placed in a specific order
-#if 0
-      foreach (PreferenceTabAddin tabAddin in addin_manager.GetPreferenceTabAddins ()) {
-        Logger.Debug ("Adding preference tab addin: {0}", tabAddin.GetType ().Name);
+    std::list<PreferenceTabAddin *> tabAddins;
+    m_addin_manager.get_preference_tab_addins(tabAddins);
+    for(std::list<PreferenceTabAddin *>::const_iterator iter = tabAddins.begin();
+          iter != tabAddins.end(); ++iter) {
+      PreferenceTabAddin *tabAddin = *iter;
+      DBG_OUT("Adding preference tab addin: %s", 
+              typeid(*tabAddin).name());
         try {
           std::string tabName;
           Gtk::Widget *tabWidget;
-          if (tabAddin.GetPreferenceTabWidget (this, out tabName, out tabWidget) == true) {
-            notebook->append_page (tabWidget, new Gtk::Label (tabName));
+          if (tabAddin->get_preference_tab_widget (this, tabName, tabWidget)) {
+            notebook->append_page (*manage(tabWidget), tabName);
           }
-        } catch {
-          Logger.Warn ("Problems adding preferences tab addin: {0}", tabAddin.GetType ().Name);
+        } 
+        catch(...)
+        {
+          DBG_OUT("Problems adding preferences tab addin: %s", 
+                  typeid(*tabAddin).name());
         }
       }
-#endif
 
       get_vbox()->pack_start (*notebook, true, true, 0);
 
diff --git a/src/preferencesdialog.hpp b/src/preferencesdialog.hpp
index 29e695a..0aad3eb 100644
--- a/src/preferencesdialog.hpp
+++ b/src/preferencesdialog.hpp
@@ -34,13 +34,13 @@
 namespace gnote {
 
 class SyncServiceAddin;
-
+class AddinManager;
 
 class PreferencesDialog
   : public Gtk::Dialog
 {
 public:
-  PreferencesDialog();
+  PreferencesDialog(AddinManager & addinmanager);
   
 
   Gtk::Widget *make_editing_pane();
@@ -92,7 +92,7 @@ private:
   Gtk::Widget *syncAddinPrefsWidget;
   Gtk::Button *resetSyncAddinButton;
   Gtk::Button *saveSyncAddinButton;
-  //AddinManager addin_manager;
+  AddinManager &m_addin_manager;
     
   Gtk::Button *font_button;
   Gtk::Label  *font_face;
diff --git a/src/preferencetabaddin.hpp b/src/preferencetabaddin.hpp
new file mode 100644
index 0000000..feaa6b6
--- /dev/null
+++ b/src/preferencetabaddin.hpp
@@ -0,0 +1,67 @@
+/*
+ * gnote
+ *
+ * Copyright (C) 2009 Hubert Figuiere
+ *
+ * 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 _PREFERENCE_TAB_ADDIN_HPP_
+#define _PREFERENCE_TAB_ADDIN_HPP_
+
+#include <string>
+
+#include <gtkmm/widget.h>
+
+#include "abstractaddin.hpp"
+
+
+namespace gnote {
+
+	/// Implement this interface to provide a new tab in
+	/// Tomboy's Preferences Dialog.  If you are writing
+	/// a standard add-in, DO NOT ABUSE THIS (you should
+	/// normally extend the /Tomboy/AddinPreferences
+	/// extension point).
+	class PreferenceTabAddin 
+    : public AbstractAddin
+	{
+		/// <summary>
+		/// Returns a Gtk.Widget to place in a new tab in Tomboy's
+		/// preferences dialog.
+		/// <param name="parent">The preferences dialog.  Add-ins should
+		/// use this for connecting to Hidden or other events as needed.
+		/// Another use would be to pop open dialogs, so they can properly
+		/// set their parent.
+		/// </param>
+		/// <param name="tabLabel">The string to be used in the tab's
+		/// label.</param>
+		/// <param name="preferenceWidget">The Gtk.Widget to use as the
+		/// content of the tab page.</param>
+		/// <returns>Returns <value>true</value> if the widget is
+		/// valid/created or <value>false</value> otherwise.</returns>
+		/// </summary>
+  public:
+    virtual bool get_preference_tab_widget (
+									PreferencesDialog * parent,
+									std::string  & tabLabel,
+									Gtk::Widget * preferenceWidget) = 0;
+	};
+
+}
+
+#endif
diff --git a/src/sharp/directory.cpp b/src/sharp/directory.cpp
index 54db968..514317b 100644
--- a/src/sharp/directory.cpp
+++ b/src/sharp/directory.cpp
@@ -40,6 +40,9 @@ namespace sharp {
   {
     boost::filesystem::path p(dir);
     
+    if(!exists(p)) {
+      return;
+    }
     boost::filesystem::directory_iterator end_itr; 
     for ( boost::filesystem::directory_iterator itr( p );
           itr != end_itr;
diff --git a/src/sharp/dynamicmodule.cpp b/src/sharp/dynamicmodule.cpp
new file mode 100644
index 0000000..a77da2f
--- /dev/null
+++ b/src/sharp/dynamicmodule.cpp
@@ -0,0 +1,72 @@
+/*
+ * gnote
+ *
+ * Copyright (C) 2009 Hubert Figuiere
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+
+
+#include "sharp/dynamicmodule.hpp"
+#include "sharp/map.hpp"
+#include "sharp/modulefactory.hpp"
+
+
+namespace sharp {
+
+  DynamicModule::DynamicModule()
+  {
+  }
+
+
+  DynamicModule::~DynamicModule()
+  {
+    sharp::map_delete_all_second(m_interfaces);
+  }
+
+  
+  IfaceFactoryBase * DynamicModule::query_interface(const char * intf) const
+  {
+    std::map<std::string, IfaceFactoryBase *>::const_iterator iter;
+    iter = m_interfaces.find(intf);
+    if(iter == m_interfaces.end()) {
+      return NULL;
+    }
+
+    return iter->second;
+  }
+
+
+  void DynamicModule::add(const char * iface, IfaceFactoryBase* mod)
+  {
+    std::map<std::string, IfaceFactoryBase *>::iterator iter;
+    iter = m_interfaces.find(iface);
+    if(iter == m_interfaces.end()) {
+      m_interfaces.insert(std::make_pair(iface, mod));
+    }
+    else {
+      // replace
+      delete iter->second;
+      iter->second = mod;
+    }
+  }
+
+  
+}
diff --git a/src/sharp/dynamicmodule.hpp b/src/sharp/dynamicmodule.hpp
new file mode 100644
index 0000000..c542e1a
--- /dev/null
+++ b/src/sharp/dynamicmodule.hpp
@@ -0,0 +1,81 @@
+/*
+ * gnote
+ *
+ * Copyright (C) 2009 Hubert Figuiere
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+
+
+
+#ifndef __SHARP_DYNAMICMODULE_HPP_
+#define __SHARP_DYNAMICMODULE_HPP_
+
+#include <map>
+#include <string>
+
+
+namespace sharp {
+
+class IfaceFactoryBase;
+class DynamicModule;
+
+typedef DynamicModule* (*instanciate_func_t)();
+
+#define DECLARE_MODULE(klass) \
+  extern "C" sharp::DynamicModule* dynamic_module_instanciate() \
+  { return new klass; }
+
+class DynamicModule
+{
+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 const char * category() const = 0;
+  virtual const char * version() const = 0;
+  /** Query an "interface" 
+   * may return NULL
+   */
+  IfaceFactoryBase * query_interface(const char *) const;
+  /** Check if the module provide and interface */
+  bool has_interface(const char *) const;
+
+  void load();
+
+protected:
+  DynamicModule();
+
+  /** */
+  void add(const char * iface, IfaceFactoryBase*);
+  
+private:
+  std::map<std::string, IfaceFactoryBase *> m_interfaces;
+};
+
+
+
+}
+
+#endif
diff --git a/src/sharp/modulefactory.hpp b/src/sharp/modulefactory.hpp
new file mode 100644
index 0000000..d0e93e6
--- /dev/null
+++ b/src/sharp/modulefactory.hpp
@@ -0,0 +1,74 @@
+/*
+ * gnote
+ *
+ * Copyright (C) 2009 Hubert Figuiere
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+
+
+#ifndef __SHARP_MODULE_FACTORY_HPP__
+#define __SHARP_MODULE_FACTORY_HPP__
+
+
+namespace sharp {
+
+class IInterface
+{
+public:
+  virtual ~IInterface()
+    {
+    }
+protected:
+  IInterface()
+    {
+    }
+};
+
+
+class IfaceFactoryBase
+{
+public:
+  virtual ~IfaceFactoryBase()
+    {}
+  
+  /** instanciate. The returned object pointer is owned by the caller. 
+   * it MAY return NULL
+   */
+  virtual IInterface *operator()() = 0;
+};
+
+
+template <typename _Interface>
+class IfaceFactory
+  : public IfaceFactoryBase
+{
+public:
+  virtual IInterface *operator()()
+    {
+      return _Interface::create();
+    }
+};
+
+}
+
+
+#endif
+
diff --git a/src/sharp/modulemanager.cpp b/src/sharp/modulemanager.cpp
new file mode 100644
index 0000000..62a4b3c
--- /dev/null
+++ b/src/sharp/modulemanager.cpp
@@ -0,0 +1,98 @@
+/*
+ * gnote
+ *
+ * Copyright (C) 2009 Hubert Figuiere
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+
+
+#include <dlfcn.h>
+
+#include <gmodule.h>
+#include <glibmm/module.h>
+
+#include "sharp/directory.hpp"
+#include "sharp/dynamicmodule.hpp"
+#include "sharp/files.hpp"
+#include "sharp/map.hpp"
+#include "sharp/modulemanager.hpp"
+#include "debug.hpp"
+
+namespace sharp {
+
+
+  ModuleManager::~ModuleManager()
+  {
+    for(ModuleList::const_iterator mod_iter = m_modules.begin();
+        mod_iter != m_modules.end(); ++mod_iter) {
+      delete *mod_iter;
+    }
+  }
+
+
+  void ModuleManager::add_path(const std::string & dir)
+  {
+    m_dirs.insert(dir);
+    DBG_OUT("add path %s", dir.c_str());
+  }
+
+
+  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();
+        }
+      }
+
+    }
+  }
+
+}
diff --git a/src/sharp/modulemanager.hpp b/src/sharp/modulemanager.hpp
new file mode 100644
index 0000000..9817037
--- /dev/null
+++ b/src/sharp/modulemanager.hpp
@@ -0,0 +1,61 @@
+/*
+ * gnote
+ *
+ * Copyright (C) 2009 Hubert Figuiere
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+
+
+#ifndef __SHARP_MODULEMANAGER_HPP_
+#define __SHARP_MODULEMANAGER_HPP_
+
+#include <list>
+#include <set>
+#include <string>
+
+namespace sharp {
+
+class DynamicModule;
+
+typedef std::list<DynamicModule *> ModuleList;
+
+class ModuleManager 
+{
+public:
+  ~ModuleManager();
+
+  /** add path to list the modules */
+  void add_path(const std::string & dir);
+  void load_modules();
+  
+  const ModuleList & get_modules() const
+    { return m_modules; }
+private:
+  std::set<std::string> m_dirs;
+
+  ModuleList m_modules;
+};
+
+
+}
+
+#endif
+



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