summaryrefslogtreecommitdiffstats
path: root/quanta/treeviews/structtreeview.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'quanta/treeviews/structtreeview.cpp')
-rw-r--r--quanta/treeviews/structtreeview.cpp1071
1 files changed, 1071 insertions, 0 deletions
diff --git a/quanta/treeviews/structtreeview.cpp b/quanta/treeviews/structtreeview.cpp
new file mode 100644
index 00000000..f6f55b40
--- /dev/null
+++ b/quanta/treeviews/structtreeview.cpp
@@ -0,0 +1,1071 @@
+/***************************************************************************
+ 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 <qpixmap.h>
+#include <qheader.h>
+#include <qregexp.h>
+#include <qdatetime.h>
+#include <qdragobject.h>
+#include <qcursor.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(QWidget *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(QWidget::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, SIGNAL(activated(int)), this, SLOT(slotDTDChanged(int)));
+
+ connect(this, SIGNAL(dropped(QDropEvent*, QListViewItem*, QListViewItem*)),
+ SLOT(slotDropped(QDropEvent*, QListViewItem*, QListViewItem*)));
+
+ emptyAreaMenu = new KPopupMenu(this);
+ emptyAreaMenu->insertItem(i18n("Show Groups For"), dtdMenu);
+ emptyAreaMenu->insertItem(SmallIcon("reload"), i18n("&Reparse"), this, SLOT(slotReparseMenuItem()));
+
+ popupMenu = new KPopupMenu(this);
+
+ popupMenu -> insertItem( i18n("Show Groups For"), dtdMenu);
+ popupMenu -> insertSeparator();
+ popupMenu -> insertItem( i18n("Select Tag Area"), this ,SLOT(slotSelectTag()));
+ popupMenu -> insertItem( i18n("Go to End of Tag"), this ,SLOT(slotGotoClosingTag()));
+ openFileMenuId = popupMenu -> insertItem( i18n("Open File"), this ,SLOT(slotOpenFile()));
+ popupMenu -> insertSeparator();
+ popupMenu -> insertItem( i18n("Open Subtrees"), this ,SLOT(slotOpenSubTree()));
+ popupMenu -> insertItem( i18n("Close Subtrees"),this ,SLOT(slotCloseSubTree()));
+ popupMenu -> insertSeparator();
+#if 0
+ popupMenu -> insertItem( i18n("Remove"),this ,SLOT(slotRemoveTags()));
+ popupMenu -> insertSeparator();
+#endif
+ popupMenu -> insertItem( SmallIcon("reload"), i18n("&Reparse"), this ,SLOT(slotReparseMenuItem()));
+ followCursorId = popupMenu -> insertItem( i18n("Follow Cursor"), this ,SLOT(changeFollowCursor()));
+
+ popupMenu -> setItemChecked ( followCursorId, followCursor() );
+
+
+ connect( this, SIGNAL(mouseButtonPressed(int, QListViewItem*, const QPoint&, int)),
+ this, SLOT (slotMouseClicked(int, QListViewItem*, const QPoint&, int)));
+
+ connect( this, SIGNAL(doubleClicked(QListViewItem *)), SLOT(slotDoubleClicked(QListViewItem *)));
+
+ connect(this, SIGNAL(expanded(QListViewItem *)), SLOT(slotExpanded(QListViewItem *)));
+ connect(this, SIGNAL(collapsed(QListViewItem *)), SLOT(slotCollapsed(QListViewItem *)));
+
+ write = 0L;
+ timer = new QTime();
+ 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;
+ QString title;
+ QString tagStr;
+ QString 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
+ {
+ QMap<QString, 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;
+ QMap<QString, QListViewItem*> lastItemInGroup;
+ QMap<QString, QListViewItem*> 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 (QValueList<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]];
+ QListViewItem* insertAfter = 0L;
+ QListViewItem* 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
+ QListViewItem *insertUnder;
+ QListViewItem *insertAfter;
+ QListViewItem *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];
+ QString 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;
+}
+
+/** repaint 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
+ {
+ QMap<QString, 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( QListViewItem *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, QListViewItem *item, const QPoint& point, int dummy)
+{
+ if (item)
+ {
+ config->setGroup("Parser options");
+
+ QString handleMBM = config->readEntry("MBM", i18n("Select Tag Area"));
+ QString handleLBM = config->readEntry("LBM", i18n("Find tag"));
+ QString 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() & Qt::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( QListViewItem *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()
+{
+ QListViewItem *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;
+ QListViewItem *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( QListViewItem *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()
+{
+ QListViewItem *item = currentItem();
+ if (item)
+ {
+ item->setOpen( true );
+ setOpenSubTree( item->firstChild(), true );
+ }
+}
+
+
+/** Recursively close the tree and all its subtrees */
+void StructTreeView::slotCloseSubTree()
+{
+ QListViewItem *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(QListViewItem *item)
+{
+ StructTreeTag *it = dynamic_cast<StructTreeTag*>(item);
+ if (!m_dirty && it && it->node)
+ it->node->opened = true;
+}
+
+/** No descriptions */
+void StructTreeView::slotCollapsed(QListViewItem *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(QShowEvent* /*ev*/)
+{
+ slotReparseMenuItem();
+}
+
+/** Do a reparse before showing. */
+void StructTreeView::hideEvent(QHideEvent* /*ev*/)
+{
+ emit clearProblemOutput();
+}
+
+enum {
+ DRAG_COPY = 0,
+ DRAG_MOVE = 1,
+ DRAG_CANCEL = 2
+};
+
+void StructTreeView::setContiguousSelectedItems()
+{
+ kdDebug(25001) << "setContiguousSelectedItems" << endl;
+
+ QPtrList<QListViewItem> selected_items = selectedItems(false);
+
+ QListViewItem* first = selected_items.getFirst();
+ QListViewItem* last = selected_items.getLast();
+
+ QListViewItemIterator it(first);
+ while(it.current() && it.current() != last)
+ {
+ QListViewItem* item = it.current();
+ if(!item->isSelected())
+ item->setSelected(true);
+
+ ++it;
+ }
+}
+
+bool StructTreeView::acceptDrag(QDropEvent* e) const
+{
+ static int i = 0;
+ kdDebug(25001) << "acceptDrag: " << ++i << endl;
+
+ QPoint p = contentsToViewport(e->pos());
+ QListViewItem* 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(Qt::ForbiddenCursor);
+ else
+ m_thisWidget->setCursor(Qt::ForbiddenCursor);*/
+ kdDebug(25001) << "Princ�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() == (QWidget *)this) || !m_marker)
+ {
+ e->accept(false);
+ last_accept = false;
+/* if(last_accept)
+ m_thisWidget->setCursor(Qt::ForbiddenCursor);
+ else
+ m_thisWidget->setCursor(Qt::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(Qt::ForbiddenCursor);
+ else
+ m_thisWidget->setCursor(Qt::ForbiddenCursor);*/
+ kdDebug(25001) << "PROIBIDO! #2" << endl;
+ return false;
+ }
+ QTag* nodeQTag = QuantaCommon::tagFromDTD(after_node->parent);
+ bool is_child = (nodeQTag && nodeQTag->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(Qt::ForbiddenCursor);
+// else
+// m_thisWidget->setCursor(Qt::ForbiddenCursor);
+
+ return is_child;
+}
+
+void StructTreeView::slotDropped(QDropEvent* e, QListViewItem* parent, QListViewItem* after)
+{
+ if(!e)
+ return;
+ if (e->source() != this)
+ return; // Only internal drags are supported atm
+
+ if(!QTextDrag::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(QCursor::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.
+ QTextDrag* drag = new QTextDrag(this);
+// m_thisWidget = drag->source();
+ drag->setSubtype("x-struct_tree_tag_item");
+ drag->setPixmap(SmallIcon("node"));
+ drag->dragMove();
+
+}
+
+void StructTreeView::contentsMousePressEvent(QMouseEvent* e)
+{
+ if(e->button() == LeftButton)
+ {
+ QPoint p = contentsToViewport(e->pos());
+ m_draggedItem = itemAt(p);
+ m_marker = m_draggedItem;
+ }
+ KListView::contentsMousePressEvent(e);
+}
+
+void StructTreeView::copySelectedItems(QListViewItem* parent, QListViewItem* 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;
+
+ QPtrList<QListViewItem> selected_items = selectedItems(false);
+ QListViewItem* first_item = selected_items.getFirst();
+ QListViewItem* 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(QListViewItem* parent, QListViewItem* after)
+{
+ StructTreeTag* parent_item = dynamic_cast<StructTreeTag*> (parent);
+ StructTreeTag* after_item = dynamic_cast<StructTreeTag*> (after);
+ if(!parent_item || !after_item)
+ return;
+
+ QPtrList<QListViewItem> selected_items = selectedItems(false);
+ QListViewItem* first_item = selected_items.getFirst();
+ QListViewItem* 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)
+{
+ QString text = dtdMenu->text(id);
+ if (dtdMenu->indexOf(id) > 0)
+ {
+ QString dtdName = DTDs::ref()->getDTDNameFromNickName(text);
+ emit showGroupsForDTEP(dtdName, !dtdMenu->isItemChecked(id));
+ } else
+ emit showGroupsForDTEP("clear", true);
+}
+
+void StructTreeView::setParsingDTDs(const QStringList &parsingDTDList)
+{
+ m_parsingDTDList.clear();
+ for (uint i = 0; i < dtdList.count(); i++)
+ {
+ dtdMenu->setItemChecked(i, false);
+ }
+ QString dtdNickName;
+ for (QStringList::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)
+ {
+ QString 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>").arg(url.prettyURL(0, KURL::StripFileProtocol)));
+ }
+}
+
+void StructTreeView::slotNodeTreeChanged()
+{
+ m_dirty = true;
+}
+
+void StructTreeView::showMessage(const QString& message)
+{
+ emit showProblemMessage(message);
+}
+
+void StructTreeView::slotMouseClickedVPL(int /*button*/, QListViewItem* item, const QPoint&, int)
+{
+ ViewManager::ref()->activeView()->setFocus();
+
+ QPtrList<QListViewItem> 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()
+{
+ QPtrList<QListViewItem> 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);
+}
+