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.
tdevelop/parts/classview/classtreebase.cpp

638 lines
18 KiB

/***************************************************************************
* Copyright (C) 1999 by Jonas Nordin *
* jonas.nordin@syncom.se *
* Copyright (C) 2000-2001 by Bernd Gehrmann *
* bernd@kdevelop.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. *
* *
***************************************************************************/
#include "classtreebase.h"
#include <tqtooltip.h>
#include <tqheader.h>
#include <tqregexp.h>
#include <kdebug.h>
#include <kconfig.h>
#include <kpopupmenu.h>
#include <klocale.h>
#include <kiconloader.h>
#include "kdevcore.h"
#include "kdevlanguagesupport.h"
#include "kdevmainwindow.h"
#include "kdevpartcontroller.h"
#include "classstore.h"
#include "classviewpart.h"
#include "classtooldlg.h"
KPopupMenu *ClassTreeItem::createPopup()
{
if (!m_item || m_item->itemType() == PIT_SCOPE)
return 0;
KDevLanguageSupport::Features features = classTree()->m_part->languageSupport()->features();
KPopupMenu *popup = new KPopupMenu();
if (features & KDevLanguageSupport::Declarations)
popup->insertItem( i18n("Go to Declaration"), classTree(), TQT_SLOT(slotGotoDeclaration()) );
if (m_item->itemType() == PIT_METHOD)
popup->insertItem( i18n("Go to Definition"), classTree(), TQT_SLOT(slotGotoImplementation()) );
TQString title;
switch(m_item->itemType()) {
case PIT_CLASS:
{
title = i18n("Class");
bool hasAddMethod = features & KDevLanguageSupport::AddMethod;
bool hasAddAttribute = features & KDevLanguageSupport::AddAttribute;
if (hasAddMethod)
popup->insertItem( i18n("Add Method..."), classTree(), TQT_SLOT(slotAddMethod()));
if (hasAddAttribute)
popup->insertItem( i18n("Add Attribute..."), classTree(), TQT_SLOT(slotAddAttribute()));
popup->insertSeparator();
popup->insertItem( i18n("Parent Classes..."), classTree(), TQT_SLOT(slotClassBaseClasses()));
popup->insertItem( i18n("Child Classes..."), classTree(), TQT_SLOT(slotClassDerivedClasses()));
popup->insertItem( i18n("Class Tool..."), classTree(), TQT_SLOT(slotClassTool()));
}
break;
case PIT_STRUCT:
title = i18n("Struct");
break;
case PIT_ATTRIBUTE:
if (m_item->isGlobal())
title = i18n("Variable");
else
title = i18n("Attribute");
break;
case PIT_METHOD:
if (static_cast<ParsedMethod*>(m_item)->isSlot())
title = i18n("Slot");
else if (static_cast<ParsedMethod*>(m_item)->isSignal())
title = i18n("Signal");
else if (m_item->isGlobal())
title = i18n("Function");
else
title = i18n("Method");
break;
default:
;
}
popup->insertSeparator();
popup->insertTitle(title, -1, 0);
return popup;
}
TQString ClassTreeItem::scopedText() const
{
if (m_item)
return m_item->path();
return TQString();
}
void ClassTreeItem::getDeclaration(TQString *toFile, int *toLine)
{
if (m_item) {
*toFile = m_item->declaredInFile();
*toLine = m_item->declaredOnLine();
}
}
void ClassTreeItem::getImplementation(TQString *toFile, int *toLine)
{
if (m_item) {
*toFile = m_item->definedInFile();
*toLine = m_item->definedOnLine();
}
}
TQString ClassTreeItem::text( int ) const
{
if (m_item)
return m_item->asString();
return TQString();
}
TQString ClassTreeItem::tipText() const
{
// Purposefully avoid virtual dispatch here
return ClassTreeItem::text(0);
}
void ClassTreeOrganizerItem::init()
{
setExpandable(true);
setPixmap(0, SmallIcon("folder"));
}
void ClassTreeScopeItem::init()
{
setExpandable(true);
setPixmap(0, UserIcon("CVnamespace", KIcon::DefaultState, ClassViewFactory::instance()));
}
TQString ClassTreeScopeItem::text( int col ) const
{
if (!m_item)
return TQString();
if (m_item->name().isEmpty())
return i18n("Global");
return ClassTreeItem::text( col );
}
void ClassTreeScopeItem::setOpen(bool o)
{
if ( !m_item)
return;
kdDebug(9003) << (o? "Open scope item" : "Close scope item") << endl;
if (o && childCount() == 0) {
ParsedScopeContainer *pScope = static_cast<ParsedScopeContainer*>(m_item);
ClassTreeItem *lastItem = 0;
// Ok, this is a hack...
KDevLanguageSupport::Features features = classTree()->m_part->languageSupport()->features();
// Add namespaces
TQValueList<ParsedScopeContainer*> scopeList = pScope->getSortedScopeList();
TQValueList<ParsedScopeContainer*>::ConstIterator it;
for (it = scopeList.begin(); it != scopeList.end(); ++it)
lastItem = new ClassTreeScopeItem(this, lastItem, *it);
if (features & KDevLanguageSupport::Classes) {
// Add classes
TQValueList<ParsedClass*> classList = pScope->getSortedClassList();
TQValueList<ParsedClass*>::ConstIterator it;
for (it = classList.begin(); it != classList.end(); ++it)
lastItem = new ClassTreeClassItem(this, lastItem, *it);
}
if (features & KDevLanguageSupport::Structs) {
// Add structs
TQValueList<ParsedClass*> structList = pScope->getSortedStructList();
TQValueList<ParsedClass*>::ConstIterator it;
for (it = structList.begin(); it != structList.end(); ++it)
lastItem = new ClassTreeClassItem(this, lastItem, *it, true);
}
if (features & KDevLanguageSupport::Functions) {
// Add functions
TQValueList<ParsedMethod*> methodList = pScope->getSortedMethodList();
TQValueList<ParsedMethod*>::ConstIterator it;
for (it = methodList.begin(); it != methodList.end(); ++it)
lastItem = new ClassTreeMethodItem(this, lastItem, *it);
}
if (features & KDevLanguageSupport::Variables) {
// Add attributes
TQValueList<ParsedAttribute*> attrList = pScope->getSortedAttributeList();
TQValueList<ParsedAttribute*>::ConstIterator it;
for (it = attrList.begin(); it != attrList.end(); ++it)
lastItem = new ClassTreeAttrItem(this, lastItem, *it);
}
}
ClassTreeItem::setOpen(o);
}
void ClassTreeClassItem::init()
{
setExpandable(true);
setPixmap(0, UserIcon(m_isStruct ? "CVstruct" : "CVclass", KIcon::DefaultState, ClassViewFactory::instance()));
}
void ClassTreeClassItem::setOpen(bool o)
{
if ( !m_item )
return;
kdDebug(9003) << (o? "Open class item" : "Close class item") << endl;
if (o && childCount() == 0) {
ParsedClass *pClass = static_cast<ParsedClass*>(m_item);
ClassTreeItem *lastItem = 0;
// Add nested classes
TQValueList<ParsedClass*> classList = pClass->getSortedClassList();
TQValueList<ParsedClass*>::ConstIterator classIt;
for (classIt = classList.begin(); classIt != classList.end(); ++classIt)
lastItem = new ClassTreeClassItem(this, lastItem, *classIt);
// Add nested structs
TQValueList<ParsedClass*> structList = pClass->getSortedStructList();
TQValueList<ParsedClass*>::ConstIterator structIt;
for (structIt = structList.begin(); structIt != structList.end(); ++structIt)
lastItem = new ClassTreeClassItem(this, lastItem, *structIt, true);
// Add methods
TQValueList<ParsedMethod*> methodList = pClass->getSortedMethodList();
TQValueList<ParsedMethod*>::ConstIterator methodIt;
for (methodIt = methodList.begin(); methodIt != methodList.end(); ++methodIt)
lastItem = new ClassTreeMethodItem(this, lastItem, *methodIt);
// Add slots
TQValueList<ParsedMethod*> slotList = pClass->getSortedSlotList();
TQValueList<ParsedMethod*>::ConstIterator slotIt;
for (slotIt = slotList.begin(); slotIt != slotList.end(); ++slotIt)
lastItem = new ClassTreeMethodItem(this, lastItem, *slotIt);
// Add signals
TQValueList<ParsedMethod*> signalList = pClass->getSortedSignalList();
TQValueList<ParsedMethod*>::ConstIterator signalIt;
for (signalIt = signalList.begin(); signalIt != signalList.end(); ++signalIt)
lastItem = new ClassTreeMethodItem(this, lastItem, *signalIt);
// Add attributes
TQValueList<ParsedAttribute*> attrList = pClass->getSortedAttributeList();
TQValueList<ParsedAttribute*>::ConstIterator attrIt;
for (attrIt = attrList.begin(); attrIt != attrList.end(); ++attrIt)
lastItem = new ClassTreeAttrItem(this, lastItem, *attrIt);
}
ClassTreeItem::setOpen(o);
}
ClassTreeMethodItem::ClassTreeMethodItem(ClassTreeItem *parent, ClassTreeItem *lastSibling,
ParsedMethod *parsedMethod)
: ClassTreeItem(parent, lastSibling, parsedMethod)
{
TQString icon;
if ( !parsedMethod )
return;
if (parsedMethod->isSignal())
icon = "CVpublic_signal";
else if (parsedMethod->isSlot()) {
if (parsedMethod->isPublic())
icon = "CVpublic_slot";
else if (parsedMethod->isProtected())
icon = "CVprotected_slot";
else
icon = "CVprivate_slot";
}
else if (parsedMethod->isPublic())
icon = "CVpublic_meth";
else if (parsedMethod->isProtected())
icon = "CVprotected_meth";
else if (parsedMethod->isPrivate())
icon = "CVprivate_meth";
else if (parsedMethod->isPackage())
icon = "CVpackage_meth";
else
icon = "CVglobal_meth";
setPixmap(0, UserIcon(icon, KIcon::DefaultState, ClassViewFactory::instance()));
}
TQString ClassTreeMethodItem::text( int ) const
{
TQString str;
if ( !m_item )
return TQString();
ParsedMethod* method = static_cast<ParsedMethod*>(m_item);
str = method->name();
if( method->arguments.count() > 0 ) {
str += "( ";
for ( ParsedArgument *arg = method->arguments.first(); arg != NULL; arg = method->arguments.next() ) {
if ( arg != method->arguments.getFirst() )
str += ", ";
str += arg->toString();
}
str += " )";
} else {
str += "()";
}
if( method->isConst() )
str += " const";
return str;
}
ClassTreeAttrItem::ClassTreeAttrItem(ClassTreeItem *parent, ClassTreeItem *lastSibling,
ParsedAttribute *parsedAttr)
: ClassTreeItem(parent, lastSibling, parsedAttr)
{
TQString icon;
if ( !parsedAttr )
return;
if (parsedAttr->isPublic())
icon = "CVpublic_var";
else if (parsedAttr->isProtected())
icon = "CVprotected_var";
else if (parsedAttr->isPrivate())
icon = "CVprivate_var";
else if (parsedAttr->isPackage())
icon = "CVpackage_var";
else
icon = "CVglobal_var";
setPixmap(0, UserIcon(icon, KIcon::DefaultState, ClassViewFactory::instance()));
}
TQString ClassTreeAttrItem::text( int ) const
{
if ( !m_item )
return TQString();
return m_item->name();
}
ClassTreeScriptItem::ClassTreeScriptItem(ClassTreeItem *parent, ClassTreeItem *lastSibling,
ParsedScript *parsedScript)
: ClassTreeItem(parent, lastSibling, parsedScript)
{
TQString icon;
if ( !parsedScript )
return;
setExpandable(true);
//need a icon for scripts
icon = "CVpublic_var";
setPixmap(0, UserIcon(icon, KIcon::DefaultState, ClassViewFactory::instance()));
}
TQString ClassTreeScriptItem::text( int ) const
{
if ( !m_item )
return TQString();
return m_item->name();
}
void ClassTreeScriptItem::setOpen(bool o)
{
if ( !m_item )
return;
kdDebug(9003) << (o? "Open script item" : "Close script item") << endl;
if (o && childCount() == 0) {
ParsedScript *pClass = static_cast<ParsedScript*>(m_item);
ClassTreeItem *lastItem = 0;
// Add methods
TQValueList<ParsedMethod*> methodList = pClass->getSortedMethodList();
TQValueList<ParsedMethod*>::ConstIterator methodIt;
for (methodIt = methodList.begin(); methodIt != methodList.end(); ++methodIt)
lastItem = new ClassTreeMethodItem(this, lastItem, *methodIt);
// Add attributes
TQValueList<ParsedAttribute*> attrList = pClass->getSortedAttributeList();
TQValueList<ParsedAttribute*>::ConstIterator attrIt;
for (attrIt = attrList.begin(); attrIt != attrList.end(); ++attrIt)
lastItem = new ClassTreeAttrItem(this, lastItem, *attrIt);
}
ClassTreeItem::setOpen(o);
}
class ClassToolTip : public TQToolTip
{
public:
ClassToolTip( TQWidget *parent )
: TQToolTip(parent)
{}
protected:
void maybeTip(const TQPoint &p);
};
void ClassToolTip::maybeTip(const TQPoint &p)
{
ClassTreeBase *ctw = static_cast<ClassTreeBase*>(parentWidget());
TQListViewItem *item = ctw->itemAt(p);
TQRect r = ctw->itemRect(item);
if (item && r.isValid()) {
ClassTreeItem *ctitem = static_cast<ClassTreeItem*>(item);
TQString str = ctitem->tipText();
if (!str.isEmpty())
tip(r, str);
}
}
ClassTreeBase::ClassTreeBase(ClassViewPart *part, TQWidget *parent, const char *name)
: KListView(parent, name)
{
setFocusPolicy(ClickFocus);
setRootIsDecorated(true);
setResizeMode(TQListView::LastColumn);
setSorting(-1);
header()->hide();
addColumn(TQString());
(void) new ClassToolTip(this);
connect( this, TQT_SIGNAL(executed(TQListViewItem*)),
this, TQT_SLOT(slotItemExecuted(TQListViewItem*)) );
connect( this, TQT_SIGNAL(mouseButtonPressed(int, TQListViewItem*, const TQPoint&, int)),
this, TQT_SLOT(slotItemPressed(int, TQListViewItem*)) );
connect( this, TQT_SIGNAL(returnPressed( TQListViewItem*)),
TQT_SLOT( slotItemExecuted(TQListViewItem*)) );
connect( this, TQT_SIGNAL(contextMenuRequested(TQListViewItem*, const TQPoint&, int)),
this, TQT_SLOT(slotContextMenuRequested(TQListViewItem*, const TQPoint&)) );
m_part = part;
}
ClassTreeBase::~ClassTreeBase()
{}
ClassTreeBase::TreeState ClassTreeBase::treeState() const
{
TreeState state;
ClassTreeBase *that = const_cast<ClassTreeBase*>(this);
TQListViewItemIterator it(that);
for (; it.current(); ++it)
if (it.current()->isOpen()) {
TQStringList path;
TQListViewItem *item = it.current();
while (item) {
path.prepend(item->text(0));
item = item->parent();
}
state.append(path);
}
return state;
}
void ClassTreeBase::setTreeState(TreeState state)
{
TreeStateIterator tsit;
for (tsit = state.begin(); tsit != state.end(); ++tsit) {
TQListViewItemIterator it(this);
for (; it.current(); ++it) {
TQStringList path;
TQListViewItem *item = it.current();
while (item) {
path.prepend(item->text(0));
item = item->parent();
}
if (*tsit == path) {
it.current()->setOpen(true);
break;
}
}
}
}
void ClassTreeBase::slotItemExecuted( TQListViewItem* item )
{
if (!item)
return;
// toggle open state for parents
if (item->childCount() > 0)
setOpen(item, !isOpen(item));
// We assume here that ALL (!) items in the list view
// are ClassTreeItem's
ClassTreeItem *ctitem = static_cast<ClassTreeItem*>(item);
if (ctitem->isOrganizer())
return;
TQString toFile;
int toLine = -1;
if (dynamic_cast<ClassTreeClassItem*>(item)) {
ctitem->getDeclaration(&toFile, &toLine);
}
else {
ctitem->getImplementation(&toFile, &toLine);
}
m_part->partController()->editDocument(toFile, toLine);
m_part->mainWindow()->lowerView(this);
}
void ClassTreeBase::slotItemPressed(int button, TQListViewItem *item)
{
if (!item)
return;
// We assume here that ALL (!) items in the list view
// are ClassTreeItem's
ClassTreeItem *ctitem = static_cast<ClassTreeItem*>(item);
if (ctitem->isOrganizer())
return;
if (button == MidButton) {
TQString toFile;
int toLine = -1;
ctitem->getDeclaration(&toFile, &toLine);
m_part->partController()->editDocument(toFile, toLine);
m_part->mainWindow()->lowerView(this);
}
}
void ClassTreeBase::slotContextMenuRequested(TQListViewItem *item, const TQPoint &p)
{
contextItem = static_cast<ClassTreeItem*>(item);
KPopupMenu *popup = createPopup();
popup->exec(p);
delete popup;
}
void ClassTreeBase::slotGotoDeclaration()
{
TQString toFile;
int toLine = -1;
contextItem->getDeclaration(&toFile, &toLine);
m_part->partController()->editDocument(toFile, toLine);
}
void ClassTreeBase::slotGotoImplementation()
{
TQString toFile;
int toLine = -1;
contextItem->getImplementation(&toFile, &toLine);
m_part->partController()->editDocument(toFile, toLine);
}
void ClassTreeBase::slotAddMethod()
{
if (m_part->languageSupport())
m_part->languageSupport()->addMethod(contextItem->scopedText());
}
void ClassTreeBase::slotAddAttribute()
{
if (m_part->languageSupport())
m_part->languageSupport()->addAttribute(contextItem->scopedText());
}
void ClassTreeBase::slotClassBaseClasses()
{
ClassToolDialog *dlg = new ClassToolDialog(m_part);
dlg->setClassName(contextItem->scopedText());
dlg->viewParents();
}
void ClassTreeBase::slotClassDerivedClasses()
{
ClassToolDialog *dlg = new ClassToolDialog(m_part);
dlg->setClassName(contextItem->scopedText());
dlg->viewChildren();
}
void ClassTreeBase::slotClassTool()
{
ClassToolDialog *dlg = new ClassToolDialog(m_part);
dlg->setClassName(contextItem->scopedText());
dlg->viewNone();
}
#include "classtreebase.moc"