changeset 76:1e6e7699f0b8

Add replacements.ini to configure text replacements
author Andre Heinecke <andre.heinecke@intevation.de>
date Wed, 05 Oct 2016 14:23:23 +0200
parents 92139cc60121
children 9412d60c8ac1
files packaging/win-createpackage.sh.in src/CMakeLists.txt src/constants.h src/converter.cpp src/replacements.ini
diffstat 5 files changed, 118 insertions(+), 30 deletions(-) [+]
line wrap: on
line diff
--- a/packaging/win-createpackage.sh.in	Tue Oct 04 17:12:28 2016 +0200
+++ b/packaging/win-createpackage.sh.in	Wed Oct 05 14:23:23 2016 +0200
@@ -11,6 +11,8 @@
 
 echo File \"@CMAKE_BINARY_DIR@/src/@PROJECT_NAME@.exe\" >> @CMAKE_CURRENT_BINARY_DIR@/filelist_in.nsh
 echo Delete \"$INSTDIR\\@PROJECT_NAME@.exe\" >> @CMAKE_CURRENT_BINARY_DIR@/filelist_un.nsh
+echo File \"@CMAKE_SOURCE_DIR@/src/replacements.ini\" >> @CMAKE_CURRENT_BINARY_DIR@/filelist_in.nsh
+echo Delete \"$INSTDIR\\replacements.ini\" >> @CMAKE_CURRENT_BINARY_DIR@/filelist_un.nsh
 echo File \"@CMAKE_SOURCE_DIR@/LICENSE.txt\" >> @CMAKE_CURRENT_BINARY_DIR@/filelist_in.nsh
 echo Delete \"$INSTDIR\\LICENSE.txt\" >> @CMAKE_CURRENT_BINARY_DIR@/filelist_un.nsh
 
--- a/src/CMakeLists.txt	Tue Oct 04 17:12:28 2016 +0200
+++ b/src/CMakeLists.txt	Wed Oct 05 14:23:23 2016 +0200
@@ -20,6 +20,7 @@
     icons/icon.rc
     filenamerequester.cpp
     mainwindow.cpp
+    replacements.ini
 )
 
 find_package(Qt5LinguistTools)
@@ -119,6 +120,7 @@
 endif(WIN32)
 
 install(TARGETS ${PROJECT_NAME} DESTINATION bin BUNDLE DESTINATION .)
+install(FILES replacements.ini DESTINATION share/apps/${PROJECT_NAME} COMPONENT config)
 
 if(APPLE)
    install(CODE "
--- a/src/constants.h	Tue Oct 04 17:12:28 2016 +0200
+++ b/src/constants.h	Wed Oct 05 14:23:23 2016 +0200
@@ -75,15 +75,6 @@
  * @brief The pattern used to match a free text answer. */
 #define FREETXT_PATTERN "\"([^\"]*)\"?", QRegularExpression::MultilineOption
 
-/**
- * @brief the pattern to unsecape images. */
-#define IMAGE_PATTERN "##(.*)##", QRegularExpression::MultilineOption
-
-
-/**
- * @brief the pattern to unsecape latex. */
-#define LATEX_PATTERN "\\$\\$(.*)\\$\\$", QRegularExpression::MultilineOption
-
 #define TITLE_ROW_HEIGHT 30
 
 #define CHOICE_ROW_HEIGHT 30
@@ -114,5 +105,7 @@
 
 #define PRETTY_NAME "EduExportConverter"
 
+#define CONFIG_FILE_NAME "replacements.ini"
+
 
 #endif // CONSTANTS_H
--- a/src/converter.cpp	Tue Oct 04 17:12:28 2016 +0200
+++ b/src/converter.cpp	Wed Oct 05 14:23:23 2016 +0200
@@ -14,6 +14,10 @@
 #include <QPrinter>
 #include <QImage>
 #include <QPainter>
+#include <QMessageBox>
+#include <QDir>
+#include <QCoreApplication>
+#include <QSettings>
 
 #include "xlsxdocument.h"
 #include "xlsxconditionalformatting.h"
@@ -135,22 +139,80 @@
     return;
 }
 
