[niepce] Basic addin modules manager, copied from Gnote



commit cdaefbad43a06fa3548eaf83d110fab750ab6c2c
Author: Hub Figuiere <hub figuiere net>
Date:   Fri Oct 28 21:25:00 2011 -0700

    Basic addin modules manager, copied from Gnote

 configure.ac                                       |    1 +
 src/fwk/Makefile.am                                |    3 +-
 src/fwk/base/debug.cpp                             |    2 +-
 src/fwk/base/map.hpp                               |   73 ++++++++++++++
 src/fwk/toolkit/Makefile.am                        |    2 +
 src/fwk/toolkit/application.cpp                    |    7 +-
 src/fwk/toolkit/application.hpp                    |   10 ++
 src/fwk/toolkit/widgets/addinstreemodel.cpp        |   80 +++++++++++++++
 src/fwk/toolkit/widgets/addinstreemodel.hpp        |   75 ++++++++++++++
 src/fwk/utils/MODULES_HOWTO                        |   73 ++++++++++++++
 src/fwk/utils/Makefile.am                          |    8 +-
 src/fwk/utils/dynamicmodule.cpp                    |   90 +++++++++++++++++
 src/fwk/utils/dynamicmodule.hpp                    |   96 ++++++++++++++++++
 src/fwk/utils/files.cpp                            |   18 +++-
 src/fwk/utils/files.hpp                            |    2 +
 src/fwk/utils/modulefactory.hpp                    |   74 ++++++++++++++
 src/fwk/utils/modulemanager.cpp                    |  102 ++++++++++++++++++++
 src/fwk/utils/modulemanager.hpp                    |   61 ++++++++++++
 src/niepce/Makefile.am                             |    1 +
 src/niepce/modules/Makefile.am                     |    2 +-
 src/niepce/modules/interfaces/Makefile.am          |   14 +++
 .../modules/interfaces/ipostimportprocessing.cpp   |    9 ++
 .../modules/interfaces/ipostimportprocessing.hpp   |   25 +++++
 src/niepce/ui/niepceapplication.cpp                |   13 ++-
 24 files changed, 825 insertions(+), 16 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 9d5123c..aa4c50e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -157,6 +157,7 @@ src/niepce/ui/dialogs/Makefile
 src/niepce/ui/thumb-view/Makefile
 src/niepce/modules/Makefile
 src/niepce/modules/darkroom/Makefile
+src/niepce/modules/interfaces/Makefile
 src/niepce/Makefile
 src/fwk/Makefile
 src/fwk/utils/Makefile
diff --git a/src/fwk/Makefile.am b/src/fwk/Makefile.am
index 4dfe978..0cdeacb 100644
--- a/src/fwk/Makefile.am
+++ b/src/fwk/Makefile.am
@@ -25,5 +25,6 @@ libfwk_a_SOURCES = base/color.hpp base/color.cpp \
 	base/fractions.hpp base/fractions.cpp \
 	base/moniker.hpp base/moniker.cpp \
 	base/geometry.hpp base/geometry.cpp \
-	base/singleton.hpp
+	base/singleton.hpp \
+	base/map.hpp \
 	$(NULL)
