You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1286 lines
44 KiB
1286 lines
44 KiB
/***************************************************************************
|
|
tagaction.cpp - description
|
|
-------------------
|
|
begin : ?
|
|
copyright : (C) ? Dmitry Poplavsky
|
|
(C) 2002-2005 Andras Mantia <amantia@kde.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. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
//other includes
|
|
#include <sys/types.h>
|
|
#include <unistd.h>
|
|
|
|
|
|
//qt includes
|
|
#include <tqdir.h>
|
|
#include <tqdom.h>
|
|
#include <tqfile.h>
|
|
#include <tqtimer.h>
|
|
|
|
//kde includes
|
|
#include <kapplication.h>
|
|
#include <kdebug.h>
|
|
#include <kprocess.h>
|
|
#include <klocale.h>
|
|
#include <kmessagebox.h>
|
|
#include <kshortcut.h>
|
|
#include <kstandarddirs.h>
|
|
#include <ktempfile.h>
|
|
#include <ktexteditor/document.h>
|
|
#include <ktexteditor/viewcursorinterface.h>
|
|
#include <ktexteditor/editinterface.h>
|
|
#include <ktexteditor/selectioninterface.h>
|
|
#include <ktexteditor/selectioninterfaceext.h>
|
|
|
|
//app includes
|
|
#include "tagaction.h"
|
|
#include "myprocess.h"
|
|
#include "document.h"
|
|
#include "quantaview.h"
|
|
#include "quanta.h"
|
|
// #include "quantadoc.h"
|
|
#include "tagdialog.h"
|
|
#include "messageoutput.h"
|
|
#include "quantacommon.h"
|
|
#include "resource.h"
|
|
#include "qextfileinfo.h"
|
|
#include "undoredo.h"
|
|
#include "kafkacommon.h"
|
|
#include "wkafkapart.h"
|
|
#include "cursors.h"
|
|
#include "tag.h"
|
|
#include "project.h"
|
|
|
|
#include "viewmanager.h"
|
|
|
|
MyProcess::MyProcess():KProcess()
|
|
{
|
|
}
|
|
|
|
int MyProcess::commSetupDoneC()
|
|
{
|
|
::setpgid(pid_, 0);
|
|
return KProcess::commSetupDoneC();
|
|
}
|
|
|
|
TagAction::TagAction( TQDomElement *element, KMainWindow *parentMainWindow, bool toggle)
|
|
: KToggleAction(element->attribute("text").isEmpty() ? TQString("") : i18n(element->attribute("text").utf8()),
|
|
KShortcut(element->attribute("shortcut")), 0, 0, parentMainWindow->actionCollection(), element->attribute("name").ascii()),
|
|
//disable toggle now m_toggle(toggle)
|
|
m_toggle(false)
|
|
{
|
|
setToolTip(element->attribute("tooltip"));
|
|
m_parentMainWindow = parentMainWindow;
|
|
m_modified = false;
|
|
m_useInputFile = false;
|
|
m_useOutputFile = false;
|
|
tag = element->cloneNode().toElement();
|
|
TQString s = tag.attribute("icon");
|
|
if (!TQFileInfo(s).exists())
|
|
{
|
|
s = TQFileInfo(s).fileName();
|
|
}
|
|
setIcon(s);
|
|
m_file = 0L;
|
|
loopStarted = false;
|
|
#if TDE_VERSION >= TDE_MAKE_VERSION(3,4,0)
|
|
connect(this, TQT_SIGNAL(activated(KAction::ActivationReason, TQt::ButtonState)),
|
|
TQT_SLOT(slotActionActivated(KAction::ActivationReason, TQt::ButtonState)));
|
|
#else
|
|
connect(this, TQT_SIGNAL(activated()), TQT_SLOT(slotActionActivated()));
|
|
#endif
|
|
connect(this, TQT_SIGNAL(showMessage(const TQString&, bool)), m_parentMainWindow, TQT_SIGNAL(showMessage(const TQString&, bool)));
|
|
connect(this, TQT_SIGNAL(clearMessages()), m_parentMainWindow, TQT_SIGNAL(clearMessages()));
|
|
connect(this, TQT_SIGNAL(showMessagesView()), m_parentMainWindow, TQT_SLOT(slotShowMessagesView()));
|
|
connect(this, TQT_SIGNAL(createNewFile()), m_parentMainWindow, TQT_SLOT(slotFileNew()));
|
|
}
|
|
|
|
TagAction::~TagAction()
|
|
{
|
|
}
|
|
|
|
TQString TagAction::type()
|
|
{
|
|
return tag.attribute("type","");
|
|
}
|
|
|
|
#if TDE_VERSION >= TDE_MAKE_VERSION(3,4,0)
|
|
bool TagAction::slotActionActivated(KAction::ActivationReason reason, TQt::ButtonState /*state*/)
|
|
{
|
|
QuantaView *view = ViewManager::ref()->activeView();
|
|
if ( !view || !view->document())
|
|
return false;
|
|
|
|
unsigned int line, col;
|
|
Document *w = view->document();
|
|
w->viewCursorIf->cursorPositionReal(&line, &col);
|
|
NodeModifsSet* modifs = new NodeModifsSet();
|
|
|
|
TQString space;
|
|
space.fill( ' ', col);
|
|
|
|
TQString type = tag.attribute("type","");
|
|
|
|
if ( type == "tag" && view->hadLastFocus() == QuantaView::VPLFocus && toggable())
|
|
{
|
|
KafkaWidget* kafka_widget = KafkaDocument::ref()->getKafkaWidget();
|
|
TQString tag_name = XMLTagName();
|
|
|
|
NodeSelectionInd selection;
|
|
selection.fillWithVPLCursorSelection();
|
|
|
|
Node* start_node = 0, *end_node = 0, *current_node = 0;
|
|
int start_offset = 0, end_offset = 0, current_offset = 0;
|
|
TQString scope;
|
|
if(kafka_widget->hasSelection())
|
|
{
|
|
// get selection
|
|
start_node = kafkaCommon::getNodeFromLocation(selection.cursorNode());
|
|
end_node = kafkaCommon::getNodeFromLocation(selection.cursorNodeEndSel());
|
|
current_node = end_node;
|
|
start_offset = selection.cursorOffset();
|
|
end_offset = selection.cursorOffsetEndSel();
|
|
current_offset = end_offset;
|
|
}
|
|
else
|
|
{
|
|
current_node = kafkaCommon::getNodeFromLocation(selection.cursorNode());
|
|
Q_ASSERT(current_node);
|
|
if (current_node)
|
|
{
|
|
current_offset = selection.cursorOffset();
|
|
|
|
start_node = end_node = current_node;
|
|
start_offset = end_offset = current_offset;
|
|
|
|
TQTag* tag_description = QuantaCommon::tagFromDTD(KafkaDocument::ref()->getCurrentDoc()->defaultDTD(), XMLTagName());
|
|
scope = tag_description->scope();
|
|
// Q_ASSERT(!scope.isNull());
|
|
if(scope.isNull())
|
|
scope = "word"; // FIXME temporary
|
|
|
|
if(scope.lower() == "word")
|
|
{
|
|
// Apply/deapply the tag in the word
|
|
if(kafkaCommon::isBetweenWords(current_node, current_offset))
|
|
{
|
|
kafkaCommon::getStartOfWord(start_node, start_offset);
|
|
kafkaCommon::getEndOfWord(end_node, end_offset);
|
|
}
|
|
}
|
|
else if(scope.lower() == "paragraph")
|
|
{
|
|
kafkaCommon::getStartOfParagraph(start_node, start_offset);
|
|
kafkaCommon::getEndOfParagraph(end_node, end_offset);
|
|
}
|
|
else if(reason != KAction::EmulatedActivation) // is between words: save the state and return
|
|
{
|
|
if(!toggled())
|
|
quantaApp->insertTagActionPoolItem(name());
|
|
else
|
|
quantaApp->removeTagActionPoolItem(name());
|
|
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
Q_ASSERT(start_node && end_node);
|
|
|
|
/* kdDebug(23100) << "start node string: " << start_node->tag->tagStr() << endl;
|
|
kdDebug(23100) << "start node offset: " << start_offset << endl;
|
|
kdDebug(23100) << "start node string length: " << start_node->tag->tagStr().length() << endl; */
|
|
if (!start_node || !end_node)
|
|
return true; //FIXME: AndraS: don't crash
|
|
if(scope != "paragraph") {
|
|
start_node = kafkaCommon::getCorrectStartNode(start_node, start_offset);
|
|
end_node = kafkaCommon::getCorrectEndNode(end_node, end_offset);
|
|
if (!start_node || !end_node)
|
|
return true; //FIXME: AndraS: don't crash
|
|
}
|
|
NodeSelection cursor_holder;
|
|
cursor_holder.setCursorNode(current_node);
|
|
cursor_holder.setCursorOffset(current_offset);
|
|
|
|
int inside_tag = kafkaCommon::isInsideTag(start_node, end_node, tag_name);
|
|
if(inside_tag == -1)
|
|
{
|
|
applyTagInSelection(start_node, start_offset, end_node, end_offset, cursor_holder, modifs);
|
|
}
|
|
else if(inside_tag == 1)
|
|
{
|
|
TQString attribute_name(tag.attribute("attribute_name", TQString()));
|
|
TQString attribute_value(tag.attribute("attribute_value", TQString()));
|
|
|
|
// special case
|
|
if(!attribute_name.isEmpty() && !attribute_value.isEmpty())
|
|
{
|
|
Node* tag_parent = kafkaCommon::hasParent(start_node, end_node, tag_name);
|
|
|
|
Node* aux1 = start_node->previousSibling();
|
|
while(aux1->tag->type == Tag::Empty)
|
|
aux1 = aux1->previousSibling();
|
|
Node* aux2 = end_node->nextSibling();
|
|
while(aux2->tag->type == Tag::Empty)
|
|
aux2 = aux2->nextSibling();
|
|
|
|
if(aux1 == tag_parent && aux2 == tag_parent->getClosingNode())
|
|
{
|
|
if(tag_parent->tag->attributeValue(attribute_name, true) == attribute_value)
|
|
kafkaCommon::editNodeAttribute(tag_parent, attribute_name, TQString(), modifs);
|
|
else
|
|
kafkaCommon::editNodeAttribute(tag_parent, attribute_name, attribute_value, modifs);
|
|
}
|
|
else
|
|
applyTagInSelection(start_node, start_offset, end_node, end_offset, cursor_holder, modifs);
|
|
}
|
|
else
|
|
deapplyTagInSelection(start_node, start_offset, end_node, end_offset, cursor_holder, modifs);
|
|
}
|
|
else
|
|
{
|
|
applyTagInMixedSelection(start_node, start_offset, end_node, end_offset, cursor_holder, modifs);
|
|
}
|
|
w->docUndoRedo->addNewModifsSet(modifs, undoRedo::NodeTreeModif, &cursor_holder);
|
|
KafkaDocument::ref()->getKafkaWidget()->setCurrentNode(cursor_holder.cursorNode(), cursor_holder.cursorOffset());
|
|
return true;
|
|
}
|
|
|
|
if ( type == "tag" ) {
|
|
TQDomElement otag = (tag.namedItem("tag")).toElement();
|
|
TQDomElement xtag = (tag.namedItem("xtag")).toElement();
|
|
|
|
TQString attr = otag.text();
|
|
if ( attr[0] == '<' )
|
|
attr.remove(0,1);
|
|
if ( attr.right(1) == ">" )
|
|
attr.remove( attr.length()-1, 1 );
|
|
attr = attr.stripWhiteSpace();
|
|
int i = 0;
|
|
while ( !attr[i].isSpace() && !attr[i].isNull() ) i++;
|
|
TQString name = attr.left(i);
|
|
attr = attr.remove(0,i).stripWhiteSpace();
|
|
|
|
if (otag.attribute("useDialog","false") == "true" && QuantaCommon::isKnownTag(w->defaultDTD()->name, name))
|
|
{
|
|
view->insertNewTag(name, attr, xtag.attribute("inLine","true") == "true");
|
|
}
|
|
else
|
|
{
|
|
TQString s1 = QuantaCommon::tagCase(name);
|
|
if (otag.text().left(1) == "<") s1 = "<"+s1;
|
|
if (!attr.isEmpty())
|
|
s1 += " "+QuantaCommon::attrCase(attr);
|
|
if (otag.text().right(1) == ">")
|
|
{
|
|
TQTag *dtdTag = QuantaCommon::tagFromDTD(w->defaultDTD(), name);
|
|
if ( w->defaultDTD()->singleTagStyle == "xml" && dtdTag &&
|
|
(dtdTag->isSingle() || (!qConfig.closeOptionalTags && dtdTag->isOptional()))
|
|
)
|
|
{
|
|
s1.append(" /");
|
|
}
|
|
|
|
s1.append(">");
|
|
}
|
|
|
|
TQString s2;
|
|
if ( xtag.attribute("use","false") == "true" )
|
|
{
|
|
if (qConfig.closeTags)
|
|
s2 = QuantaCommon::tagCase(xtag.text());
|
|
if ( xtag.attribute("inLine","true") == "true" )
|
|
{
|
|
/** FIXME this is quick and temporary */
|
|
view->insertOutputInTheNodeTree(s1, s2);
|
|
}
|
|
else
|
|
{
|
|
view->insertOutputInTheNodeTree(s1, s2);
|
|
}
|
|
}
|
|
else
|
|
view->insertOutputInTheNodeTree(s1, s2);
|
|
}
|
|
}
|
|
|
|
if (view->hadLastFocus() != QuantaView::VPLFocus)
|
|
{
|
|
|
|
|
|
if ( type == "text" )
|
|
w->insertTag( tag.namedItem("text").toElement().text() );
|
|
|
|
if ( type == "script" )
|
|
{
|
|
proc = new MyProcess();
|
|
proc->setWorkingDirectory(quantaApp->projectBaseURL().path());
|
|
|
|
TQDomElement script = tag.namedItem("script").toElement();
|
|
TQString command = script.text();
|
|
|
|
|
|
if ( !w->isUntitled() ) {
|
|
TQString fname = w->url().url();
|
|
if ( w->url().protocol() == "file")
|
|
fname = w->url().path();
|
|
command.replace("%f", fname );
|
|
}
|
|
|
|
pid_t pid = ::getpid();
|
|
if (kapp->inherits("KUniqueApplication"))
|
|
{
|
|
command.replace("%pid", TQString("unique %1").arg(pid));
|
|
} else
|
|
{
|
|
command.replace("%pid", TQString("%1").arg(pid));
|
|
}
|
|
TQString buffer;
|
|
TQString inputType = script.attribute("input","none");
|
|
|
|
if ( inputType == "current" ) {
|
|
buffer = w->editIf->text();
|
|
} else
|
|
if ( inputType == "selected" && w->selectionIf) {
|
|
buffer = w->selectionIf->selection();
|
|
}
|
|
command.replace("%input", buffer);
|
|
command = command.stripWhiteSpace();
|
|
int pos = command.find(' ');
|
|
TQString args;
|
|
if (pos != -1)
|
|
{
|
|
args = command.mid(pos+1);
|
|
command = command.left(pos);
|
|
}
|
|
if (command.startsWith("~"))
|
|
{
|
|
command = command.mid(1);
|
|
command.prepend(TQDir::homeDirPath());
|
|
}
|
|
|
|
*proc << command.stripWhiteSpace();
|
|
args = args.stripWhiteSpace();
|
|
if (!args.isEmpty())
|
|
{
|
|
pos = 0;
|
|
while (pos != -1 )
|
|
{
|
|
pos = args.find("%scriptdir");
|
|
TQString scriptname;
|
|
if (pos != -1)
|
|
{
|
|
int begin = args.findRev('"', pos);
|
|
int end = -1;
|
|
if (begin == -1)
|
|
{
|
|
begin = args.findRev('\'', pos);
|
|
if (begin != -1)
|
|
end = args.find('\'', pos);
|
|
} else
|
|
{
|
|
end = args.find('"', pos);
|
|
}
|
|
if (begin == -1 || end != -1)
|
|
{
|
|
begin = args.findRev(' ', pos);
|
|
if (begin == -1)
|
|
begin = 0;
|
|
end = args.find(' ', pos);
|
|
if (end == -1)
|
|
end = args.length();
|
|
}
|
|
scriptname = args.mid(begin, end - begin).stripWhiteSpace();
|
|
scriptname.replace("%scriptdir","scripts");
|
|
// kdDebug(24000) << "Script name is: |" << scriptname << "|" << endl;
|
|
scriptname = " " + locate("appdata", scriptname);
|
|
// kdDebug(24000) << "Script found at: " << scriptname << endl;
|
|
args.replace(begin, end - begin, scriptname);
|
|
// kdDebug(24000) << "Modified argument list: " << args << endl;
|
|
}
|
|
}
|
|
int pos = args.find("%projectbase");
|
|
if (pos != -1)
|
|
{
|
|
TQString s;
|
|
if (Project::ref()->hasProject())
|
|
s = Project::ref()->projectBaseURL().url();
|
|
args.replace("%projectbase", s);
|
|
}
|
|
TQStringList argsList1 = TQStringList::split(' ', args);
|
|
TQStringList argsList;
|
|
for (uint i = 0; i < argsList1.count(); i++)
|
|
{
|
|
if (argsList1[i] == "%userarguments")
|
|
{
|
|
for (uint j = 0; j < m_argsList.count(); j++)
|
|
{
|
|
argsList.append(m_argsList[j]);
|
|
}
|
|
} else
|
|
argsList.append(argsList1[i]);
|
|
}
|
|
m_argsList.clear();
|
|
*proc << argsList;
|
|
}
|
|
firstOutput = true;
|
|
firstError = true;
|
|
|
|
connect( proc, TQT_SIGNAL(receivedStdout( KProcess*,char*,int)), this,
|
|
TQT_SLOT( slotGetScriptOutput(KProcess*,char*,int)));
|
|
connect( proc, TQT_SIGNAL(receivedStderr( KProcess*,char*,int)), this,
|
|
TQT_SLOT( slotGetScriptError(KProcess*,char*,int)));
|
|
connect( proc, TQT_SIGNAL(processExited( KProcess*)), this,
|
|
TQT_SLOT( slotProcessExited(KProcess*)));
|
|
|
|
|
|
|
|
if (!m_useOutputFile)
|
|
scriptOutputDest = script.attribute("output","none");
|
|
else
|
|
scriptOutputDest = "file";
|
|
scriptErrorDest = script.attribute("error","none");
|
|
if (scriptOutputDest == "message")
|
|
{
|
|
emit showMessagesView();
|
|
}
|
|
|
|
if (m_useInputFile)
|
|
{
|
|
*proc << m_inputFileName;
|
|
}
|
|
|
|
if (proc->start(KProcess::NotifyOnExit, KProcess::All))
|
|
{
|
|
emit clearMessages();
|
|
emit showMessage(i18n("The \"%1\" script started.\n").arg(actionText()), false);
|
|
if (!m_useInputFile)
|
|
{
|
|
if ( inputType == "current" || inputType == "selected" )
|
|
{
|
|
proc->writeStdin( buffer.local8Bit(), buffer.length() );
|
|
}
|
|
}
|
|
proc->closeStdin();
|
|
} else
|
|
{
|
|
KMessageBox::error(m_parentMainWindow, i18n("<qt>There was an error running <b>%1</b>.<br>Check that you have the <i>%2</i> executable installed and it is accessible.</qt>").arg(command + " " + args).arg(command), i18n("Script Not Found"));
|
|
ViewManager::ref()->activeView()->setFocus();
|
|
if (loopStarted)
|
|
{
|
|
tqApp->exit_loop();
|
|
loopStarted = false;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
#else
|
|
// hack to compile. tqmoc doesn't check the "#ifdef" at the declaration and the compiler complains
|
|
// of no matching function.
|
|
bool TagAction::slotActionActivated(KAction::ActivationReason /*reason*/, TQt::ButtonState /*state*/)
|
|
{return true;}
|
|
#endif
|
|
|
|
bool TagAction::slotActionActivated()
|
|
{
|
|
QuantaView *view = ViewManager::ref()->activeView();
|
|
if ( !view || !view->document())
|
|
return false;
|
|
|
|
TQString space="";
|
|
TQString output;
|
|
unsigned int line, col;
|
|
|
|
Document *w = view->document();
|
|
w->viewCursorIf->cursorPositionReal(&line, &col);
|
|
space.fill( ' ', col);
|
|
|
|
TQString type = tag.attribute("type","");
|
|
|
|
if ( type == "tag" ) {
|
|
TQDomElement otag = (tag.namedItem("tag")).toElement();
|
|
TQDomElement xtag = (tag.namedItem("xtag")).toElement();
|
|
|
|
TQString attr = otag.text();
|
|
if ( attr[0] == '<' )
|
|
attr.remove(0,1);
|
|
if ( attr.right(1) == ">" )
|
|
attr.remove( attr.length()-1, 1 );
|
|
attr = attr.stripWhiteSpace();
|
|
int i = 0;
|
|
while ( !attr[i].isSpace() && !attr[i].isNull() ) i++;
|
|
TQString name = attr.left(i);
|
|
attr = attr.remove(0,i).stripWhiteSpace();
|
|
|
|
if (otag.attribute("useDialog","false") == "true" && QuantaCommon::isKnownTag(w->defaultDTD()->name, name))
|
|
{
|
|
view->insertNewTag(name, attr, xtag.attribute("inLine","true") == "true");
|
|
}
|
|
else
|
|
{
|
|
TQString s1 = QuantaCommon::tagCase(name);
|
|
if (otag.text().left(1) == "<") s1 = "<"+s1;
|
|
if (!attr.isEmpty())
|
|
s1 += " "+QuantaCommon::attrCase(attr);
|
|
if (otag.text().right(1) == ">")
|
|
{
|
|
TQTag *dtdTag = QuantaCommon::tagFromDTD(w->defaultDTD(), name);
|
|
if ( w->defaultDTD()->singleTagStyle == "xml" && dtdTag &&
|
|
(dtdTag->isSingle() || (!qConfig.closeOptionalTags && dtdTag->isOptional()))
|
|
)
|
|
{
|
|
s1.append(" /");
|
|
}
|
|
|
|
s1.append(">");
|
|
}
|
|
|
|
TQString s2;
|
|
if ( xtag.attribute("use","false") == "true" )
|
|
{
|
|
if (qConfig.closeTags)
|
|
s2 = QuantaCommon::tagCase(xtag.text());
|
|
if ( xtag.attribute("inLine","true") == "true" )
|
|
{
|
|
/** FIXME this is quick and temporary */
|
|
view->insertOutputInTheNodeTree(s1, s2);
|
|
}
|
|
else
|
|
{
|
|
view->insertOutputInTheNodeTree(s1, s2);
|
|
}
|
|
}
|
|
else
|
|
view->insertOutputInTheNodeTree(s1, s2);
|
|
}
|
|
}
|
|
|
|
if (view->hadLastFocus() != QuantaView::VPLFocus)
|
|
{
|
|
|
|
|
|
if ( type == "text" )
|
|
w->insertTag( tag.namedItem("text").toElement().text() );
|
|
|
|
if ( type == "script" )
|
|
{
|
|
proc = new MyProcess();
|
|
proc->setWorkingDirectory(quantaApp->projectBaseURL().path());
|
|
|
|
TQDomElement script = tag.namedItem("script").toElement();
|
|
TQString command = script.text();
|
|
|
|
|
|
if ( !w->isUntitled() ) {
|
|
TQString fname = w->url().url();
|
|
if ( w->url().protocol() == "file")
|
|
fname = w->url().path();
|
|
command.replace("%f", fname );
|
|
}
|
|
|
|
pid_t pid = ::getpid();
|
|
if (kapp->inherits("KUniqueApplication"))
|
|
{
|
|
command.replace("%pid", TQString("unique %1").arg(pid));
|
|
} else
|
|
{
|
|
command.replace("%pid", TQString("%1").arg(pid));
|
|
}
|
|
TQString buffer;
|
|
TQString inputType = script.attribute("input","none");
|
|
|
|
if ( inputType == "current" ) {
|
|
buffer = w->editIf->text();
|
|
} else
|
|
if ( inputType == "selected" && w->selectionIf) {
|
|
buffer = w->selectionIf->selection();
|
|
}
|
|
command.replace("%input", buffer);
|
|
command = command.stripWhiteSpace();
|
|
int pos = command.find(' ');
|
|
TQString args;
|
|
if (pos != -1)
|
|
{
|
|
args = command.mid(pos+1);
|
|
command = command.left(pos);
|
|
}
|
|
if (command.startsWith("~"))
|
|
{
|
|
command = command.mid(1);
|
|
command.prepend(TQDir::homeDirPath());
|
|
}
|
|
|
|
*proc << command.stripWhiteSpace();
|
|
args = args.stripWhiteSpace();
|
|
if (!args.isEmpty())
|
|
{
|
|
pos = 0;
|
|
while (pos != -1 )
|
|
{
|
|
pos = args.find("%scriptdir");
|
|
TQString scriptname;
|
|
if (pos != -1)
|
|
{
|
|
int begin = args.findRev('"', pos);
|
|
int end = -1;
|
|
if (begin == -1)
|
|
{
|
|
begin = args.findRev('\'', pos);
|
|
if (begin != -1)
|
|
end = args.find('\'', pos);
|
|
} else
|
|
{
|
|
end = args.find('"', pos);
|
|
}
|
|
if (begin == -1 || end != -1)
|
|
{
|
|
begin = args.findRev(' ', pos);
|
|
if (begin == -1)
|
|
begin = 0;
|
|
end = args.find(' ', pos);
|
|
if (end == -1)
|
|
end = args.length();
|
|
}
|
|
scriptname = args.mid(begin, end - begin).stripWhiteSpace();
|
|
scriptname.replace("%scriptdir","scripts");
|
|
// kdDebug(24000) << "Script name is: |" << scriptname << "|" << endl;
|
|
scriptname = " " + locate("appdata", scriptname);
|
|
// kdDebug(24000) << "Script found at: " << scriptname << endl;
|
|
args.replace(begin, end - begin, scriptname);
|
|
// kdDebug(24000) << "Modified argument list: " << args << endl;
|
|
}
|
|
}
|
|
int pos = args.find("%projectbase");
|
|
if (pos != -1)
|
|
{
|
|
TQString s;
|
|
if (Project::ref()->hasProject())
|
|
s = Project::ref()->projectBaseURL().url();
|
|
args.replace("%projectbase", s);
|
|
}
|
|
TQStringList argsList1 = TQStringList::split(' ', args);
|
|
TQStringList argsList;
|
|
for (uint i = 0; i < argsList1.count(); i++)
|
|
{
|
|
if (argsList1[i] == "%userarguments")
|
|
{
|
|
for (uint j = 0; j < m_argsList.count(); j++)
|
|
{
|
|
argsList.append(m_argsList[j]);
|
|
}
|
|
} else
|
|
argsList.append(argsList1[i]);
|
|
}
|
|
m_argsList.clear();
|
|
*proc << argsList;
|
|
}
|
|
firstOutput = true;
|
|
firstError = true;
|
|
|
|
connect( proc, TQT_SIGNAL(receivedStdout( KProcess*,char*,int)), this,
|
|
TQT_SLOT( slotGetScriptOutput(KProcess*,char*,int)));
|
|
connect( proc, TQT_SIGNAL(receivedStderr( KProcess*,char*,int)), this,
|
|
TQT_SLOT( slotGetScriptError(KProcess*,char*,int)));
|
|
connect( proc, TQT_SIGNAL(processExited( KProcess*)), this,
|
|
TQT_SLOT( slotProcessExited(KProcess*)));
|
|
|
|
|
|
|
|
if (!m_useOutputFile)
|
|
scriptOutputDest = script.attribute("output","none");
|
|
else
|
|
scriptOutputDest = "file";
|
|
scriptErrorDest = script.attribute("error","none");
|
|
if (scriptOutputDest == "message")
|
|
{
|
|
emit showMessagesView();
|
|
}
|
|
|
|
if (m_useInputFile)
|
|
{
|
|
*proc << m_inputFileName;
|
|
}
|
|
|
|
if (proc->start(KProcess::NotifyOnExit, KProcess::All))
|
|
{
|
|
emit clearMessages();
|
|
emit showMessage(i18n("The \"%1\" script started.\n").arg(actionText()), false);
|
|
if (!m_useInputFile)
|
|
{
|
|
if ( inputType == "current" || inputType == "selected" )
|
|
{
|
|
proc->writeStdin( buffer.local8Bit(), buffer.length() );
|
|
}
|
|
}
|
|
proc->closeStdin();
|
|
} else
|
|
{
|
|
KMessageBox::error(m_parentMainWindow, i18n("<qt>There was an error running <b>%1</b>.<br>Check that you have the <i>%2</i> executable installed and it is accessible.</qt>").arg(command + " " + args).arg(command), i18n("Script Not Found"));
|
|
ViewManager::ref()->activeView()->setFocus();
|
|
if (loopStarted)
|
|
{
|
|
tqApp->exit_loop();
|
|
loopStarted = false;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void TagAction::slotGetScriptOutput( KProcess *, char *buffer, int buflen )
|
|
{
|
|
TQCString tmp( buffer, buflen + 1 );
|
|
TQString text( TQString::fromLocal8Bit(tmp) );
|
|
// kdDebug(24000) << "Script output received: |" << text << "|" << endl;
|
|
Document *w = ViewManager::ref()->activeDocument();
|
|
if (!w)
|
|
{
|
|
kdDebug(24000) << "Document not found." << endl;
|
|
return;
|
|
}
|
|
if ( scriptOutputDest == "cursor" )
|
|
{
|
|
w->insertTag( text );
|
|
} else
|
|
if ( scriptOutputDest == "selection" )
|
|
{
|
|
if ( firstOutput )
|
|
{
|
|
int line = dynamic_cast<KTextEditor::SelectionInterfaceExt*>(w->doc())->selEndLine();
|
|
int col = dynamic_cast<KTextEditor::SelectionInterfaceExt*>(w->doc())->selEndCol();
|
|
w->viewCursorIf->setCursorPositionReal(line, col);
|
|
if (w->selectionIf)
|
|
w->selectionIf->removeSelectedText();
|
|
}
|
|
w->insertTag( text );
|
|
} else
|
|
if ( scriptOutputDest == "replace" )
|
|
{
|
|
if ( firstOutput )
|
|
w->editIf->clear();
|
|
w->insertTag( text );
|
|
} else
|
|
if ( scriptOutputDest == "new" )
|
|
{
|
|
if (firstOutput)
|
|
{
|
|
emit createNewFile();
|
|
w = ViewManager::ref()->activeDocument();
|
|
}
|
|
w->insertTag( text );
|
|
} else
|
|
if ( scriptOutputDest == "message" )
|
|
{
|
|
if ( firstOutput )
|
|
{
|
|
emit showMessagesView();
|
|
emit showMessage(i18n("The \"%1\" script output:\n").arg(actionText()), false);
|
|
}
|
|
emit showMessage(text, true);
|
|
} else
|
|
if ( scriptOutputDest == "file" && m_file)
|
|
{
|
|
if (!m_file->isOpen())
|
|
m_file->open(IO_ReadWrite);
|
|
m_file->writeBlock(buffer, buflen);
|
|
}
|
|
|
|
firstOutput = false;
|
|
}
|
|
|
|
void TagAction::slotGetScriptError( KProcess *, char *buffer, int buflen )
|
|
{
|
|
Document *w = ViewManager::ref()->activeDocument();
|
|
TQCString tmp( buffer, buflen + 1 );
|
|
TQString text( TQString::fromLocal8Bit(tmp) );
|
|
|
|
if ( scriptErrorDest == "merge" )
|
|
{
|
|
scriptErrorDest = scriptOutputDest;
|
|
firstError = firstOutput;
|
|
}
|
|
if ( scriptErrorDest == "cursor" )
|
|
w->insertTag( text );
|
|
else
|
|
if ( scriptErrorDest == "selection" )
|
|
{
|
|
if ( firstError )
|
|
{
|
|
int line = dynamic_cast<KTextEditor::SelectionInterfaceExt*>(w->doc())->selEndLine();
|
|
int col = dynamic_cast<KTextEditor::SelectionInterfaceExt*>(w->doc())->selEndCol();
|
|
w->viewCursorIf->setCursorPositionReal(line, col);
|
|
if (w->selectionIf)
|
|
w->selectionIf->removeSelectedText();
|
|
}
|
|
w->insertTag( text );
|
|
} else
|
|
if ( scriptErrorDest == "replace" )
|
|
{
|
|
if ( firstError )
|
|
w->editIf->clear();
|
|
w->insertTag( text );
|
|
} else
|
|
if ( scriptErrorDest == "new" )
|
|
{
|
|
if (firstError)
|
|
{
|
|
emit createNewFile();
|
|
w = ViewManager::ref()->activeDocument();
|
|
}
|
|
w->insertTag( text );
|
|
} else
|
|
if ( scriptErrorDest == "message" )
|
|
{
|
|
if ( firstError )
|
|
{
|
|
emit showMessagesView();
|
|
emit showMessage(i18n("The \"%1\" script output:\n").arg(actionText()), false);
|
|
}
|
|
emit showMessage(text, true);
|
|
}
|
|
|
|
firstError = false;
|
|
}
|
|
|
|
void TagAction::scriptDone()
|
|
{
|
|
delete proc;
|
|
proc = 0;
|
|
}
|
|
|
|
void TagAction::setOutputFile(TQFile* file)
|
|
{
|
|
m_file = file;
|
|
}
|
|
|
|
void TagAction::setInputFileName(const TQString& fileName)
|
|
{
|
|
m_inputFileName = fileName;
|
|
}
|
|
|
|
TQString TagAction::actionText()
|
|
{
|
|
TQString t = tag.attribute("text");
|
|
int pos = t.find('&');
|
|
if (pos < (int)t.length()-1 && t[pos+1] != '&')
|
|
return t.remove(pos, 1);
|
|
else
|
|
return t;
|
|
}
|
|
|
|
TQString TagAction::XMLTagName() const
|
|
{
|
|
if(tag.attribute("type","").lower() != "tag")
|
|
return TQString();
|
|
|
|
TQDomElement otag = (tag.namedItem("tag")).toElement();
|
|
TQDomElement xtag = (tag.namedItem("xtag")).toElement();
|
|
|
|
TQString attr = otag.text();
|
|
if ( attr[0] == '<' )
|
|
attr.remove(0,1);
|
|
if ( attr.right(1) == ">" )
|
|
attr.remove( attr.length()-1, 1 );
|
|
attr = attr.stripWhiteSpace();
|
|
int i = 0;
|
|
while ( !attr[i].isSpace() && !attr[i].isNull() )
|
|
++i;
|
|
TQString name = attr.left(i);
|
|
|
|
return name;
|
|
}
|
|
|
|
TQString TagAction::openXMLTagString() const
|
|
{
|
|
TQString name = XMLTagName();
|
|
|
|
TQDomElement otag = (tag.namedItem("tag")).toElement();
|
|
TQDomElement xtag = (tag.namedItem("xtag")).toElement();
|
|
|
|
TQString attr = otag.text();
|
|
if ( attr[0] == '<' )
|
|
attr.remove(0,1);
|
|
if ( attr.right(1) == ">" )
|
|
attr.remove( attr.length()-1, 1 );
|
|
attr = attr.stripWhiteSpace();
|
|
attr.remove(0, name.length());
|
|
|
|
TQString s1 = QuantaCommon::tagCase(name);
|
|
if (otag.text().left(1) == "<") s1 = "<"+s1;
|
|
if (!attr.isEmpty())
|
|
s1 += " "+QuantaCommon::attrCase(attr);
|
|
if (otag.text().right(1) == ">")
|
|
{
|
|
Document* w = ViewManager::ref()->activeView()->document();
|
|
TQTag *dtdTag = QuantaCommon::tagFromDTD(w->defaultDTD(), name);
|
|
if ( w->defaultDTD()->singleTagStyle == "xml" && dtdTag &&
|
|
(dtdTag->isSingle() || (!qConfig.closeOptionalTags && dtdTag->isOptional()))
|
|
)
|
|
{
|
|
s1.append(" /");
|
|
}
|
|
|
|
s1.append(">");
|
|
}
|
|
|
|
return s1;
|
|
}
|
|
|
|
TQString TagAction::closeXMLTagString() const
|
|
{
|
|
TQString s2;
|
|
TQDomElement xtag = (tag.namedItem("xtag")).toElement();
|
|
if ( xtag.attribute("use","false") == "true" )
|
|
{
|
|
if (qConfig.closeTags)
|
|
s2 = QuantaCommon::tagCase(xtag.text());
|
|
}
|
|
return s2;
|
|
}
|
|
|
|
void TagAction::slotActivated()
|
|
{
|
|
// if(m_toggle)
|
|
KToggleAction::slotActivated();
|
|
//Andras: Disable toggle behavior. It is just too broken.
|
|
setChecked(false);
|
|
/*
|
|
if(!m_toggle)
|
|
setChecked(!isChecked());
|
|
*/
|
|
}
|
|
|
|
void TagAction::slotProcessExited(KProcess *process)
|
|
{
|
|
if (loopStarted)
|
|
{
|
|
tqApp->exit_loop();
|
|
loopStarted = false;
|
|
}
|
|
emit showMessage(i18n("The \"%1\" script has exited.").arg(actionText()), false);
|
|
delete process;
|
|
}
|
|
|
|
void TagAction::addArguments(const TQStringList &arguments)
|
|
{
|
|
m_argsList = arguments;
|
|
}
|
|
|
|
void TagAction::execute(bool blocking)
|
|
{
|
|
m_useInputFile = false;
|
|
m_useOutputFile = false;
|
|
if (blocking)
|
|
{
|
|
m_useInputFile = !m_inputFileName.isEmpty();
|
|
m_useOutputFile = (m_file);
|
|
if (slotActionActivated())
|
|
{
|
|
//To avoid lock-ups, start a timer.
|
|
timer = new TQTimer(this);
|
|
connect(timer, TQT_SIGNAL(timeout()), TQT_SLOT(slotTimeout()));
|
|
timer->start(180*1000, true);
|
|
QExtFileInfo internalFileInfo;
|
|
loopStarted = true;
|
|
m_killCount = 0;
|
|
internalFileInfo.enter_loop();
|
|
delete timer;
|
|
m_useInputFile = false;
|
|
m_useOutputFile = false;
|
|
}
|
|
} else
|
|
slotActionActivated();
|
|
}
|
|
|
|
/** Timeout occurred while waiting for some network function to return. */
|
|
void TagAction::slotTimeout()
|
|
{
|
|
if ((m_killCount == 0) && (KMessageBox::questionYesNo(m_parentMainWindow, i18n("<qt>The filtering action <b>%1</b> seems to be locked.<br>Do you want to terminate it?</qt>").arg(actionText()), i18n("Action Not Responding"), i18n("Terminate"), i18n("Keep Running")) == KMessageBox::Yes))
|
|
{
|
|
if (::kill(-proc->pid(), SIGTERM))
|
|
{
|
|
m_killCount++;
|
|
return;
|
|
}
|
|
}
|
|
if (m_killCount > 0)
|
|
{
|
|
::kill(-proc->pid(), SIGKILL);
|
|
if (loopStarted)
|
|
{
|
|
tqApp->exit_loop();
|
|
loopStarted = false;
|
|
}
|
|
return;
|
|
}
|
|
timer->start(180*1000, true);
|
|
}
|
|
|
|
void TagAction::applyTagInSelection(Node* start_node, int start_offset, Node* end_node, int end_offset,
|
|
NodeSelection& selection, NodeModifsSet* modifs) const
|
|
{
|
|
QuantaView *view = ViewManager::ref()->activeView();
|
|
Document* w = view->document();
|
|
|
|
Q_ASSERT(view->hadLastFocus() == QuantaView::VPLFocus);
|
|
Q_ASSERT(toggable());
|
|
|
|
TQString tag_name = XMLTagName();
|
|
Q_ASSERT(kafkaCommon::isInsideTag(start_node, end_node, tag_name) == -1);
|
|
|
|
TQString open_tag = openXMLTagString();
|
|
|
|
//We build the node from the tag name
|
|
Node* node = kafkaCommon::createNode("", "", Tag::XmlTag, w);
|
|
node->tag->parse(open_tag, w);
|
|
node->tag->name = QuantaCommon::tagCase(node->tag->name);
|
|
node->tag->single = QuantaCommon::isSingleTag(w->defaultDTD()->name,
|
|
node->tag->name);
|
|
|
|
long cursor_offset = selection.cursorOffset();
|
|
|
|
Node* nodeCursor = start_node;
|
|
Node* nodeParent = start_node;
|
|
if (nodeParent->tag->type == Tag::Text)
|
|
nodeParent = nodeParent->parent;
|
|
|
|
//Checking if at least one parent of node can have a Text Node as child, otherwise
|
|
//it is impossible for the
|
|
//user to add this node. In that case, try to insert the Node in the closest parent accepting it.
|
|
//e.g. TR : a normal insertion would require to have the caret in the TABLE Node, but it is
|
|
//impossible
|
|
TQTag* nodeTQTag = QuantaCommon::tagFromDTD(w->defaultDTD(), node->tag->name);
|
|
if (!nodeTQTag) return;
|
|
|
|
bool specialTagInsertion = false;
|
|
TQPtrList<TQTag> qTagList = nodeTQTag->parents();
|
|
TQTag* qTag = 0;
|
|
for (qTag = qTagList.first(); qTag; qTag = qTagList.next())
|
|
{
|
|
if (qTag->isChild("#text", false))
|
|
break;
|
|
if (qTag == qTagList.getLast())
|
|
specialTagInsertion = true;
|
|
}
|
|
|
|
bool nodeTreeModified = false;
|
|
|
|
if (specialTagInsertion) // Attention: not smartTagInsertion
|
|
{
|
|
//let's try to insert this node in the closest parent accepting it.
|
|
while (nodeParent)
|
|
{
|
|
TQTag* nodeParentTQTag = QuantaCommon::tagFromDTD(w->defaultDTD(), nodeParent->tag->name);
|
|
if (nodeParentTQTag && nodeParentTQTag->isChild(node))
|
|
{
|
|
nodeCursor = kafkaCommon::createMandatoryNodeSubtree(node, w);
|
|
start_offset = 0;
|
|
kafkaCommon::insertNodeSubtree(node, nodeParent, 0L, 0L, modifs);
|
|
nodeTreeModified = true;
|
|
break;
|
|
}
|
|
nodeParent = nodeParent->parent;
|
|
}
|
|
}
|
|
else if(!nodeTQTag->isSingle())
|
|
{
|
|
//If some text is selected in kafka, surround the selection with the new Node.
|
|
if(!start_node|| !end_node)
|
|
return;
|
|
nodeTreeModified = kafkaCommon::DTDinsertRemoveNode(node, start_node, start_offset,
|
|
end_node, end_offset, w, &nodeCursor, cursor_offset, modifs);
|
|
}
|
|
|
|
// w->docUndoRedo->addNewModifsSet(modifs, undoRedo::NodeTreeModif);
|
|
|
|
// FIXME Set the cursor right: the selection can be inverted
|
|
if(KafkaDocument::ref()->getKafkaWidget()->hasSelection())
|
|
{
|
|
nodeCursor = end_node;
|
|
cursor_offset = end_node->tag->tagStr().length();
|
|
}
|
|
|
|
selection.setCursorNode(nodeCursor);
|
|
selection.setCursorOffset(cursor_offset);
|
|
|
|
//Now update the VPL cursor position
|
|
// KafkaDocument::ref()->getKafkaWidget()->setCurrentNode(nodeCursor, cursor_offset);
|
|
|
|
if (!nodeTreeModified)
|
|
quantaApp->slotStatusMsg(i18n("Cannot insert the tag: invalid location."));
|
|
}
|
|
|
|
void TagAction::applyTagInMixedSelection(Node* start_node, int start_offset, Node* end_node, int end_offset,
|
|
NodeSelection& selection, NodeModifsSet* modifs) const
|
|
{
|
|
Q_ASSERT(start_node != end_node);
|
|
|
|
TQString const tag_name = XMLTagName();
|
|
|
|
// FIXME o pai pode ser do endNode. nao sei se esta merda eh precisa
|
|
/* Node* tag_parent = kafkaCommon::hasParent(start_node, tag_name);
|
|
Q_ASSERT(tag_parent);*/
|
|
|
|
QuantaView *view = ViewManager::ref()->activeView();
|
|
Document* w = view->document();
|
|
|
|
// Set start and end nodes to the correct node
|
|
start_node = kafkaCommon::getCorrectStartNode(start_node, start_offset);
|
|
end_node = kafkaCommon::getCorrectEndNode(end_node, end_offset);
|
|
|
|
// look for commonParent
|
|
TQValueList<int> commonParentStartChildLocation;
|
|
TQValueList<int> commonParentEndChildLocation;
|
|
|
|
Node* commonParent = kafkaCommon::DTDGetCommonParent(start_node, end_node, commonParentStartChildLocation, commonParentEndChildLocation, 0);
|
|
if(!commonParent) return;
|
|
|
|
Node* cursor_node = selection.cursorNode();
|
|
long cursor_offset = selection.cursorOffset();
|
|
kafkaCommon::splitStartAndEndNodeSubtree(start_node, start_offset, end_node, end_offset, commonParent,
|
|
commonParentStartChildLocation, commonParentEndChildLocation,
|
|
selection, 0, modifs);
|
|
|
|
Q_ASSERT(start_node != end_node);
|
|
|
|
// kafkaCommon::coutTree(baseNode, 3);
|
|
|
|
//We build the node from the tag name
|
|
TQString const open_tag_string = openXMLTagString();
|
|
Node* new_node = kafkaCommon::createNode("", "", Tag::XmlTag, w);
|
|
new_node->tag->parse(open_tag_string, w);
|
|
new_node->tag->name = QuantaCommon::tagCase(new_node->tag->name);
|
|
new_node->tag->single = QuantaCommon::isSingleTag(w->defaultDTD()->name,
|
|
new_node->tag->name);
|
|
|
|
Q_ASSERT(new_node->tag->type == Tag::XmlTag);
|
|
|
|
Node* commonParentStartChild = kafkaCommon::getNodeFromLocation(commonParentStartChildLocation, commonParent);
|
|
Node* commonParentEndChild = kafkaCommon::getNodeFromLocation(commonParentEndChildLocation, commonParent);
|
|
// if(!commonParentStartChild)
|
|
commonParentStartChild = kafkaCommon::getCommonParentChild(start_node, commonParent);
|
|
/* if(!commonParentEndChild)
|
|
commonParentEndChild = kafkaCommon::getCommonParentChild(end_node, commonParent);*/
|
|
|
|
// insert the node, child of commonParent and commonParentStartChild as nextSibling
|
|
kafkaCommon::insertNode(new_node, commonParent, commonParentStartChild, commonParentStartChild, modifs);
|
|
|
|
// move commonParentStartChild and commonParentEndChild inside new_node
|
|
kafkaCommon::moveNode(commonParentStartChild, new_node, 0, selection, modifs, true, true);
|
|
if(commonParentEndChild)
|
|
kafkaCommon::moveNode(commonParentEndChild, new_node, 0, selection, modifs, true, true);
|
|
|
|
// FIXME Set the cursor right: the selection can be inverted
|
|
if(KafkaDocument::ref()->getKafkaWidget()->hasSelection())
|
|
{
|
|
/*Node* */cursor_node = end_node;
|
|
/*int */cursor_offset = end_node->tag->tagStr().length();
|
|
selection.setCursorNode(cursor_node);
|
|
selection.setCursorOffset(cursor_offset);
|
|
}
|
|
cursor_node = selection.cursorNode();
|
|
cursor_offset = selection.cursorOffset();
|
|
|
|
Q_ASSERT(new_node->getClosingNode());
|
|
|
|
// FIXME remove possible equal tags inside the main surrounding tag
|
|
kafkaCommon::mergeInlineNode(new_node, new_node->getClosingNode(), &cursor_node, cursor_offset, modifs);
|
|
selection.setCursorNode(cursor_node);
|
|
selection.setCursorOffset(cursor_offset);
|
|
|
|
//Now update the VPL cursor position
|
|
// KafkaDocument::ref()->getKafkaWidget()->setCurrentNode(cursor_node, cursor_offset);
|
|
}
|
|
|
|
void TagAction::deapplyTagInSelection(Node* start_node, int start_offset, Node* end_node, int end_offset,
|
|
NodeSelection& selection, NodeModifsSet* modifs) const
|
|
{
|
|
// QuantaView *view = ViewManager::ref()->activeView();
|
|
// Document* w = view->document();
|
|
|
|
TQString const tag_name = XMLTagName();
|
|
|
|
// Set start and end nodes to the correct node
|
|
start_node = kafkaCommon::getCorrectStartNode(start_node, start_offset);
|
|
end_node = kafkaCommon::getCorrectEndNode(end_node, end_offset);
|
|
|
|
// look for commonParent
|
|
TQValueList<int> commonParentStartChildLocation;
|
|
TQValueList<int> commonParentEndChildLocation;
|
|
|
|
Node* commonParent = kafkaCommon::DTDGetCommonParent(start_node, end_node, commonParentStartChildLocation, commonParentEndChildLocation, 0);
|
|
if(!commonParent) return;
|
|
|
|
/* Node* cursor_node = selection.cursorNode();
|
|
int cursor_offset = selection.cursorOffset();*/
|
|
kafkaCommon::splitStartAndEndNodeSubtree(start_node, start_offset, end_node, end_offset, commonParent,
|
|
commonParentStartChildLocation, commonParentEndChildLocation,
|
|
selection, /*cursor_node, cursor_offset, */0, modifs);
|
|
|
|
// kafkaCommon::coutTree(baseNode, 3);
|
|
|
|
Node* tag_parent = kafkaCommon::hasParent(start_node, end_node, tag_name);
|
|
Q_ASSERT(tag_parent);
|
|
|
|
TQString attribute_name(tag.attribute("attribute_name", TQString()));
|
|
TQString attribute_value(tag.attribute("attribute_value", TQString()));
|
|
|
|
if(!attribute_name.isEmpty() && !attribute_value.isEmpty())
|
|
{
|
|
kafkaCommon::editNodeAttribute(tag_parent, attribute_name, TQString(), modifs);
|
|
}
|
|
|
|
else
|
|
{
|
|
Node* common_parent_start_child = kafkaCommon::getCommonParentChild(start_node, tag_parent);
|
|
Node* common_parent_end_child = kafkaCommon::getCommonParentChild(end_node, tag_parent);
|
|
|
|
Node* parent_of_tag_parent = tag_parent->parent;
|
|
if(common_parent_end_child == common_parent_start_child)
|
|
common_parent_end_child = 0;
|
|
if(!common_parent_start_child)
|
|
common_parent_start_child = kafkaCommon::getCommonParentChild(start_node, commonParent);
|
|
kafkaCommon::moveNode(common_parent_start_child, parent_of_tag_parent, tag_parent, selection, modifs, true, true);
|
|
|
|
if(common_parent_end_child)
|
|
kafkaCommon::moveNode(common_parent_end_child, parent_of_tag_parent, tag_parent, selection, modifs, true, true);
|
|
|
|
// Remove tag_parent node subtree if empty
|
|
if(!tag_parent->hasChildNodes())
|
|
kafkaCommon::extractAndDeleteNode(tag_parent, modifs);
|
|
|
|
// FIXME Set the cursor right: the selection can be inverted
|
|
if(KafkaDocument::ref()->getKafkaWidget()->hasSelection())
|
|
{
|
|
Node* cursor_node = end_node;
|
|
int cursor_offset = end_node->tag->tagStr().length();
|
|
selection.setCursorNode(cursor_node);
|
|
selection.setCursorOffset(cursor_offset);
|
|
}
|
|
//Now update the VPL cursor position
|
|
// KafkaDocument::ref()->getKafkaWidget()->setCurrentNode(cursor_node, cursor_offset);
|
|
}
|
|
}
|
|
|
|
// void TagAction::deapplyTagInMixedSelection(Node* start_node, int start_offset, Node* end_node, int end_offset, NodeModifsSet* modifs) const
|
|
// {
|
|
//
|
|
// }
|
|
|
|
|
|
#include "tagaction.moc"
|
|
#include "myprocess.moc"
|