void QGithubMarkdown::read(const QByteArray &markdown, QTextDocument *target) { doc = target; doc->clear(); cursor = QTextCursor(doc); cursor.beginEditBlock(); const QList<Token> tokens = tokenize(clean(QString::fromUtf8(markdown))); const QList<Paragraph> paragraphs = paragraphize(tokens); const auto paralists = listize(paragraphs); //std::for_each(paragraphs.begin(), paragraphs.end(), [](const Paragraph &item){qDebug() << item;}); bool firstBlock = true; for (const auto paralist : paralists) { auto insertTokens = [&](const QList<Token> &tokens, const QTextCharFormat &format, const bool isCode) { QTextCharFormat fmt(format); QTextCharFormat codeFmt(format); codeFmt.setFontFamily("Monospace"); QListIterator<Token> iterator(tokens); while (iterator.hasNext()) { const Token token = iterator.next(); if (isCode) { cursor.insertText(token.source); } else { if (token.type == Token::Bold) { if (fmt.fontWeight() == QFont::Bold) { fmt.setFontWeight(QFont::Normal); } else { fmt.setFontWeight(QFont::Bold); } } else if (token.type == Token::Italic) { fmt.setFontItalic(!fmt.fontItalic()); } else if (token.type == Token::InlineCodeDelimiter) { while (iterator.hasNext()) { const Token next = iterator.next(); if (next.type == Token::InlineCodeDelimiter) { break; } else { cursor.insertText(token.source, codeFmt); } } } else if (token.type == Token::Character) { cursor.insertText(token.content.toChar(), fmt); } else { cursor.insertText(token.source, fmt); } } } }; if (paralist.second.indent == -1) { const Paragraph paragraph = paralist.first; QTextCharFormat charFmt; QTextBlockFormat blockFmt; blockFmt.setBottomMargin(5.0f); if (Paragraph::FirstHeading <= paragraph.type && paragraph.type <= Paragraph::LastHeading) { charFmt.setFontPointSize(sizeMap[paragraph.type]); } else if (paragraph.type == Paragraph::Quote) { blockFmt.setIndent(1); } else if (paragraph.type == Paragraph::Code) { blockFmt.setNonBreakableLines(true); charFmt.setFontFamily("Monospace"); } if (!firstBlock) { cursor.insertBlock(); } else { firstBlock = false; } cursor.setBlockFormat(blockFmt); cursor.block().setUserState(paragraph.type); insertTokens(paragraph.tokens, charFmt, paragraph.type == Paragraph::Code); } else { const List list = paralist.second; qDebug() << "##########################" << list.indent << list.ordered; std::for_each(list.paragraphs.begin(), list.paragraphs.end(), [](const Paragraph &item){qDebug() << item;}); cursor.setBlockFormat(QTextBlockFormat()); cursor.setBlockCharFormat(QTextCharFormat()); QTextListFormat listFormat; listFormat.setStyle(list.ordered ? QTextListFormat::ListDecimal : QTextListFormat::ListDisc); listFormat.setIndent(list.indent); QTextList *l = cursor.insertList(listFormat); qDebug() << "inserting list" << list.indent; bool firstBlock = true; for (const Paragraph ¶graph : list.paragraphs) { if (firstBlock) { firstBlock = false; } else { cursor.insertBlock(); qDebug() << "inserting block"; } insertTokens(paragraph.tokens, QTextCharFormat(), false); qDebug() << l->count(); l->add(cursor.block()); qDebug() << l->count(); qDebug() << "inserting characters"; } } } cursor.endEditBlock(); qDebug() << doc->toHtml(); }
//Lecture des paragraphes bool OpenDocument::contenu_paragraphe(QDomElement e, QTextCursor &curseur, bool puces, bool h_item, bool tableau){ ErrorManager instance_erreur; p_current++; case_tableau = ""; //On change la QProgressBar //chargement-> QString nom_style = e.attribute("text:style-name", "default"); QTextCharFormat format = cree_bloc_format(nom_style); //On récupère le format de bloc QTextBlockFormat format_bloc = cree_bloc_format2(nom_style); //On ajoute un marginTop de 5 pour plus de lisibilité format_bloc.setTopMargin(2); //Style spécifique aux puces if(puces || h_item){ int id_style = -1; for(int i=0; i<styles.size(); i++){ //On parcourt les styles if(id_style >= 0){ break; } for(int j=0; j<styles.at(i).size(); j++){ //On rentre dans le QMultiMap if(puces){ if(styles.at(i).value("style-puces") == nom_style){ id_style = i; //On sort de la boucle break; } } else{ //Ce ne peut être que le "h_item" sinon la boucle ne se déclencherait pas if(styles.at(i).value("style-h") == nom_style){ id_style = i; //On se casse break; } } } } if(id_style != -1){ //On merge le style format.merge(cree_bloc_format(styles.at(id_style).value("style-puces"))); } } //On applique le format au curseur curseur.setCharFormat(format); if(!tableau){ curseur.beginEditBlock(); } curseur.setBlockCharFormat(format); curseur.setBlockFormat(format_bloc); if(puces){ contenu_puce.append("<li>"); //On vérifie la taille int taille = format.fontPointSize(); if(taille == 0){ //Il y a eu un bug lors de la sélection du style, on applique la taille par défaut format.setFontPointSize(12); } } //Maintenant on lit les <span> QDomNode enfants = e.firstChild(); while(!enfants.isNull()){ if(enfants.isElement()){ QDomElement type = enfants.toElement(); //On parcours le type d'élément if(type.tagName() == "text:span"){ traite_span(format, curseur, type, puces, tableau); } else if(type.tagName() == "text:a"){ //Il s'agit d'un lien traite_lien(curseur, type, format); } else if(type.tagName() == "text:line-break"){ } else if(type.tagName() == "text:s"){ curseur.insertText(QString(" ")); } else if(type.tagName() == "text:tab"){ curseur.insertText(QString(" ")); } else if(type.tagName() == "draw:frame"){ QDomNode enfants_image = type.firstChild(); QString style_image = type.attribute("draw:style-name"); if(enfants_image.toElement().tagName() == "draw:image"){ if(!traite_image(curseur, enfants_image.toElement(), style_image)){ instance_erreur.Erreur_msg(tr("ODT : Erreur lors de la lecture des images (return false)"), QMessageBox::Ignore); } } } else if(type.tagName() == "text:list"){ if(!contenu_puces(type, curseur)){ instance_erreur.Erreur_msg(tr("ODT : Une erreur est survenue lors de la lecture d'une liste à puces; elle ne sera pas affichée"), QMessageBox::Warning); } else{ QTextCursor curseur(document); curseur.movePosition(QTextCursor::End); curseur.movePosition(QTextCursor::PreviousBlock); curseur.insertHtml(contenu_puce); contenu_puce = ""; } } else if(type.tagName() == "text:soft-page-break"){ } else{ instance_erreur.Erreur_msg(tr("ODT: Type de contenu non supporté : %1").arg(type.tagName()), QMessageBox::Ignore); } } else if(enfants.isText()){ //On gére le texte if(!puces && !tableau){ curseur.insertText(enfants.nodeValue(), format); } else if(tableau){ case_tableau.append(enfants.nodeValue()); } else{ //Insertion du contenu des puces si on est dans un "p" //On récupère le style par défaut QTextDocument *temp = new QTextDocument; QTextCursor curseur(temp); curseur.insertText(enfants.nodeValue(), format); contenu_puce.append(nettoye_code(temp->toHtml())); delete temp; } } else{ instance_erreur.Erreur_msg(tr("ODT : type de données non supporté"), QMessageBox::Ignore); } enfants = enfants.nextSibling(); } //On a fini la boucle OU il n'y avait pas de <span> //On récupère le contenu if(!puces && !tableau){ curseur.insertText("\n"); } if(puces){ contenu_puce.append("</li>"); } if(!tableau){ curseur.endEditBlock(); } if(tableau){ ligne_tableau.append(case_tableau); } //std::cout << e.text().toStdString() << std::endl; return true; }