-static void unescapeRegex(QString &str, const QRegularExpression &exp)
+static const QMap<QRegularExpression*, QString> loadExpressionsFromFile(const QString &path, QStringList &errors)
 {
-    QRegularExpressionMatch match = exp.match(str);
-    while (match.hasMatch()) {
-        str.replace(match.capturedStart(), match.capturedLength(), match.captured(1));
-        match = exp.match(str);
+    QFile file(path);
+    QMap<QRegularExpression*, QString> ret;
+
+    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+        errors << QObject::tr("Failed to open replacement file:") + "\n\"" + path + "\"";
+        return ret;
     }
+
+    while (!file.atEnd()) {
+        const auto line = file.readLine();
+        auto strline = QString::fromUtf8(line).trimmed();
+        if (strline.startsWith(QStringLiteral(";")) || strline.isEmpty()) {
+            continue;
+        }
+
+        auto split = strline.split("=");
+        if (split.count() != 2) {
+            errors << QObject::tr("Invalid replacement line:") + "\n\"" + strline + "\"";
+            continue;
+        }
+
+        auto exp = new QRegularExpression (split[0], QRegularExpression::MultilineOption);
+        if (!exp->isValid()) {
+            errors << QObject::tr("Invalid regular expression:") + "\n\"" + split[0] + "\"" +
+                                 "\n" + QObject::tr("Error: ") + exp->errorString();
+            continue;
+        }
+        const auto rep = split[1].replace("\"", "");
+        ret.insert(exp, rep);
+        qDebug() << "Loaded replacement: " << *exp << " replacement:" << rep << "";
+    }
+    /* Special one that does not fit into the ini format well. */
+    ret.insert(new QRegularExpression("^="), " =");
+    return ret;
 }
 
