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.
638 lines
18 KiB
638 lines
18 KiB
/***************************************************************************
|
|
* Copyright (C) 1999 by Jonas Nordin *
|
|
* jonas.nordin@syncom.se *
|
|
* Copyright (C) 2000-2001 by Bernd Gehrmann *
|
|
* bernd@tdevelop.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->tqitemRect(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"
|