35 #include "klfbackend_p.h"
36 #include "klfuserscript.h"
110 for (
int k = 0; k < idlist.
size(); ++k) {
116 inline int ref() {
return ++refcount; }
117 inline int deref() {
return --refcount; }
131 void _set_xml_read_error(
const QString& fullerrmsg)
133 scriptInfoError = 999;
134 scriptInfoErrorString = fullerrmsg;
136 void _set_xml_parsing_error(
const QString& xmlfname,
const QString& errmsg)
138 scriptInfoError = 999;
139 scriptInfoErrorString =
QString(
"Error parsing scriptinfo XML contents: %1: %2")
140 .
arg(xmlfname).
arg(errmsg);
143 void read_script_info()
146 scriptInfoErrorString =
QString();
149 QFile fxml(xmlfname);
150 if ( ! fxml.open(QIODevice::ReadOnly) ) {
151 _set_xml_read_error(
QString(
"Can't open XML file %1: %2").arg(xmlfname).arg(fxml.errorString()));
156 QString errMsg;
int errLine, errCol;
157 bool r = doc.setContent(&fxml,
false, &errMsg, &errLine, &errCol);
159 _set_xml_read_error(
QString(
"XML parse error: %1 (file %2 line %3 col %4)")
160 .arg(errMsg).arg(xmlfname).arg(errLine).arg(errCol));
166 if (root.
nodeName() !=
"klfuserscript-info") {
167 _set_xml_parsing_error(xmlfname,
QString(
"expected <klfuserscript-info> as root document element"));
180 if ( n.
nodeType() != QDomNode::ElementNode ) {
198 }
else if (e.
nodeName() ==
"name") {
204 }
else if (e.
nodeName() ==
"author") {
206 }
else if (e.
nodeName() ==
"version") {
212 }
else if (e.
nodeName() ==
"license") {
218 }
else if (e.
nodeName() ==
"klf-min-version") {
220 _set_xml_parsing_error(xmlfname,
QString::fromLatin1(
"duplicate <klf-min-version> element"));
224 }
else if (e.
nodeName() ==
"klf-max-version") {
226 _set_xml_parsing_error(xmlfname,
QString::fromLatin1(
"duplicate <klf-max-version> element"));
230 }
else if (e.
nodeName() ==
"category") {
236 }
else if (e.
nodeName() ==
"settings-form-ui") {
238 _set_xml_parsing_error(xmlfname,
QString::fromLatin1(
"duplicate <settings-form-ui> element"));
242 }
else if (e.
nodeName() ==
"can-provide-default-settings") {
255 e.
save(tstream, 2); }
256 klfDbg(
"Read category-specific XML: " << xmlrepr);
290 QString normalizedfn = normalizedFn(userScriptFileName);
291 Private::userScriptInfoCache.remove(normalizedfn);
295 klfWarning(qPrintable(usinfo.scriptInfoErrorString()));
301 void KLFUserScriptInfo::clearCacheAll()
304 Private::userScriptInfoCache.clear();
309 bool KLFUserScriptInfo::hasScriptInfoInCache(
const QString& userScriptFileName)
311 QString normalizedfn = normalizedFn(userScriptFileName);
312 klfDbg(
"userScriptFileName = " << userScriptFileName <<
"; normalizedfn = " << normalizedfn) ;
313 klfDbg(
"cache: " << Private::userScriptInfoCache) ;
314 return Private::userScriptInfoCache.contains(normalizedfn);
323 if (Private::userScriptInfoCache.contains(normalizedfn)) {
324 d = Private::userScriptInfoCache[normalizedfn];
326 d =
new KLFUserScriptInfo::Private;
328 d()->uspath = normalizedfn;
329 d()->normalizedfname = normalizedfn;
333 d()->read_script_info();
336 Private::userScriptInfoCache[normalizedfn] = d();
348 KLFUserScriptInfo::~KLFUserScriptInfo()
363 return d()->basename;
366 int KLFUserScriptInfo::scriptInfoError()
const
368 return d()->scriptInfoError;
370 QString KLFUserScriptInfo::scriptInfoErrorString()
const
372 return d()->scriptInfoErrorString;
376 void KLFUserScriptInfo::setScriptInfoError(
int code,
const QString & msg)
378 d()->scriptInfoError = code;
379 d()->scriptInfoErrorString = msg;
382 QString KLFUserScriptInfo::relativeFile(
const QString& fname)
const
387 QString KLFUserScriptInfo::exeScript()
const {
return scriptInfo(ExeScript).
toString(); }
388 QString KLFUserScriptInfo::exeScriptFullPath()
const
390 return relativeFile(exeScript());
393 QString KLFUserScriptInfo::category()
const {
return scriptInfo(Category).
toString(); }
394 QString KLFUserScriptInfo::name()
const {
return scriptInfo(Name).
toString(); }
397 QString KLFUserScriptInfo::version()
const {
return scriptInfo(Version).
toString(); }
398 QString KLFUserScriptInfo::license()
const {
return scriptInfo(License).
toString(); }
399 QString KLFUserScriptInfo::klfMinVersion()
const {
return scriptInfo(KLFMinVersion).
toString(); }
400 QString KLFUserScriptInfo::klfMaxVersion()
const {
return scriptInfo(KLFMaxVersion).
toString(); }
403 bool KLFUserScriptInfo::canProvideDefaultSettings()
const {
return scriptInfo(CanProvideDefaultSettings).
toBool(); }
413 proc.setProcessAppEvents(
false);
420 proc.collectStdoutTo(&stdoutdata);
421 proc.collectStderrTo(&stderrdata);
423 bool ok = proc.run();
426 << qPrintable(proc.resultErrorString())) ;
430 klfDbg(
"stdoutdata = " << stdoutdata) ;
431 klfDbg(
"stderrdata = " << stderrdata) ;
445 QString errMsg;
int errLine, errCol;
446 bool r = doc.setContent(trimmedstdoutdata,
false, &errMsg, &errLine, &errCol);
448 klfWarning(
"XML parse error: "<<qPrintable(errMsg)
450 <<errLine<<
" col "<<errCol<<
")") ;
451 return QVariantMap();
455 if (root.
nodeName() !=
"klfuserscript-default-settings") {
456 klfWarning(
"expected <klfuserscript-default-settings> as root document element");
457 return QVariantMap();
474 klfWarning(
"Invalid line in reported userscript default config: " << line) ;
491 bool KLFUserScriptInfo::hasNotices()
const
493 return d->notices.size();
495 bool KLFUserScriptInfo::hasWarnings()
const
497 return d->warnings.size();
499 bool KLFUserScriptInfo::hasErrors()
const
501 return d->errors.size();
512 QVariant KLFUserScriptInfo::scriptInfo(
int propId)
const
514 return d()->property(propId);
527 int id = d()->propertyIdForName(x);
530 <<field<<
" ("<<x<<
")") ;
533 return scriptInfo(
id);
538 return d()->propertyNameList();
541 QString KLFUserScriptInfo::objectKind()
const {
return d()->objectKind(); }
545 void KLFUserScriptInfo::internalSetProperty(
const QString& key,
const QVariant &val)
547 d()->setProperty(key, val);
568 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
569 "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
570 "p, li { white-space: pre-wrap; }\n"
571 "p.msgnotice { color: blue; font-weight: bold; margin: 2px 0px; }\n"
572 "p.msgwarning { color: #a06000; font-weight: bold; margin: 2px 0px; }\n"
573 "p.msgerror { color: #a00000; font-weight: bold; margin: 2px 0px; }\n"
574 ".scriptinfokey { }\n"
575 ".scriptinfovalue { font-weight: bold; }\n"
582 txt += escapeListIntoTags(notices(),
"<p class=\"msgnotice\">",
"</p>\n");
585 txt += escapeListIntoTags(warnings(),
"<p class=\"msgwarning\">",
"</p>\n");
588 txt += escapeListIntoTags(errors(),
"<p class=\"msgerror\">",
"</p>\n");
593 "<p style=\"-qt-block-indent: 0; text-indent: 0px; margin-top: 8px; margin-bottom: 0px\">\n"
594 "<span class=\"scriptinfokey\">" +
QObject::tr(
"Script Name:",
"[[user script info text]]")
595 +
"</span> "
599 txt +=
"<span class=\"scriptinfokey\">" +
QObject::tr(
"Category:",
"[[user script info text]]")
600 +
"</span> "
601 "<span class=\"scriptinfovalue\">" + category().
toHtmlEscaped() +
"</span><br />\n";
603 if (!version().isEmpty()) {
605 txt +=
"<span class=\"scriptinfokey\">" +
QObject::tr(
"Version:",
"[[user script info text]]")
606 +
"</span> "
607 "<span class=\"scriptinfovalue\">" + version().
toHtmlEscaped() +
"</span><br />\n";
609 if (!author().isEmpty()) {
611 txt +=
"<span class=\"scriptinfokey\">" +
QObject::tr(
"Author:",
"[[user script info text]]")
612 +
"</span> "
613 "<span class=\"scriptinfovalue\">" + author().
toHtmlEscaped() +
"</span><br />\n";
616 if (!license().isEmpty()) {
618 txt +=
"<span class=\"scriptinfokey\">" +
QObject::tr(
"License:",
"[[user script info text]]")
619 +
"</span> "
620 "<span class=\"scriptinfovalue\">" + license().
toHtmlEscaped() +
"</span><br />\n";
632 for (QVariantMap::const_iterator it = usconfig.begin(); it != usconfig.end(); ++it)
638 QStringList KLFUserScriptInfo::usConfigToEnvList(
const QVariantMap& usconfig)
646 return val.
split(
QRegExp(
"\\s+"), QString::SkipEmptyParts);
666 for (
int k = 0; k < idlist.
size(); ++k) {
671 void _set_xml_parsing_error(
const QString& errmsg)
673 K->setScriptInfoError(1001,
QString(
"Error parsing klf-backend-engine XML config: %1: %2")
674 .arg(K->userScriptBaseName()).
arg(errmsg));
676 void parse_category_config(
const QByteArray & ba)
679 QString errMsg;
int errLine, errCol;
680 bool r = doc.setContent(ba,
false, &errMsg, &errLine, &errCol);
682 K->setScriptInfoError(
684 QString(
"XML parse error: %1 (klf-backend-engine in %2, relative line %3 col %4)")
685 .arg(errMsg).arg(K->userScriptBaseName()).
arg(errLine).
arg(errCol));
690 if (root.
nodeName() !=
"klf-backend-engine") {
691 _set_xml_parsing_error(
QString(
"expected <klf-backend-engine> element"));
702 if ( n.
nodeType() != QDomNode::ElementNode ) {
715 if (!
property(KLFBackendEngineUserScriptInfo::SpitsOut).toStringList().isEmpty()) {
716 _set_xml_parsing_error(
QString(
"duplicate <spits-out> element"));
719 setProperty(KLFBackendEngineUserScriptInfo::SpitsOut, space_sep_values(val));
720 }
else if (e.
nodeName() ==
"skip-formats") {
721 if (!
property(KLFBackendEngineUserScriptInfo::SkipFormats).
toString().isEmpty()) {
722 _set_xml_parsing_error(
QString(
"duplicate <skip-formats> element"));
729 lst << space_sep_values(s.
replace(
'-',
'_'));
731 lst << space_sep_values(val);
732 setProperty(KLFBackendEngineUserScriptInfo::SkipFormats, lst);
733 }
else if (e.
nodeName() ==
"disable-inputs") {
734 if (!
property(KLFBackendEngineUserScriptInfo::DisableInputs).toStringList().isEmpty()) {
735 _set_xml_parsing_error(
QString(
"duplicate <disable-inputs> element"));
742 lst << space_sep_values(s.
replace(
'-',
'_'));
744 lst << space_sep_values(val);
745 setProperty(KLFBackendEngineUserScriptInfo::DisableInputs, lst);
746 }
else if (e.
nodeName() ==
"input-form-ui") {
747 if (!
property(KLFBackendEngineUserScriptInfo::InputFormUI).toStringList().isEmpty()) {
748 _set_xml_parsing_error(
QString(
"duplicate <input-form-ui> element"));
751 setProperty(KLFBackendEngineUserScriptInfo::InputFormUI, val);
753 _set_xml_parsing_error(
QString(
"Found unexpected element: %1").arg(e.
nodeName()));
758 klfDbg(
"Read all klfbackend-engine properties:\n" << qPrintable(
toString()));
764 KLFBackendEngineUserScriptInfo::KLFBackendEngineUserScriptInfo(
const QString& uspath)
769 if (category() !=
"klf-backend-engine") {
770 klfWarning(
"KLFBackendEngineUserScriptInfo instantiated for user script "
771 << uspath <<
", which is of category " << category()) ;
777 KLFBackendEngineUserScriptInfo::~KLFBackendEngineUserScriptInfo()
790 return klfBackendEngineInfo(SkipFormats).
toStringList();
794 return klfBackendEngineInfo(DisableInputs).
toStringList();
798 return klfBackendEngineInfo(InputFormUI).
toString();
802 QVariant KLFBackendEngineUserScriptInfo::klfBackendEngineInfo(
int propId)
const
804 return d->property(propId);
807 QVariant KLFBackendEngineUserScriptInfo::klfBackendEngineInfo(
const QString& field)
const
813 int id = d->propertyIdForName(x);
815 klfDbg(
"KLFBackendEngineUserScriptInfo for "<<
userScriptName()<<
" does not have any information about "
816 <<field<<
" ("<<x<<
")") ;
819 return scriptInfo(
id);
822 QStringList KLFBackendEngineUserScriptInfo::klfBackendEngineInfosList()
const
824 return d->propertyNameList();
838 struct KLFUserScriptFilterProcessPrivate
860 klfDbg(
"userScriptFileName= "<<userScriptFileName) ;
866 QString exescript = d->usinfo->exeScriptFullPath();
867 klfDbg(
"exescript = " << exescript) ;
872 KLFUserScriptFilterProcess::~KLFUserScriptFilterProcess()
878 void KLFUserScriptFilterProcess::addUserScriptConfig(
const QVariantMap& usconfig)
880 QStringList envlist = KLFUserScriptInfo::usConfigToEnvList(usconfig);
881 addExecEnviron(envlist);
892 +d->usinfo->userScriptBaseName().toHtmlEscaped()
906 "<pre class=\"output\">%2</pre></p>\n") ;
909 if (bstdout.
size()) {
913 if (bstderr.
size()) {
918 if (KLFUserScriptFilterProcessPrivate::log.size() > 255) {
919 KLFUserScriptFilterProcessPrivate::log.
erase(KLFUserScriptFilterProcessPrivate::log.begin());
922 KLFUserScriptFilterProcessPrivate::log << thislog;
932 while (it != KLFUserScriptFilterProcessPrivate::log.cbegin()) {
940 "<meta charset=\"utf-8\">"
941 "<title>User Script Log</title>"
942 "<style type=\"text/css\">"
943 ".userscript-run { font-weight: bold; font-size: 2em; } "
944 ".userscriptname { font: monospace; } "
945 ".output-type { font-weight: bold; } "
QStringList spitsOut() const
List of formats that this script will generate.
QString inputFormUI() const
A UI input form file (Qt designer file) for additional input.
QStringList skipFormats() const
List of formats that klfbackend should not attempt to generate.
QStringList disableInputs() const
List of user input fields that should be disabled.
virtual bool do_run(const QByteArray &indata, const QMap< QString, QByteArray * > outdatalist)
Actually run the process.
QByteArray collectedStdout() const
The collected stdout data of the process that just ran.
QByteArray collectedStderr() const
The collected stderr data of the process that just ran.
virtual QString resultErrorString() const
virtual QVariant property(const QString &propName) const
KLFPropertizedObject(const QString &propertyNameSpace)
virtual bool setProperty(const QString &propname, const QVariant &value)
void registerBuiltInProperty(int propId, const QString &propName) const
QList< int > registeredPropertyIdList() const
virtual QString toString(uint toStringFlags=0) const
static QString getUserScriptLogHtml(bool include_head=true)
Return the user script log, formatted in human-readable HTML.
virtual bool do_run(const QByteArray &indata, const QMap< QString, QByteArray * > outdatalist)
KLFUserScriptFilterProcess(const QString &scriptFileName, const KLFBackend::klfSettings *settings=NULL)
Summary of the info returned by a user script.
QString userScriptPath() const
e.g. "/path/to/klffeynmf.klfuserscript"
@ CategorySpecificXmlConfig
XML representation of the category-specific configuration (QByteArray)
QString settingsFormUI() const
A UI widget form file (Qt designer file) to display for setting up the user script.
QString userScriptName() const
e.g. "klffeynmf.klfuserscript"
QStringList scriptInfosList() const
A list of Keys (eg. "Name", "Author", ... including custom infos) found in the scriptinfo.
QString htmlInfo(const QString &extra_css=QString()) const
Formats most (all?) properties in HTML, suitable for human-readable text display.
QString userScriptBaseName() const
e.g. "klffeynmf"
KLFUserScriptInfo(const QString &userScriptPath)
QByteArray categorySpecificXmlConfig() const
The XML for the category-specific config.
Definition of class KLFBackend.
#define KLFERR_NOERROR
No Error.
KLF_EXPORT QVariant klfLoadVariantFromText(const QByteArray &stringdata, const char *dataTypeName, const char *listOrMapDataTypeName)
KLF_EXPORT QByteArray klfSaveVariantToText(const QVariant &value, bool saveListAndMapsAsXML, QByteArray *savedType, QByteArray *savedListOrMapType)
KLF_EXPORT QVariantMap klfLoadVariantMapFromXML(const QDomElement &xmlNode)
#define klfWarning(streamableItems)
#define KLF_DEBUG_BLOCK(msg)
#define klfDbg(streamableItems)
#define KLF_PRIVATE_HEAD(ClassName)
#define KLF_DELETE_PRIVATE
#define KLF_PRIVATE_INHERIT_HEAD(ClassName, BaseInit)
#define KLF_INIT_PRIVATE(ClassName)
QStringList klfMapToEnvironmentList(const QMap< QString, QString > &map)
int indexOf(char ch, int from) const
QByteArray left(int len) const
QByteArray mid(int pos, int len) const
QList< QByteArray > split(char sep) const
bool startsWith(const QByteArray &ba) const
QByteArray trimmed() const
QDateTime currentDateTime()
QString toString(Qt::DateFormat format) const
QString toNativeSeparators(const QString &pathName)
QString attribute(const QString &name, const QString &defValue) const
bool hasAttribute(const QString &name) const
QDomNode firstChild() const
QDomNode nextSibling() const
NodeType nodeType() const
void save(QTextStream &stream, int indent, EncodingPolicy encodingPolicy) const
QDomElement toElement() const
QString canonicalFilePath() const
const_iterator cend() const
iterator erase(iterator pos)
QString tr(const char *sourceText, const char *disambiguation, int n)
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const
QString fromLatin1(const char *str, int size)
QString fromLocal8Bit(const char *str, int size)
QString fromUtf8(const char *str, int size)
QString & replace(int position, int n, QChar after)
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
QString toHtmlEscaped() const
QByteArray toUtf8() const
QString join(const QString &separator) const
QByteArray toByteArray() const
QStringList toStringList() const
General settings for KLFBackend::getLatexFormula()