Commit b835ef43 authored by Sebastian Eichelbaum's avatar Sebastian Eichelbaum
Browse files

[ADD #125] added error report for WProjectFile and WProjectFileIO.

parent ec7b5d10
......@@ -22,9 +22,13 @@
//
//---------------------------------------------------------------------------
#include <vector>
#include <string>
#include "WProjectFileIO.h"
WProjectFileIO::WProjectFileIO()
WProjectFileIO::WProjectFileIO():
m_errors()
{
// initialize
}
......@@ -39,3 +43,13 @@ void WProjectFileIO::done()
// do nothing here. Overwrite this method if your specific parser needs to do some post processing.
}
bool WProjectFileIO::hadErrors() const
{
return m_errors.size();
}
const std::vector< std::string >& WProjectFileIO::getErrors() const
{
return m_errors;
}
......@@ -27,11 +27,12 @@
#include <ostream>
#include <string>
#include <vector>
/**
* A base class for all parts of OpenWalnut which can be serialized to a project file. It is used by WProjectFile to actually parse the file line
* by line. Derive from this class if you write your own parser and use it to fill your internal data structures.
* by line. Derive from this class if you write your own parser and use it to fill your internal data structures. But write it in a very
* error-tolerant way. We want to avoid that small problems in the project file cause the whole file to be useless.
*/
class WProjectFileIO // NOLINT
{
......@@ -47,7 +48,8 @@ public:
virtual ~WProjectFileIO();
/**
* This method parses the specified line and interprets it. It gets called line by line by WProjectFile.
* This method parses the specified line and interprets it. It gets called line by line by WProjectFile. You should avoid applying anything
* of the loaded information here. You should use \ref done for this.
*
* \param line the current line as string
* \param lineNumber the current line number. Useful for error/warning/debugging output.
......@@ -57,8 +59,9 @@ public:
virtual bool parse( std::string line, unsigned int lineNumber ) = 0;
/**
* Called whenever the end of the project file has been reached. This is useful if your specific parser class wants to do some post
* processing after parsing line by line.
* Called whenever the end of the project file has been reached. Use this to actually apply your loaded settings. Do this in a error-tolerant
* way and apply as most settings as possible even if some other settings are erroneous. Add errors with \ref addError. Try avoiding
* exceptions if possible.
*/
virtual void done();
......@@ -69,8 +72,34 @@ public:
*/
virtual void save( std::ostream& output ) = 0; // NOLINT
/**
* Checks whether there where errors during load or save.
*
* \return true if there where.
*/
bool hadErrors() const;
/**
* Get error list.
*
* \return the list
*/
const std::vector< std::string >& getErrors() const;
protected:
/**
* Add an error. Use this when you encounter some difficulties during parsing or applying settings. Provide useful errors. They will be
* presented to the user.
*
* \param description the error description
*/
void addError( std::string description );
private:
/**
* List of errors if any.
*/
std::vector< std::string > m_errors;
};
#endif // WPROJECTFILEIO_H
......
......@@ -22,6 +22,7 @@
//
//---------------------------------------------------------------------------
#include <algorithm>
#include <fstream>
#include <string>
#include <vector>
......@@ -34,6 +35,7 @@
#include "../graphicsEngine/WGEProjectFileIO.h"
#include "../common/exceptions/WFileNotFound.h"
#include "../common/exceptions/WFileOpenFailed.h"
#include "../common/WStringUtils.h"
#include "WProjectFile.h"
......@@ -54,6 +56,22 @@ WProjectFile::WProjectFile( boost::filesystem::path project ):
m_parsers.push_back( boost::shared_ptr< WProjectFileIO >( new WGEProjectFileIO() ) );
}
WProjectFile::WProjectFile( boost::filesystem::path project, ProjectLoadCallback doneCallback ):
WThreadedRunner(),
boost::enable_shared_from_this< WProjectFile >(),
m_project( project ),
m_signalLoadDoneConnection( m_signalLoadDone.connect( doneCallback ) )
{
// The module graph parser
m_parsers.push_back( boost::shared_ptr< WProjectFileIO >( new WModuleProjectFileCombiner() ) );
// The ROI parser
m_parsers.push_back( boost::shared_ptr< WProjectFileIO >( new WRoiProjectFileIO() ) );
// The Camera parser
m_parsers.push_back( boost::shared_ptr< WProjectFileIO >( new WGEProjectFileIO() ) );
}
WProjectFile::~WProjectFile()
{
// cleanup
......@@ -128,6 +146,7 @@ void WProjectFile::threadMain()
static const boost::regex commentRe( "^ *//.*$" );
// read it line by line
std::vector< std::string > errors;
std::string line; // the current line
int i = 0; // line counter
bool match = false; // true of a parser successfully parsed the line
......@@ -152,14 +171,15 @@ void WProjectFile::threadMain()
}
catch( const std::exception& e )
{
wlog::error( "Project Loader" ) << "Line " << i << ": Parsing caused an exception. Line Malformed? Skipping.";
errors.push_back( "Parse error on line " + string_utils::toString( i ) + ": " + e.what() );
wlog::error( "Project Loader" ) << errors.back();
}
}
// did someone match this line? Or is it empty or a comment?
if( !match && !line.empty() && !boost::regex_match( line, matches, commentRe ) )
{
// no it is something else -> warning!
// no it is something else -> warning! Not a critical error.
wlog::warn( "Project Loader" ) << "Line " << i << ": Malformed. Skipping.";
}
}
......@@ -169,9 +189,23 @@ void WProjectFile::threadMain()
// finally, let every one know that we have finished
for( std::vector< boost::shared_ptr< WProjectFileIO > >::const_iterator iter = m_parsers.begin(); iter != m_parsers.end(); ++iter )
{
( *iter )->done();
try
{
( *iter )->done();
// append errors
std::copy( ( *iter )->getErrors().begin(), ( *iter )->getErrors().begin(), errors.begin() );
}
catch( const std::exception& e )
{
errors.push_back( "Exception while applying settings: " + std::string( e.what() ) );
wlog::error( "Project Loader" ) << errors.back();
}
}
// give some feedback
m_signalLoadDone( m_project, errors );
m_signalLoadDoneConnection.disconnect();
// remove from thread list
WKernel::getRunningKernel()->getRootContainer()->finishedPendingThread( shared_from_this() );
}
......
......@@ -30,6 +30,8 @@
#include <boost/filesystem.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
#include <boost/signals2/signal.hpp>
#include "../common/WProjectFileIO.h"
......@@ -53,12 +55,30 @@ public:
typedef boost::shared_ptr< const WProjectFile > ConstSPtr;
/**
* Default constructor. It does NOT parse the file. Parsing is done by apply().
* A callback function type reporting bach a finished load job. The given string vector contains a list of errors if any.
*/
typedef boost::function< void( boost::filesystem::path, std::vector< std::string > ) > ProjectLoadCallback;
/**
* A callback function signal type reporting bach a finished load job. The given string vector contains a list of errors if any.
*/
typedef boost::signals2::signal< void( boost::filesystem::path, std::vector< std::string > ) > ProjectLoadCallbackSignal;
/**
* Default constructor. It does NOT parse the file. Parsing is done by using load.
*
* \param project the project file to load.
* \param project the project file to load or save.
*/
explicit WProjectFile( boost::filesystem::path project );
/**
* Default constructor. It does NOT parse the file. Parsing is done by using load.
*
* \param project the project file to load.
* \param doneCallback gets called whenever the load thread finishes.
*/
WProjectFile( boost::filesystem::path project, ProjectLoadCallback doneCallback );
/**
* Destructor.
*/
......@@ -126,8 +146,17 @@ protected:
* \param e the exception
*/
virtual void onThreadException( const WException& e );
private:
/**
* Signal used to callback someone that the loader was finished.
*/
ProjectLoadCallbackSignal m_signalLoadDone;
/**
* Connection managing the signal m_signalLoadDone. This is the one and only connection allowed and will be disconnected upon thread has
* finished.
*/
boost::signals2::connection m_signalLoadDoneConnection;
};
#endif // WPROJECTFILE_H
......
......@@ -227,9 +227,9 @@ void WQtNetworkItem::updater()
}
// show crash state as text too
if( ( m_currentState == Crashed ) && ( m_subtitleFull != "Crashed" ) )
if( ( m_currentState == Crashed ) && ( m_subtitleFull != "Error" ) )
{
m_subtitleFull = "Crashed";
m_subtitleFull = "Error";
// this method ensures the text is shortened and correctly placed in the iem
fitLook( m_itemBestWidth, m_itemBestWidth );
needUpdate = true;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment