diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | 84da08d7b7fcda12c85caeb5a10b4903770a6f69 (patch) | |
tree | 2a6aea76f2dfffb4cc04bb907c4725af94f70e72 /konq-plugins/domtreeviewer/domtreecommands.cpp | |
download | tdeaddons-84da08d7b7fcda12c85caeb5a10b4903770a6f69.tar.gz tdeaddons-84da08d7b7fcda12c85caeb5a10b4903770a6f69.zip |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdeaddons@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'konq-plugins/domtreeviewer/domtreecommands.cpp')
-rw-r--r-- | konq-plugins/domtreeviewer/domtreecommands.cpp | 562 |
1 files changed, 562 insertions, 0 deletions
diff --git a/konq-plugins/domtreeviewer/domtreecommands.cpp b/konq-plugins/domtreeviewer/domtreecommands.cpp new file mode 100644 index 0000000..1f91cf1 --- /dev/null +++ b/konq-plugins/domtreeviewer/domtreecommands.cpp @@ -0,0 +1,562 @@ +/* This file is part of the KDE project + * + * Copyright (C) 2005 Leo Savernik <l.savernik@aon.at> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "domtreecommands.h" + +#include <dom/dom_doc.h> +#include <dom/dom_exception.h> + +#include <klocale.h> + +#include <qmap.h> + +using namespace domtreeviewer; + +static const char * const dom_error_msgs[] = { + I18N_NOOP("No error"), + I18N_NOOP("Index size exceeded"), + I18N_NOOP("DOMString size exceeded"), + I18N_NOOP("Hierarchy request error"), + I18N_NOOP("Wrong document"), + I18N_NOOP("Invalid character"), + I18N_NOOP("No data allowed"), + I18N_NOOP("No modification allowed"), + I18N_NOOP("Not found"), + I18N_NOOP("Not supported"), + I18N_NOOP("Attribute in use"), + I18N_NOOP("Invalid state"), + I18N_NOOP("Syntax error"), + I18N_NOOP("Invalid modification"), + I18N_NOOP("Namespace error"), + I18N_NOOP("Invalid access") +}; + +// == global functions ============================================== + +QString domtreeviewer::domErrorMessage(int dom_err) +{ + if ((unsigned)dom_err > sizeof dom_error_msgs/sizeof dom_error_msgs[0]) + return i18n("Unknown Exception %1").arg(dom_err); + else + return i18n(dom_error_msgs[dom_err]); +} + +// == ManipulationCommandSignalEmitter ============================== + +static ManipulationCommandSignalEmitter *_mcse; + +ManipulationCommandSignalEmitter::ManipulationCommandSignalEmitter() +{} +ManipulationCommandSignalEmitter::~ManipulationCommandSignalEmitter() +{} + +namespace domtreeviewer { + +ManipulationCommandSignalEmitter* ManipulationCommand::mcse() +{ + if (!_mcse) _mcse = new ManipulationCommandSignalEmitter; + return _mcse; +} + +} + +// == ChangedNodeSet ================================================ + +namespace domtreeviewer { + +// collection of nodes for which to emit the nodeChanged signal +inline static bool operator <(const DOM::Node &n1, const DOM::Node &n2) +{ + return (long)n1.handle() - (long)n2.handle() < 0; +} + +class ChangedNodeSet : public QMap<DOM::Node, bool> +{ +}; + +} + +// == ManipulationCommand =========================================== + +ManipulationCommand::ManipulationCommand() : _exception(0), changedNodes(0) + , _reapplied(false) , allow_signals(true) +{ +} + +ManipulationCommand::~ManipulationCommand() +{ +} + +void ManipulationCommand::connect(const char *signal, QObject *recv, const char *slot) +{ + QObject::connect(mcse(), signal, recv, slot); +} + +void ManipulationCommand::handleException(DOM::DOMException &ex) +{ + _exception = ex; + QString msg = name() + ": " + domErrorMessage(ex.code); + emit mcse()->error(ex.code, msg); +} + +void ManipulationCommand::checkAndEmitSignals() +{ + if (allow_signals) { + if (changedNodes) { + ChangedNodeSet::Iterator end = changedNodes->end(); + for (ChangedNodeSet::Iterator it = changedNodes->begin(); it != end; ++it) { + emit mcse()->nodeChanged(it.key()); + } + } + + if (struc_changed) emit mcse()->structureChanged(); + } + if (changedNodes) changedNodes->clear(); +} + +void ManipulationCommand::addChangedNode(const DOM::Node &node) +{ + if (!changedNodes) changedNodes = new ChangedNodeSet; + changedNodes->insert(node, true); +} + +void ManipulationCommand::execute() +{ + if (!isValid()) return; + + struc_changed = false; + + try { + if (shouldReapply()) + reapply(); + else + apply(); + + checkAndEmitSignals(); + + } catch(DOM::DOMException &ex) { + handleException(ex); + } + _reapplied = true; +} + +void ManipulationCommand::unexecute() +{ + if (!isValid()) return; + + struc_changed = false; + + try { + unapply(); + checkAndEmitSignals(); + } catch(DOM::DOMException &ex) { + handleException(ex); + } +} + +void ManipulationCommand::reapply() +{ + apply(); +} + +// == MultiCommand =========================================== + +MultiCommand::MultiCommand(const QString &desc) +: _name(desc) +{ + cmds.setAutoDelete(true); +} + +MultiCommand::~MultiCommand() +{ +} + +void MultiCommand::addCommand(ManipulationCommand *cmd) +{ + cmd->allow_signals = false; + cmds.append(cmd); +} + +void MultiCommand::apply() +{ + // apply in forward order + for (QPtrListIterator<ManipulationCommand> it = cmds; *it; ++it) { + try { + if (shouldReapply()) (*it)->reapply(); + else (*it)->apply(); + + struc_changed |= (*it)->struc_changed; + mergeChangedNodesFrom(*it); + + } catch (DOM::DOMException &) { + // rollback + for (--it; *it; --it) { + try { + (*it)->unapply(); + } catch(DOM::DOMException &) { + // ignore + } + } + throw; + } + + } +} + +void MultiCommand::unapply() +{ + // unapply in reverse order + QPtrListIterator<ManipulationCommand> it = cmds; + for (it.toLast(); *it; --it) { + try { + (*it)->unapply(); + + struc_changed |= (*it)->struc_changed; + mergeChangedNodesFrom(*it); + + } catch (DOM::DOMException &) { + // rollback + for (++it; *it; ++it) { + try { + (*it)->reapply(); + } catch(DOM::DOMException &) { + // ignore + } + } + throw; + } + + } +} + +void MultiCommand::mergeChangedNodesFrom(ManipulationCommand *cmd) +{ + if (!cmd->changedNodes) return; + + ChangedNodeSet::ConstIterator end = cmd->changedNodes->end(); + for (ChangedNodeSet::ConstIterator it = cmd->changedNodes->begin(); it != end; ++it) { + addChangedNode(it.key()); + } + + cmd->changedNodes->clear(); +} + +QString MultiCommand::name() const +{ + return _name; +} + +// == AddAttributeCommand =========================================== + +AddAttributeCommand::AddAttributeCommand(const DOM::Element &element, const QString &attrName, const QString &attrValue) +: _element(element), attrName(attrName), attrValue(attrValue) +{ + if (attrValue.isEmpty()) this->attrValue = "<dummy>"; +} + +AddAttributeCommand::~AddAttributeCommand() +{ +} + +void AddAttributeCommand::apply() +{ + _element.setAttribute(attrName, attrValue); + addChangedNode(_element); +} + +void AddAttributeCommand::unapply() +{ + _element.removeAttribute(attrName); + addChangedNode(_element); +} + +QString AddAttributeCommand::name() const +{ + return i18n("Add attribute"); +} + +// == ChangeAttributeValueCommand ==================================== + +ChangeAttributeValueCommand::ChangeAttributeValueCommand( +const DOM::Element &element, const QString &attr, const QString &value) +: _element(element), _attr(attr), new_value(value) +{ +} + +ChangeAttributeValueCommand::~ChangeAttributeValueCommand() +{ +} + +void ChangeAttributeValueCommand::apply() +{ + if (!shouldReapply()) old_value = _element.getAttribute(_attr); + _element.setAttribute(_attr, new_value); + addChangedNode(_element); +} + +void ChangeAttributeValueCommand::unapply() +{ + _element.setAttribute(_attr, old_value); + addChangedNode(_element); +} + +QString ChangeAttributeValueCommand::name() const +{ + return i18n("Change attribute value"); +} + +// == RemoveAttributeCommand ======================================== + +RemoveAttributeCommand::RemoveAttributeCommand(const DOM::Element &element, const QString &attrName) +: _element(element), attrName(attrName) +{ +} + +RemoveAttributeCommand::~RemoveAttributeCommand() +{ +} + +void RemoveAttributeCommand::apply() +{ +// kdDebug(90180) << k_funcinfo << _element.nodeName().string() << ": " << attrName.string() << endl; + if (!shouldReapply()) + oldAttrValue = _element.getAttribute(attrName); + _element.removeAttribute(attrName); + addChangedNode(_element); +} + +void RemoveAttributeCommand::unapply() +{ + _element.setAttribute(attrName, oldAttrValue); + addChangedNode(_element); +} + +QString RemoveAttributeCommand::name() const +{ + return i18n("Remove attribute"); +} + +// == RenameAttributeCommand ======================================== + +RenameAttributeCommand::RenameAttributeCommand(const DOM::Element &element, const QString &attrOldName, const QString &attrNewName) +: _element(element), attrOldName(attrOldName), attrNewName(attrNewName) +{ +} + +RenameAttributeCommand::~RenameAttributeCommand() +{ +} + +void RenameAttributeCommand::apply() +{ + if (!shouldReapply()) + attrValue = _element.getAttribute(attrOldName); + _element.removeAttribute(attrOldName); + _element.setAttribute(attrNewName, attrValue); + addChangedNode(_element); +} + +void RenameAttributeCommand::unapply() +{ + _element.removeAttribute(attrNewName); + _element.setAttribute(attrOldName, attrValue); + addChangedNode(_element); +} + +QString RenameAttributeCommand::name() const +{ + return i18n("Rename attribute"); +} + +// == ChangeCDataCommand ======================================== + +ChangeCDataCommand::ChangeCDataCommand(const DOM::CharacterData &cdata, const QString &value) +: cdata(cdata), value(value), has_newlines(false) +{ +} + +ChangeCDataCommand::~ChangeCDataCommand() +{ +} + +void ChangeCDataCommand::apply() +{ + if (!shouldReapply()) { + oldValue = cdata.data(); + has_newlines = + QConstString(value.unicode(), value.length()).string().contains('\n') + || QConstString(oldValue.unicode(), oldValue.length()).string().contains('\n'); + } + cdata.setData(value); + addChangedNode(cdata); + struc_changed = has_newlines; +} + +void ChangeCDataCommand::unapply() +{ + cdata.setData(oldValue); + addChangedNode(cdata); + struc_changed = has_newlines; +} + +QString ChangeCDataCommand::name() const +{ + return i18n("Change textual content"); +} + +// == ManipulateNodeCommand =========================================== + +ManipulateNodeCommand::ManipulateNodeCommand(const DOM::Node &node, const DOM::Node &parent, const DOM::Node &after) +: _node(node), _parent(parent), _after(after) +{ +} + +ManipulateNodeCommand::~ManipulateNodeCommand() +{ +} + +void ManipulateNodeCommand::insert() +{ + _parent.insertBefore(_node, _after); +} + +void ManipulateNodeCommand::remove() +{ + DOM::DocumentFragment frag = _node; + + if (frag.isNull()) { // do a normal remove + _node = _parent.removeChild(_node); + + } else { // remove fragment nodes and recreate fragment + DOM::DocumentFragment newfrag = _parent.ownerDocument().createDocumentFragment(); + + for (DOM::Node i = frag.firstChild(); !i.isNull(); i = i.nextSibling()) { + newfrag.appendChild(_parent.removeChild(i)); + } + + _node = newfrag; + } +} + +// == InsertNodeCommand =========================================== + +InsertNodeCommand::InsertNodeCommand(const DOM::Node &node, const DOM::Node &parent, const DOM::Node &after) +: ManipulateNodeCommand(node, parent, after) +{ +} + +InsertNodeCommand::~InsertNodeCommand() +{ +} + +void InsertNodeCommand::apply() +{ + insert(); + struc_changed = true; +} + +void InsertNodeCommand::unapply() +{ + remove(); + struc_changed = true; +} + +QString InsertNodeCommand::name() const +{ + return i18n("Insert node"); +} + +// == RemoveNodeCommand =========================================== + +RemoveNodeCommand::RemoveNodeCommand(const DOM::Node &node, const DOM::Node &parent, const DOM::Node &after) +: ManipulateNodeCommand(node, parent, after) +{ +} + +RemoveNodeCommand::~RemoveNodeCommand() +{ +} + +void RemoveNodeCommand::apply() +{ + remove(); + struc_changed = true; +} + +void RemoveNodeCommand::unapply() +{ + insert(); + struc_changed = true; +} + +QString RemoveNodeCommand::name() const +{ + return i18n("Remove node"); +} + +// == MoveNodeCommand =========================================== + +MoveNodeCommand::MoveNodeCommand(const DOM::Node &node, const DOM::Node &parent, const DOM::Node &after) +: _node(node), new_parent(parent), new_after(after) +{ + old_parent = node.parentNode(); + old_after = node.nextSibling(); +} + +MoveNodeCommand::~MoveNodeCommand() +{ +} + +void MoveNodeCommand::apply() +{ + old_parent.removeChild(_node); + try { + new_parent.insertBefore(_node, new_after); + } catch (DOM::DOMException &) { + try { // rollback + old_parent.insertBefore(_node, old_after); + } catch (DOM::DOMException &) {} + throw; + } + struc_changed = true; +} + +void MoveNodeCommand::unapply() +{ + new_parent.removeChild(_node); + try { + old_parent.insertBefore(_node, old_after); + } catch (DOM::DOMException &) { + try { // rollback + new_parent.insertBefore(_node, new_after); + } catch (DOM::DOMException &) {} + throw; + } + struc_changed = true; +} + +QString MoveNodeCommand::name() const +{ + return i18n("Move node"); +} + +#include "domtreecommands.moc" + +#undef MCSE |