comparison src/converter.cpp @ 25:e5c5ebfa4205

Refactor to centralise html tags
author Andre Heinecke <andre.heinecke@intevation.de>
date Mon, 11 Apr 2016 11:24:17 +0200
parents 927794e3cc52
children 5acd601356ba
comparison
equal deleted inserted replaced
24:1470cb8a00a8 25:e5c5ebfa4205
32 mTitleFmt.setFontSize(18); 32 mTitleFmt.setFontSize(18);
33 mTitleFmt.setFontName("Calibri"); 33 mTitleFmt.setFontName("Calibri");
34 mTitleFmt.setFontBold(true); 34 mTitleFmt.setFontBold(true);
35 mTitleFmt.setVerticalAlignment(Format::AlignTop); 35 mTitleFmt.setVerticalAlignment(Format::AlignTop);
36 36
37 mTitleStyle = QStringLiteral("style='vertical-align: top;font-weight: bold;font-size:18; text-decoration: underline;'");
38 37
39 mQuestionFmt.setFontSize(11); 38 mQuestionFmt.setFontSize(11);
40 mQuestionFmt.setFontName("Calibri"); 39 mQuestionFmt.setFontName("Calibri");
41 mQuestionFmt.setFontBold(true); 40 mQuestionFmt.setFontBold(true);
42 mQuestionFmt.setTopBorderStyle(Format::BorderThin); 41 mQuestionFmt.setTopBorderStyle(Format::BorderThin);
43 mQuestionFmt.setBottomBorderStyle(Format::BorderThin); 42 mQuestionFmt.setBottomBorderStyle(Format::BorderThin);
44 mQuestionFmt.setTextWarp(true); 43 mQuestionFmt.setTextWarp(true);
45 mQuestionStyle = QStringLiteral("style='border-bottom: 1pt solid black;border-top: 1pt solid black;font-weight: bold;font-size:11;'");
46 44
47 mAnswerChoiceFmt.setFontSize(11); 45 mAnswerChoiceFmt.setFontSize(11);
48 mAnswerChoiceFmt.setFontName("Calibri"); 46 mAnswerChoiceFmt.setFontName("Calibri");
49 mAnswerChoiceFmt.setHorizontalAlignment(Format::AlignLeft); 47 mAnswerChoiceFmt.setHorizontalAlignment(Format::AlignLeft);
50 mAnswerChoiceFmt.setTextWarp(true); 48 mAnswerChoiceFmt.setTextWarp(true);
51 mAnswerChoiceStyle= QStringLiteral("style='text-align: left;font-size:11;'");
52 49
53 mChoiceTextFmt = mAnswerChoiceFmt; 50 mChoiceTextFmt = mAnswerChoiceFmt;
54 mChoiceTextFmt.setVerticalAlignment(Format::AlignVCenter); 51 mChoiceTextFmt.setVerticalAlignment(Format::AlignVCenter);
55 mChoiceTextStyle= QStringLiteral("style='text-align: right;vertical-algin: center; font-size:11;'");
56 52
57 mChoiceVotesFmt = mChoiceTextFmt; 53 mChoiceVotesFmt = mChoiceTextFmt;
58 mChoiceVotesFmt.setFontSize(10); 54 mChoiceVotesFmt.setFontSize(10);
59 mChoiceVotesStyle = QStringLiteral("style='text-align: left;vertical-algin: center; font-size:10;'");
60 55
61 mFreeTextFmt = mQuestionFmt; 56 mFreeTextFmt = mQuestionFmt;
62 mFreeTextFmt.setFontBold(false); 57 mFreeTextFmt.setFontBold(false);
63 mFreeTextStyle = QStringLiteral("style='border-bottom: 1pt solid black;border-top: 1pt solid black;font-size:11;'");
64 58
65 mAnswerTextFmt = mQuestionFmt; 59 mAnswerTextFmt = mQuestionFmt;
66 mAnswerTextFmt.setVerticalAlignment(Format::AlignVCenter); 60 mAnswerTextFmt.setVerticalAlignment(Format::AlignVCenter);
67 mAnswerTextFmt.setHorizontalAlignment(Format::AlignLeft); 61 mAnswerTextFmt.setHorizontalAlignment(Format::AlignLeft);
68 mAnswerTextStyle = QStringLiteral("style='text-align: left;font-weight: bold;vertical-algin: center; border-bottom: 1pt solid black;border-top: 1pt solid black;font-size:11;'"); 62
63 mTitleStyle = QStringLiteral("<tr><td colspan='3' style='vertical-align: top;"
64 "font-weight: bold;font-size:18; text-decoration:"
65 "underline;'>%1</td></tr>");
66 const QString questionBorders = QStringLiteral("style='border-bottom: 1pt solid black;"
67 "border-top: 1pt solid black;font-weight:"
68 "bold;font-size:11;'");
69 mQuestionStyle = QStringLiteral("<tr><td ") + questionBorders + QStringLiteral(">%1</td>") +
70 QStringLiteral("<td %1</td>").arg(questionBorders) +
71 QStringLiteral("<td %1</td>").arg(questionBorders);
72 mAnswerChoiceStyle= QStringLiteral("<tr><td style='text-align: left;font-size:11;'>Answer</td><td/><td/></tr>");
73 mChoiceTextStyle= QStringLiteral("<tr><td style='text-align: right;vertical-algin: center; font-size:11;'>%1</td>");
74 mChoiceVotesStyle = QStringLiteral("<td style='text-align: left;vertical-algin: center;"
75 "font-size:10;'</td>%1</td></tr>");
76 mAnswerTextStyle = QStringLiteral("<tr><td style='text-align: left;font-weight: bold;vertical-algin: center;"
77 "border-bottom: 1pt solid black;border-top: 1pt solid black;font-size:11;'"
78 ">Answer</td><td/></td></tr>");
79 mFreeTextStyle = QStringLiteral("<tr><td colspan='3' style='border-bottom: 1pt solid black;"
80 "border-top: 1pt solid black;font-size:11;'>%1</td></tr>");
81 mEmptyRow = QStringLiteral("<tr style='height: %1px'/>").arg(CHOICE_ROW_HEIGHT);
69 } 82 }
70 83
71 void Converter::run() 84 void Converter::run()
72 { 85 {
73 QFile infile; 86 QFile infile;
98 mErrors << tr("Failed to open %1 for writing.").arg(mOutput); 111 mErrors << tr("Failed to open %1 for writing.").arg(mOutput);
99 return; 112 return;
100 } 113 }
101 } 114 }
102 convertToXSLX(instream, outfile); 115 convertToXSLX(instream, outfile);
116 }
117
118 static void makeBar(QTextStream &html, double percent, QTextDocument &doc, bool forPDF)
119 {
120 html << QStringLiteral("<td style='background:linear-gradient(to right,"
121 "#ff9933, #ff9933 %1%, #ffffff %1%)'></td>").arg(percent);
122 return;
103 } 123 }
104 124
105 void Converter::convertToXSLX(QTextStream& instream, QFile &output) 125 void Converter::convertToXSLX(QTextStream& instream, QFile &output)
106 { 126 {
107 Document xlsx; 127 Document xlsx;
136 156
137 int row = 1; 157 int row = 1;
138 html << "<tr><th width=\"" << col1Width << "\"</th>"; 158 html << "<tr><th width=\"" << col1Width << "\"</th>";
139 html << "<th width=\"" << col2Width << "\"</th>"; 159 html << "<th width=\"" << col2Width << "\"</th>";
140 html << "<th width=\"" << col3Width << "\"</th>"; 160 html << "<th width=\"" << col3Width << "\"</th>";
141 html << "<tr><td colspan='3' " << mTitleStyle << "/>";
142 const QString title = mTitle.isEmpty() ? DEFAULT_TITLE : mTitle; 161 const QString title = mTitle.isEmpty() ? DEFAULT_TITLE : mTitle;
143 // Set the title of the Questionaire 162 // Set the title of the Questionaire
144 xlsx.write(row++, 1, title, mTitleFmt); 163 xlsx.write(row++, 1, title, mTitleFmt);
145 html << title.toHtmlEscaped() << "</td></tr>"; 164 html << mTitleStyle.arg(title.toHtmlEscaped());
146 xlsx.mergeCells("A1:C1"); 165 xlsx.mergeCells("A1:C1");
147 xlsx.setRowHeight(1, TITLE_ROW_HEIGHT); 166 xlsx.setRowHeight(1, TITLE_ROW_HEIGHT);
148 167
149 const QString input = instream.readAll(); 168 const QString input = instream.readAll();
150 169
167 const QString question = match.captured(1).trimmed(); 186 const QString question = match.captured(1).trimmed();
168 const QString answerLine = match.captured(2).trimmed(); 187 const QString answerLine = match.captured(2).trimmed();
169 xlsx.write(row, 2, QString(" "), mQuestionFmt); 188 xlsx.write(row, 2, QString(" "), mQuestionFmt);
170 xlsx.write(row, 3, QString(" "), mQuestionFmt); 189 xlsx.write(row, 3, QString(" "), mQuestionFmt);
171 xlsx.write(row++, 1, question, mQuestionFmt); 190 xlsx.write(row++, 1, question, mQuestionFmt);
172 html << "<tr><td " << mQuestionStyle << ">" << question.toHtmlEscaped() << "</td>" 191 html << mQuestionStyle.arg(question.toHtmlEscaped());
173 "<td " << mQuestionStyle << "/>"
174 "<td " << mQuestionStyle << "/></tr>";
175 192
176 if (answerLine == QStringLiteral(CHOICE_IDENTIFIER)) { 193 if (answerLine == QStringLiteral(CHOICE_IDENTIFIER)) {
177 QRegularExpressionMatch choiceMatch = choiceEx.match(input, cursor); 194 QRegularExpressionMatch choiceMatch = choiceEx.match(input, cursor);
178 xlsx.setRowHeight(row, CHOICE_ROW_HEIGHT); 195 xlsx.setRowHeight(row, CHOICE_ROW_HEIGHT);
179 xlsx.write(row++, 1, "Answer", mAnswerChoiceFmt); 196 xlsx.write(row++, 1, "Answer", mAnswerChoiceFmt);
180 html << "<tr><td " << mAnswerChoiceStyle << ">" << "Answer" << "</td><td/><td/></tr>"; 197 html << mAnswerChoiceStyle;
181 int firstChoiceRow = row; 198 int firstChoiceRow = row;
182 int lastChoiceRow = row; 199 int lastChoiceRow = row;
183 while (choiceMatch.hasMatch() && choiceMatch.capturedStart() == cursor + 1) { 200 while (choiceMatch.hasMatch() && choiceMatch.capturedStart() == cursor + 1) {
184 /* We use the cursor here to keep track of the state. Only if an answer 201 /* We use the cursor here to keep track of the state. Only if an answer
185 follows immediately behind the last answer we treat it as valid as 202 follows immediately behind the last answer we treat it as valid as
190 QString choiceName = choiceMatch.captured(1).trimmed(); 207 QString choiceName = choiceMatch.captured(1).trimmed();
191 if (choiceName.startsWith("=")) { 208 if (choiceName.startsWith("=")) {
192 choiceName = " " + choiceName; 209 choiceName = " " + choiceName;
193 } 210 }
194 xlsx.write(row, 1, choiceName, mChoiceTextFmt); 211 xlsx.write(row, 1, choiceName, mChoiceTextFmt);
195 html << "<tr><td " << mChoiceTextStyle << ">" << choiceName.toHtmlEscaped() << "</td>"; 212 html << mChoiceTextStyle.arg(choiceName.toHtmlEscaped());
196 bool ok; 213 bool ok;
197 double percent = choiceMatch.captured(3).toDouble(&ok); 214 double percent = choiceMatch.captured(3).toDouble(&ok);
198 if (!ok) { 215 if (!ok) {
199 mErrors << "Unparsable number in string: " + choiceMatch.captured(); 216 mErrors << "Unparsable number in string: " + choiceMatch.captured();
200 } 217 }
201 html << QStringLiteral("<td style='background:linear-gradient(to right," 218 makeBar(html, percent, doc, mFmt == Format_PDF);
202 "#ff9933, #ff9933 %1%, #ffffff %1%)'>").arg(percent);
203 html << "</td>";
204 xlsx.write(row, 2, percent); 219 xlsx.write(row, 2, percent);
205 const QString numVotesString = QString("%1% | %2 Number of votes"). 220 const QString numVotesString = QString("%1% | %2 Number of votes").
206 arg(choiceMatch.captured(3)).arg(choiceMatch.captured(2)); 221 arg(choiceMatch.captured(3)).arg(choiceMatch.captured(2));
207 html << "<td " << mChoiceVotesStyle << ">" << numVotesString.toHtmlEscaped() << "</td></tr>"; 222 html << mChoiceVotesStyle.arg(numVotesString.toHtmlEscaped());
208 xlsx.write(row, 3, numVotesString, mChoiceVotesFmt); 223 xlsx.write(row, 3, numVotesString, mChoiceVotesFmt);
209 xlsx.setRowHeight(row, CHOICE_ROW_HEIGHT); 224 xlsx.setRowHeight(row, CHOICE_ROW_HEIGHT);
210 /* As long as we can match a choice which is either before the next question 225 /* As long as we can match a choice which is either before the next question
211 or before the end of the document */ 226 or before the end of the document */
212 choiceMatch = choiceEx.match(input, cursor); 227 choiceMatch = choiceEx.match(input, cursor);
217 // xlsx.groupRows(firstChoiceRow - 2, lastChoiceRow - 1, false); 232 // xlsx.groupRows(firstChoiceRow - 2, lastChoiceRow - 1, false);
218 } else if (answerLine == QStringLiteral(TEXT_IDENTIFIER)) { 233 } else if (answerLine == QStringLiteral(TEXT_IDENTIFIER)) {
219 QRegularExpressionMatch textMatch = freetxtEx.match(input, cursor); 234 QRegularExpressionMatch textMatch = freetxtEx.match(input, cursor);
220 xlsx.setRowHeight(row, CHOICE_ROW_HEIGHT); 235 xlsx.setRowHeight(row, CHOICE_ROW_HEIGHT);
221 xlsx.write(row++, 1, "Answer", mAnswerTextFmt); 236 xlsx.write(row++, 1, "Answer", mAnswerTextFmt);
222 html << "<tr><td " << mAnswerTextStyle << ">" << "Answer" << "</td><td/><td/></tr>"; 237 html << mAnswerTextStyle;
223 238
224 /* To handle the workaround for quotes in answers we store 239 /* To handle the workaround for quotes in answers we store
225 * the number of rows and only afterwards create the html rows. */ 240 * the number of rows and only afterwards create the html rows. */
226 int firstFreeRow = row; 241 int firstFreeRow = row;
227 while (textMatch.hasMatch()) { 242 while (textMatch.hasMatch()) {
278 row++; 293 row++;
279 294
280 textMatch = freetxtEx.match(input, cursor); 295 textMatch = freetxtEx.match(input, cursor);
281 } 296 }
282 for (int i = firstFreeRow; i < row; i++) { 297 for (int i = firstFreeRow; i < row; i++) {
283 html << "<tr><td colspan='3' " << mFreeTextStyle << ">"; 298 html << mFreeTextStyle.arg(xlsx.read(i, 1).toString().toHtmlEscaped());
284 html << xlsx.read(i, 1).toString().toHtmlEscaped();
285 html << "</td></tr>";
286 } 299 }
287 } 300 }
288 /* Insert Empty row. */ 301 /* Insert Empty row. */
289 xlsx.setRowHeight(row++, CHOICE_ROW_HEIGHT); 302 xlsx.setRowHeight(row++, CHOICE_ROW_HEIGHT);
290 match = questionEx.match(input, cursor); 303 match = questionEx.match(input, cursor);
291 cursor = match.capturedEnd(); 304 cursor = match.capturedEnd();
292 html << QStringLiteral("<tr style='height: %1px'/>").arg(CHOICE_ROW_HEIGHT); 305 html << mEmptyRow;
293 } 306 }
294 xlsx.addConditionalFormatting(bars); 307 xlsx.addConditionalFormatting(bars);
295 308
296 if (!foundSomething) { 309 if (!foundSomething) {
297 mErrors << tr("Failed to parse input document."); 310 mErrors << tr("Failed to parse input document.");
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)