/*************************************************************************** * 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 #include #include #include #include #include #include #include #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(), SLOT(slotGotoDeclaration()) ); if (m_item->itemType() == PIT_METHOD) popup->insertItem( i18n("Go to Definition"), classTree(), SLOT(slotGotoImplementation()) ); QString 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(), SLOT(slotAddMethod())); if (hasAddAttribute) popup->insertItem( i18n("Add Attribute..."), classTree(), SLOT(slotAddAttribute())); popup->insertSeparator(); popup->insertItem( i18n("Parent Classes..."), classTree(), SLOT(slotClassBaseClasses())); popup->insertItem( i18n("Child Classes..."), classTree(), SLOT(slotClassDerivedClasses())); popup->insertItem( i18n("Class Tool..."), classTree(), 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(m_item)->isSlot()) title = i18n("Slot"); else if (static_cast(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; } QString ClassTreeItem::scopedText() const { if (m_item) return m_item->path(); return QString::null; } void ClassTreeItem::getDeclaration(QString *toFile, int *toLine) { if (m_item) { *toFile = m_item->declaredInFile(); *toLine = m_item->declaredOnLine(); } } void ClassTreeItem::getImplementation(QString *toFile, int *toLine) { if (m_item) { *toFile = m_item->definedInFile(); *toLine = m_item->definedOnLine(); } } QString ClassTreeItem::text( int ) const { if (m_item) return m_item->asString(); return QString::null; } QString 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())); } QString ClassTreeScopeItem::text( int col ) const { if (!m_item) return QString::null; 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(m_item); ClassTreeItem *lastItem = 0; // Ok, this is a hack... KDevLanguageSupport::Features features = classTree()->m_part->languageSupport()->features(); // Add namespaces QValueList scopeList = pScope->getSortedScopeList(); QValueList::ConstIterator it; for (it = scopeList.begin(); it != scopeList.end(); ++it) lastItem = new ClassTreeScopeItem(this, lastItem, *it); if (features & KDevLanguageSupport::Classes) { // Add classes QValueList classList = pScope->getSortedClassList(); QValueList::ConstIterator it; for (it = classList.begin(); it != classList.end(); ++it) lastItem = new ClassTreeClassItem(this, lastItem, *it); } if (features & KDevLanguageSupport::Structs) { // Add structs QValueList structList = pScope->getSortedStructList(); QValueList::ConstIterator it; for (it = structList.begin(); it != structList.end(); ++it) lastItem = new ClassTreeClassItem(this, lastItem, *it, true); } if (features & KDevLanguageSupport::Functions) { // Add functions QValueList methodList = pScope->getSortedMethodList(); QValueList::ConstIterator it; for (it = methodList.begin(); it != methodList.end(); ++it) lastItem = new ClassTreeMethodItem(this, lastItem, *it); } if (features & KDevLanguageSupport::Variables) { // Add attributes QValueList attrList = pScope->getSortedAttributeList(); QValueList::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(m_item); ClassTreeItem *lastItem = 0; // Add nested classes QValueList classList = pClass->getSortedClassList(); QValueList::ConstIterator classIt; for (classIt = classList.begin(); classIt != classList.end(); ++classIt) lastItem = new ClassTreeClassItem(this, lastItem, *classIt); // Add nested structs QValueList structList = pClass->getSortedStructList(); QValueList::ConstIterator structIt; for (structIt = structList.begin(); structIt != structList.end(); ++structIt) lastItem = new ClassTreeClassItem(this, lastItem, *structIt, true); // Add methods QValueList methodList = pClass->getSortedMethodList(); QValueList::ConstIterator methodIt; for (methodIt = methodList.begin(); methodIt != methodList.end(); ++methodIt) lastItem = new ClassTreeMethodItem(this, lastItem, *methodIt); // Add slots QValueList slotList = pClass->getSortedSlotList(); QValueList::ConstIterator slotIt; for (slotIt = slotList.begin(); slotIt != slotList.end(); ++slotIt) lastItem = new ClassTreeMethodItem(this, lastItem, *slotIt); // Add signals QValueList signalList = pClass->getSortedSignalList(); QValueList::ConstIterator signalIt; for (signalIt = signalList.begin(); signalIt != signalList.end(); ++signalIt) lastItem = new ClassTreeMethodItem(this, lastItem, *signalIt); // Add attributes QValueList attrList = pClass->getSortedAttributeList(); QValueList::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) { QString 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())); } QString ClassTreeMethodItem::text( int ) const { QString str; if ( !m_item ) return QString::null; ParsedMethod* method = static_cast(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) { QString 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())); } QString ClassTreeAttrItem::text( int ) const { if ( !m_item ) return QString::null; return m_item->name(); } ClassTreeScriptItem::ClassTreeScriptItem(ClassTreeItem *parent, ClassTreeItem *lastSibling, ParsedScript *parsedScript) : ClassTreeItem(parent, lastSibling, parsedScript) { QString icon; if ( !parsedScript ) return; setExpandable(true); //need a icon for scripts icon = "CVpublic_var"; setPixmap(0, UserIcon(icon, KIcon::DefaultState, ClassViewFactory::instance())); } QString ClassTreeScriptItem::text( int ) const { if ( !m_item ) return QString::null; 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(m_item); ClassTreeItem *lastItem = 0; // Add methods QValueList methodList = pClass->getSortedMethodList(); QValueList::ConstIterator methodIt; for (methodIt = methodList.begin(); methodIt != methodList.end(); ++methodIt) lastItem = new ClassTreeMethodItem(this, lastItem, *methodIt); // Add attributes QValueList attrList = pClass->getSortedAttributeList(); QValueList::ConstIterator attrIt; for (attrIt = attrList.begin(); attrIt != attrList.end(); ++attrIt) lastItem = new ClassTreeAttrItem(this, lastItem, *attrIt); } ClassTreeItem::setOpen(o); } class ClassToolTip : public QToolTip { public: ClassToolTip( QWidget *parent ) : QToolTip(parent) {} protected: void maybeTip(const QPoint &p); }; void ClassToolTip::maybeTip(const QPoint &p) { ClassTreeBase *ctw = static_cast(parentWidget()); QListViewItem *item = ctw->itemAt(p); QRect r = ctw->itemRect(item); if (item && r.isValid()) { ClassTreeItem *ctitem = static_cast(item); QString str = ctitem->tipText(); if (!str.isEmpty()) tip(r, str); } } ClassTreeBase::ClassTreeBase(ClassViewPart *part, QWidget *parent, const char *name) : KListView(parent, name) { setFocusPolicy(ClickFocus); setRootIsDecorated(true); setResizeMode(QListView::LastColumn); setSorting(-1); header()->hide(); addColumn(QString::null); (void) new ClassToolTip(this); connect( this, SIGNAL(executed(QListViewItem*)), this, SLOT(slotItemExecuted(QListViewItem*)) ); connect( this, SIGNAL(mouseButtonPressed(int, QListViewItem*, const QPoint&, int)), this, SLOT(slotItemPressed(int, QListViewItem*)) ); connect( this, SIGNAL(returnPressed( QListViewItem*)), SLOT( slotItemExecuted(QListViewItem*)) ); connect( this, SIGNAL(contextMenuRequested(QListViewItem*, const QPoint&, int)), this, SLOT(slotContextMenuRequested(QListViewItem*, const QPoint&)) ); m_part = part; } ClassTreeBase::~ClassTreeBase() {} ClassTreeBase::TreeState ClassTreeBase::treeState() const { TreeState state; ClassTreeBase *that = const_cast(this); QListViewItemIterator it(that); for (; it.current(); ++it) if (it.current()->isOpen()) { QStringList path; QListViewItem *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) { QListViewItemIterator it(this); for (; it.current(); ++it) { QStringList path; QListViewItem *item = it.current(); while (item) { path.prepend(item->text(0)); item = item->parent(); } if (*tsit == path) { it.current()->setOpen(true); break; } } } } void ClassTreeBase::slotItemExecuted( QListViewItem* 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(item); if (ctitem->isOrganizer()) return; QString toFile; int toLine = -1; if (dynamic_cast(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, QListViewItem *item) { if (!item) return; // We assume here that ALL (!) items in the list view // are ClassTreeItem's ClassTreeItem *ctitem = static_cast(item); if (ctitem->isOrganizer()) return; if (button == MidButton) { QString toFile; int toLine = -1; ctitem->getDeclaration(&toFile, &toLine); m_part->partController()->editDocument(toFile, toLine); m_part->mainWindow()->lowerView(this); } } void ClassTreeBase::slotContextMenuRequested(QListViewItem *item, const QPoint &p) { contextItem = static_cast(item); KPopupMenu *popup = createPopup(); popup->exec(p); delete popup; } void ClassTreeBase::slotGotoDeclaration() { QString toFile; int toLine = -1; contextItem->getDeclaration(&toFile, &toLine); m_part->partController()->editDocument(toFile, toLine); } void ClassTreeBase::slotGotoImplementation() { QString 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"