Blame synfig-studio/src/gui/pluginmanager.cpp

bb9720
/* === S Y N F I G ========================================================= */
bb9720
/*!	\file synfigapp/pluginmanager.cpp
bb9720
**	\brief  Plugin Manager responsible for loading plugins
bb9720
**
bb9720
**	$Id$
bb9720
**
bb9720
**	\legal
705108
**	Copyright (c) 2012-2013 Konstantin Dmitriev
bb9720
**
bb9720
**	This package is free software; you can redistribute it and/or
bb9720
**	modify it under the terms of the GNU General Public License as
bb9720
**	published by the Free Software Foundation; either version 2 of
bb9720
**	the License, or (at your option) any later version.
bb9720
**
bb9720
**	This package is distributed in the hope that it will be useful,
bb9720
**	but WITHOUT ANY WARRANTY; without even the implied warranty of
bb9720
**	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
bb9720
**	General Public License for more details.
bb9720
**	\endlegal
bb9720
*/
bb9720
/* ========================================================================= */
bb9720
bb9720
/* === H E A D E R S ======================================================= */
bb9720
bb9720
#ifdef USING_PCH
bb9720
#	include "pch.h"
bb9720
#else
bb9720
#ifdef HAVE_CONFIG_H
bb9720
#	include <config.h></config.h>
bb9720
#endif
bb9720
bb9720
#include "pluginmanager.h"
bb9720
bb9720
#include <libxml++ libxml++.h=""></libxml++>
bb9720
bb9720
#include <dirent.h></dirent.h>
bb9720
#include <sys stat.h=""></sys>
bb9720
bb9720
#include <synfig general.h=""></synfig>
862ccf
#include <synfig savecanvas.h=""></synfig>
784691
#include <synfig filesystemnative.h=""></synfig>
862ccf
#include <synfigapp main.h=""></synfigapp>
bb9720
abdbf2
#include <synfigapp localization.h=""></synfigapp>
bw 94d8a6
bb9720
#endif
bb9720
bb9720
/* === U S I N G =========================================================== */
bb9720
bb9720
using namespace std;
bb9720
using namespace etl;
bb9720
using namespace synfig;
300985
using namespace studio;
bb9720
bb9720
/* === M A C R O S ========================================================= */
bb9720
862ccf
bb9720
/* === G L O B A L S ======================================================= */
bb9720
bb9720
/* === M E T H O D S ======================================================= */
bb9720
bb9720
PluginManager::PluginManager():
bb9720
	list_()
