/**************************************************************** * This file is distributed under the following license: * * Copyright (c) 2010, Thomas Kister * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. ****************************************************************/ #include "HandleRichText.h" namespace RsHtml { EmbedInHtmlImg defEmbedImg; void EmbedInHtmlImg::InitFromAwkwardHash(const QHash< QString, QString >& hash) { QString newRE; for(QHash::const_iterator it = hash.begin(); it != hash.end(); ++it) foreach(QString smile, it.key().split("|")) { if (smile.isEmpty()) { continue; } smileys.insert(smile, it.value()); newRE += "(" + QRegExp::escape(smile) + ")|"; } newRE.chop(1); // remove last | myRE.setPattern(newRE); } QString formatText(const QString &text, unsigned int flag) { if (flag == 0) { // nothing to do return text; } QDomDocument doc; doc.setContent(text); QDomElement body = doc.documentElement(); if (flag & RSHTML_FORMATTEXT_EMBED_SMILEYS) { embedHtml(doc, body, defEmbedImg); } if (flag & RSHTML_FORMATTEXT_EMBED_LINKS) { EmbedInHtmlAhref defEmbedAhref; embedHtml(doc, body, defEmbedAhref); } return doc.toString(-1); // -1 removes any annoying carriage return misinterpreted by QTextEdit } /** * Parses a DOM tree and replaces text by HTML tags. * The tree is traversed depth-first, but only through children of Element type * nodes. Any other kind of node is terminal. * * If the node is of type Text, its data is checked against the user-provided * regular expression. If there is a match, the text is cut in three parts: the * preceding part that will be inserted before, the part to be replaced, and the * following part which will be itself checked against the regular expression. * * The part to be replaced is sent to a user-provided functor that will create * the necessary embedding and return a new Element node to be inserted. * * @param[in] doc The whole DOM tree, necessary to create new nodes * @param[in,out] currentElement The current node (which is of type Element) * @param[in] embedInfos The regular expression and the type of embedding to use */ void embedHtml(QDomDocument& doc, QDomElement& currentElement, EmbedInHtml& embedInfos) { if(embedInfos.myRE.pattern().length() == 0) // we'll get stuck with an empty regexp return; QDomNodeList children = currentElement.childNodes(); for(uint index = 0; index < children.length(); index++) { QDomNode tempNode = children.item(index); if(tempNode.isElement()) { // child is an element, we skip it if it's an tag QDomElement tempElement = tempNode.toElement(); if(tempElement.tagName().toLower() != "head" && tempElement.tagName().toLower() != "a") embedHtml(doc, tempElement, embedInfos); } else if(tempNode.isText()) { // child is a text, we parse it QString tempText = tempNode.toText().data(); if(embedInfos.myRE.indexIn(tempText) == -1) continue; // there is at least one link inside, we start replacing int currentPos = 0; int nextPos = 0; while((nextPos = embedInfos.myRE.indexIn(tempText, currentPos)) != -1) { // if nextPos == 0 it means the text begins by a link if(nextPos > 0) { QDomText textPart = doc.createTextNode(tempText.mid(currentPos, nextPos - currentPos)); currentElement.insertBefore(textPart, tempNode); index++; } // inserted tag QDomElement insertedTag; switch(embedInfos.myType) { case Ahref: insertedTag = doc.createElement("a"); insertedTag.setAttribute("href", embedInfos.myRE.cap(0)); insertedTag.appendChild(doc.createTextNode(embedInfos.myRE.cap(0))); break; case Img: insertedTag = doc.createElement("img"); { const EmbedInHtmlImg& embedImg = static_cast(embedInfos); insertedTag.setAttribute("src", embedImg.smileys[embedInfos.myRE.cap(0)]); } break; } currentElement.insertBefore(insertedTag, tempNode); currentPos = nextPos + embedInfos.myRE.matchedLength(); index++; } // text after the last link, only if there's one, don't touch the index // otherwise decrement the index because we're going to remove tempNode if(currentPos < tempText.length()) { QDomText textPart = doc.createTextNode(tempText.mid(currentPos)); currentElement.insertBefore(textPart, tempNode); } else index--; currentElement.removeChild(tempNode); } } } } // namespace RsHtml