summaryrefslogtreecommitdiffstats
path: root/quanta/parts/kafka/htmlenhancer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'quanta/parts/kafka/htmlenhancer.cpp')
-rw-r--r--quanta/parts/kafka/htmlenhancer.cpp392
1 files changed, 392 insertions, 0 deletions
diff --git a/quanta/parts/kafka/htmlenhancer.cpp b/quanta/parts/kafka/htmlenhancer.cpp
new file mode 100644
index 00000000..257ad239
--- /dev/null
+++ b/quanta/parts/kafka/htmlenhancer.cpp
@@ -0,0 +1,392 @@
+/***************************************************************************
+ htmltranslator.cpp
+ -------------------
+
+ copyright : (C) 2003, 2004 - Nicolas Deschildre
+ email : ndeschildre@kdewebdev.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#include <dom/dom_node.h>
+#include <dom/dom_string.h>
+#include <dom/dom_exception.h>
+#include <kdebug.h>
+#include <kstandarddirs.h>
+#include <kconfig.h>
+
+#include "quantacommon.h"
+#include "document.h"
+#include "tag.h"
+#include "node.h"
+#include "wkafkapart.h"
+#include "nodeproperties.h"
+#include "kafkacommon.h"
+#include "qextfileinfo.h"
+#include "viewmanager.h"
+
+#include "htmlenhancer.h"
+
+HTMLEnhancer::HTMLEnhancer(KafkaDocument *_wkafkapart)
+ : NodeEnhancer()
+{
+ m_showIconForScripts = true;
+ m_wkafkapart = _wkafkapart;
+ m_stddirs = new KStandardDirs();
+}
+
+HTMLEnhancer::~HTMLEnhancer()
+{
+ delete m_stddirs;
+}
+
+bool HTMLEnhancer::enhanceNode(Node *node, DOM::Node parentDNode, DOM::Node nextDNode)
+{
+ DOM::Node domNode, domNode2, attr, *ptDomNode;
+ bool tbody, goUp;
+ Node *n;
+ QString script, filename, text, oldName;
+ KURL url, baseURL;
+ int oldType;
+
+ //FIRST update the src attr with the baseURL
+ if(node->rootNode())
+ {
+ domNode = node->rootNode()->attributes().getNamedItem("src");
+ if(!domNode.isNull())
+ {
+ baseURL.setPath(ViewManager::ref()->activeDocument()->url().directory());
+ QuantaCommon::setUrl(url, domNode.nodeValue().string());
+ url = QExtFileInfo::toAbsolute(url, baseURL);
+ domNode.setNodeValue(url.url());
+#ifdef HEAVY_DEBUG
+ kdDebug(25001)<< "HTMLTranslator::translateNode() - new src : " << url.url() << endl;
+#endif
+ }
+ }
+
+ //THEN update the href attr of the LINK node with the baseURL
+ if(node->tag->name.lower() == "link" && node->rootNode())
+ {
+ domNode = node->rootNode()->attributes().getNamedItem("href");
+ if(!domNode.isNull())
+ {
+ baseURL.setPath(ViewManager::ref()->activeDocument()->url().directory());
+ QuantaCommon::setUrl(url, domNode.nodeValue().string());
+ url = QExtFileInfo::toAbsolute(url, baseURL);
+ domNode.setNodeValue(url.url());
+#ifdef HEAVY_DEBUG
+ kdDebug(25001)<< "HTMLTranslator::translateNode() - new href : " << url.url() << endl;
+#endif
+ }
+ }
+
+ //THEN if it is the style element, add a DOM::Node::TEXT_NODE child gathering all the CSS
+ //by default, the parser parse it as a script, which can't be translated in DOM::Nodes.
+ if((node->tag->type == Tag::XmlTag && node->tag->name.lower() == "style") ||
+ (node->tag->type == Tag::ScriptTag && node->tag->name.lower().contains("style") != 0))
+ {
+ //If the style Node doesn't exists, create it
+ if(!node->rootNode())
+ {
+ oldType = node->tag->type;
+ node->tag->type = Tag::XmlTag;
+ oldName = node->tag->name;
+ node->tag->name = "style";
+ m_wkafkapart->buildKafkaNodeFromNode(node);
+ node->tag->type = oldType;
+ node->tag->name = oldName;
+ }
+
+ if(node->rootNode())
+ {
+ domNode = *node->rootNode();
+ n = node->child;
+ text = "";
+ goUp = false;
+ while(n)
+ {
+ text += n->tag->tagStr();
+ n = kafkaCommon::getNextNode(n, goUp, node);
+ }
+#ifdef HEAVY_DEBUG
+ kdDebug(25001)<< "HTMLTranslator::translateNode() - CSS code : " << text << endl;
+#endif
+ domNode2 = kafkaCommon::createTextDomNode(text, m_wkafkapart->getKafkaWidget()->document());
+ if(!kafkaCommon::insertDomNode(domNode2, domNode))
+ return false;
+ m_wkafkapart->connectDomNodeToQuantaNode(domNode2, node);
+ }
+ }
+
+ QTag* qTag = QuantaCommon::tagFromDTD(m_wkafkapart->getCurrentDoc()->defaultDTD(),
+ parentDNode.nodeName().string());
+
+ //THEN replace, if asked, scripts by a little icon.
+ if(node->tag->type == Tag::ScriptTag && m_showIconForScripts && qTag->isChild("IMG", false))
+ {
+ script = node->tag->name.left(node->tag->name.find("block", 0, false) - 1).lower();
+#ifdef LIGHT_DEBUG
+ kdDebug(25001)<< "HTMLTranslator::translateNode() - BLOCK:" << script << ":" << endl;
+#endif
+ filename = m_stddirs->findResource("data", "kafkapart/pics/" + script + ".png" );
+ if(!filename.isEmpty())
+ {
+ //FIXME DTD!
+ domNode = kafkaCommon::createDomNode("IMG", m_wkafkapart->defaultDTD(),
+ m_wkafkapart->getKafkaWidget()->document());
+
+ kafkaCommon::editDomNodeAttribute(domNode, "IMG", m_wkafkapart->defaultDTD(), "src",
+ filename, m_wkafkapart->getKafkaWidget()->document());
+
+ //Add a tooltip indicating the content of the script
+ n = node->child;
+ text = "";
+ goUp = false;
+ while(n && n != node)
+ {
+ text += n->tag->tagStr();
+ n = kafkaCommon::getNextNode(n, goUp, node);
+ }
+ //if(text == "")
+ // text = i18n("Empty")
+ kafkaCommon::editDomNodeAttribute(domNode, "img", m_wkafkapart->defaultDTD(),
+ "title", text, m_wkafkapart->getKafkaWidget()->document());
+
+ if(!kafkaCommon::insertDomNode(domNode, parentDNode, nextDNode))
+ return false;
+ m_wkafkapart->connectDomNodeToQuantaNode(domNode, node);
+ }
+ }
+
+ //THEN if it is a comment, add a little icon ;o)
+ if(node->tag->type == Tag::Comment && m_showIconForScripts && qTag->isChild("IMG", false))
+ {
+#ifdef LIGHT_DEBUG
+ kdDebug(25001)<< "HTMLTranslator::translateNode() - Comment" << endl;
+#endif
+
+ filename = m_stddirs->findResource("data", "kafkapart/pics/comment.png" );
+ if(!filename.isEmpty())
+ {
+ //FIXME DTD!
+ domNode = kafkaCommon::createDomNode("IMG", m_wkafkapart->defaultDTD(),
+ m_wkafkapart->getKafkaWidget()->document());
+ kafkaCommon::editDomNodeAttribute(domNode, "IMG", m_wkafkapart->defaultDTD(), "src",
+ filename, m_wkafkapart->getKafkaWidget()->document());
+
+ //Add a tooltip indicating the content of the script
+ n = node->child;
+ text = "";
+ goUp = false;
+ while(n && n != node)
+ {
+ text += n->tag->tagStr();
+ n = kafkaCommon::getNextNode(n, goUp, node);
+ }
+ //if(text == "")
+ // text = i18n("Empty")
+ kafkaCommon::editDomNodeAttribute(domNode, "img", m_wkafkapart->defaultDTD(),
+ "title", text, m_wkafkapart->getKafkaWidget()->document());
+
+ if(!kafkaCommon::insertDomNode(domNode, parentDNode, nextDNode))
+ return false;
+ m_wkafkapart->connectDomNodeToQuantaNode(domNode, node);
+ }
+ }
+
+ //THEN add a TBODY tag if necessary
+ if(node->rootNode() && node->rootNode()->nodeName().string().lower() == "table")
+ {
+ tbody = false;
+ n = node->child;
+ while(n)
+ {
+ if(n->tag->name.lower() == "tbody")
+ tbody = true;
+ n = n->next;
+ }
+ if(!tbody)
+ {
+ domNode = kafkaCommon::createDomNode("TBODY", m_wkafkapart->defaultDTD(),
+ m_wkafkapart->getKafkaWidget()->htmlDocument());
+ if(!kafkaCommon::insertDomNode(domNode, *node->rootNode()))
+ return false;
+ m_wkafkapart->connectDomNodeToQuantaNode(domNode, node);
+ ptDomNode = new DOM::Node(domNode);
+ node->setLeafNode(ptDomNode);
+ }
+ }
+
+ //THEN add a red dotted border to FORM tags.
+ if(node->rootNode() && node->rootNode()->nodeName().string().lower() == "form")
+ {
+ kafkaCommon::editDomNodeAttribute(*node->rootNode(), node, "style", "border: 1px dotted red",
+ m_wkafkapart->getKafkaWidget()->document());
+ }
+
+ // THEN add a tooltip indicating the content of the name attribute
+ if(node->rootNode() && node->rootNode()->nodeName().string().lower() == "input")
+ {
+ domNode = *(node->rootNode());
+ QString text = node->tag->attributeValue("name");
+ kafkaCommon::editDomNodeAttribute(domNode, "input", m_wkafkapart->defaultDTD(),
+ "title", text, m_wkafkapart->getKafkaWidget()->document());
+ }
+
+ //THEN add a blue dotted border to DL, OL, UL tags
+ if(node->rootNode())
+ {
+ text = node->rootNode()->nodeName().string().lower();
+ if(text == "dl" || text == "ol" || text == "ul")
+ {
+ kafkaCommon::editDomNodeAttribute(*node->rootNode(), node, "style", "border: 1px dotted blue",
+ m_wkafkapart->getKafkaWidget()->document());
+ }
+ }
+
+ //THEN add a minimal border for borderless tables
+ //TODO: make it configurable, and look if CSS hasn't defined a border first
+ if(node->rootNode() && node->rootNode()->nodeName().string().lower() == "table")
+ {
+ attr = node->rootNode()->attributes().getNamedItem("border");
+ if(attr.isNull() || (!attr.isNull() && attr.nodeValue().string() == "0"))
+ {
+ kafkaCommon::editDomNodeAttribute(*node->rootNode(), node, "border", "1",
+ m_wkafkapart->getKafkaWidget()->document());
+ }
+ }
+
+ //THEN add a blue dotted border to DIV tags
+ if(node->rootNode())
+ {
+ text = node->rootNode()->nodeName().string().lower();
+ if(text == "div")
+ {
+ kafkaCommon::editDomNodeAttribute(*node->rootNode(), node, "style", "border: 1px dotted green",
+ m_wkafkapart->getKafkaWidget()->document());
+ }
+ }
+
+ return true;
+}
+
+void HTMLEnhancer::postEnhanceNode(DOM::Node domNode)
+{
+ DOM::Node textNode;
+ kNodeAttrs *props;
+ QTag *qTag;
+ bool isInline;
+
+ if(domNode.isNull())
+ return;
+
+ //If domNode is a Block and there is no text around, and if domNode's parent can handle
+ //text or a P tag, add an empty text DOM::Node
+ // so that the user can access this area.
+ qTag = QuantaCommon::tagFromDTD(m_wkafkapart->getCurrentDoc()->defaultDTD(),
+ domNode.nodeName().string());
+ isInline = kafkaCommon::isInline(domNode.nodeName().string());
+ if(domNode.nodeType() == DOM::Node::ELEMENT_NODE &&
+ (!isInline || (isInline && qTag && qTag->isSingle())))
+ {
+ qTag = QuantaCommon::tagFromDTD(m_wkafkapart->getNode(domNode.parentNode()));
+
+ if((domNode.nextSibling().isNull() ||
+ (!domNode.nextSibling().isNull() &&
+ domNode.nextSibling().nodeType() == DOM::Node::ELEMENT_NODE &&
+ !kafkaCommon::isInline(domNode.nextSibling().nodeName().string())))
+ && qTag && (qTag->isChild("#text", false) || qTag->isChild("p", false)) &&
+ domNode.nodeName().string().lower() != "p")
+ {
+ textNode = kafkaCommon::createTextDomNode("",
+ m_wkafkapart->getKafkaWidget()->document());
+ props = m_wkafkapart->connectDomNodeToQuantaNode(textNode, 0L);
+ props->setIsLinkedToNode(false);
+ props->setSpecialBehavior(kNodeAttrs::emptyTextSurroundingBlockElementAtTheRight);
+ kafkaCommon::insertDomNode(textNode, domNode.parentNode(),
+ domNode.nextSibling());
+ }
+
+ if((domNode.previousSibling().isNull() || (!domNode.previousSibling().isNull() &&
+ domNode.previousSibling().nodeType() == DOM::Node::ELEMENT_NODE &&
+ !kafkaCommon::isInline(domNode.previousSibling().nodeName().string())))
+ && qTag && (qTag->isChild("#text", false) || qTag->isChild("p", false)) &&
+ domNode.nodeName().string().lower() != "p")
+ {
+ textNode = kafkaCommon::createTextDomNode("",
+ m_wkafkapart->getKafkaWidget()->document());
+ props = m_wkafkapart->connectDomNodeToQuantaNode(textNode, 0L);
+ props->setIsLinkedToNode(false);
+ props->setSpecialBehavior(kNodeAttrs::emptyTextSurroundingBlockElementAtTheLeft);
+ kafkaCommon::insertDomNode(textNode, domNode.parentNode(),
+ domNode);
+ }
+ }
+
+ //If domNode is an childless element, and if it can handle Text or a P tag,
+ //add an empty text DOM::Node so that the
+ //user can access this area.
+ qTag = QuantaCommon::tagFromDTD(m_wkafkapart->getNode(domNode));
+ if(domNode.nodeType() == DOM::Node::ELEMENT_NODE &&
+ !domNode.hasChildNodes() && qTag && (qTag->isChild("#text", false) ||
+ qTag->isChild("p", false)))
+ {
+ textNode = kafkaCommon::createTextDomNode("",
+ m_wkafkapart->getKafkaWidget()->document());
+ props = m_wkafkapart->connectDomNodeToQuantaNode(textNode, 0L);
+ props->setIsLinkedToNode(false);
+ props->setSpecialBehavior(kNodeAttrs::emptyTextAsChildOfAChildlessElement);
+ kafkaCommon::insertDomNode(textNode, domNode);
+ }
+}
+
+void HTMLEnhancer::postUnenhanceNode(DOM::Node domNode)
+{
+ DOM::Node child, next;
+ kNodeAttrs *attrs;
+
+ if(domNode.isNull())
+ return;
+
+ //Try to remove the EmptyTextAsChildOfAChildlessElement Node first if present
+ if(domNode.hasChildNodes())
+ {
+ child = domNode.firstChild();
+ while(!child.isNull())
+ {
+ attrs = m_wkafkapart->getAttrs(child);
+ next = child.nextSibling();
+ if(attrs && attrs->specialBehavior() == kNodeAttrs::emptyTextAsChildOfAChildlessElement)
+ kafkaCommon::removeDomNode(child);
+ child = next;
+ }
+ }
+
+ //Then try to remove the emptyTextSurroundingBlockElement* Nodes if present.
+ if(!domNode.previousSibling().isNull())
+ {
+ attrs = m_wkafkapart->getAttrs(domNode.previousSibling());
+ if(attrs && attrs->specialBehavior() == kNodeAttrs::emptyTextSurroundingBlockElementAtTheLeft)
+ kafkaCommon::removeDomNode(domNode.previousSibling());
+ }
+ if(!domNode.nextSibling().isNull())
+ {
+ attrs = m_wkafkapart->getAttrs(domNode.nextSibling());
+ if(attrs && attrs->specialBehavior() == kNodeAttrs::emptyTextSurroundingBlockElementAtTheRight)
+ kafkaCommon::removeDomNode(domNode.nextSibling());
+ }
+}
+
+void HTMLEnhancer::readConfig(KConfig *m_config)
+{
+ m_config->setGroup("HTML Enhancer");
+ m_showIconForScripts = m_config->readBoolEntry("Show Scripts Icons", true);
+}