bb9720
{
bb9720
} // END of synfigapp::PluginManager::PluginManager()
bb9720
bb9720
void
bb9720
PluginManager::load_dir( const std::string &pluginsprefix )
bb9720
{
bb9720
	
bb9720
	synfig::info("Loading plugins from %s", pluginsprefix.c_str());
bb9720
	
bb9720
	DIR *dir;
bb9720
	struct dirent *entry;
bb9720
	
bb9720
	dir = opendir(pluginsprefix.c_str());
bb9720
	if(dir) {
bb9720
		while ( (entry = readdir(dir)) != NULL) {
bb9720
			if ( std::string(entry->d_name) != std::string(".") && std::string(entry->d_name) != std::string("..") ) {
bb9720
				std::string pluginpath;
bb9720
				pluginpath = pluginsprefix+ETL_DIRECTORY_SEPARATOR+entry->d_name;
bb9720
				struct stat sb;
b2570b
				stat(pluginpath.c_str(), &sb);
bb9720
				// error handling if stat failed
bb9720
				if (S_ISDIR(sb.st_mode)) {
bb9720
					// checking if directory contains a plugin...
bb9720
					DIR *plugindir;
bb9720
					struct dirent *plugindirentry;
bb9720
					
bb9720
					plugindir = opendir(pluginpath.c_str());
943360
					if(plugindir) {
943360
						while ( (plugindirentry = readdir(plugindir)) != NULL) {
943360
							if ( std::string(plugindirentry->d_name) == std::string("plugin.xml") ){
943360
								std::string pluginfilepath;
943360
								pluginfilepath = pluginpath+ETL_DIRECTORY_SEPARATOR+plugindirentry->d_name;
943360
								
943360
								load_plugin(pluginfilepath);
943360
							}
943360
						}
943360
						closedir(plugindir);
943360
					} 
943360
					else 
943360
						synfig::warning("Can't read plugin directory!");
943360
943360
					/*plugindir = opendir(pluginpath.c_str());
bb9720
					if(!plugindir) {
bb9720
						synfig::warning("Can't read plugin directory!");
bb9720
						return;
bb9720
					}
bb9720
					
bb9720
					while ( (plugindirentry = readdir(plugindir)) != NULL) {
bb9720
						if ( std::string(plugindirentry->d_name) == std::string("plugin.xml") ){
bb9720
							std::string pluginfilepath;
bb9720
							pluginfilepath = pluginpath+ETL_DIRECTORY_SEPARATOR+plugindirentry->d_name;
bb9720
							
bb9720
							load_plugin(pluginfilepath);
bb9720
						}
943360
					}*/
bb9720
					
bb9720
				}
bb9720
			}
bb9720
bb9720
		};
bb9720
		
bb9720
		closedir(dir);
bb9720
	}
bb9720
} // END of synfigapp::PluginManager::load_dir()
bb9720
bb9720
void
bb9720
PluginManager::load_plugin( const std::string &path )
bb9720
{
bb9720
	// Get locale
bb9720
	std::string current_locale = setlocale(LC_ALL, NULL);
bb9720
	
36b669
	synfig::info("   Loading plugin: %s", basename(dirname(path)).c_str());
bb9720
							
bb9720
	PluginManager::plugin p;
bb9720
	std::string plugindir = dirname(path);
bb9720
	p.id=plugindir;
bb9720
	
bb9720
	// parse xml file
bb9720
	try
bb9720
	{
bb9720
		xmlpp::DomParser parser;
bb9720
		//parser.set_validate();
bb9720
		parser.set_substitute_entities(); //We just want the text to be resolved/unescaped automatically.
bb9720
		parser.parse_file(path);
bb9720
		if(parser)
bb9720
		{
bb9720
			//Walk the tree:
bb9720
			const xmlpp::Node* pNode = parser.get_document()->get_root_node(); //deleted by DomParser.
bb9720
			if ( std::string(pNode->get_name()) == std::string("plugin") ){
bb9720
				//Recurse through child nodes:
bb9720
				xmlpp::Node::NodeList list = pNode->get_children();
bb9720
				
bb9720
				unsigned int name_relevance = 0;
bb9720
				
bb9720
				for(xmlpp::Node::NodeList::iterator iter = list.begin(); iter != list.end(); ++iter)
bb9720
				{
bb9720
					const xmlpp::Node* node = *iter;
bb9720
					if ( std::string(node->get_name()) == std::string("name") ) {
bb9720
bb9720
						const xmlpp::Element* nodeElement = dynamic_cast<const xmlpp::element*="">(node);</const>
bb9720
						
bb9720
						xmlpp::Node::NodeList l = nodeElement->get_children();
bb9720
						xmlpp::Node::NodeList::iterator i = l.begin();
bb9720
						xmlpp::Node* n = *i;
bb9720
						
bb9720
						const xmlpp::TextNode* nodeText = dynamic_cast<const xmlpp::textnode*="">(n);</const>
bb9720
						
bb9720
						if(nodeText)
bb9720
						{
bb9720
							// Get the language attribute
bb9720
							const xmlpp::Attribute* langAttribute = nodeElement->get_attribute("lang", "xml");
bb9720
bb9720
							if (langAttribute) {
bb9720
								// Element have language attribute,
bb9720
								std::string lang = langAttribute->get_value();
bb9720
								// let's compare it with current locale
bb9720
								 if (!current_locale.compare(0, lang.size(), lang)) {
bb9720
									 if (lang.size() > name_relevance){
bb9720
										 p.name=nodeText->get_content();
bb9720
									 }
bb9720
								 }
bb9720
							} else {
bb9720
								// Element have no language attribute - use as fallback
bb9720
								if (name_relevance == 0){
bb9720
									p.name=nodeText->get_content();
bb9720
								}
bb9720
							}
bb9720
						}
bb9720
						
bb9720
					} else if ( std::string(node->get_name()) == std::string("exec") ) {
bb9720
						
bb9720
						xmlpp::Node::NodeList l = node->get_children();
bb9720
						xmlpp::Node::NodeList::iterator i = l.begin();
bb9720
						xmlpp::Node* n = *i;
bb9720
						
bb9720
						const xmlpp::TextNode* nodeText = dynamic_cast<const xmlpp::textnode*="">(n);</const>
bb9720
						
bb9720
						if(nodeText)
bb9720
						{
bb9720
							p.path=plugindir+ETL_DIRECTORY_SEPARATOR+nodeText->get_content();
bb9720
						}
bb9720
					}
bb9720
				}
bb9720
			} else {
bb9720
				synfig::info("Invalid plugin.xml file.");
bb9720
			}
bb9720
		}
bb9720
	}
bb9720
	catch(const std::exception& ex)
bb9720
	{
bb9720
		std::cout << "Exception caught: " << ex.what() << std::endl;
bb9720
	}
bb9720
	
bb9720
	if ( p.id != "" && p.name != "" && p.path != ""){
bb9720
		list_.push_back(p);
bb9720
	} else {
bb9720
		synfig::warning("Invalid plugin.xml file!");
bb9720
	}
bb9720
}
bb9720
bb9720
PluginManager::~PluginManager()
bb9720
{
862ccf
}