@@ -698,18 +698,31 @@ QJsonValue fitToQuestion(const Question &q, const QJsonValue &v)
698698 return {};
699699}
700700
701- QString summaryText (int answered, int total, int changed, int clarify)
701+ QString summaryText (int answered, int total, int changed, int clarify, bool hasNote )
702702{
703703 const QString head = answered == total
704704 ? QStringLiteral (" Answered %1 question%2" ).arg (total).arg (total == 1 ? QString () : QStringLiteral (" s" ))
705705 : QStringLiteral (" Answered %1 of %2 questions" ).arg (answered).arg (total);
706706 QString out = head + QStringLiteral (" · %1 changed" ).arg (changed);
707707 if (clarify > 0 )
708708 out += QStringLiteral (" · %1 to clarify" ).arg (clarify);
709+ if (hasNote)
710+ out += QStringLiteral (" · note" );
709711 return out;
710712}
711713
712714constexpr QLatin1String kNeedsClarification (" needs clarification" );
715+ // Never a question line: those start `<id> "`.
716+ constexpr QLatin1String kUserNoteLead (" Note from the user: " );
717+
718+ // The form note as a prompt line; continuation lines are indented so the
719+ // summary and overview parsers never read them as questions.
720+ QString userNoteLine (const QString ¬e)
721+ {
722+ QString text = note.trimmed ();
723+ text.replace (QLatin1Char (' \n ' ), QStringLiteral (" \n " ));
724+ return kUserNoteLead + text;
725+ }
713726
714727} // namespace
715728
@@ -767,7 +780,7 @@ QVector<Answer> carryOver(const Spec &next, const QVector<Answer> &previous)
767780 return out;
768781}
769782
770- QString formatAnswers (const Spec &spec, const QVector<Answer> &answers)
783+ QString formatAnswers (const Spec &spec, const QVector<Answer> &answers, const QString ¬e )
771784{
772785 QString out = QLatin1String (kAnswersHeader ) + QLatin1Char (' \n ' );
773786 if (!spec.title .isEmpty ())
@@ -801,6 +814,8 @@ QString formatAnswers(const Spec &spec, const QVector<Answer> &answers)
801814 out += QStringLiteral (" note: " ) + indented + QLatin1Char (' \n ' );
802815 }
803816 }
817+ if (!note.trimmed ().isEmpty ())
818+ out += userNoteLine (note) + QLatin1Char (' \n ' );
804819 // No `": ` in this line: the summary and overview parsers skip it.
805820 if (!unclear.isEmpty ()) {
806821 out += QStringLiteral (" To clarify: %1. Explain them in the user's language, then call ask_user again "
@@ -810,7 +825,7 @@ QString formatAnswers(const Spec &spec, const QVector<Answer> &answers)
810825 return out;
811826}
812827
813- QString answerSummary (const Spec &spec, const QVector<Answer> &answers)
828+ QString answerSummary (const Spec &spec, const QVector<Answer> &answers, const QString ¬e )
814829{
815830 int answered = 0 ;
816831 int changed = 0 ;
@@ -827,7 +842,8 @@ QString answerSummary(const Spec &spec, const QVector<Answer> &answers)
827842 if (isChanged (q, *a))
828843 ++changed;
829844 }
830- return summaryText (answered, static_cast <int >(spec.questions .size ()), changed, clarify);
845+ return summaryText (answered, static_cast <int >(spec.questions .size ()), changed, clarify,
846+ !note.trimmed ().isEmpty ());
831847}
832848
833849QString summaryFromAnswersText (const QString &text)
@@ -841,16 +857,23 @@ QString summaryFromAnswersText(const QString &text)
841857 return QStringLiteral (" Asked to clarify " ) + text.mid (from + kLead .size (), to - from - kLead .size ());
842858 return QStringLiteral (" Asked to clarify a question" );
843859 }
844- if (text.contains (QLatin1String (kDismissedLine )))
845- return QStringLiteral (" Dismissed the form" );
860+ if (text.contains (QLatin1String (kDismissedLine ))) {
861+ const bool hasNote = text.contains (QString (QLatin1Char (' \n ' )) + kUserNoteLead );
862+ return hasNote ? QStringLiteral (" Dismissed the form · note" ) : QStringLiteral (" Dismissed the form" );
863+ }
846864 int total = 0 ;
847865 int answered = 0 ;
848866 int changed = 0 ;
849867 int clarify = 0 ;
868+ bool hasNote = false ;
850869 static const QString kClarifyEnd = QStringLiteral (" \" : " ) + kNeedsClarification ;
851870 const QStringList lines = text.split (QLatin1Char (' \n ' ));
852871 for (int i = 1 ; i < lines.size (); ++i) { // line 0 is the header
853872 const QString &line = lines.at (i);
873+ if (line.startsWith (kUserNoteLead )) {
874+ hasNote = true ;
875+ continue ;
876+ }
854877 if (line.isEmpty () || line.at (0 ).isSpace () || line.startsWith (QLatin1String (" Form: " ))
855878 || !line.contains (QLatin1String (" \" : " ))) {
856879 continue ;
@@ -866,7 +889,7 @@ QString summaryFromAnswersText(const QString &text)
866889 if (line.contains (QStringLiteral (" — changed (recommended: " )))
867890 ++changed;
868891 }
869- return summaryText (answered, total, changed, clarify);
892+ return summaryText (answered, total, changed, clarify, hasNote );
870893}
871894
872895namespace {
@@ -1116,9 +1139,25 @@ QStringList answerOverview(const QString &text, int maxAnswerChars)
11161139 return out;
11171140 static const QLatin1String kRecommended (" (recommended)" );
11181141 static const QString kChanged = QStringLiteral (" — changed (recommended: " );
1142+ auto cut = [maxAnswerChars](QString s) {
1143+ if (maxAnswerChars > 1 && s.size () > maxAnswerChars)
1144+ s = s.left (maxAnswerChars - 1 ) + QStringLiteral (" …" );
1145+ return s;
1146+ };
11191147 const QStringList lines = text.split (QLatin1Char (' \n ' ));
11201148 for (int i = 1 ; i < lines.size (); ++i) {
11211149 const QString &line = lines.at (i);
1150+ if (line.startsWith (kUserNoteLead )) {
1151+ // The form note on one line: its indented continuation joins it.
1152+ QString note = line.mid (kUserNoteLead .size ());
1153+ while (i + 1 < lines.size () && lines.at (i + 1 ).startsWith (QLatin1String (" " ))) {
1154+ const QString more = lines.at (++i).trimmed ();
1155+ if (!more.isEmpty ())
1156+ note += QLatin1Char (' ' ) + more;
1157+ }
1158+ out.append (QStringLiteral (" Note → " ) + cut (note));
1159+ continue ;
1160+ }
11221161 if (line.isEmpty () || line.at (0 ).isSpace () || line.startsWith (QLatin1String (" Form: " )))
11231162 continue ;
11241163 const qsizetype space = line.indexOf (QLatin1Char (' ' ));
@@ -1150,8 +1189,7 @@ QStringList answerOverview(const QString &text, int maxAnswerChars)
11501189 item = displayItem (item);
11511190 shown = items.join (QStringLiteral (" , " ));
11521191 }
1153- if (maxAnswerChars > 1 && shown.size () > maxAnswerChars)
1154- shown = shown.left (maxAnswerChars - 1 ) + QStringLiteral (" …" );
1192+ shown = cut (shown);
11551193 out.append (QStringLiteral (" %1 %2 → %3" ).arg (id, title, shown)
11561194 + (changed ? QStringLiteral (" · changed" ) : QString ()));
11571195 }
@@ -1162,7 +1200,7 @@ QString dismissPrompt(const QString ¬e)
11621200{
11631201 QString out = QLatin1String (kAnswersHeader ) + QLatin1Char (' \n ' ) + QLatin1String (kDismissedLine );
11641202 if (!note.trimmed ().isEmpty ())
1165- out += QStringLiteral ( " \n Note from the user: " ) + note. trimmed ( );
1203+ out += QLatin1Char ( ' \n ' ) + userNoteLine (note );
11661204 return out;
11671205}
11681206
0 commit comments