-static void unescapeString(QString &str)
+static const QMap<QRegularExpression*, QString> loadExpressions(QStringList &errors)
 {
-    static const QRegularExpression imgEx(IMAGE_PATTERN);
-    static const QRegularExpression texEx(LATEX_PATTERN);
+    QMap<QRegularExpression*, QString> regexs;
+    /* Look for file next to our place */
+    auto ourDir = QDir(QCoreApplication::applicationDirPath());
+    const auto filename = QStringLiteral(CONFIG_FILE_NAME);
+    if (ourDir.exists(filename)) {
+        regexs = loadExpressionsFromFile(ourDir.filePath(filename), errors);
+        return regexs;
+    }
 
-    unescapeRegex(str, imgEx);
-    unescapeRegex(str, texEx);
+    /* Look in ../share/apps/PROJECT_NAME */
+    ourDir.cd(QStringLiteral("../share/apps/" APPNAME).toLower());
+    if (ourDir.exists(filename)) {
+        regexs = loadExpressionsFromFile(ourDir.filePath(filename), errors);
+    } else {
+        qDebug() << "Failed to find regular expressions.";
+    }
+    return regexs;
+}
+
+static const QStringList sanitizeInput(QString &str)
+{
+    QStringList errors;
+    str.replace("\r\n", "\n");
+    str.replace("\n\r", "\n");
+    const auto expressions = loadExpressions(errors);
+    for (const auto regex: expressions.keys()) {
+        str.replace(*regex, expressions.value(regex));
+        delete regex;
+    }
+    return errors;
+}
+
+static void xlsEscape(QString &str)
+{
     if (str.startsWith("=")) {
         str = " " + str;
     }
@@ -203,9 +265,7 @@
     QRegularExpression freetxtEx(FREETXT_PATTERN);
     QRegularExpression firstQuestionEx(FIRST_QUESTION_PATTERN);
 
-    input.replace("\r\n", "\n");
-    input.replace("\n\r", "\n");
-    input.replace("#NAME?\n", "");
+    mErrors += sanitizeInput(input);
 
     QRegularExpressionMatch match = firstQuestionEx.match(input);
     bool foundSomething = false;
@@ -229,6 +289,7 @@
         const QString answerLine = match.captured(2).trimmed();
         xlsx.write(row, 2, QString(" "), mQuestionFmt);
         xlsx.write(row, 3, QString(" "), mQuestionFmt);
+        xlsEscape(question);
         xlsx.write(row++, 1, question, mQuestionFmt);
         html << mQuestionStyle.arg(question.toHtmlEscaped());
 
@@ -248,10 +309,7 @@
 
                 /* Write the values */
                 QString choiceName = choiceMatch.captured(1).trimmed();
-                if (choiceName.startsWith("=")) {
-                    choiceName = " " + choiceName;
-                }
-                unescapeString(choiceName);
+                xlsEscape(choiceName);
                 xlsx.write(row, 1, choiceName, mChoiceTextFmt);
                 html << mChoiceTextStyle.arg(choiceName.toHtmlEscaped());
                 qDebug() << "Captured for choice: " << choiceMatch.captured(0);
@@ -292,10 +350,10 @@
                 QString choice = choiceMatch.captured(1);
                 cursor = choiceMatch.capturedEnd();
                 /* Alternative answer that is just a list of strings */
-                unescapeString(choice);
                 qDebug() << "Captured unfilled choice: " << choice;
                 html << mChoiceTextStyle.arg(choice.toHtmlEscaped());
                 makeBar(html, 0, doc);
+                xlsEscape(choice);
                 xlsx.write(row, 1, choice);
                 xlsx.write(row, 2, QVariant());
                 const QString numVotesString = QStringLiteral("Keine eingegangenen Antworten");
@@ -345,14 +403,15 @@
                     const QString unquoted = input.mid(cursor, unquotedLen);
                     qDebug() << "Found inner quoted string: " << unquoted;
                     /* Now combine */
-                    const QString combined = QString("%1\"%2\"%3").arg(lastRow).
-                                                                   arg(unquoted).
-                                                                   arg(textMatch.captured(1).trimmed());
+                    QString combined = QString("%1\"%2\"%3").arg(lastRow).
+                                                                 arg(unquoted).
+                                                                 arg(textMatch.captured(1).trimmed());
                     qDebug() << "Last row: " << lastRow;
                     qDebug() << "Next Question is at: " << nextQuestion.capturedStart();
                     qDebug() << "Text match is: " << textMatch.captured(1).trimmed();
                     qDebug() << "cursor is at: " << cursor;
                     qDebug() << "text match starts at: " << textMatch.capturedStart();
+                    xlsEscape(combined);
                     xlsx.write(row - 1, 26, combined, mFreeTextFmt);
                     xlsx.write(row - 1, 1, combined, mFreeTextFmt);
                     cursor = textMatch.capturedEnd();
@@ -374,6 +433,7 @@
                    http://excel.tips.net/T003207_Automatic_Row_Height_For_Merged_Cells_with_Text_Wrap.html
                 */
                 /* Write the values */
+                xlsEscape(text);
                 xlsx.write(QString("Z%1").arg(row), text, mFreeTextFmt);
                 xlsx.write(row, 1, text, mFreeTextFmt);
                 row++;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/replacements.ini	Wed Oct 05 14:23:23 2016 +0200
@@ -0,0 +1,31 @@
+; Replacements for EduExportConvert
+;
+; This file describes replacements done by EduExportConvert
+;
+; The Syntax is:
+;
+; <Regular Expression>=<Replacement>
+;
+; Any input that matches the Expression will be replaced
+; by the right hand side of the equation.
+;
+; The Regular Expression syntax is perl compatible.
+; Please refer to:
+; http://perldoc.perl.org/perlretut.html
+; For documentation about the syntax.
+;
+; Groups can be referenced through \1 \2 etc. see examples below.
+;
+; Lines starting with ; are ignored
+;
+; This file should be UTF-8 encoded.
+
+; Excel artifiacts ?
+#NAME\?=
+; Remove latex escape characters.
+\$\$(.*?)\$\$=" \1 "
+; Remove image escape characters.
+##(.*?)##=" \1 "
+; Image qualifiers
+\\hfill=
+\\filbreak=
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)