\ No newline at end of file
diff --git a/src/fwk/base/debug.cpp b/src/fwk/base/debug.cpp
index 761127c..817eb02 100644
--- a/src/fwk/base/debug.cpp
+++ b/src/fwk/base/debug.cpp
@@ -107,7 +107,7 @@ namespace fwk {
 							const char* func,	va_list marker)
 	{
 		char buf[128];
-		snprintf(buf, 128, "(%d) ", (int)pthread_self());
+		snprintf(buf, 128, "(%ld) ", (long)pthread_self());
 		fwrite(buf, 1, strlen(buf), stderr);
 		fwrite(prefix, 1, strlen(prefix), stderr);
 
diff --git a/src/fwk/base/map.hpp b/src/fwk/base/map.hpp
new file mode 100644
index 0000000..c4f54cf
--- /dev/null
+++ b/src/fwk/base/map.hpp
@@ -0,0 +1,73 @@
+/*
+ * 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 __FWK_MAP_HPP_
+#define __FWK_MAP_HPP_
+
+#include <list>
+#include <vector>
+#include <map>
+
+namespace fwk {
+
+  /** get all the keys from the map. */
+  template <typename _Map>
+  void map_get_keys(const _Map & m, std::vector<typename _Map::mapped_type> & l) 
+  {
+    l.clear();
+    for(typename _Map::const_iterator iter = m.begin();
+        iter != m.end(); ++iter) {
+      l.push_back(iter->first);
+    }
+  }
+
+
+  /** get all the mapped elements from the map. */
+  template <typename _Map>
+  void map_get_values(const _Map & m, std::list<typename _Map::mapped_type> & l) 
+  {
+    l.clear();
+    for(typename _Map::const_iterator iter = m.begin();
+        iter != m.end(); ++iter) {
+      l.push_back(iter->second);
+    }
+  }
+
+
+  /** call operator delete on all the data element. */
+  template <typename _Map>
+  void map_delete_all_second(const _Map & m)
+  {
+    for(typename _Map::const_iterator iter = m.begin();
+        iter != m.end(); ++iter) {
+      delete iter->second;
+    }    
+  }
+
+}
+
+
+#endif
diff --git a/src/fwk/toolkit/Makefile.am b/src/fwk/toolkit/Makefile.am
index 7c0940a..3de9bc1 100644
--- a/src/fwk/toolkit/Makefile.am
+++ b/src/fwk/toolkit/Makefile.am
@@ -1,6 +1,7 @@
 
 
 
+
 INCLUDES = -I$(top_srcdir)/src -I$(top_srcdir)/src/ext \
 	@LIBGLIBMM_CFLAGS@ \
 	@LIBGTKMM_CFLAGS@ \
@@ -25,6 +26,7 @@ libniepceframework_a_SOURCES = configuration.hpp configuration.cpp \
 	configdatabinder.hpp configdatabinder.cpp \
 	gdkutils.hpp gdkutils.cpp \
 	gtkutils.hpp gtkutils.cpp \
+	widgets/addinstreemodel.hpp widgets/addinstreemodel.cpp \
 	widgets/toolboxitemwidget.hpp widgets/toolboxitemwidget.cpp \
 	widgets/editablehscale.hpp widgets/editablehscale.cpp \
 	widgets/dock-item.cpp widgets/dock-item.hpp \
diff --git a/src/fwk/toolkit/application.cpp b/src/fwk/toolkit/application.cpp
index 800b8b3..c7a8334 100644
--- a/src/fwk/toolkit/application.cpp
+++ b/src/fwk/toolkit/application.cpp
@@ -29,6 +29,7 @@
 
 #include "fwk/base/debug.hpp"
 #include "fwk/utils/boost.hpp"
+#include "fwk/utils/modulemanager.hpp"
 #include "application.hpp"
 #include "uicontroller.hpp"
 #include "frame.hpp"
