|
|
/***************************************************************************
|
|
|
structtreeview.cpp - description
|
|
|
-------------------
|
|
|
begin : Sat Apr 29 2000
|
|
|
copyright : (C) 2000 by Yacovlev Alexander & Dmitry Poplavsky <pdima@mail.univ.kiev.ua>
|
|
|
(C) 2002, 2003 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. *
|
|
|
* *
|
|
|
***************************************************************************/
|
|
|
|
|
|
// system headers
|
|
|
#include <assert.h>
|
|
|
|
|
|
// QT headers
|
|
|
#include <tqpixmap.h>
|
|
|
#include <tqheader.h>
|
|
|
#include <tqregexp.h>
|
|
|
#include <tqdatetime.h>
|
|
|
#include <tqdragobject.h>
|
|
|
#include <tqcursor.h>
|
|
|
|
|
|
// KDE headers
|
|
|
#include <kapplication.h>
|
|
|
#include <kiconloader.h>
|
|
|
#include <kpopupmenu.h>
|
|
|
#include <klocale.h>
|
|
|
#include <kmessagebox.h>
|
|
|
#include <kconfig.h>
|
|
|
#include <kdebug.h>
|
|
|
#include <ktexteditor/view.h>
|
|
|
|
|
|
// app includes
|
|
|
#include "messageoutput.h"
|
|
|
#include "node.h"
|
|
|
#include "qtag.h"
|
|
|
#include "document.h"
|
|
|
#include "resource.h"
|
|
|
#include "qextfileinfo.h"
|
|
|
#include "quantacommon.h"
|
|
|
#include "dtds.h"
|
|
|
#include "viewmanager.h"
|
|
|
#include "kafkacommon.h"
|
|
|
#include "cursors.h"
|
|
|
#include "undoredo.h"
|
|
|
#include "quantaview.h"
|
|
|
#include "wkafkapart.h"
|
|
|
|
|
|
#include "structtreetag.h"
|
|
|
#include "structtreeview.h"
|
|
|
#include "structtreeview.moc"
|
|
|
extern GroupElementMapList globalGroupMap;
|
|
|
|
|
|
StructTreeView::StructTreeView(TQWidget *parent, const char *name )
|
|
|
: KListView(parent,name), m_marker(0), m_draggedItem(0)/*, m_thisWidget(0)*/
|
|
|
{
|
|
|
for (int i = 0; i < 15; i++)
|
|
|
groupOpened.append(false);
|
|
|
top = 0L;
|
|
|
lastTag = 0L;
|
|
|
groupsCount = 0;
|
|
|
followCursorFlag = true;
|
|
|
config = kapp->config();
|
|
|
|
|
|
topOpened = true;
|
|
|
useOpenLevelSetting = true;
|
|
|
|
|
|
setRootIsDecorated( true );
|
|
|
header()->hide();
|
|
|
setSorting(-1,false);
|
|
|
setAcceptDrops(false); // disabled d&d is broken
|
|
|
setDropVisualizer(true);
|
|
|
setDragEnabled(false); // disabled d&d is broken
|
|
|
// setSelectionModeExt(FileManager); disabled d&d is broken
|
|
|
|
|
|
setFrameStyle( Panel | Sunken );
|
|
|
setLineWidth( 2 );
|
|
|
addColumn( i18n("Name"), -1 );
|
|
|
|
|
|
setFocusPolicy(TQ_ClickFocus);
|
|
|
|
|
|
dtdMenu = new KPopupMenu(this);
|
|
|
|
|
|
dtdMenu->insertItem(i18n("All Present DTEP"));
|
|
|
dtdMenu->insertSeparator();
|
|
|
dtdList = DTDs::ref()->nickNameList();
|
|
|
for(uint i = 0; i < dtdList.count(); i++ )
|
|
|
{
|
|
|
dtdMenu->insertItem(dtdList[i], i, -1);
|
|
|
}
|
|
|
|
|
|
connect(dtdMenu, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotDTDChanged(int)));
|
|
|
|
|
|
connect(this, TQT_SIGNAL(dropped(TQDropEvent*, TQListViewItem*, TQListViewItem*)),
|
|
|
TQT_SLOT(slotDropped(TQDropEvent*, TQListViewItem*, TQListViewItem*)));
|
|
|
|
|
|
emptyAreaMenu = new KPopupMenu(this);
|
|
|
emptyAreaMenu->insertItem(i18n("Show Groups For"), dtdMenu);
|
|
|
emptyAreaMenu->insertItem(SmallIcon("reload"), i18n("&Reparse"), this, TQT_SLOT(slotReparseMenuItem()));
|
|
|
|
|
|
popupMenu = new KPopupMenu(this);
|
|
|
|
|
|
popupMenu -> insertItem( i18n("Show Groups For"), dtdMenu);
|
|
|
popupMenu -> insertSeparator();
|
|
|
popupMenu -> insertItem( i18n("Select Tag Area"), this ,TQT_SLOT(slotSelectTag()));
|
|
|
popupMenu -> insertItem( i18n("Go to End of Tag"), this ,TQT_SLOT(slotGotoClosingTag()));
|
|
|
openFileMenuId = popupMenu -> insertItem( i18n("Open File"), this ,TQT_SLOT(slotOpenFile()));
|
|
|
popupMenu -> insertSeparator();
|
|
|
popupMenu -> insertItem( i18n("Open Subtrees"), this ,TQT_SLOT(slotOpenSubTree()));
|
|
|
popupMenu -> insertItem( i18n("Close Subtrees"),this ,TQT_SLOT(slotCloseSubTree()));
|
|
|
popupMenu -> insertSeparator();
|
|
|
#if 0
|
|
|
popupMenu -> insertItem( i18n("Remove"),this ,TQT_SLOT(slotRemoveTags()));
|
|
|
popupMenu -> insertSeparator();
|
|
|
#endif
|
|
|
popupMenu -> insertItem( SmallIcon("reload"), i18n("&Reparse"), this ,TQT_SLOT(slotReparseMenuItem()));
|
|
|
followCursorId = popupMenu -> insertItem( i18n("Follow Cursor"), this ,TQT_SLOT(changeFollowCursor()));
|
|
|
|
|
|
popupMenu -> setItemChecked ( followCursorId, followCursor() );
|
|
|
|
|
|
|
|
|
connect( this, TQT_SIGNAL(mouseButtonPressed(int, TQListViewItem*, const TQPoint&, int)),
|
|
|
this, TQT_SLOT (slotMouseClicked(int, TQListViewItem*, const TQPoint&, int)));
|
|
|
|
|
|
connect( this, TQT_SIGNAL(doubleClicked(TQListViewItem *)), TQT_SLOT(slotDoubleClicked(TQListViewItem *)));
|
|
|
|
|
|
connect(this, TQT_SIGNAL(expanded(TQListViewItem *)), TQT_SLOT(slotExpanded(TQListViewItem *)));
|
|
|
connect(this, TQT_SIGNAL(collapsed(TQListViewItem *)), TQT_SLOT(slotCollapsed(TQListViewItem *)));
|
|
|
|
|
|
write = 0L;
|
|
|
timer = new TQTime();
|
|
|
timer->start();
|
|
|
m_dirty = true;
|
|
|
}
|
|
|
|
|
|
|
|
|
StructTreeView::~StructTreeView(){
|
|
|
delete timer;
|
|
|
}
|
|
|
|
|
|
/** builds the structure tree */
|
|
|
void StructTreeView::buildTree(Node *baseNode, int openLevel, bool groupOnly)
|
|
|
{
|
|
|
#ifdef DEBUG_PARSER
|
|
|
kdDebug(24000) << "Starting to rebuild the structure tree. Grouponly = " << groupOnly << endl;
|
|
|
#endif
|
|
|
if (!groupOnly)
|
|
|
{
|
|
|
top = new StructTreeTag( this, i18n("Document Structure") );
|
|
|
top->setOpen(topOpened);
|
|
|
emit clearProblemOutput();
|
|
|
}
|
|
|
Node *currentNode = baseNode;
|
|
|
StructTreeTag *currentItem = top; //after this
|
|
|
StructTreeTag *item = 0L;
|
|
|
StructTreeTag *parentItem = top; //under this
|
|
|
int level = 0;
|
|
|
TQString title;
|
|
|
TQString tagStr;
|
|
|
TQString tmpStr;
|
|
|
int groupId = 0;
|
|
|
const DTDStruct* parsingDTD;
|
|
|
for (uint index = 0; index < m_parsingDTDList.count(); index++)
|
|
|
{
|
|
|
parsingDTD = m_parsingDTDList[index];
|
|
|
if (parsingDTD->family == Script)
|
|
|
{
|
|
|
StructTreeGroup group;
|
|
|
uint gCount = parsingDTD->structTreeGroups.count();
|
|
|
for (uint i = 0; i < gCount; i++)
|
|
|
{
|
|
|
group = parsingDTD->structTreeGroups[i];
|
|
|
StructTreeTag *groupTag = new StructTreeTag(this, i18n(group.name.utf8()) + " [" + parsingDTD->nickName+"]");
|
|
|
if (!group.icon.isEmpty())
|
|
|
{
|
|
|
groupTag->setPixmap(0, SmallIcon(group.icon));
|
|
|
}
|
|
|
groupTag->setOpen(groupOpened[groupId]);
|
|
|
#ifdef DEBUG_PARSER
|
|
|
kdDebug(24001) << "Grouptag created: " << groupId << " " << groupTag->text(0) << " "<< groupTag << endl;
|
|
|
#endif
|
|
|
groups.append(groupTag);
|
|
|
groupIds.insert(group.name + parsingDTD->name, groupId);
|
|
|
groupId++;
|
|
|
}
|
|
|
} else
|
|
|
{
|
|
|
TQMap<TQString, XMLStructGroup>::ConstIterator it;
|
|
|
for (it = parsingDTD->xmlStructTreeGroups.begin(); it != parsingDTD->xmlStructTreeGroups.end(); ++it)
|
|
|
{
|
|
|
XMLStructGroup group = it.data();
|
|
|
StructTreeTag *groupTag = new StructTreeTag(this, i18n(group.name.utf8()) + " [" + parsingDTD->nickName+"]");
|
|
|
if (!group.icon.isEmpty())
|
|
|
{
|
|
|
groupTag->setPixmap(0, SmallIcon(group.icon));
|
|
|
}
|
|
|
groupTag->setOpen(groupOpened[groupId]);
|
|
|
#ifdef DEBUG_PARSER
|
|
|
kdDebug(24001) << "Grouptag created: " << groupId << " " << groupTag->text(0) << " "<< groupTag << endl;
|
|
|
#endif
|
|
|
groups.append(groupTag);
|
|
|
groupIds.insert(group.name + parsingDTD->name, groupId);
|
|
|
groupId++;
|
|
|
}
|
|
|
|
|
|
}
|
|
|
}
|
|
|
groupsCount = groupId;
|
|
|
TQMap<TQString, TQListViewItem*> lastItemInGroup;
|
|
|
TQMap<TQString, TQListViewItem*> groupItems;
|
|
|
while (currentNode)
|
|
|
{
|
|
|
if (!groupOnly)
|
|
|
{
|
|
|
title = "";
|
|
|
item = new StructTreeTag(parentItem, currentNode, title, currentItem);
|
|
|
item->setOpen(level < openLevel);
|
|
|
currentNode->mainListItem = item;
|
|
|
|
|
|
if ( (!qConfig.showEmptyNodes && currentNode->tag->type == Tag::Empty) ||
|
|
|
(!qConfig.showClosingTags &&
|
|
|
(currentNode->tag->type == Tag::XmlTagEnd ||
|
|
|
currentNode->tag->type == Tag::ScriptStructureEnd) ) )
|
|
|
{
|
|
|
item->setVisible(false);
|
|
|
}
|
|
|
}
|
|
|
const DTDStruct *dtd = currentNode->tag->dtd();
|
|
|
//add all the group elements belonging to this node to the tree
|
|
|
for (TQValueList<GroupElement*>::ConstIterator it = currentNode->m_groupElements.constBegin(); it != currentNode->m_groupElements.constEnd(); ++it)
|
|
|
{
|
|
|
GroupElement *groupElement = (*it);
|
|
|
if (!groupIds.contains(groupElement->group->name + dtd->name))
|
|
|
continue;
|
|
|
StructTreeTag *groupItem = groups[groupIds[groupElement->group->name + dtd->name]];
|
|
|
TQListViewItem* insertAfter = 0L;
|
|
|
TQListViewItem* insertUnder = groupItem;
|
|
|
if (groupItems.contains(groupElement->group->name + groupElement->tag->name))
|
|
|
insertUnder = groupItems[groupElement->group->name + groupElement->tag->name];
|
|
|
if (lastItemInGroup.contains(groupElement->group->name))
|
|
|
insertAfter = lastItemInGroup[groupElement->group->name];
|
|
|
|
|
|
StructTreeTag *item = new StructTreeTag(static_cast<StructTreeTag*>(insertUnder), currentNode, groupElement->tag->name, insertAfter);
|
|
|
item->groupTag = groupElement->tag;
|
|
|
if (insertUnder == groupItem)
|
|
|
{
|
|
|
groupItems[groupElement->group->name + groupElement->tag->name] = item;
|
|
|
lastItemInGroup[groupElement->group->name] = item;
|
|
|
}
|
|
|
item->hasOpenFileMenu = groupElement->group->hasFileName;
|
|
|
item->fileNameRx = groupElement->group->fileNameRx;
|
|
|
#ifdef DEBUG_PARSER
|
|
|
kdDebug(24001) << "Tree element "<< groupElement->tag->tagStr() << "[" << groupElement->group->name<<"]"<< " inserted: " << item << " under " <<insertUnder << " after " << insertAfter << endl;
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
//go to the child node, if it exists
|
|
|
if (currentNode->child)
|
|
|
{
|
|
|
currentNode = currentNode->child;
|
|
|
parentItem = item;
|
|
|
currentItem = 0L;
|
|
|
level++;
|
|
|
} else
|
|
|
{
|
|
|
//go to the next node if it exists
|
|
|
if (currentNode->next)
|
|
|
{
|
|
|
currentNode = currentNode->next;
|
|
|
currentItem = item;
|
|
|
} else
|
|
|
{
|
|
|
//go up some levels, to the parent, if the node has no child or next
|
|
|
while (currentNode)
|
|
|
{
|
|
|
level--;
|
|
|
//parentItem = dynamic_cast<StructTreeTag*>(parentItem->parent());
|
|
|
if (currentNode->parent && currentNode->parent->next)
|
|
|
{
|
|
|
currentNode = currentNode->parent->next;
|
|
|
break;
|
|
|
} else
|
|
|
{
|
|
|
currentNode = currentNode->parent;
|
|
|
}
|
|
|
}
|
|
|
if (!groupOnly && currentNode)
|
|
|
{
|
|
|
if (currentNode->prev)
|
|
|
currentItem = static_cast<StructTreeTag*>(currentNode->prev->mainListItem);
|
|
|
if (currentNode->parent)
|
|
|
{
|
|
|
parentItem = static_cast<StructTreeTag*>(currentNode->parent->mainListItem);
|
|
|
if (!parentItem)
|
|
|
{
|
|
|
parentItem = top;
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
parentItem = top;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
//add the externally found items to the tree
|
|
|
TQListViewItem *insertUnder;
|
|
|
TQListViewItem *insertAfter;
|
|
|
TQListViewItem *listItem;
|
|
|
GroupElementMapList::Iterator it;
|
|
|
IncludedGroupElementsMap::Iterator externalIt;
|
|
|
for (uint index = 0; index < m_parsingDTDList.count(); index++)
|
|
|
{
|
|
|
parsingDTD = m_parsingDTDList[index];
|
|
|
if (parsingDTD->family == Script)
|
|
|
{
|
|
|
StructTreeGroup group;
|
|
|
uint gCount = parsingDTD->structTreeGroups.count();
|
|
|
for (uint i = 0; i < gCount; i++)
|
|
|
{
|
|
|
group = parsingDTD->structTreeGroups[i];
|
|
|
groupId = groupIds[group.name + parsingDTD->name];
|
|
|
TQString name = group.name+"|";
|
|
|
StructTreeTag *groupTag = groups[groupId];
|
|
|
for (externalIt = parser->includedMap.begin(); externalIt != parser->includedMap.end(); ++externalIt)
|
|
|
{
|
|
|
insertUnder = new StructTreeTag(static_cast<StructTreeTag*>(groupTag), 0L, externalIt.key(), groupTag);
|
|
|
insertAfter = insertUnder;
|
|
|
IncludedGroupElements elements = externalIt.data();
|
|
|
GroupElementMapList::Iterator elIt;
|
|
|
for (elIt = elements[group.name].begin(); elIt != elements[group.name].end(); ++elIt)
|
|
|
{
|
|
|
listItem = new StructTreeTag(static_cast<StructTreeTag*>(insertUnder), elIt.data()[0]->node, elIt.key(), insertAfter);
|
|
|
static_cast<StructTreeTag*>(listItem)->hasOpenFileMenu = group.hasFileName;
|
|
|
static_cast<StructTreeTag*>(listItem)->fileNameRx = group.fileNameRx;
|
|
|
insertAfter = listItem;
|
|
|
}
|
|
|
if (!insertUnder->firstChild())
|
|
|
delete insertUnder;
|
|
|
else
|
|
|
insertUnder->sortChildItems(0, true);
|
|
|
}
|
|
|
groupTag->sortChildItems(0, true);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/** Delete the items */
|
|
|
void StructTreeView::deleteList(bool groupOnly)
|
|
|
{
|
|
|
if (!groupOnly && top )
|
|
|
{
|
|
|
topOpened = top->isOpen();
|
|
|
delete top;
|
|
|
top = 0L;
|
|
|
}
|
|
|
for (uint i = 0; i < groupsCount; i++)
|
|
|
{
|
|
|
groupOpened.append(groups[i]->isOpen());
|
|
|
#ifdef DEBUG_PARSER
|
|
|
kdDebug(24001) << "Grouptag deleted: " << i << " " << groups[i]->text(0) << endl;
|
|
|
#endif
|
|
|
delete groups[i];
|
|
|
}
|
|
|
groups.clear();
|
|
|
groupIds.clear();
|
|
|
groupsCount = 0;
|
|
|
}
|
|
|
|
|
|
/** tqrepaint document structure */
|
|
|
void StructTreeView::slotReparse(Document *w, Node* node, int openLevel, bool groupOnly)
|
|
|
{
|
|
|
timer->restart();
|
|
|
if (typingInProgress)
|
|
|
return;
|
|
|
deleteList(groupOnly);
|
|
|
if (!node)
|
|
|
return;
|
|
|
write = w;
|
|
|
if (write)
|
|
|
write->clearAnnotations();
|
|
|
write->clearErrorMarks();
|
|
|
buildTree(node, openLevel, groupOnly);
|
|
|
|
|
|
kdDebug(24000) << "StructTreeView building: " << timer->elapsed() << " ms\n";
|
|
|
|
|
|
const DTDStruct *parsingDTD;
|
|
|
int groupId = 0;
|
|
|
for (uint index = 0; index < m_parsingDTDList.count(); index++)
|
|
|
{
|
|
|
parsingDTD = m_parsingDTDList[index];
|
|
|
if (parsingDTD->family == Script)
|
|
|
{
|
|
|
uint gCount = parsingDTD->structTreeGroups.count();
|
|
|
for (uint i = 0; i < gCount; i++)
|
|
|
{
|
|
|
StructTreeTag *groupTag = groups[groupId];
|
|
|
if (groupTag->childCount() == 0)
|
|
|
{
|
|
|
if (qConfig.showEmptyNodes)
|
|
|
{
|
|
|
//kdDebug(24000) << "No elements in group: " << groupId << " " << groupTag->text(0) << endl;
|
|
|
groupTag->setText(0, i18n(parsingDTD->structTreeGroups[i].noName.utf8()) + " [" + parsingDTD->nickName+"]");
|
|
|
} else
|
|
|
{
|
|
|
groupTag->setVisible(false);
|
|
|
}
|
|
|
}
|
|
|
groupId++;
|
|
|
}
|
|
|
} else
|
|
|
{
|
|
|
TQMap<TQString, XMLStructGroup>::ConstIterator it;
|
|
|
uint i = 0;
|
|
|
for (it = parsingDTD->xmlStructTreeGroups.begin(); it != parsingDTD->xmlStructTreeGroups.end(); ++it)
|
|
|
{
|
|
|
StructTreeTag *groupTag = groups[groupId];
|
|
|
if (groupTag->childCount() == 0)
|
|
|
{
|
|
|
if (qConfig.showEmptyNodes)
|
|
|
{
|
|
|
//kdDebug(24000) << "No elements in group: " << groupId << " " << groupTag->text(0) << endl;
|
|
|
groupTag->setText(0, i18n(it.data().noName.utf8()) + " [" + parsingDTD->nickName+"]");
|
|
|
} else
|
|
|
{
|
|
|
groupTag->setVisible(false);
|
|
|
}
|
|
|
}
|
|
|
i++;
|
|
|
groupId++;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
useOpenLevelSetting = false;
|
|
|
m_dirty = false;
|
|
|
}
|
|
|
|
|
|
void StructTreeView::slotGotoTag( TQListViewItem *item )
|
|
|
{
|
|
|
StructTreeTag *it = dynamic_cast<StructTreeTag*>(item);
|
|
|
if (!m_dirty && it && it->node && it->node->tag)
|
|
|
{
|
|
|
Tag *tag = new Tag(*it->node->tag);
|
|
|
int line, col;
|
|
|
tag->beginPos(line, col);
|
|
|
if (!it->node->fileName.isEmpty())
|
|
|
{
|
|
|
KURL url;
|
|
|
QuantaCommon::setUrl(url, it->node->fileName);
|
|
|
emit openFile(url);
|
|
|
}
|
|
|
int el, ec;
|
|
|
tag->endPos(el, ec);
|
|
|
/*
|
|
|
kdDebug(24000) << "Node area: " << line << ", " << col << ", " << el << ", " << ec << endl;
|
|
|
kdDebug(24000) << "Node type: " << tag->type << endl;
|
|
|
kdDebug(24000) << "Node str: " << tag->tagStr() << endl;
|
|
|
kdDebug(24000) << "Node cleanstr: " << tag->cleanStr << endl;
|
|
|
*/
|
|
|
if (tag->type == Tag::XmlTag || tag->type == Tag::XmlTagEnd)
|
|
|
col++; //position the cursor inside the tag
|
|
|
emit newCursorPosition(line, col);
|
|
|
Document *w = ViewManager::ref()->activeDocument();
|
|
|
if (w)
|
|
|
w->view()->setFocus();
|
|
|
delete tag;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
void StructTreeView::slotMouseClicked(int button, TQListViewItem *item, const TQPoint& point, int dummy)
|
|
|
{
|
|
|
if (item)
|
|
|
{
|
|
|
config->setGroup("Parser options");
|
|
|
|
|
|
TQString handleMBM = config->readEntry("MBM", i18n("Select Tag Area"));
|
|
|
TQString handleLBM = config->readEntry("LBM", i18n("Find tag"));
|
|
|
TQString handleDoubleClick = config->readEntry("Double click", i18n("Select Tag Area"));
|
|
|
|
|
|
setSelected(item, true);
|
|
|
|
|
|
if (button == Qt::RightButton)
|
|
|
{
|
|
|
if (dynamic_cast<StructTreeTag*>(item))
|
|
|
{
|
|
|
popupMenu->setItemVisible(openFileMenuId, static_cast<StructTreeTag*>(item)->hasOpenFileMenu);
|
|
|
}
|
|
|
popupMenu->popup(point);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if (button == Qt::LeftButton)
|
|
|
{
|
|
|
if (handleLBM == i18n("Find Tag && Open Tree"))
|
|
|
setOpen(item, !isOpen(item));
|
|
|
setSelected(item, true);
|
|
|
|
|
|
bool const ctrlPressed = KApplication::keyboardMouseState() & TQt::ControlButton;
|
|
|
|
|
|
if(ctrlPressed)
|
|
|
setContiguousSelectedItems();
|
|
|
|
|
|
if(ViewManager::ref()->activeView()->hadLastFocus() == QuantaView::VPLFocus)
|
|
|
slotMouseClickedVPL(button, item, point, dummy);
|
|
|
else
|
|
|
slotGotoTag(item);
|
|
|
}
|
|
|
|
|
|
if (button == Qt::MidButton)
|
|
|
{
|
|
|
if (handleMBM == i18n("nothing"))
|
|
|
return;
|
|
|
|
|
|
if (handleMBM == i18n("Find Tag && Open Tree"))
|
|
|
{
|
|
|
setOpen(item, !isOpen(item));
|
|
|
setSelected(item, true);
|
|
|
slotGotoTag(item);
|
|
|
}
|
|
|
|
|
|
if (handleMBM == i18n("Select Tag Area"))
|
|
|
slotSelectTag();
|
|
|
|
|
|
if (handleMBM == i18n("Go to End of Tag"))
|
|
|
slotGotoClosingTag();
|
|
|
|
|
|
setSelected(item, true);
|
|
|
}
|
|
|
} else
|
|
|
if (button == Qt::RightButton)
|
|
|
emptyAreaMenu->popup(point);
|
|
|
}
|
|
|
|
|
|
|
|
|
void StructTreeView::slotDoubleClicked( TQListViewItem *item)
|
|
|
{
|
|
|
config->setGroup("Parser options");
|
|
|
|
|
|
if ( config->readEntry("Double click") != i18n("nothing") )
|
|
|
{
|
|
|
slotSelectTag();
|
|
|
} else
|
|
|
{
|
|
|
item->setOpen(!item->isOpen());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void StructTreeView::slotReparseMenuItem()
|
|
|
{
|
|
|
useOpenLevelSetting = true;
|
|
|
emit needReparse();
|
|
|
}
|
|
|
|
|
|
void StructTreeView::slotGotoClosingTag()
|
|
|
{
|
|
|
TQListViewItem *item = currentItem();
|
|
|
StructTreeTag *it = dynamic_cast<StructTreeTag*>(item);
|
|
|
if (!m_dirty && it && it->node)
|
|
|
{
|
|
|
int newLine, newCol;
|
|
|
Tag *tag = it->node->tag;
|
|
|
if (tag->single || !it->node->next)
|
|
|
{
|
|
|
tag->endPos(newLine, newCol);
|
|
|
} else
|
|
|
{
|
|
|
if (tag->closingMissing)
|
|
|
{
|
|
|
Node *node = it->node;
|
|
|
while (node->child) node = node->child;
|
|
|
node->tag->endPos(newLine, newCol);
|
|
|
} else
|
|
|
{
|
|
|
it->node->next->tag->endPos(newLine, newCol);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
emit newCursorPosition( newLine, newCol + 1 );
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void StructTreeView::slotSelectTag()
|
|
|
{
|
|
|
bool newFileOpened = false;
|
|
|
TQListViewItem *item = currentItem();
|
|
|
StructTreeTag *it = dynamic_cast<StructTreeTag*>(item);
|
|
|
if (!m_dirty && it && it->node)
|
|
|
{
|
|
|
int bLine, bCol, eLine, eCol;
|
|
|
if (it->node->fileName.isEmpty())
|
|
|
{
|
|
|
if (it->groupTag)
|
|
|
{
|
|
|
Tag *tag = it->groupTag;
|
|
|
tag->beginPos(bLine, bCol);
|
|
|
tag->endPos(eLine, eCol);
|
|
|
} else
|
|
|
{
|
|
|
Tag *tag = it->node->tag;
|
|
|
if (tag->single || !it->node->next)
|
|
|
{
|
|
|
tag->endPos(eLine, eCol);
|
|
|
} else
|
|
|
{
|
|
|
emit selectTagArea(it->node);
|
|
|
return;
|
|
|
}
|
|
|
tag->beginPos(bLine, bCol);
|
|
|
}
|
|
|
} else
|
|
|
{
|
|
|
KURL url;
|
|
|
QuantaCommon::setUrl(url, it->node->fileName);
|
|
|
it->node->tag->beginPos(bLine, bCol);
|
|
|
it->node->tag->endPos(eLine, eCol);
|
|
|
eCol--;
|
|
|
emit openFile(url);
|
|
|
newFileOpened = true;
|
|
|
|
|
|
}
|
|
|
emit selectArea( bLine, bCol, eLine, eCol + 1);
|
|
|
|
|
|
if (!newFileOpened)
|
|
|
{
|
|
|
setSelected(item, true);
|
|
|
it->node->tag->write()->view()->setFocus();
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
/** Do the recursive opening or closing of the trees */
|
|
|
void StructTreeView::setOpenSubTree( TQListViewItem *it, bool open)
|
|
|
{
|
|
|
if (it)
|
|
|
{
|
|
|
it->setOpen(open);
|
|
|
setOpenSubTree( it->nextSibling(), open );
|
|
|
setOpenSubTree( it->firstChild(), open );
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/** Recursively open the tree and all its subtrees */
|
|
|
void StructTreeView::slotOpenSubTree()
|
|
|
{
|
|
|
TQListViewItem *item = currentItem();
|
|
|
if (item)
|
|
|
{
|
|
|
item->setOpen( true );
|
|
|
setOpenSubTree( item->firstChild(), true );
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
/** Recursively close the tree and all its subtrees */
|
|
|
void StructTreeView::slotCloseSubTree()
|
|
|
{
|
|
|
TQListViewItem *item = currentItem();
|
|
|
if (item)
|
|
|
{
|
|
|
item->setOpen( false );
|
|
|
setOpenSubTree( item->firstChild(), false );
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/** Show the element in tree according to cursor position (x,y) */
|
|
|
void StructTreeView::showTagAtPos(Node *node)
|
|
|
{
|
|
|
if (followCursorFlag)
|
|
|
{
|
|
|
if (node && node->mainListItem)
|
|
|
{
|
|
|
clearSelection();
|
|
|
ensureItemVisible(node->mainListItem);
|
|
|
setSelected(node->mainListItem, true);
|
|
|
}
|
|
|
} //if (followCursorFlag)
|
|
|
}
|
|
|
|
|
|
void StructTreeView::setFollowCursor(bool follow)
|
|
|
{
|
|
|
followCursorFlag = follow;
|
|
|
popupMenu->setItemChecked(followCursorId, follow);
|
|
|
}
|
|
|
|
|
|
/** No descriptions */
|
|
|
void StructTreeView::slotExpanded(TQListViewItem *item)
|
|
|
{
|
|
|
StructTreeTag *it = dynamic_cast<StructTreeTag*>(item);
|
|
|
if (!m_dirty && it && it->node)
|
|
|
it->node->opened = true;
|
|
|
}
|
|
|
|
|
|
/** No descriptions */
|
|
|
void StructTreeView::slotCollapsed(TQListViewItem *item)
|
|
|
{
|
|
|
StructTreeTag *it = dynamic_cast<StructTreeTag*>(item);
|
|
|
if (!m_dirty && it && it->node)
|
|
|
it->node->opened = false;
|
|
|
}
|
|
|
/** Do a reparse before showing. */
|
|
|
void StructTreeView::showEvent(TQShowEvent* /*ev*/)
|
|
|
{
|
|
|
slotReparseMenuItem();
|
|
|
}
|
|
|
|
|
|
/** Do a reparse before showing. */
|
|
|
void StructTreeView::hideEvent(TQHideEvent* /*ev*/)
|
|
|
{
|
|
|
emit clearProblemOutput();
|
|
|
}
|
|
|
|
|
|
enum {
|
|
|
DRAG_COPY = 0,
|
|
|
DRAG_MOVE = 1,
|
|
|
DRAG_CANCEL = 2
|
|
|
};
|
|
|
|
|
|
void StructTreeView::setContiguousSelectedItems()
|
|
|
{
|
|
|
kdDebug(25001) << "setContiguousSelectedItems" << endl;
|
|
|
|
|
|
TQPtrList<TQListViewItem> selected_items = selectedItems(false);
|
|
|
|
|
|
TQListViewItem* first = selected_items.getFirst();
|
|
|
TQListViewItem* last = selected_items.getLast();
|
|
|
|
|
|
TQListViewItemIterator it(first);
|
|
|
while(it.current() && it.current() != last)
|
|
|
{
|
|
|
TQListViewItem* item = it.current();
|
|
|
if(!item->isSelected())
|
|
|
item->setSelected(true);
|
|
|
|
|
|
++it;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
bool StructTreeView::acceptDrag(TQDropEvent* e) const
|
|
|
{
|
|
|
static int i = 0;
|
|
|
kdDebug(25001) << "acceptDrag: " << ++i << endl;
|
|
|
|
|
|
TQPoint p = contentsToViewport(e->pos());
|
|
|
TQListViewItem* current_item = itemAt(p);
|
|
|
|
|
|
// assert(m_thisWidget);
|
|
|
|
|
|
static bool last_accept = false;
|
|
|
|
|
|
if(current_item == m_marker)
|
|
|
{
|
|
|
e->accept(last_accept);
|
|
|
/* if(last_accept)
|
|
|
m_thisWidget->setCursor(TQt::ForbiddenCursor);
|
|
|
else
|
|
|
m_thisWidget->setCursor(TQt::ForbiddenCursor);*/
|
|
|
kdDebug(25001) << "Princ<EFBFBD>io: " << last_accept << endl;
|
|
|
|
|
|
return last_accept;
|
|
|
}
|
|
|
else
|
|
|
m_marker = current_item;
|
|
|
|
|
|
if(current_item == m_draggedItem ||
|
|
|
!(e->provides("text/x-struct_tree_tag_item") || e->source() == (TQWidget *)this) || !m_marker)
|
|
|
{
|
|
|
e->accept(false);
|
|
|
last_accept = false;
|
|
|
/* if(last_accept)
|
|
|
m_thisWidget->setCursor(TQt::ForbiddenCursor);
|
|
|
else
|
|
|
m_thisWidget->setCursor(TQt::ForbiddenCursor);*/
|
|
|
kdDebug(25001) << "PROIBIDO! #1" << endl;
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
Node* dragged_node = (dynamic_cast<StructTreeTag*> (m_draggedItem))->node;
|
|
|
Node* after_node = (dynamic_cast<StructTreeTag*> (m_marker))->node;
|
|
|
if(!after_node)
|
|
|
{
|
|
|
e->accept(false);
|
|
|
last_accept = false;
|
|
|
/* if(last_accept)
|
|
|
m_thisWidget->setCursor(TQt::ForbiddenCursor);
|
|
|
else
|
|
|
m_thisWidget->setCursor(TQt::ForbiddenCursor);*/
|
|
|
kdDebug(25001) << "PROIBIDO! #2" << endl;
|
|
|
return false;
|
|
|
}
|
|
|
TQTag* nodeTQTag = QuantaCommon::tagFromDTD(after_node->parent);
|
|
|
bool is_child = (nodeTQTag && nodeTQTag->isChild(dragged_node));
|
|
|
|
|
|
if(!is_child)
|
|
|
kdDebug(25001) << "PROIBIDO! #3" << endl;
|
|
|
else
|
|
|
kdDebug(25001) << "ACEITE!" << endl;
|
|
|
|
|
|
e->accept(is_child);
|
|
|
last_accept = is_child;
|
|
|
// if(last_accept)
|
|
|
// m_thisWidget->setCursor(TQt::ForbiddenCursor);
|
|
|
// else
|
|
|
// m_thisWidget->setCursor(TQt::ForbiddenCursor);
|
|
|
|
|
|
return is_child;
|
|
|
}
|
|
|
|
|
|
void StructTreeView::slotDropped(TQDropEvent* e, TQListViewItem* parent, TQListViewItem* after)
|
|
|
{
|
|
|
if(!e)
|
|
|
return;
|
|
|
if (e->source() != this)
|
|
|
return; // Only internal drags are supported atm
|
|
|
|
|
|
if(!TQTextDrag::canDecode(e))
|
|
|
return;
|
|
|
|
|
|
KPopupMenu *menu = new KPopupMenu( this );
|
|
|
menu->insertItem( i18n("&Move Here"), DRAG_MOVE, 0 );
|
|
|
menu->insertItem( SmallIcon("editcopy"), i18n("&Copy Here"), DRAG_COPY, 1 );
|
|
|
menu->insertSeparator();
|
|
|
menu->insertItem( SmallIcon("cancel"), i18n("C&ancel"), DRAG_CANCEL, 3 );
|
|
|
int id = menu->exec(TQCursor::pos(), 0);
|
|
|
|
|
|
switch(id) {
|
|
|
case DRAG_COPY:
|
|
|
copySelectedItems(parent, after);
|
|
|
break;
|
|
|
case DRAG_MOVE:
|
|
|
moveSelectedItems(parent, after);
|
|
|
break;
|
|
|
case DRAG_CANCEL: // cancelled by menuitem
|
|
|
break;
|
|
|
case -1: // cancelled by Esc
|
|
|
break;
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
m_draggedItem = 0;
|
|
|
}
|
|
|
|
|
|
void StructTreeView::startDrag()
|
|
|
{
|
|
|
// This a dummy drag object. Decode is made by the objects selected on the tree.
|
|
|
TQTextDrag* drag = new TQTextDrag(this);
|
|
|
// m_thisWidget = drag->source();
|
|
|
drag->setSubtype("x-struct_tree_tag_item");
|
|
|
drag->setPixmap(SmallIcon("node"));
|
|
|
drag->dragMove();
|
|
|
|
|
|
}
|
|
|
|
|
|
void StructTreeView::contentsMousePressEvent(TQMouseEvent* e)
|
|
|
{
|
|
|
if(e->button() == Qt::LeftButton)
|
|
|
{
|
|
|
TQPoint p = contentsToViewport(e->pos());
|
|
|
m_draggedItem = itemAt(p);
|
|
|
m_marker = m_draggedItem;
|
|
|
}
|
|
|
KListView::contentsMousePressEvent(e);
|
|
|
}
|
|
|
|
|
|
void StructTreeView::copySelectedItems(TQListViewItem* parent, TQListViewItem* after)
|
|
|
{
|
|
|
StructTreeTag* parent_item = dynamic_cast<StructTreeTag*> (parent);
|
|
|
StructTreeTag* after_item = dynamic_cast<StructTreeTag*> (after);
|
|
|
if(!parent_item/* || !after_item*/) // can happen if the element is inserted as the first child
|
|
|
return;
|
|
|
|
|
|
TQPtrList<TQListViewItem> selected_items = selectedItems(false);
|
|
|
TQListViewItem* first_item = selected_items.getFirst();
|
|
|
TQListViewItem* last_item = selected_items.getLast();
|
|
|
|
|
|
Node* start_node = (dynamic_cast<StructTreeTag*> (first_item))->node;
|
|
|
Node* end_node = (dynamic_cast<StructTreeTag*> (last_item))->node;
|
|
|
assert(start_node && end_node);
|
|
|
|
|
|
Node* start_node_subtree = 0;
|
|
|
if(start_node == end_node)
|
|
|
start_node_subtree = kafkaCommon::duplicateNodeSubtree(start_node, true);
|
|
|
else
|
|
|
start_node_subtree = kafkaCommon::getNodeSubtree(start_node, 0, end_node, end_node->tag->tagStr().length());
|
|
|
|
|
|
Node* parent_node = parent_item->node;
|
|
|
if(!parent_node)
|
|
|
return;
|
|
|
Node* next_node = 0;
|
|
|
if(after_item)
|
|
|
next_node = after_item->node->SNext();
|
|
|
else
|
|
|
next_node = parent_node->firstChild();
|
|
|
|
|
|
NodeSelection cursor_holder;
|
|
|
NodeModifsSet *modifs = new NodeModifsSet();
|
|
|
|
|
|
kafkaCommon::DTDInsertNodeSubtree(start_node_subtree, parent_node, next_node, cursor_holder, modifs);
|
|
|
|
|
|
write->docUndoRedo->addNewModifsSet(modifs, undoRedo::NodeTreeModif, 0, false);
|
|
|
}
|
|
|
|
|
|
void StructTreeView::moveSelectedItems(TQListViewItem* parent, TQListViewItem* after)
|
|
|
{
|
|
|
StructTreeTag* parent_item = dynamic_cast<StructTreeTag*> (parent);
|
|
|
StructTreeTag* after_item = dynamic_cast<StructTreeTag*> (after);
|
|
|
if(!parent_item || !after_item)
|
|
|
return;
|
|
|
|
|
|
TQPtrList<TQListViewItem> selected_items = selectedItems(false);
|
|
|
TQListViewItem* first_item = selected_items.getFirst();
|
|
|
TQListViewItem* last_item = selected_items.getLast();
|
|
|
|
|
|
Node* start_node = (dynamic_cast<StructTreeTag*> (first_item))->node;
|
|
|
Node* end_node = (dynamic_cast<StructTreeTag*> (last_item))->node;
|
|
|
assert(start_node && end_node);
|
|
|
|
|
|
Node* cursor_node = 0;
|
|
|
long cursor_offset = 0;
|
|
|
NodeModifsSet *modifs = new NodeModifsSet();
|
|
|
|
|
|
Node* start_node_subtree = 0;
|
|
|
if(start_node == end_node)
|
|
|
start_node_subtree = kafkaCommon::extractNodeSubtreeAux(start_node, end_node, modifs);
|
|
|
else
|
|
|
start_node_subtree = kafkaCommon::DTDExtractNodeSubtree(start_node, 0, end_node, end_node->tag->tagStr().length(),
|
|
|
&cursor_node, cursor_offset, modifs);
|
|
|
|
|
|
Node* parent_node = parent_item->node;
|
|
|
if(!parent_node)
|
|
|
return;
|
|
|
Node* next_node = after_item->node->SNext();
|
|
|
|
|
|
NodeSelection cursor_holder(cursor_node, cursor_offset);
|
|
|
|
|
|
kafkaCommon::DTDInsertNodeSubtree(start_node_subtree, parent_node, next_node, cursor_holder, modifs);
|
|
|
|
|
|
write->docUndoRedo->addNewModifsSet(modifs, undoRedo::NodeTreeModif, &cursor_holder, false);
|
|
|
}
|
|
|
|
|
|
/** The treeview DTD has changed to id. */
|
|
|
void StructTreeView::slotDTDChanged(int id)
|
|
|
{
|
|
|
TQString text = dtdMenu->text(id);
|
|
|
if (dtdMenu->indexOf(id) > 0)
|
|
|
{
|
|
|
TQString dtdName = DTDs::ref()->getDTDNameFromNickName(text);
|
|
|
emit showGroupsForDTEP(dtdName, !dtdMenu->isItemChecked(id));
|
|
|
} else
|
|
|
emit showGroupsForDTEP("clear", true);
|
|
|
}
|
|
|
|
|
|
void StructTreeView::setParsingDTDs(const TQStringList &parsingDTDList)
|
|
|
{
|
|
|
m_parsingDTDList.clear();
|
|
|
for (uint i = 0; i < dtdList.count(); i++)
|
|
|
{
|
|
|
dtdMenu->setItemChecked(i, false);
|
|
|
}
|
|
|
TQString dtdNickName;
|
|
|
for (TQStringList::ConstIterator it = parsingDTDList.constBegin(); it != parsingDTDList.constEnd(); ++it)
|
|
|
{
|
|
|
dtdNickName = DTDs::ref()->getDTDNickNameFromName(*it);
|
|
|
for (uint i = 0; i < dtdList.count(); i++)
|
|
|
{
|
|
|
if (dtdList[i] == dtdNickName)
|
|
|
dtdMenu->setItemChecked(i, true);
|
|
|
}
|
|
|
m_parsingDTDList.append(DTDs::ref()->find(*it));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void StructTreeView::slotOpenFile()
|
|
|
{
|
|
|
StructTreeTag *item = dynamic_cast<StructTreeTag*>(currentItem());
|
|
|
if (!m_dirty && item->node)
|
|
|
{
|
|
|
TQString text = item->groupTag->name;
|
|
|
text.remove(item->fileNameRx);
|
|
|
KURL baseUrl = QExtFileInfo::path(write->url());
|
|
|
KURL url = baseUrl;
|
|
|
QuantaCommon::setUrl(url, text.stripWhiteSpace());
|
|
|
url = QExtFileInfo::toAbsolute(url, baseUrl);
|
|
|
if (QExtFileInfo::exists(url, true, this))
|
|
|
{
|
|
|
if (QuantaCommon::checkMimeGroup(url, "text" ))
|
|
|
{
|
|
|
emit openFile(url);
|
|
|
}
|
|
|
else if (QuantaCommon::checkMimeGroup(url," image" ))
|
|
|
{
|
|
|
emit openImage(url);
|
|
|
}
|
|
|
} else
|
|
|
KMessageBox::error(this, i18n("<qt>The file <b>%1</b> does not exist or is not a recognized mime type.</qt>").tqarg(url.prettyURL(0, KURL::StripFileProtocol)));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void StructTreeView::slotNodeTreeChanged()
|
|
|
{
|
|
|
m_dirty = true;
|
|
|
}
|
|
|
|
|
|
void StructTreeView::showMessage(const TQString& message)
|
|
|
{
|
|
|
emit showProblemMessage(message);
|
|
|
}
|
|
|
|
|
|
void StructTreeView::slotMouseClickedVPL(int /*button*/, TQListViewItem* item, const TQPoint&, int)
|
|
|
{
|
|
|
ViewManager::ref()->activeView()->setFocus();
|
|
|
|
|
|
TQPtrList<TQListViewItem> selected_items = selectedItems(true);
|
|
|
if(selected_items.count() == 1)
|
|
|
{
|
|
|
StructTreeTag* tag_item = dynamic_cast<StructTreeTag*> (item);
|
|
|
if(!tag_item)
|
|
|
return;
|
|
|
Node* node = tag_item->node;
|
|
|
if(!node)
|
|
|
return;
|
|
|
if(node->tag->type == Tag::Text || node->tag->type == Tag::Empty)
|
|
|
{
|
|
|
KafkaDocument::ref()->setCursor(node, 0);
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
Node* start_node = (dynamic_cast<StructTreeTag*> (selected_items.getFirst()))->node;
|
|
|
Node* end_node = (dynamic_cast<StructTreeTag*> (selected_items.getLast()))->node;
|
|
|
|
|
|
NodeSelectionInd selection(start_node, 0, end_node, 1/*end_node->tag->tagStr().length()*/);
|
|
|
KafkaDocument::ref()->setCursorAndSelection(&selection);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void StructTreeView::slotRemoveTags()
|
|
|
{
|
|
|
TQPtrList<TQListViewItem> selected_items = selectedItems(true);
|
|
|
|
|
|
Node* start_node = (dynamic_cast<StructTreeTag*> (selected_items.getFirst()))->node;
|
|
|
Node* end_node = start_node;
|
|
|
if(selected_items.count() > 1)
|
|
|
end_node = (dynamic_cast<StructTreeTag*> (selected_items.getLast()))->node;
|
|
|
|
|
|
kafkaCommon::coutTree(start_node, 3);
|
|
|
|
|
|
Node* cursor_node = 0;
|
|
|
long cursor_offset = 0;
|
|
|
|
|
|
NodeModifsSet *modifs = new NodeModifsSet();
|
|
|
kafkaCommon::DTDExtractNodeSubtree(start_node, 0, end_node, end_node->tag->tagStr().length(), &cursor_node, cursor_offset, modifs);
|
|
|
|
|
|
NodeSelection* selection = new NodeSelection(cursor_node, cursor_offset);
|
|
|
|
|
|
write->docUndoRedo->addNewModifsSet(modifs, undoRedo::NodeTreeModif, selection, false);
|
|
|
}
|
|
|
|