Example #1
0
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 &paragraph : 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();
}
Example #2
0
//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;
}