Mercurial > clickerconvert
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."); |