diff --git a/src/common/mlexception.h b/src/common/mlexception.h index 7518b5b66..2c452f4d2 100644 --- a/src/common/mlexception.h +++ b/src/common/mlexception.h @@ -1,32 +1,45 @@ #ifndef ML_EXCEPTION #define ML_EXCEPTION -class ParsingException : public std::exception +class MeshLabException : public std::exception +{ +public: + MeshLabException(const QString& text) + :std::exception(),excText(text){_ba = excText.toLocal8Bit();} + + ~MeshLabException() throw() {} + inline const char* what() const throw() {return _ba.constData();} + +protected: + QString excText; + QByteArray _ba; + +}; + +class ParsingException : public MeshLabException { public: ParsingException(const QString& text) - :excText(text){excText = QString("Parsing Error: ") + excText;_ba = excText.toLocal8Bit();} + :MeshLabException(QString("Parsing Error: ") + text){} ~ParsingException() throw() {} - inline const char* what() const throw() {return _ba.constData();} - -private: - QString excText; - QByteArray _ba; }; -class ValueNotFoundException : public std::exception +class ValueNotFoundException : public MeshLabException { public: ValueNotFoundException(const QString& valName) - :valNM(valName){valNM = QString("Value Name: ") + valNM + QString(" has not been found in current environment.");_ba = valNM.toLocal8Bit();} + :MeshLabException(QString("Value Name: ") + valName + QString(" has not been found in current environment.")){} ~ValueNotFoundException() throw() {} - inline const char* what() const throw() { return _ba.constData();} - -private: - QString valNM; - QByteArray _ba; }; +class QueryException : public MeshLabException +{ +public: + QueryException(const QString& syntaxError) + :MeshLabException(QString("Query Error: ") + syntaxError){} + + ~QueryException() throw() {} +}; #endif diff --git a/src/common/pluginmanager.cpp b/src/common/pluginmanager.cpp index 24c8e31b0..24e222bca 100644 --- a/src/common/pluginmanager.cpp +++ b/src/common/pluginmanager.cpp @@ -64,8 +64,7 @@ void PluginManager::loadPlugins(RichParameterSet& defaultGlobal) fc.xmlInfo = XMLFilterInfo::createXMLFileInfo(xmlFile,xmlSchemaFile(),xmlErr); if (fc.xmlInfo != NULL) { - XMLMessageHandler errQuery; - QStringList fn = fc.xmlInfo->filterNames(errQuery); + QStringList fn = fc.xmlInfo->filterNames(); foreach(QString filtName,fn) { fc.act = new QAction(filtName,plugin); @@ -78,7 +77,7 @@ void PluginManager::loadPlugins(RichParameterSet& defaultGlobal) else { QString err = xmlErr.statusMessage(); - qDebug("Error in XMLFile: %s - %s",qPrintable(xmlFile),qPrintable(err)); + qDebug("Error in XMLFile: %s - line: %d, column: %d - %s",qPrintable(xmlFile),xmlErr.line(),xmlErr.column(),qPrintable(err)); } } @@ -253,7 +252,7 @@ void PluginManager::LoadFormats(QStringList &filters, QHash #include #include +#include "mlexception.h" XMLFilterInfo* XMLFilterInfo::createXMLFileInfo( const QString& XMLFileName,const QString& XMLSchemaFileName,XMLMessageHandler& errXML) { @@ -33,51 +34,61 @@ XMLFilterInfo* XMLFilterInfo::createXMLFileInfo( const QString& XMLFileName,cons } file.close(); validator.setMessageHandler(oldHandler); + return new XMLFilterInfo(XMLFileName); } - return new XMLFilterInfo(XMLFileName); + return NULL; } -QStringList XMLFilterInfo::filterNames(XMLMessageHandler& errQuery) const +QStringList XMLFilterInfo::filterNames() const { QString namesQuery = "doc(\"" + this->fileName + "\")/MESHLAB_FILTER_INTERFACE/PLUGIN/FILTER/

{data(@name)}

