From 24d0c2ad34de2cbd89fed76058f2995cdf81d239 Mon Sep 17 00:00:00 2001 From: Leonardo Florez-Valencia Date: Mon, 16 May 2016 11:38:22 -0500 Subject: [PATCH] ... --- appli/bash/CMakeLists.txt | 2 + appli/bash/cpPlugins_ExecuteWorkspace.cxx | 63 +++++++++++--- .../examples/plugins/example_GuessPlugins.cxx | 6 ++ data/ReadWriteImage.wxml | 15 ++++ lib/cpPipelineEditor/BaseQtMainWindow.cxx | 13 +-- lib/cpPlugins/Config.h.in | 83 +------------------ lib/cpPlugins/Interface.cxx | 25 ++++-- lib/cpPlugins/Interface.h | 5 +- lib/cpPlugins/Object.h | 4 +- lib/cpPlugins/WorkspaceIO.cxx | 48 +++++++++++ lib/cpPlugins_Config.h | 15 +++- 11 files changed, 169 insertions(+), 110 deletions(-) create mode 100644 data/ReadWriteImage.wxml diff --git a/appli/bash/CMakeLists.txt b/appli/bash/CMakeLists.txt index 6d2c288..129a542 100644 --- a/appli/bash/CMakeLists.txt +++ b/appli/bash/CMakeLists.txt @@ -24,4 +24,6 @@ FOREACH(source ${all_SOURCE_CXX_FILES}) SET(${name}_APP ${name} CACHE INTERNAL "bash program ${name}") ENDFOREACH(source) +TARGET_LINK_LIBRARIES(cpPlugins_ExecuteWorkspace cpPlugins) + ## eof - $RCSfile$ diff --git a/appli/bash/cpPlugins_ExecuteWorkspace.cxx b/appli/bash/cpPlugins_ExecuteWorkspace.cxx index 4c847b1..e5ee4cb 100644 --- a/appli/bash/cpPlugins_ExecuteWorkspace.cxx +++ b/appli/bash/cpPlugins_ExecuteWorkspace.cxx @@ -2,7 +2,8 @@ #include #include #include -#include +#include +#include int main( int argc, char* argv[] ) { @@ -12,21 +13,63 @@ int main( int argc, char* argv[] ) return( 1 ); } // fi - std::set< std::string > parameters; - std::set< std::string > plugins; + std::string ws_file = argv[ 1 ]; + + // Configure a plugin interface and load given workspace + cpPlugins::Interface interface; + cpPlugins::Workspace ws; + ws.SetInterface( &interface ); + std::string err = ws.LoadWorkspace( ws_file ); + if( err != "" ) + { + std::cerr + << "Error loading workspace \"" << ws_file << "\": " + << err << std::endl; + return( 1 ); + + } // fi // Read arguments - std::string ws_file = argv[ 1 ]; - for( unsigned int i = 2; i < argc; ++i ) + for( unsigned int i = 2; i < argc; i += 2 ) { std::vector< std::string > tokens; - cpPlugins::TokenizeString( tokens, argv[ i ], "=" ); - if( tokens.size( ) < 2 ) - continue; - if ( tokens[ 0 ] == "pl" ) plugins.insert( tokens[ 1 ] ); - else if( tokens[ 0 ] == "pa" ) parameters.insert( tokens[ 1 ] ); + cpPlugins::TokenizeString( tokens, argv[ i ], "@" ); + std::string filter_name = tokens[ 1 ]; + std::string param_name = tokens[ 0 ]; + std::string param_value = argv[ i + 1 ]; + + auto filter = ws.GetFilter( filter_name ); + if( filter != NULL ) + filter->GetParameters( )->SetString( param_name, param_value ); + else + std::cerr + << "Warning: filter \"" << filter_name + << "\" is not defined inside the loaded workspace." << std::endl; } // rof + + // Execute workspace + ws.PrintExecutionOn( ); + try + { + ws.Execute( ); + } + catch( itk::ExceptionObject& err1 ) + { + std::cerr << "Error caught: " << err1 << std::endl; + return( 1 ); + } + catch( std::exception& err2 ) + { + std::cerr << "Error caught: " << err2.what( ) << std::endl; + return( 1 ); + } + catch( ... ) + { + std::cerr << "Unknown error caught." << std::endl; + return( 1 ); + + } // yrt return( 0 ); } diff --git a/appli/examples/plugins/example_GuessPlugins.cxx b/appli/examples/plugins/example_GuessPlugins.cxx index 6d2f7a1..8a54b74 100644 --- a/appli/examples/plugins/example_GuessPlugins.cxx +++ b/appli/examples/plugins/example_GuessPlugins.cxx @@ -7,6 +7,12 @@ int main( int argc, char* argv[] ) cpPlugins::Interface interface; interface.GuessAccesiblePlugins( ); + // Show loaded plugins + auto plugins = interface.GetPlugins( ); + for( auto pIt = plugins.begin( ); pIt != plugins.end( ); ++pIt ) + std::cout << "Plugin: " << *pIt << std::endl; + std::cout << std::endl; + // Show loaded filters auto filters = interface.GetFilters( ); for( auto cIt = filters.begin( ); cIt != filters.end( ); ++cIt ) diff --git a/data/ReadWriteImage.wxml b/data/ReadWriteImage.wxml new file mode 100644 index 0000000..5d597c5 --- /dev/null +++ b/data/ReadWriteImage.wxml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/lib/cpPipelineEditor/BaseQtMainWindow.cxx b/lib/cpPipelineEditor/BaseQtMainWindow.cxx index b600c0e..8a9536b 100644 --- a/lib/cpPipelineEditor/BaseQtMainWindow.cxx +++ b/lib/cpPipelineEditor/BaseQtMainWindow.cxx @@ -45,14 +45,10 @@ BaseQtMainWindow( { this->m_Interface.GuessAccesiblePlugins( ); + // Try to load plugins from executable dir QFileInfo info( argv[ 0 ] ); if( info.exists( ) ) - { - auto exec_dir = info.canonicalPath( ).toStdString( ); - this->_LoadPluginsFromPath( exec_dir ); - - } // fi - this->_UpdateLoadedPlugins( ); + this->_LoadPluginsFromPath( info.canonicalPath( ).toStdString( ) ); // Prepare workspace this->m_Workspace.SetInterface( &( this->m_Interface ) ); @@ -187,7 +183,6 @@ _UpdateLoadedPlugins( ) } // fi this->_UnBlock( ); - this->m_Interface.SaveConfiguration( cpPlugins_CONFIG_FILE ); } // ------------------------------------------------------------------------- @@ -250,9 +245,9 @@ _InteractiveLoadPlugins( ) dlg.setDirectory( this->m_PluginsPath.c_str( ) ); std::stringstream name_filter; - std::string suffix = std::string( cpPlugins_PLUGIN_EXT ); + std::string suffix = std::string( cpPlugins_LIB_EXT ); name_filter - << "Plugins file (*." << cpPlugins_PLUGIN_EXT << ");;All files (*)"; + << "Plugins file (*." << cpPlugins_LIB_EXT << ");;All files (*)"; dlg.setNameFilter( name_filter.str( ).c_str( ) ); dlg.setDefaultSuffix( suffix.c_str( ) ); if( !( dlg.exec( ) ) ) diff --git a/lib/cpPlugins/Config.h.in b/lib/cpPlugins/Config.h.in index 6cec4ad..c7668b5 100644 --- a/lib/cpPlugins/Config.h.in +++ b/lib/cpPlugins/Config.h.in @@ -22,8 +22,6 @@ * ========================================================================= */ -#define cpPlugins_CONFIG_FILE "plugins.cfg" - #define cpPlugins_QT4_USED @QT4_FOUND@ #if cpPlugins_QT4_USED == 1 # define cpPlugins_QT4 @@ -31,37 +29,6 @@ # undef cpPlugins_QT4 #endif // cpPlugins_QT4_USED == 1 -/* - * ========================================================================= - * Identify OS - * ========================================================================= - */ -#if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) -# define cpPlugins_SYS_WINDOWS -# define cpPlugins_PLUGIN_PREFIX "" -# define cpPlugins_PLUGIN_EXT "dll" -# ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -# endif -# define NOMINMAX -# include -# include -#elif defined( linux ) || defined( __linux ) -# define cpPlugins_SYS_LINUX -# define cpPlugins_PLUGIN_PREFIX "lib" -# define cpPlugins_PLUGIN_EXT "so" -#elif defined( __APPLE__ ) || defined( MACOSX ) || defined( macintosh ) || defined( Macintosh ) -# define cpPlugins_SYS_MACOS -# define cpPlugins_PLUGIN_PREFIX "lib" -# define cpPlugins_PLUGIN_EXT "dylib" -#elif defined( __FreeBSD__ ) || defined( __FreeBSD_kernel__ ) -# define cpPlugins_SYS_FREEBSD -# define cpPlugins_PLUGIN_PREFIX "lib" -# define cpPlugins_PLUGIN_EXT "so" -#else -# error "This operating system is not supported by cpPlugins" -#endif - /* * ========================================================================= * Some macros @@ -69,52 +36,10 @@ */ #define cpPlugins_Id_Macro( N, C ) \ public: \ - virtual const char* GetClassName( ) override { return( #N ); } \ - virtual const char* GetClassCategory( ) override { return( #C ); } - -/* - * ========================================================================= - * Some functions - * ========================================================================= - */ -#include -namespace cpPlugins -{ - struct PathHelper - { - // --------------------------------------------------------------------- - inline bool operator()( char c ) const - { -#ifdef cpPlugins_SYS_WINDOWS - return( c == '\\' || c == '/' ); -#else // cpPlugins_SYS_WINDOWS - return( c == '/' ); -#endif // cpPlugins_SYS_WINDOWS - } - - // --------------------------------------------------------------------- - inline static std::string CanonicalPath( const std::string& path ) - { - std::string ret = ""; -#ifdef cpPlugins_SYS_WINDOWS - TCHAR buffer[ 4096 ] = TEXT( "" ); - TCHAR** lppPart = { NULL }; - GetFullPathName( path.c_str( ), 4096, buffer, lppPart ); - ret = std::string( buffer ); -#else // cpPlugins_SYS_WINDOWS - char* canonical_path = realpath( path.c_str( ), NULL ); - if( canonical_path != NULL ) - { - ret = canonical_path; - free( canonical_path ); - - } // fi -#endif // cpPlugins_SYS_WINDOWS - return( ret ); - } - }; - -} // ecapseman + virtual const char* GetClassName( ) const ITK_OVERRIDE \ + { return( #N ); } \ + virtual const char* GetClassCategory( ) const ITK_OVERRIDE \ + { return( #C ); } #endif // __CPPLUGINS__CONFIG__H__ diff --git a/lib/cpPlugins/Interface.cxx b/lib/cpPlugins/Interface.cxx index 1f0a015..8b5e106 100644 --- a/lib/cpPlugins/Interface.cxx +++ b/lib/cpPlugins/Interface.cxx @@ -36,7 +36,7 @@ UpdatePaths( ) { // Load environment configuration this->m_Paths.clear( ); - char* p = std::getenv( "cpPlugins_PATHS" ); + char* p = std::getenv( cpPlugins_PATHS ); if( p != NULL ) cpPlugins::TokenizeString( this->m_Paths, p, cpPlugins_SEPARATOR ); this->m_Paths.push_back( "." ); @@ -117,7 +117,7 @@ void cpPlugins::Interface:: LoadPluginFile( const std::string& filename ) { // Canonical filename - auto canonical = cpPlugins::PathHelper::CanonicalPath( filename ); + auto canonical = cpPlugins::CanonicalPath( filename ); if( canonical == "" ) throw std::runtime_error( std::string( "cpPlugins::Interface: Library \"" ) + @@ -239,13 +239,28 @@ GetPluginName( const std::string& category, const std::string& name ) const } // ------------------------------------------------------------------------- -std::vector< std::string > cpPlugins::Interface:: +std::string cpPlugins::Interface:: +GetPluginName( const ProcessObject* obj ) const +{ + if( obj != NULL ) + return( + this->GetPluginName( + obj->GetClassCategory( ), + obj->GetClassName( ) + ) + ); + else + return( "" ); +} + +// ------------------------------------------------------------------------- +std::set< std::string > cpPlugins::Interface:: GetPlugins( ) const { - std::vector< std::string > res; + std::set< std::string > res; auto i = this->m_DynLibraries.begin( ); for( ; i != this->m_DynLibraries.end( ); ++i ) - res.push_back( i->first ); + res.insert( i->first ); return( res ); } diff --git a/lib/cpPlugins/Interface.h b/lib/cpPlugins/Interface.h index 655bbfa..0a31e63 100644 --- a/lib/cpPlugins/Interface.h +++ b/lib/cpPlugins/Interface.h @@ -37,13 +37,14 @@ namespace cpPlugins void LoadPluginFile( const std::string& filename ); void UnloadAll( ); - cpPlugins::ProcessObject::Pointer Create( + ProcessObject::Pointer Create( const std::string& category, const std::string& name ); std::string GetPluginName( const std::string& category, const std::string& name ) const; - std::vector< std::string > GetPlugins( ) const; + std::string GetPluginName( const ProcessObject* obj ) const; + std::set< std::string > GetPlugins( ) const; protected: static void* _DLOpen( const std::string& fname ); diff --git a/lib/cpPlugins/Object.h b/lib/cpPlugins/Object.h index d861d15..c4ce85a 100644 --- a/lib/cpPlugins/Object.h +++ b/lib/cpPlugins/Object.h @@ -30,8 +30,8 @@ namespace cpPlugins itkTypeMacro( Object, itk::Object ); public: - virtual const char* GetClassName( ) = 0; - virtual const char* GetClassCategory( ) = 0; + virtual const char* GetClassName( ) const = 0; + virtual const char* GetClassCategory( ) const = 0; const float& GetViewX( ) const; const float& GetViewY( ) const; diff --git a/lib/cpPlugins/WorkspaceIO.cxx b/lib/cpPlugins/WorkspaceIO.cxx index c23852a..f7b25ca 100644 --- a/lib/cpPlugins/WorkspaceIO.cxx +++ b/lib/cpPlugins/WorkspaceIO.cxx @@ -5,6 +5,8 @@ std::string cpPlugins::Workspace:: LoadWorkspace( const std::string& fname ) { + if( this->m_Interface == NULL ) + return( "cpPlugins::Workspace: No valid plugins interface" ); tinyxml2::XMLDocument* doc = new tinyxml2::XMLDocument( ); doc->LoadFile( fname.c_str( ) ); tinyxml2::XMLElement* root = doc->RootElement( ); @@ -14,6 +16,38 @@ LoadWorkspace( const std::string& fname ) return( "cpPlugins::Workspace: No valid workspace" ); std::stringstream err; + // Load plugins + auto loaded_plugins = this->m_Interface->GetPlugins( ); + tinyxml2::XMLElement* plugins = root->FirstChildElement( "plugins" ); + std::string plugins_errors = ""; + while( plugins != NULL ) + { + tinyxml2::XMLElement* plugin = plugins->FirstChildElement( "plugin" ); + while( plugin != NULL ) + { + std::string name = plugin->Attribute( "name" ); + if( loaded_plugins.find( name ) == loaded_plugins.end( ) ) + { + try + { + this->m_Interface->LoadPlugin( name ); + } + catch( std::exception& err ) + { + plugins_errors += err.what( ) + std::string( "\n" ); + + } // yrt + + } // fi + plugin = plugin->NextSiblingElement( "plugin" ); + + } // elihw + plugins = plugins->NextSiblingElement( "plugins" ); + + } // elihw + if( plugins_errors != "" ) + return( std::string( "cpPlugins::Workspace: " ) + plugins_errors ); + // Read filters tinyxml2::XMLElement* filter = root->FirstChildElement( "filter" ); while( filter != NULL ) @@ -107,6 +141,7 @@ SaveWorkspace( const std::string& fname ) const std::stringstream err; tinyxml2::XMLDocument* doc = new tinyxml2::XMLDocument( ); tinyxml2::XMLElement* root = doc->NewElement( "cpPlugins_Workspace" ); + std::set< std::string > used_plugins; // Save vertices auto vIt = this->m_Graph->BeginVertices( ); @@ -116,6 +151,8 @@ SaveWorkspace( const std::string& fname ) const auto data = dynamic_cast< DataObject* >( vIt->second.GetPointer( ) ); if( filter != NULL ) { + used_plugins.insert( this->m_Interface->GetPluginName( filter ) ); + tinyxml2::XMLElement* e = doc->NewElement( "filter" ); e->SetAttribute( "category", filter->GetClassCategory( ) ); e->SetAttribute( "class", filter->GetClassName( ) ); @@ -134,6 +171,17 @@ SaveWorkspace( const std::string& fname ) const } // rof + // Save used plugins + tinyxml2::XMLElement* plugins = doc->NewElement( "plugins" ); + for( auto pIt = used_plugins.begin( ); pIt != used_plugins.end( ); ++pIt ) + { + tinyxml2::XMLElement* e = doc->NewElement( "plugin" ); + e->SetAttribute( "name", pIt->c_str( ) ); + plugins->LinkEndChild( e ); + + } // rof + root->LinkEndChild( plugins ); + // Save connections auto mIt = this->m_Graph->BeginEdgesRows( ); for( ; mIt != this->m_Graph->EndEdgesRows( ); ++mIt ) diff --git a/lib/cpPlugins_Config.h b/lib/cpPlugins_Config.h index 9886262..984f23b 100644 --- a/lib/cpPlugins_Config.h +++ b/lib/cpPlugins_Config.h @@ -1,6 +1,13 @@ #ifndef __CPPLUGINS_CONFIG__H__ #define __CPPLUGINS_CONFIG__H__ +/* + * ========================================================================= + * Some global values + * ========================================================================= + */ +#define cpPlugins_PATHS "cpPlugins_PATHS" + /* * ========================================================================= * ITK related macros @@ -101,9 +108,9 @@ namespace cpPlugins }; // ----------------------------------------------------------------------- - inline bool IsBlank( const char& value ) + inline bool IsBlank( const char& v ) { - return( value == ' ' || value == '\t' || value == '\n' || value == '\r' ); + return( v == ' ' || v == '\t' || v == '\n' || v == '\r' ); } // ----------------------------------------------------------------------- @@ -146,7 +153,9 @@ namespace cpPlugins } // ----------------------------------------------------------------------- - inline bool ReadFileIntoString( std::string& buffer, const std::string& fname ) + inline bool ReadFileIntoString( + std::string& buffer, const std::string& fname + ) { buffer = ""; std::ifstream file_stream( fname.c_str( ) ); -- 2.45.1