📄 dom_nodeimpl.cpp
字号:
if (exceptioncode)
return 0;
}
dispatchChildRemovalEvents(oldChild,exceptioncode);
if (exceptioncode)
return 0;
// Remove from rendering tree
if (oldChild->attached())
oldChild->detach();
// Remove the child
NodeImpl *prev, *next;
prev = oldChild->previousSibling();
next = oldChild->nextSibling();
if(next) next->setPreviousSibling(prev);
if(prev) prev->setNextSibling(next);
if(_first == oldChild) _first = next;
if(_last == oldChild) _last = prev;
oldChild->setPreviousSibling(0);
oldChild->setNextSibling(0);
oldChild->setParent(0);
getDocument()->setDocumentChanged(true);
// Dispatch post-removal mutation events
dispatchSubtreeModifiedEvent();
if (oldChild->inDocument())
oldChild->removedFromDocument();
return oldChild;
}
void NodeBaseImpl::removeChildren()
{
int exceptionCode;
while (NodeImpl *n = _first) {
NodeImpl *next = n->nextSibling();
n->ref();
// Fire removed from document mutation events.
dispatchChildRemovalEvents(n, exceptionCode);
if (n->attached())
n->detach();
n->setPreviousSibling(0);
n->setNextSibling(0);
n->setParent(0);
if (n->inDocument())
n->removedFromDocument();
n->deref();
_first = next;
}
_last = 0;
// Dispatch a single post-removal mutation event denoting a modified subtree.
dispatchSubtreeModifiedEvent();
}
NodeImpl *NodeBaseImpl::appendChild ( NodeImpl *newChild, int &exceptioncode )
{
exceptioncode = 0;
Node protectNewChild(newChild); // make sure the new child is ref'd and deref'd so we don't leak it
// Make sure adding the new child is ok
checkAddChild(newChild, exceptioncode);
if (exceptioncode)
return 0;
if ( newChild == _last ) // nothing to do
return newChild;
bool isFragment = newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE;
// If newChild is a DocumentFragment with no children.... there's nothing to do.
// Just return the document fragment
if (isFragment && !newChild->firstChild())
return newChild;
// Now actually add the child(ren)
NodeImpl *nextChild;
NodeImpl *child = isFragment ? newChild->firstChild() : newChild;
while (child) {
nextChild = isFragment ? child->nextSibling() : 0;
// If child is already present in the tree, first remove it
NodeImpl *oldParent = child->parentNode();
if(oldParent) {
oldParent->removeChild( child, exceptioncode );
if (exceptioncode)
return 0;
}
// Append child to the end of the list
child->setParent(this);
if(_last)
{
child->setPreviousSibling(_last);
_last->setNextSibling(child);
_last = child;
}
else
{
_first = _last = child;
}
// Add child to the rendering tree
// ### should we detach() it first if it's already attached?
if (attached() && !child->attached())
child->attach();
// Dispatch the mutation events
dispatchChildInsertedEvents(child,exceptioncode);
child = nextChild;
}
getDocument()->setDocumentChanged(true);
// ### set style in case it's attached
dispatchSubtreeModifiedEvent();
return newChild;
}
bool NodeBaseImpl::hasChildNodes ( ) const
{
return _first != 0;
}
// not part of the DOM
void NodeBaseImpl::setFirstChild(NodeImpl *child)
{
_first = child;
}
void NodeBaseImpl::setLastChild(NodeImpl *child)
{
_last = child;
}
// check for same source document:
bool NodeBaseImpl::checkSameDocument( NodeImpl *newChild, int &exceptioncode )
{
exceptioncode = 0;
DocumentImpl *ownerDocThis = getDocument();
DocumentImpl *ownerDocNew = getDocument();
if(ownerDocThis != ownerDocNew) {
kdDebug(6010)<< "not same document, newChild = " << newChild << "document = " << getDocument() << endl;
exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
return true;
}
return false;
}
// check for being (grand-..)father:
// ### remove in favor or isAncestor()
bool NodeBaseImpl::checkNoOwner( NodeImpl *newChild, int &exceptioncode )
{
//check if newChild is parent of this...
NodeImpl *n;
for( n = this; (n != getDocument()) && (n!= 0); n = n->parentNode() )
if(n == newChild) {
exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
return true;
}
return false;
}
// check for being child:
bool NodeBaseImpl::checkIsChild( NodeImpl *oldChild, int &exceptioncode )
{
if(!oldChild || oldChild->parentNode() != this) {
exceptioncode = DOMException::NOT_FOUND_ERR;
return true;
}
return false;
}
NodeImpl *NodeBaseImpl::addChild(NodeImpl *newChild)
{
// do not add applyChanges here! This function is only used during parsing
Node protectNewChild(newChild); // make sure the new child is ref'd and deref'd so we don't leak it
// short check for consistency with DTD
if(!isXMLElementNode() && !newChild->isXMLElementNode() && !childAllowed(newChild))
{
//kdDebug( 6020 ) << "AddChild failed! id=" << id() << ", child->id=" << newChild->id() << endl;
return 0;
}
// just add it...
newChild->setParent(this);
if(_last)
{
newChild->setPreviousSibling(_last);
_last->setNextSibling(newChild);
_last = newChild;
}
else
{
_first = _last = newChild;
}
if (inDocument())
newChild->insertedIntoDocument();
childrenChanged();
if(newChild->nodeType() == Node::ELEMENT_NODE)
return newChild;
return this;
}
void NodeBaseImpl::attach()
{
NodeImpl *child = _first;
while(child != 0)
{
child->attach();
child = child->nextSibling();
}
NodeImpl::attach();
}
void NodeBaseImpl::detach()
{
NodeImpl *child = _first;
while(child != 0)
{
NodeImpl* prev = child;
child = child->nextSibling();
prev->detach();
}
NodeImpl::detach();
}
void NodeBaseImpl::insertedIntoDocument()
{
NodeImpl::insertedIntoDocument();
for (NodeImpl *child = _first; child; child = child->nextSibling())
child->insertedIntoDocument();
}
void NodeBaseImpl::removedFromDocument()
{
NodeImpl::removedFromDocument();
for (NodeImpl *child = _first; child; child = child->nextSibling())
child->removedFromDocument();
}
void NodeBaseImpl::cloneChildNodes(NodeImpl *clone)
{
int exceptioncode = 0;
NodeImpl *n;
for(n = firstChild(); n && !exceptioncode; n = n->nextSibling())
{
clone->appendChild(n->cloneNode(true),exceptioncode);
}
}
NodeListImpl* NodeBaseImpl::getElementsByTagNameNS ( DOMStringImpl* namespaceURI,
DOMStringImpl* localName )
{
if (!localName) return 0;
NodeImpl::Id idMask = namespaceMask | localNameMask;
if (localName->l && localName->s[0] == '*')
idMask &= ~localNameMask;
if (!namespaceURI || (namespaceURI->l && namespaceURI->s[0] == '*'))
idMask &= ~namespaceMask;
Id id = 0; // 0 means "all items"
if ( (idMask & localNameMask) || namespaceURI ) // not getElementsByTagName("*")
{
id = getDocument()->tagId( namespaceURI, localName, true);
if ( !id ) // not found -> we want to return an empty list, not "all items"
id = (Id)-1; // HACK. HEAD has a cleaner implementation of TagNodeListImpl it seems.
}
return new TagNodeListImpl( this, id, idMask );
}
// I don't like this way of implementing the method, but I didn't find any
// other way. Lars
bool NodeBaseImpl::getUpperLeftCorner(int &xPos, int &yPos) const
{
if (!m_render)
return false;
RenderObject *o = m_render;
xPos = yPos = 0;
if ( !o->isInline() || o->isReplaced() ) {
o->absolutePosition( xPos, yPos );
return true;
}
// find the next text/image child, to get a position
while(o) {
if(o->firstChild())
o = o->firstChild();
else if(o->nextSibling())
o = o->nextSibling();
else {
RenderObject *next = 0;
while(!next) {
o = o->parent();
if(!o) return false;
next = o->nextSibling();
}
o = next;
}
if((o->isText() && !o->isBR()) || o->isReplaced()) {
o->container()->absolutePosition( xPos, yPos );
if (o->isText())
xPos += static_cast<RenderText *>(o)->minXPos();
else
xPos += o->xPos();
yPos += o->yPos();
return true;
}
}
return true;
}
bool NodeBaseImpl::getLowerRightCorner(int &xPos, int &yPos) const
{
if (!m_render)
return false;
RenderObject *o = m_render;
xPos = yPos = 0;
if (!o->isInline() || o->isReplaced())
{
o->absolutePosition( xPos, yPos );
xPos += o->width();
yPos += o->height();
return true;
}
// find the last text/image child, to get a position
while(o) {
if(o->lastChild())
o = o->lastChild();
else if(o->previousSibling())
o = o->previousSibling();
else {
RenderObject *prev = 0;
while(!prev) {
o = o->parent();
if(!o) return false;
prev = o->previousSibling();
}
o = prev;
}
if(o->isText() || o->isReplaced()) {
o->container()->absolutePosition(xPos, yPos);
if (o->isText())
xPos += static_cast<RenderText *>(o)->minXPos() + o->width();
else
xPos += o->xPos()+o->width();
yPos += o->yPos()+o->height();
return true;
}
}
return true;
}
QRect NodeBaseImpl::getRect() const
{
int xPos, yPos;
if (!getUpperLeftCorner(xPos,yPos))
{
xPos=-1;
yPos=-1;
}
int xEnd, yEnd;
if (!getLowerRightCorner(xEnd,yEnd))
{
if (xPos)
xEnd = xPos;
if (yPos)
yEnd = yPos;
}
else
{
if (xPos==-1)
xPos = xEnd;
if (yPos==-1)
yPos = yEnd;
}
if ( xEnd <= xPos || yEnd <= yPos )
return QRect( QPoint( xPos, yPos ), QSize() );
return QRect(xPos, yPos, xEnd - xPos, yEnd - yPos);
}
void NodeBaseImpl::setFocus(bool received)
{
if (m_focused == received) return;
NodeImpl::setFocus(received);
if (received && isEditableBlock() && !hasChildNodes()) {
getDocument()->part()->setSelection(Selection(Position(this, 0), DOWNSTREAM));
}
// note that we need to recalc the style
setChanged();
}
void NodeBaseImpl::setActive(bool down)
{
if (down == active()) return;
NodeImpl::setActive(down);
// note that we need to recalc the style
if (m_render && m_render->style()->affectedByActiveRules())
setChanged();
}
unsigned long NodeBaseImpl::childNodeCount() const
{
unsigned long count = 0;
NodeImpl *n;
for (n = firstChild(); n; n = n->nextSibling())
count++;
return count;
}
NodeImpl *NodeBaseImpl::childNode(unsigned long index)
{
unsigned long i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -