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(); }
395 QString KLFUserScriptInfo::author()
const {
return scriptInfo(Author).toStringList().join(
"; "); }
396 QStringList KLFUserScriptInfo::authorList()
const {
return scriptInfo(Author).toStringList(); }
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(); }
423 bool ok = proc.run();
430 klfDbg(
"stdoutdata = " << stdoutdata) ;
431 klfDbg(
"stderrdata = " << stderrdata) ;
433 klfDbg(
"Ran script "<<
userScriptPath()<<
": stdout="<<stdoutdata<<
"\n\tstderr="<<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();
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(); }
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);
657 registerBuiltInProperty(KLFBackendEngineUserScriptInfo::SpitsOut,
QLatin1String(
"SpitsOut"));
658 registerBuiltInProperty(KLFBackendEngineUserScriptInfo::SkipFormats,
QLatin1String(
"SkipFormats"));
659 registerBuiltInProperty(KLFBackendEngineUserScriptInfo::DisableInputs,
QLatin1String(
"DisableInputs"));
660 registerBuiltInProperty(KLFBackendEngineUserScriptInfo::InputFormUI,
QLatin1String(
"InputFormUI"));
665 QList<int> idlist = registeredPropertyIdList();
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()
786 return klfBackendEngineInfo(SpitsOut).toStringList();
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
859 klfDbg(
"userScriptFileName= "<<userScriptFileName) ;
865 QString exescript = d->usinfo->exeScriptFullPath();
866 klfDbg(
"exescript = " << exescript) ;
871 KLFUserScriptFilterProcess::~KLFUserScriptFilterProcess()
877 void KLFUserScriptFilterProcess::addUserScriptConfig(
const QVariantMap& usconfig)
879 QStringList envlist = KLFUserScriptInfo::usConfigToEnvList(usconfig);
880 addExecEnviron(envlist);
891 +d->usinfo->userScriptBaseName().toHtmlEscaped()
905 "<pre class=\"output\">%2</pre></p>\n") ;
908 if (bstdout.
size()) {
912 if (bstderr.
size()) {
917 if (KLFUserScriptFilterProcessPrivate::log.size() > 255) {
918 KLFUserScriptFilterProcessPrivate::log.
erase(KLFUserScriptFilterProcessPrivate::log.begin());
921 KLFUserScriptFilterProcessPrivate::log << thislog;
931 while (it != KLFUserScriptFilterProcessPrivate::log.cbegin()) {
939 "<meta charset=\"utf-8\">" 940 "<title>User Script Log</title>" 941 "<style type=\"text/css\">" 942 ".userscript-run { font-weight: bold; font-size: 2em; } " 943 ".userscriptname { font: monospace; } " 944 ".output-type { font-weight: bold; } " QStringList skipFormats() const
List of formats that klfbackend should not attempt to generate.
static QString getUserScriptLogHtml(bool include_head=true)
Return the user script log, formatted in human-readable HTML.
QStringList disableInputs() const
List of user input fields that should be disabled.
QString toString(Qt::DateFormat format) const
QByteArray toByteArray() const
QString toNativeSeparators(const QString &pathName)
virtual bool do_run(const QByteArray &indata, const QMap< QString, QByteArray *> outdatalist)
Actually run the process.
KLF_EXPORT QByteArray klfSaveVariantToText(const QVariant &value, bool saveListAndMapsAsXML, QByteArray *savedType, QByteArray *savedListOrMapType)
#define KLF_PRIVATE_HEAD(ClassName)
XML representation of the category-specific configuration (QByteArray)
QString htmlInfo(const QString &extra_css=QString()) const
Formats most (all?) properties in HTML, suitable for human-readable text display. ...
QList< QByteArray > split(char sep) const
QByteArray trimmed() const
KLFUserScriptFilterProcess(const QString &scriptFileName, const KLFBackend::klfSettings *settings=NULL)
QString attribute(const QString &name, const QString &defValue) const
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
KLFAbstractPropertizedObject()
bool startsWith(const QByteArray &ba) const
#define klfDbg(streamableItems)
QString userScriptName() const
e.g. "klffeynmf.klfuserscript"
#define KLF_DEBUG_BLOCK(msg)
iterator erase(iterator pos)
void collectStdoutTo(QByteArray *stdoutstore)
QDomElement documentElement() const
#define KLFERR_NOERROR
No Error.
NodeType nodeType() const
void registerBuiltInProperty(int propId, const QString &propName) const
QByteArray collectedStderr() const
The collected stderr data of the process that just ran.
virtual QVariant property(const QString &propName) const
QString tr(const char *sourceText, const char *disambiguation, int n)
KLFUserScriptInfo(const QString &userScriptPath)
void collectStderrTo(QByteArray *stderrstore)
QString inputFormUI() const
A UI input form file (Qt designer file) for additional input.
QStringList scriptInfosList() const
A list of Keys (eg. "Name", "Author", ... including custom infos) found in the scriptinfo.
QStringList spitsOut() const
List of formats that this script will generate.
QDomNode nextSibling() const
QDomElement toElement() const
#define KLF_DELETE_PRIVATE
QString userScriptPath() const
e.g. "/path/to/klffeynmf.klfuserscript"
int indexOf(char ch, int from) const
QByteArray collectedStdout() const
The collected stdout data of the process that just ran.
QString canonicalFilePath() const
QString fromLocal8Bit(const char *str, int size)
virtual bool do_run(const QByteArray &indata, const QMap< QString, QByteArray *> outdatalist)
QString fromUtf8(const char *str, int size)
bool hasAttribute(const QString &name) const
virtual QString resultErrorString() const
#define klfWarning(streamableItems)
virtual bool setProperty(const QString &propname, const QVariant &value)
QByteArray mid(int pos, int len) const
QString userScriptBaseName() const
e.g. "klffeynmf"
QList< int > registeredPropertyIdList() const
QString toHtmlEscaped() const
Definition of class KLFBackend.
QString & replace(int position, int n, QChar after)
#define KLF_PRIVATE_INHERIT_HEAD(ClassName, BaseInit)
QByteArray left(int len) const
const_iterator cend() const
QString settingsFormUI() const
A UI widget form file (Qt designer file) to display for setting up the user script.
QDateTime currentDateTime()
void save(QTextStream &stream, int indent, EncodingPolicy encodingPolicy) const
QDomNode firstChild() const
Summary of the info returned by a user script.
QStringList klfMapToEnvironmentList(const QMap< QString, QString > &map)
QByteArray categorySpecificXmlConfig() const
The XML for the category-specific config.
QString fromLatin1(const char *str, int size)
#define KLF_INIT_PRIVATE(ClassName)
virtual QString toString(uint toStringFlags=0) const
KLF_EXPORT QVariant klfLoadVariantFromText(const QByteArray &stringdata, const char *dataTypeName, const char *listOrMapDataTypeName)
KLF_EXPORT QVariantMap klfLoadVariantMapFromXML(const QDomElement &xmlNode)
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const
General settings for KLFBackend::getLatexFormula()
bool setContent(const QByteArray &data, bool namespaceProcessing, QString *errorMsg, int *errorLine, int *errorColumn)
void setProcessAppEvents(bool processEvents)
QByteArray toUtf8() const