@@ -39,8 +40,9 @@ namespace fwk {
 Application::Ptr Application::m_application;
 
 Application::Application(const char * name)
-    : m_config(Glib::ustring("/apps/") + name),
-      m_refUIManager(Gtk::UIManager::create())
+    : m_config(Glib::ustring("/apps/") + name)
+    , m_refUIManager(Gtk::UIManager::create())
+    , m_module_manager(new ModuleManager())
 {
     register_theme(_("System"), "");
 }
@@ -48,6 +50,7 @@ Application::Application(const char * name)
 
 Application::~Application()
 {
+    delete m_module_manager;
 }
 
 
diff --git a/src/fwk/toolkit/application.hpp b/src/fwk/toolkit/application.hpp
index 14d563a..cdd4d67 100644
--- a/src/fwk/toolkit/application.hpp
+++ b/src/fwk/toolkit/application.hpp
@@ -34,6 +34,8 @@
 
 namespace fwk {
 
+class ModuleManager;
+
 class Application 
     : public Controller
 {
@@ -75,6 +77,13 @@ public:
     UndoHistory & undo_history()
         { return m_undo; }
     UndoTransaction * begin_undo(const std::string & label);
+
+    // Module management
+    /** @return the module manager 
+     *  It is guaranted to be safe to call from the constructor
+     */
+    ModuleManager * module_manager() const
+        { return m_module_manager; }
 protected:
     Application(const char *);
     static Application::Ptr m_application; 
@@ -86,6 +95,7 @@ private:
     Glib::RefPtr<Gtk::UIManager> m_refUIManager;
     UndoHistory                  m_undo;
     std::vector<ThemeDesc>       m_themes;
+    ModuleManager               *m_module_manager;
 };
 
 }
diff --git a/src/fwk/toolkit/widgets/addinstreemodel.cpp b/src/fwk/toolkit/widgets/addinstreemodel.cpp
new file mode 100644
index 0000000..83eb17d
--- /dev/null
+++ b/src/fwk/toolkit/widgets/addinstreemodel.cpp
@@ -0,0 +1,80 @@
+/*
+ * 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 <glibmm/i18n.h>
+
+#include "fwk/toolkit/widgets/addinstreemodel.hpp"
+
+
+
+namespace fwk {
+
+
+  AddinsTreeModel::Ptr AddinsTreeModel::create(Gtk::TreeView * treeview)
+  {
+    AddinsTreeModel::Ptr p(new AddinsTreeModel());
+    if(treeview) {
+      treeview->set_model(p);
+      p->set_columns(treeview);
+    }
+    return p;
+  }
+
+  AddinsTreeModel::AddinsTreeModel()
+    : Gtk::TreeStore()
+  {
+    set_column_types(m_columns);
+  }
+
+  fwk::DynamicModule * AddinsTreeModel::get_module(const Gtk::TreeIter & iter)
+  {
+    fwk::DynamicModule * module = NULL;
+    if(iter) {
+      iter->get_value(2, module);
+    }
+    return module;
+  }
+
+
+  void AddinsTreeModel::set_columns(Gtk::TreeView *treeview)
+  {
+      treeview->append_column(_("Name"), m_columns.name);
+      treeview->append_column(_("Description"), m_columns.description);
+  }
+
+
+  Gtk::TreeIter AddinsTreeModel::append(const fwk::DynamicModule *module)
+  {
+    Gtk::TreeIter iter = Gtk::TreeStore::append();
+    iter->set_value(0, std::string(module->name()));
+    iter->set_value(1, std::string(module->description()));
+    iter->set_value(2, module);
+    return iter;
+  }
+
+
+
+}
diff --git a/src/fwk/toolkit/widgets/addinstreemodel.hpp b/src/fwk/toolkit/widgets/addinstreemodel.hpp
new file mode 100644
index 0000000..8c397bd
--- /dev/null
+++ b/src/fwk/toolkit/widgets/addinstreemodel.hpp
@@ -0,0 +1,75 @@
+/*
+ * 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 __FWK_UTILS_ADDINSTREEMODEL_HPP_
+#define __FWK_UTILS_ADDINSTREEMODEL_HPP_
+
+#include <gtkmm/treestore.h>
+#include <gtkmm/treeview.h>
+
+#include "fwk/utils/dynamicmodule.hpp"
+
+namespace fwk {
+
+class AddinsTreeModel
+  : public Gtk::TreeStore
+{
+public:
+  typedef Glib::RefPtr<AddinsTreeModel> Ptr;
+  static Ptr create(Gtk::TreeView * treeview);
+
+  DynamicModule * get_module(const Gtk::TreeIter &);
+
+  Gtk::TreeIter append(const fwk::DynamicModule *);
+  class AddinsColumns
+    : public Gtk::TreeModelColumnRecord
+  {
+  public:
+    AddinsColumns()
+      {
+        add(name); 
+        add(description); 
+        add(addin);
+      }
+
+    Gtk::TreeModelColumn<std::string>          name;
+    Gtk::TreeModelColumn<std::string>          description;
+    Gtk::TreeModelColumn<const DynamicModule *> addin;
+  };
+  AddinsColumns m_columns;
+
+protected:
+  AddinsTreeModel();
+  void set_columns(Gtk::TreeView *v);
+private:
+  
+};
+
+}
+
+
+#endif
diff --git a/src/fwk/utils/MODULES_HOWTO b/src/fwk/utils/MODULES_HOWTO
new file mode 100644
index 0000000..61300e5
--- /dev/null
+++ b/src/fwk/utils/MODULES_HOWTO
@@ -0,0 +1,73 @@
+The Module code is inherited from gnote. It is meant
+to provide lean a mean module implementing several interfaces.
+
+Modules declaration:
+
+-Create a class MyModule that inherite from fwk::DynamicModule.
+-Implement the various virtual functions needed for a module
+ (see DynamicModule.hpp)
+-You need to declare the entry point using:
+  DECLARE_MODULE(MyModule);
+
+Module implementation:
+
+The module implementation is a factory to instanciate the 
+interfaces implementations.
+
+-In the module contructor you must declare the interfaces 
+ implementation using:
+  ADD_INTERFACE(MyInterfaceImplementation)
+ MyInterfaceImplementation is one of the interface you implement. 
+ There can be any number for the module. It is the name of the 
+ class whose declaration should be accesssible.
+-MyModule::id() returns a unique id, which is a string.
+
+Generic Interface:
+
+A generic interface define an interface for the module functionality.
+This is how the app will call your module.
+-A generic interface is class that inherit from fwk::IInterface and 
+sigc::trackable.
+-It should define the following static member:
+  static const char * IFACE_NAME;
+ Its value is a string. It should be unique to all the interfaces
+ and this is how we will know what your module provides.
+
+Interface Implementation
+
+-MyInterfaceImplementation inherit for said generic interface.
+-MyInterfaceImplementation should define and implement a static 
+constructor with the following signature and implementation.
+ static MyInterface *MyInterface::create()
+ { return new MyInterface; }
+
+Loading Modules:
+
+-Declare an instance of fwk::ModuleManager.
+-Call add_path() to add directories where to load modules from
+-Call load_modules() to load them all.
+-Call get_modules() to obtain the list of loaded modules.
+
+Querying interfaces:
+
+-On the module ask it if implements an interface with has_interface()
+-Ask for the interface using query_interface() and obtain a IfaceFactoryBase*
+-Intanciate the interface.
+
+Sample code:
+
+  fwk::ModuleManager module_manager;
+  module_manager.add_path("/usr/local/share/myapp/addins");
+  module_manager.load_modules();
+  const fwk::ModuleList & modules = module_manager.get_modules();
+
+  for(fwk::ModuleList::const_iterator iter = modules.begin();
+    iter != modules.end() ++iter) {
+      const DynamicModule * dynamicmodule = *iter;
+      if(dynamicmodule->has_interface("foo::MyInterface")) {
+          IfaceFactoryBase *factory = dynamicmodule->query_interface("foo::MyInterface");
+	  MyInterface * iface = factory();
+    	  // ...
+      }
+  }
+
diff --git a/src/fwk/utils/Makefile.am b/src/fwk/utils/Makefile.am
index 5224513..519c4e5 100644
--- a/src/fwk/utils/Makefile.am
+++ b/src/fwk/utils/Makefile.am
@@ -8,7 +8,7 @@ TESTS = testfiles testxmp \
 	testpathutils \
 	teststringutils test_db test_db2 test_db3 test_db4 testufrawmeta
 
-EXTRA_DIST = test.xmp test2.ufraw
+EXTRA_DIST = test.xmp test2.ufraw MODULES_HOWTO
 
 check_PROGRAMS = testfiles testxmp \
 	testpathutils \
@@ -85,5 +85,9 @@ libniepceutils_a_SOURCES = \
 	db/insertstatement.cpp db/insertstatement.hpp \
 	db/sqlstatement.cpp db/sqlstatement.hpp \
 	db/sqlite/sqlitecnxdrv.cpp db/sqlite/sqlitecnxdrv.hpp \
-	db/sqlite/sqlitecnxmgrdrv.cpp db/sqlite/sqlitecnxmgrdrv.hpp
+	db/sqlite/sqlitecnxmgrdrv.cpp db/sqlite/sqlitecnxmgrdrv.hpp \
+	dynamicmodule.hpp dynamicmodule.cpp \
+	modulefactory.hpp \
+	modulemanager.hpp modulemanager.cpp \
+	$(NULL)
 
diff --git a/src/fwk/utils/dynamicmodule.cpp b/src/fwk/utils/dynamicmodule.cpp
new file mode 100644
index 0000000..4165767
--- /dev/null
+++ b/src/fwk/utils/dynamicmodule.cpp
@@ -0,0 +1,90 @@
+/*
+ * 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 "fwk/base/map.hpp"
+#include "dynamicmodule.hpp"
+#include "modulefactory.hpp"
+
+
+namespace fwk {
+
+  DynamicModule::DynamicModule()
+    : m_enabled(true)
+  {
+  }
+
+
+  DynamicModule::~DynamicModule()
+  {
+    fwk::map_delete_all_second(m_interfaces);
+  }
+
+  const char * DynamicModule::copyright() const
+  {
+    return "";
+  }
+
+  
+  void DynamicModule::enabled(bool enable)
+  {
+    m_enabled = enable;
+  }
+
+  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;
+  }
+
+  bool DynamicModule::has_interface(const char * intf) const
+  {
+    std::map<std::string, IfaceFactoryBase *>::const_iterator iter;
+    iter = m_interfaces.find(intf);
+    return (iter != m_interfaces.end());
+  }
+
+
+  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/fwk/utils/dynamicmodule.hpp b/src/fwk/utils/dynamicmodule.hpp
new file mode 100644
index 0000000..9614b63
--- /dev/null
+++ b/src/fwk/utils/dynamicmodule.hpp
@@ -0,0 +1,96 @@
+/*
+ * 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 __FWK_DYNAMICMODULE_HPP_
+#define __FWK_DYNAMICMODULE_HPP_
+
+#include <map>
+#include <string>
+
+
+namespace fwk {
+
+class IfaceFactoryBase;
+class DynamicModule;
+
+typedef DynamicModule* (*instanciate_func_t)();
+
+#define DECLARE_MODULE(klass) \
+  extern "C" fwk::DynamicModule* dynamic_module_instanciate() \
+  { return new klass; }
+
+
+#define ADD_INTERFACE_IMPL(klass) \
+    add(klass::IFACE_NAME, \
+        new fwk::IfaceFactory<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;
+  virtual const char * copyright() const;
+  bool enabled() const
+    {
+      return m_enabled;
+    }
+
+  void enabled(bool enable=true);
+
+  /** 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:
+  bool m_enabled;
+  std::map<std::string, IfaceFactoryBase *> m_interfaces;
+};
+
+
+
+}
+
+#endif
diff --git a/src/fwk/utils/files.cpp b/src/fwk/utils/files.cpp
index 3c2948f..4cc9821 100644
--- a/src/fwk/utils/files.cpp
+++ b/src/fwk/utils/files.cpp
@@ -34,14 +34,20 @@ namespace fwk {
 	}
 
 
+  bool filter_ext(const Glib::RefPtr<Gio::FileInfo> & file, const std::string & ext)
+  {
+    std::string file_ext = fwk::path_extension(file->get_name());
+    boost::to_lower(file_ext);
+    if(file_ext == ext) {
+      return false;
+    }
+    return true;
+  }
+
 	bool filter_xmp_out(const Glib::RefPtr<Gio::FileInfo> & file)
 	{
-		std::string ext = fwk::path_extension(file->get_name());
-		boost::to_lower(ext);
-		if(ext == ".xmp") {
-			return false;
-		}
-		return true;
+	  static const std::string ext(".xmp");
+	  return filter_ext(file, ext);
 	}
 
 
diff --git a/src/fwk/utils/files.hpp b/src/fwk/utils/files.hpp
index c9a31ec..0192828 100644
--- a/src/fwk/utils/files.hpp
+++ b/src/fwk/utils/files.hpp
@@ -34,6 +34,8 @@
 namespace fwk {
 
 	bool filter_none(const Glib::RefPtr<Gio::FileInfo> & file);
+  bool filter_ext(const Glib::RefPtr<Gio::FileInfo> & file,
+		  const std::string & ext);
 	bool filter_xmp_out(const Glib::RefPtr<Gio::FileInfo> & file);
 
 	class FileList 
diff --git a/src/fwk/utils/modulefactory.hpp b/src/fwk/utils/modulefactory.hpp
new file mode 100644
index 0000000..4308a9b
--- /dev/null
+++ b/src/fwk/utils/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 __FWK_MODULE_FACTORY_HPP__
+#define __FWK_MODULE_FACTORY_HPP__
+
+
+namespace fwk {
+
+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/fwk/utils/modulemanager.cpp b/src/fwk/utils/modulemanager.cpp
new file mode 100644
index 0000000..5f3276b
--- /dev/null
+++ b/src/fwk/utils/modulemanager.cpp
@@ -0,0 +1,102 @@
+/*
+ * niepce
+ * copied from
+ * 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 <boost/bind.hpp>
+
+#include <gmodule.h>
+#include <glibmm/module.h>
+
+#include "fwk/utils/files.hpp"
+#include "fwk/utils/pathutils.hpp"
+#include "fwk/base/debug.hpp"
+#include "fwk/base/map.hpp"
+#include "dynamicmodule.hpp"
+#include "modulemanager.hpp"
+
+namespace fwk {
+
+
+  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) {
+
+      fwk::FileList::Ptr l;
+      l = FileList::getFilesFromDirectory(*iter, boost::bind(&fwk::filter_ext, _1, ext));
+
+      for(FileList::const_iterator mod_iter = l->begin();
+          mod_iter != l->end(); ++mod_iter) {
+
+        Glib::Module module(*iter + "/" + path_basename(*mod_iter), 
+                            Glib::MODULE_BIND_LOCAL);
+        DBG_OUT("load module %s", path_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/fwk/utils/modulemanager.hpp b/src/fwk/utils/modulemanager.hpp
new file mode 100644
index 0000000..3a2d2ed
--- /dev/null
+++ b/src/fwk/utils/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 __FWK_MODULEMANAGER_HPP_
+#define __FWK_MODULEMANAGER_HPP_
+
+#include <vector>
+#include <set>
+#include <string>
+
+namespace fwk {
+
+class DynamicModule;
+
+typedef std::vector<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
+
diff --git a/src/niepce/Makefile.am b/src/niepce/Makefile.am
index ff3932a..3740b59 100644
--- a/src/niepce/Makefile.am
+++ b/src/niepce/Makefile.am
@@ -19,6 +19,7 @@ niepce_LDADD = \
 	$(top_builddir)/src/engine/library/libniepcelibrary.a \
 	$(top_builddir)/src/engine/db/libniepcedb.a \
 	$(top_builddir)/src/niepce/modules/darkroom/libmoduledarkroom.a \
+	$(top_builddir)/src/niepce/modules/interfaces/libinterfaces.a \
 	$(top_builddir)/src/fwk/toolkit/libniepceframework.a \
 	$(top_builddir)/src/fwk/utils/libniepceutils.a \
 	$(top_builddir)/src/fwk/libfwk.a \
diff --git a/src/niepce/modules/Makefile.am b/src/niepce/modules/Makefile.am
index c9cba6c..ef95e63 100644
--- a/src/niepce/modules/Makefile.am
+++ b/src/niepce/modules/Makefile.am
@@ -1,3 +1,3 @@
 
 
-SUBDIRS = darkroom
\ No newline at end of file
+SUBDIRS = darkroom interfaces
\ No newline at end of file
diff --git a/src/niepce/modules/interfaces/Makefile.am b/src/niepce/modules/interfaces/Makefile.am
new file mode 100644
index 0000000..e9bdfae
--- /dev/null
+++ b/src/niepce/modules/interfaces/Makefile.am
@@ -0,0 +1,14 @@
+
+
+INCLUDES = -I$(top_srcdir)/src/ \
+	@LIBGLIBMM_CFLAGS@ \
+	@LIBGTKMM_CFLAGS@
+
+
+noinst_HEADERS = ipostimportprocessing.hpp \
+	$(NULL)
+
+noinst_LIBRARIES = libinterfaces.a
+
+libinterfaces_a_SOURCES = ipostimportprocessing.cpp \
+	$(NULL)
\ No newline at end of file
diff --git a/src/niepce/modules/interfaces/ipostimportprocessing.cpp b/src/niepce/modules/interfaces/ipostimportprocessing.cpp
new file mode 100644
index 0000000..0dccd09
--- /dev/null
+++ b/src/niepce/modules/interfaces/ipostimportprocessing.cpp
@@ -0,0 +1,9 @@
+
+
+#include "ipostimportprocessing.hpp"
+
+namespace niepce {
+
+  const char * IPostImportProcessing::IFACE_NAME = "niepce::PostImportPorcessing";
+
+}
diff --git a/src/niepce/modules/interfaces/ipostimportprocessing.hpp b/src/niepce/modules/interfaces/ipostimportprocessing.hpp
new file mode 100644
index 0000000..58625f3
--- /dev/null
+++ b/src/niepce/modules/interfaces/ipostimportprocessing.hpp
@@ -0,0 +1,25 @@
+
+
+#ifndef __MODULES_INTF_POSTIMPORTPROCESSING_HPP_
+#define __MODULES_INTF_POSTIMPORTPROCESSING_HPP_
+
+#include <sigc++/trackable.h>
+
+#include "engine/db/libfile.hpp"
+#include "fwk/utils/modulefactory.hpp"
+
+namespace niepce {
+
+class IPostImportProcessing
+  : public fwk::IInterface
+  , public sigc::trackable
+{
+public:
+  static const char * IFACE_NAME;
+
+  virtual void post_process_image(const eng::LibFile::Ptr & file) = 0;
+};
+
+}
+
+#endif
diff --git a/src/niepce/ui/niepceapplication.cpp b/src/niepce/ui/niepceapplication.cpp
index 6fb0051..6859967 100644
--- a/src/niepce/ui/niepceapplication.cpp
+++ b/src/niepce/ui/niepceapplication.cpp
@@ -22,6 +22,7 @@
 #include <glibmm/i18n.h>
 #include <gtkmm/aboutdialog.h>
 
+#include "fwk/utils/modulemanager.hpp"
 #include "niepce/stock.hpp"
 #include "niepceapplication.hpp"
 #include "niepcewindow.hpp"
@@ -35,10 +36,15 @@ NiepceApplication::NiepceApplication()
     : Application(PACKAGE)
 {
     niepce::Stock::registerStockItems();
-    const char * themedir = DATADIR"/niepce/themes/";
+    const char * themedir = DATADIR"/"PACKAGE"/themes/";
 
     register_theme(_("Niepce Dark"),
                    std::string(themedir) + "niepce-dark.gtkrc");
+
+    fwk::ModuleManager * modmgr = module_manager();
+    DBG_ASSERT(modmgr != NULL, "module manager is NULL.");
+    // path for modules is $PREFIX/share/niepce/modules/$VERSION
+    modmgr->add_path(DATADIR"/"PACKAGE"/modules/"VERSION);
 }
 
 Application::Ptr NiepceApplication::create()
@@ -61,8 +67,9 @@ void NiepceApplication::on_about()
 //    dlg.set_name("Niepce");
     dlg.set_program_name("Niepce Digital");
     dlg.set_version(VERSION);
-    dlg.set_comments(Glib::ustring(_("A digital photo application.\n\nBuild options: " 
-                                     NIEPCE_BUILD_CONFIG)));
+    dlg.set_comments(Glib::ustring(_("A digital photo application.\n\n"
+                                     "Build options: ")) + 
+                     NIEPCE_BUILD_CONFIG);
     dlg.run();
 }
 



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