/string()"; - return query(namesQuery,errQuery); + try + { + return query(namesQuery); + } + catch(QueryException e) + { + qDebug(e.what()); + } + } -QString XMLFilterInfo::filterHelp( const QString& filterName,bool& isValid,XMLMessageHandler& errQuery) const +QString XMLFilterInfo::filterHelp( const QString& filterName) const { QString namesQuery = "doc(\"" + this->fileName + "\")/MESHLAB_FILTER_INTERFACE/PLUGIN/FILTER[@name = \"" + filterName + "\"]/FILTER_HELP/string()"; - QStringList res = query(namesQuery,errQuery); - if (res.size() != 1) + try { - isValid = false; - return QString(); - } - else - { - isValid = true; + QStringList res = query(namesQuery); + if (res.size() != 1) + throw ParsingException("There is not help tag for filter " + filterName); return res[0]; } + catch(QueryException q) + { + qDebug(q.what()); + } } -QString XMLFilterInfo::filterAttribute( const QString& filterName,const QString& attribute,bool& isValid,XMLMessageHandler& errQuery) const +QString XMLFilterInfo::filterAttribute( const QString& filterName,const QString& attribute) const { QString namesQuery = "doc(\"" + this->fileName + "\")/MESHLAB_FILTER_INTERFACE/PLUGIN/FILTER[@name = \"" + filterName + "\"]/@" + attribute + "/string()"; - QStringList res = query(namesQuery,errQuery); - if (res.size() != 1) + try { - isValid = false; - return QString(); - } - else + QStringList res = query(namesQuery); + if (res.size() != 1) + throw ParsingException("Attribute " + attribute + " has not been specified for filter " + filterName); + return res[0]; + } + catch (QueryException e) { - isValid = true; - return res[0]; + qDebug(e.what()); } } -QStringList XMLFilterInfo::query( const QString& qry,XMLMessageHandler& errQuery ) const +QStringList XMLFilterInfo::query( const QString& qry) const { + XMLMessageHandler errQuery; QXmlQuery xmlq; xmlq.setQuery(qry); QAbstractMessageHandler * oldHandler = xmlq.messageHandler(); @@ -88,21 +99,83 @@ QStringList XMLFilterInfo::query( const QString& qry,XMLMessageHandler& errQuery { //errQuery = xmlq.messageHandler(); xmlq.setMessageHandler(oldHandler); - QString mes = errQuery.statusMessage(); - return result; + throw QueryException(QString("line: ") + errQuery.line() + " column: " + errQuery.column() + " - " + errQuery.statusMessage()); + } xmlq.evaluateTo(&result); + QString res; + xmlq.evaluateTo(&res); xmlq.setMessageHandler(oldHandler); return result; } -QStringList XMLFilterInfo::filterParameters( const QString& filterName,bool& isValid,XMLMessageHandler& errQuery) const +XMLFilterInfo::MapList XMLFilterInfo::filterParameters( const QString& filterName) const { - QString namesQuery = "doc(\"" + this->fileName + "\")/MESHLAB_FILTER_INTERFACE/PLUGIN/FILTER[@name = \"" + filterName + "\"]/PARAM/

{data(@type)},{data(@name)},{data(@defaultExpression)}

/string()"; - QStringList res = query(namesQuery,errQuery); - if (res.size() == 0) - isValid = false; - else - isValid = true; - return res; + QString namesQuery = "doc(\"" + this->fileName + "\")/MESHLAB_FILTER_INTERFACE/PLUGIN/FILTER[@name = \"" + filterName + "\"]/PARAM/

type={data(@type)}|name={data(@name)}|defaultExpression={data(@defaultExpression)}

/string()"; + try + { + QStringList res = query(namesQuery); + return mapListFromStringList(res); + } + catch (QueryException e) + { + throw e; + } } + +XMLFilterInfo::MapList XMLFilterInfo::mapListFromStringList( const QStringList& list ) +{ + MapList result; + //"attribute0=value0|attribute1=value1|...|attributeN=valueN" "attribute0=value0|attribute1=value1|...|attributeN=valueN" "attribute0=value0|attribute1=value1|...|attributeN=valueN" + foreach(QString st, list) + { + QStringList coupleList = st.split('|'); + QMap attrValue; + foreach(QString couple,coupleList) + { + QStringList cl = couple.split('='); + if (cl.size() == 2) + attrValue[cl[0]]=cl[1]; + } + result.push_back(attrValue); + } + return result; +} + +QString XMLFilterInfo::defaultGuiInfo(const QString& guiType,const QString& xmlvariable) +{ + return QString("type=" + guiType + "|label={data(" + xmlvariable + "/@label)}"); +} + +QString XMLFilterInfo::floatGuiInfo(const QString& guiType,const QString& xmlvariable) +{ + return defaultGuiInfo(guiType,xmlvariable) + "|minExpr={data(" + xmlvariable + "/@minExpr)}|maxExpr={data(" + xmlvariable + "/@maxExpr)}"; +} + +QMap XMLFilterInfo::filterParameterGui( const QString& filterName,const QString& parameterName) const +{ + QString var("$gui"); + QString queryBase("for " + var + " in doc(\"" + this->fileName + "\")/MESHLAB_FILTER_INTERFACE/PLUGIN/FILTER[@name = " + filterName + "]/PARAM[@name =" + parameterName + "]/(* except PARAM_HELP) return typeswitch($gui)\n"); + QString caseABS("element (ABSPERC_GUI) return

" + defaultGuiInfo("ABSPERC_GUI",var) + "

/string()\n"); + QString caseFLOAT("element (CHECKBOX_GUI) return

" + defaultGuiInfo("CHECKBOX_GUI",var) + "

/string()\n"); + QString errorMsg("Error: Unknown GUI widget requested"); + QString defaultCase("default return " + errorMsg); + QString totQuery = queryBase + caseABS + caseFLOAT + defaultCase; + QMap mp; + try + { + QStringList res = query(totQuery); + XMLFilterInfo::MapList tmp = mapListFromStringList(res); + //MUST BE FOR EACH PARAMETER ONLY ONE GUI DECLARATION + if (tmp.size() != 1) + throw ParsingException("In filter " + filterName + " more than a single GUI declaration has been found for parameter " + parameterName); + else if (res[0] == errorMsg) + //GUI NOT DEFINED + throw ParsingException("In filter " + filterName + " no valid GUI declaration has been found for parameter " + parameterName); + else return tmp[0]; + } + catch(QueryException e) + { + qDebug(e.what()); + } +} \ No newline at end of file diff --git a/src/common/xmlfilterinfo.h b/src/common/xmlfilterinfo.h index 9da4d2deb..65791d440 100644 --- a/src/common/xmlfilterinfo.h +++ b/src/common/xmlfilterinfo.h @@ -47,28 +47,36 @@ private: }; +//Query Exception should be managed by the XMLFilterInfo class (XMLFilterInfo is the class devoted to compose queries) +//Parsing Exception instead should be managed by the code calling the XMLFilterInfo's functions. +//A Parsing Exception is raised every time an unexpected and/or missing tag or attribute in an XML has been encountered. +//So this kind of info it's sensible for the plugin's programmer. + + class XMLFilterInfo { private: XMLFilterInfo(const QString& file) :fileName(file){} - + static QString defaultGuiInfo(const QString& guiType,const QString& xmlvariable); + static QString floatGuiInfo(const QString& guiType,const QString& xmlvariable); QString fileName; public: + typedef QList< QMap > MapList; + static MapList mapListFromStringList(const QStringList& list); static XMLFilterInfo* createXMLFileInfo(const QString& XMLFileName,const QString& XMLSchemaFileName,XMLMessageHandler& errXML); inline static void deleteXMLFileInfo(XMLFilterInfo* xmlInfo) {delete xmlInfo;} - QStringList filterNames(XMLMessageHandler& errXML) const; - QString filterHelp(const QString& filterName,bool& isValid,XMLMessageHandler& errXML) const; + QStringList filterNames() const; + QString filterHelp(const QString& filterName) const; - //The function returns a string list of all parameters for filterName. Each string in the list is a triple param_type,param_name,param_defaultExpression - //In order to parse each triple component is sufficient to call split(',') - QStringList filterParameters(const QString& filterName,bool& isValid,XMLMessageHandler& errXML) const; - QString filterAttribute(const QString& filterName,const QString& attribute,bool& isValid,XMLMessageHandler& errXML) const; + //The function returns a QList>. Each map contains "type", "name" and "defaultExpression" of a single parameter. + MapList filterParameters(const QString& filterName) const; - /*QStringList filterParameters(const QString& filter); - QStringList filterParametersAndGui(const QString& filter);*/ - QStringList query(const QString& qry,XMLMessageHandler& errQuery) const; + QMap filterParameterGui(const QString& filter,const QString& parameter) const; + QString filterAttribute(const QString& filterName,const QString& attribute) const; + + QStringList query(const QString& qry) const; }; struct MeshLabXMLFilterContainer