KDevelop API Documentation

classtreebase.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 1999 by Jonas Nordin                                    *
00003  *   jonas.nordin@syncom.se                                                *
00004  *   Copyright (C) 2000-2001 by Bernd Gehrmann                             *
00005  *   bernd@kdevelop.org                                                    *
00006  *                                                                         *
00007  *   This program is free software; you can redistribute it and/or modify  *
00008  *   it under the terms of the GNU General Public License as published by  *
00009  *   the Free Software Foundation; either version 2 of the License, or     *
00010  *   (at your option) any later version.                                   *
00011  *                                                                         *
00012  ***************************************************************************/
00013 
00014 #include "classtreebase.h"
00015 
00016 #include <qtooltip.h>
00017 #include <qheader.h>
00018 #include <qregexp.h>
00019 #include <kdebug.h>
00020 #include <kconfig.h>
00021 #include <kpopupmenu.h>
00022 #include <klocale.h>
00023 #include <kiconloader.h>
00024 
00025 #include "kdevcore.h"
00026 #include "kdevlanguagesupport.h"
00027 #include "kdevmainwindow.h"
00028 #include "kdevpartcontroller.h"
00029 #include "classstore.h"
00030 
00031 #include "classviewpart.h"
00032 #include "classtooldlg.h"
00033 
00034 KPopupMenu *ClassTreeItem::createPopup()
00035 {
00036     if (!m_item || m_item->itemType() == PIT_SCOPE)
00037         return 0;
00038 
00039     KDevLanguageSupport::Features features = classTree()->m_part->languageSupport()->features();
00040 
00041     KPopupMenu *popup = new KPopupMenu();
00042     if (features & KDevLanguageSupport::Declarations)
00043         popup->insertItem( i18n("Go to Declaration"), classTree(), SLOT(slotGotoDeclaration()) );
00044     if (m_item->itemType() == PIT_METHOD)
00045         popup->insertItem( i18n("Go to Definition"), classTree(), SLOT(slotGotoImplementation()) );
00046 
00047     QString title;
00048     switch(m_item->itemType()) {
00049     case PIT_CLASS:
00050         {
00051             title = i18n("Class");
00052             bool hasAddMethod = features & KDevLanguageSupport::AddMethod;
00053             bool hasAddAttribute = features & KDevLanguageSupport::AddAttribute;
00054             if (hasAddMethod)
00055                 popup->insertItem( i18n("Add Method..."), classTree(), SLOT(slotAddMethod()));
00056             if (hasAddAttribute)
00057                 popup->insertItem( i18n("Add Attribute..."), classTree(), SLOT(slotAddAttribute()));
00058             popup->insertSeparator();
00059             popup->insertItem( i18n("Parent Classes..."), classTree(), SLOT(slotClassBaseClasses()));
00060             popup->insertItem( i18n("Child Classes..."), classTree(), SLOT(slotClassDerivedClasses()));
00061             popup->insertItem( i18n("Class Tool..."), classTree(), SLOT(slotClassTool()));
00062             }
00063         break;
00064     case PIT_STRUCT:
00065         title = i18n("Struct");
00066         break;
00067     case PIT_ATTRIBUTE:
00068         if (m_item->isGlobal())
00069             title = i18n("Variable");
00070         else
00071             title = i18n("Attribute");
00072         break;
00073     case PIT_METHOD:
00074         if (static_cast<ParsedMethod*>(m_item)->isSlot())
00075             title = i18n("Slot");
00076         else if (static_cast<ParsedMethod*>(m_item)->isSignal())
00077             title = i18n("Signal");
00078         else if (m_item->isGlobal())
00079             title = i18n("Function");
00080         else
00081             title = i18n("Method");
00082         break;
00083     default:
00084         ;
00085     }
00086     popup->insertSeparator();
00087     popup->insertTitle(title, -1, 0);
00088         
00089     return popup;
00090 }
00091 
00092 
00093 QString ClassTreeItem::scopedText() const
00094 {
00095     if (m_item)
00096         return m_item->path();
00097 
00098     return QString::null;
00099 }
00100 
00101 
00102 void ClassTreeItem::getDeclaration(QString *toFile, int *toLine)
00103 {
00104     if (m_item) {
00105         *toFile = m_item->declaredInFile();
00106         *toLine = m_item->declaredOnLine();
00107     }
00108 }
00109 
00110 
00111 void ClassTreeItem::getImplementation(QString *toFile, int *toLine)
00112 {
00113     if (m_item) {
00114         *toFile = m_item->definedInFile();
00115         *toLine = m_item->definedOnLine();
00116     }
00117 }
00118 
00119 
00120 QString ClassTreeItem::text( int ) const
00121 {
00122     if (m_item)
00123         return m_item->asString();
00124     return QString::null;
00125 }
00126 
00127 
00128 QString ClassTreeItem::tipText() const
00129 {
00130     // Purposefully avoid virtual dispatch here
00131     return ClassTreeItem::text(0);
00132 }
00133 
00134 
00135 void ClassTreeOrganizerItem::init()
00136 {
00137     setExpandable(true);
00138     setPixmap(0, SmallIcon("folder"));
00139 }
00140 
00141 
00142 void ClassTreeScopeItem::init()
00143 {
00144     setExpandable(true);
00145     setPixmap(0, UserIcon("CVnamespace", KIcon::DefaultState, ClassViewFactory::instance()));
00146 }
00147 
00148 
00149 QString ClassTreeScopeItem::text( int col ) const
00150 {
00151     if (!m_item)
00152         return QString::null;
00153     if (m_item->name().isEmpty())
00154         return i18n("Global");
00155     return ClassTreeItem::text( col );
00156 }
00157 
00158 
00159 void ClassTreeScopeItem::setOpen(bool o)
00160 {
00161     if ( !m_item)
00162         return;
00163 
00164     kdDebug(9003) << (o? "Open scope item" : "Close scope item") << endl;
00165     if (o && childCount() == 0) {
00166 
00167         ParsedScopeContainer *pScope = static_cast<ParsedScopeContainer*>(m_item);
00168         ClassTreeItem *lastItem = 0;
00169 
00170         // Ok, this is a hack...
00171         KDevLanguageSupport::Features features = classTree()->m_part->languageSupport()->features();
00172         
00173         // Add namespaces
00174         QValueList<ParsedScopeContainer*> scopeList = pScope->getSortedScopeList();
00175         QValueList<ParsedScopeContainer*>::ConstIterator it;
00176         for (it = scopeList.begin(); it != scopeList.end(); ++it)
00177             lastItem = new ClassTreeScopeItem(this, lastItem, *it);
00178 
00179         if (features & KDevLanguageSupport::Classes) {
00180             // Add classes
00181             QValueList<ParsedClass*> classList = pScope->getSortedClassList();
00182             QValueList<ParsedClass*>::ConstIterator it;
00183             for (it = classList.begin(); it != classList.end(); ++it)
00184                 lastItem = new ClassTreeClassItem(this, lastItem, *it);
00185         }
00186             
00187         if (features & KDevLanguageSupport::Structs) {
00188             // Add structs
00189             QValueList<ParsedClass*> structList = pScope->getSortedStructList();
00190             QValueList<ParsedClass*>::ConstIterator it;
00191             for (it = structList.begin(); it != structList.end(); ++it)
00192                 lastItem = new ClassTreeClassItem(this, lastItem, *it, true);
00193         }
00194 
00195         if (features & KDevLanguageSupport::Functions) {
00196             // Add functions
00197             QValueList<ParsedMethod*> methodList = pScope->getSortedMethodList();
00198             QValueList<ParsedMethod*>::ConstIterator it;
00199             for (it = methodList.begin(); it != methodList.end(); ++it)
00200                 lastItem = new ClassTreeMethodItem(this, lastItem, *it);
00201         }
00202 
00203         if (features & KDevLanguageSupport::Variables) {
00204             // Add attributes
00205             QValueList<ParsedAttribute*> attrList = pScope->getSortedAttributeList();
00206             QValueList<ParsedAttribute*>::ConstIterator it;
00207             for (it = attrList.begin(); it != attrList.end(); ++it)
00208                 lastItem = new ClassTreeAttrItem(this, lastItem, *it);
00209         }
00210 
00211     }
00212 
00213     ClassTreeItem::setOpen(o);
00214 }
00215 
00216 
00217 void ClassTreeClassItem::init()
00218 {
00219     setExpandable(true);
00220     setPixmap(0, UserIcon(m_isStruct ? "CVstruct" : "CVclass", KIcon::DefaultState, ClassViewFactory::instance()));
00221 }
00222 
00223 
00224 void ClassTreeClassItem::setOpen(bool o)
00225 {
00226     if ( !m_item )
00227         return;
00228     kdDebug(9003) << (o? "Open class item" : "Close class item") << endl;
00229     if (o && childCount() == 0) {
00230 
00231         ParsedClass *pClass = static_cast<ParsedClass*>(m_item);
00232         ClassTreeItem *lastItem = 0;
00233 
00234         // Add nested classes
00235         QValueList<ParsedClass*> classList = pClass->getSortedClassList();
00236         QValueList<ParsedClass*>::ConstIterator classIt;
00237         for (classIt = classList.begin(); classIt != classList.end(); ++classIt)
00238             lastItem = new ClassTreeClassItem(this, lastItem, *classIt);
00239 
00240         // Add nested structs
00241         QValueList<ParsedClass*> structList = pClass->getSortedStructList();
00242         QValueList<ParsedClass*>::ConstIterator structIt;
00243         for (structIt = structList.begin(); structIt != structList.end(); ++structIt)
00244             lastItem = new ClassTreeClassItem(this, lastItem, *structIt, true);
00245 
00246         // Add methods
00247         QValueList<ParsedMethod*> methodList = pClass->getSortedMethodList();
00248         QValueList<ParsedMethod*>::ConstIterator methodIt;
00249         for (methodIt = methodList.begin(); methodIt != methodList.end(); ++methodIt)
00250             lastItem = new ClassTreeMethodItem(this, lastItem, *methodIt);
00251 
00252         // Add slots
00253         QValueList<ParsedMethod*> slotList = pClass->getSortedSlotList();
00254         QValueList<ParsedMethod*>::ConstIterator slotIt;
00255         for (slotIt = slotList.begin(); slotIt != slotList.end(); ++slotIt)
00256             lastItem = new ClassTreeMethodItem(this, lastItem, *slotIt);
00257 
00258         // Add signals
00259         QValueList<ParsedMethod*> signalList = pClass->getSortedSignalList();
00260         QValueList<ParsedMethod*>::ConstIterator signalIt;
00261         for (signalIt = signalList.begin(); signalIt != signalList.end(); ++signalIt)
00262             lastItem = new ClassTreeMethodItem(this, lastItem, *signalIt);
00263 
00264         // Add attributes
00265         QValueList<ParsedAttribute*> attrList = pClass->getSortedAttributeList();
00266         QValueList<ParsedAttribute*>::ConstIterator attrIt;
00267         for (attrIt = attrList.begin(); attrIt != attrList.end(); ++attrIt)
00268             lastItem = new ClassTreeAttrItem(this, lastItem, *attrIt);
00269         
00270     }
00271     
00272     ClassTreeItem::setOpen(o);
00273 }
00274 
00275 ClassTreeMethodItem::ClassTreeMethodItem(ClassTreeItem *parent, ClassTreeItem *lastSibling,
00276                                          ParsedMethod *parsedMethod)
00277     : ClassTreeItem(parent, lastSibling, parsedMethod)
00278 {
00279     QString icon;
00280 
00281     if ( !parsedMethod )
00282       return;
00283 
00284     if (parsedMethod->isSignal())
00285         icon = "CVpublic_signal";
00286     else if (parsedMethod->isSlot()) {
00287         if (parsedMethod->isPublic())
00288             icon = "CVpublic_slot";
00289         else if (parsedMethod->isProtected())
00290             icon = "CVprotected_slot";
00291         else
00292             icon = "CVprivate_slot";
00293     }
00294     else if (parsedMethod->isPublic())
00295         icon = "CVpublic_meth";
00296     else if (parsedMethod->isProtected())
00297         icon = "CVprotected_meth";
00298     else if (parsedMethod->isPrivate())
00299         icon = "CVprivate_meth";
00300     else if (parsedMethod->isPackage())
00301         icon = "CVpackage_meth";
00302     else
00303         icon = "CVglobal_meth";
00304 
00305     setPixmap(0, UserIcon(icon, KIcon::DefaultState, ClassViewFactory::instance()));
00306 }
00307 
00308 QString ClassTreeMethodItem::text( int ) const
00309 {
00310     QString str;
00311 
00312     if ( !m_item )
00313         return QString::null;
00314  
00315     ParsedMethod* method = static_cast<ParsedMethod*>(m_item);
00316 
00317     str = method->name();
00318     
00319     if( method->arguments.count() > 0 ) {
00320         str += "( ";
00321         for ( ParsedArgument *arg = method->arguments.first(); arg != NULL; arg = method->arguments.next() ) {
00322             if ( arg != method->arguments.getFirst() )
00323                 str += ", ";
00324 
00325             str += arg->toString();
00326         }
00327         str += " )";
00328     } else {
00329         str += "()";
00330     }
00331     
00332     if( method->isConst() )
00333         str += " const";
00334 
00335     return str;
00336 }
00337 
00338 
00339 ClassTreeAttrItem::ClassTreeAttrItem(ClassTreeItem *parent, ClassTreeItem *lastSibling,
00340                                      ParsedAttribute *parsedAttr)
00341     : ClassTreeItem(parent, lastSibling, parsedAttr)
00342 {
00343     QString icon;
00344     
00345     if ( !parsedAttr )
00346       return;
00347 
00348     if (parsedAttr->isPublic())
00349         icon = "CVpublic_var";
00350     else if (parsedAttr->isProtected())
00351         icon = "CVprotected_var";
00352     else if (parsedAttr->isPrivate())
00353         icon = "CVprivate_var";
00354     else if (parsedAttr->isPackage())
00355         icon = "CVpackage_var";
00356     else
00357         icon = "CVglobal_var";
00358 
00359     setPixmap(0, UserIcon(icon, KIcon::DefaultState, ClassViewFactory::instance()));
00360 }
00361 
00362 
00363 QString ClassTreeAttrItem::text( int ) const
00364 {
00365     if ( !m_item )
00366         return QString::null;
00367     return m_item->name();
00368 }
00369 
00370 ClassTreeScriptItem::ClassTreeScriptItem(ClassTreeItem *parent, ClassTreeItem *lastSibling,
00371                                      ParsedScript *parsedScript)
00372     : ClassTreeItem(parent, lastSibling, parsedScript)
00373 {
00374     QString icon;
00375 
00376     if ( !parsedScript )
00377       return;
00378 
00379     setExpandable(true);
00380 
00381     //need a icon for scripts
00382     icon = "CVpublic_var";
00383     setPixmap(0, UserIcon(icon, KIcon::DefaultState, ClassViewFactory::instance()));
00384 }
00385 
00386 
00387 QString ClassTreeScriptItem::text( int ) const
00388 {
00389     if ( !m_item )
00390         return QString::null;
00391     return m_item->name();
00392 }
00393 
00394 void ClassTreeScriptItem::setOpen(bool o)
00395 {
00396     if ( !m_item )
00397         return;
00398     kdDebug(9003) << (o? "Open script item" : "Close script item") << endl;
00399     if (o && childCount() == 0) {
00400 
00401         ParsedScript *pClass = static_cast<ParsedScript*>(m_item);
00402         ClassTreeItem *lastItem = 0;
00403 
00404         // Add methods
00405         QValueList<ParsedMethod*> methodList = pClass->getSortedMethodList();
00406         QValueList<ParsedMethod*>::ConstIterator methodIt;
00407         for (methodIt = methodList.begin(); methodIt != methodList.end(); ++methodIt)
00408             lastItem = new ClassTreeMethodItem(this, lastItem, *methodIt);
00409 
00410         // Add attributes
00411         QValueList<ParsedAttribute*> attrList = pClass->getSortedAttributeList();
00412         QValueList<ParsedAttribute*>::ConstIterator attrIt;
00413         for (attrIt = attrList.begin(); attrIt != attrList.end(); ++attrIt)
00414             lastItem = new ClassTreeAttrItem(this, lastItem, *attrIt);
00415 
00416     }
00417 
00418     ClassTreeItem::setOpen(o);
00419 }
00420 
00421 
00422 class ClassToolTip : public QToolTip
00423 {
00424 public:
00425     ClassToolTip( QWidget *parent )
00426         : QToolTip(parent)
00427         {}
00428 
00429 protected:
00430     void maybeTip(const QPoint &p);
00431 };
00432 
00433 
00434 void ClassToolTip::maybeTip(const QPoint &p)
00435 {
00436     ClassTreeBase *ctw = static_cast<ClassTreeBase*>(parentWidget());
00437 
00438     QListViewItem *item = ctw->itemAt(p);
00439     QRect r = ctw->itemRect(item);
00440 
00441     if (item && r.isValid()) {
00442         ClassTreeItem *ctitem = static_cast<ClassTreeItem*>(item);
00443         QString str = ctitem->tipText();
00444         if (!str.isEmpty())
00445             tip(r, str);
00446     }
00447 }
00448 
00449 
00450 ClassTreeBase::ClassTreeBase(ClassViewPart *part, QWidget *parent, const char *name)
00451     : KListView(parent, name)
00452 {
00453     setFocusPolicy(ClickFocus);
00454     setRootIsDecorated(true);
00455     setResizeMode(QListView::LastColumn);
00456     setSorting(-1);
00457     header()->hide();
00458     addColumn(QString::null);
00459 
00460     (void) new ClassToolTip(this);
00461     
00462     connect( this, SIGNAL(executed(QListViewItem*)),
00463              this, SLOT(slotItemExecuted(QListViewItem*)) );
00464     connect( this, SIGNAL(mouseButtonPressed(int, QListViewItem*, const QPoint&, int)),
00465              this, SLOT(slotItemPressed(int, QListViewItem*)) );
00466     connect( this, SIGNAL(returnPressed( QListViewItem*)), 
00467              SLOT( slotItemExecuted(QListViewItem*)) );
00468     connect( this, SIGNAL(contextMenuRequested(QListViewItem*, const QPoint&, int)),
00469              this, SLOT(slotContextMenuRequested(QListViewItem*, const QPoint&)) );
00470 
00471     m_part = part;
00472 }
00473 
00474 
00475 ClassTreeBase::~ClassTreeBase()
00476 {}
00477 
00478 
00479 ClassTreeBase::TreeState ClassTreeBase::treeState() const
00480 {
00481     TreeState state;
00482 
00483     ClassTreeBase *that = const_cast<ClassTreeBase*>(this);
00484     QListViewItemIterator it(that);
00485     for (; it.current(); ++it)
00486         if (it.current()->isOpen()) {
00487             QStringList path;
00488             QListViewItem *item = it.current();
00489             while (item) {
00490                 path.prepend(item->text(0));
00491                 item = item->parent();
00492             }
00493             state.append(path);
00494         }
00495 
00496     return state;
00497 }
00498 
00499 
00500 void ClassTreeBase::setTreeState(TreeState state)
00501 {
00502     TreeStateIterator tsit;
00503     for (tsit = state.begin(); tsit != state.end(); ++tsit) {
00504         QListViewItemIterator it(this);
00505         for (; it.current(); ++it) {
00506             QStringList path;
00507             QListViewItem *item = it.current();
00508             while (item) {
00509                 path.prepend(item->text(0));
00510                 item = item->parent();
00511             }
00512             if (*tsit == path) {
00513                 it.current()->setOpen(true);
00514                 break;
00515             }
00516         }
00517     }
00518 }
00519 
00520 
00521 
00522   
00523 void ClassTreeBase::slotItemExecuted( QListViewItem* item )
00524 {
00525     if (!item)
00526         return;
00527 
00528     // toggle open state for parents
00529     if (item->childCount() > 0)
00530         setOpen(item, !isOpen(item));
00531 
00532     // We assume here that ALL (!) items in the list view
00533     // are ClassTreeItem's
00534     ClassTreeItem *ctitem = static_cast<ClassTreeItem*>(item);
00535     if (ctitem->isOrganizer())
00536         return;
00537         
00538     QString toFile;
00539     int toLine = -1;
00540     if (dynamic_cast<ClassTreeClassItem*>(item)) {
00541         ctitem->getDeclaration(&toFile, &toLine);
00542     }
00543     else {
00544     ctitem->getImplementation(&toFile, &toLine);
00545     }
00546     m_part->partController()->editDocument(toFile, toLine);
00547     m_part->mainWindow()->lowerView(this);
00548 }
00549 
00550 
00551 void ClassTreeBase::slotItemPressed(int button, QListViewItem *item)
00552 {
00553     if (!item)
00554         return;
00555 
00556     // We assume here that ALL (!) items in the list view
00557     // are ClassTreeItem's
00558     ClassTreeItem *ctitem = static_cast<ClassTreeItem*>(item);
00559     if (ctitem->isOrganizer())
00560         return;
00561 
00562     if (button == MidButton) {
00563         QString toFile;
00564         int toLine = -1;
00565         ctitem->getDeclaration(&toFile, &toLine);
00566         m_part->partController()->editDocument(toFile, toLine);
00567         m_part->mainWindow()->lowerView(this);
00568     }
00569 }
00570 
00571 void ClassTreeBase::slotContextMenuRequested(QListViewItem *item, const QPoint &p)
00572 {
00573     contextItem = static_cast<ClassTreeItem*>(item);
00574     
00575     KPopupMenu *popup = createPopup();
00576     popup->exec(p);
00577     delete popup;
00578 }
00579 
00580 void ClassTreeBase::slotGotoDeclaration()
00581 {
00582     QString toFile;
00583     int toLine = -1;
00584     
00585     contextItem->getDeclaration(&toFile, &toLine);
00586     m_part->partController()->editDocument(toFile, toLine);
00587 }
00588 
00589 
00590 void ClassTreeBase::slotGotoImplementation()
00591 {
00592     QString toFile;
00593     int toLine = -1;
00594     
00595     contextItem->getImplementation(&toFile, &toLine);
00596     m_part->partController()->editDocument(toFile, toLine);
00597 }
00598 
00599 
00600 void ClassTreeBase::slotAddMethod()
00601 {
00602     if (m_part->languageSupport())
00603         m_part->languageSupport()->addMethod(contextItem->scopedText());
00604 }
00605 
00606 
00607 void ClassTreeBase::slotAddAttribute()
00608 {
00609     if (m_part->languageSupport())
00610         m_part->languageSupport()->addAttribute(contextItem->scopedText());
00611 }
00612 
00613 
00614 void ClassTreeBase::slotClassBaseClasses()
00615 {
00616     ClassToolDialog *dlg = new ClassToolDialog(m_part);
00617     dlg->setClassName(contextItem->scopedText());
00618     dlg->viewParents();
00619 }
00620 
00621 
00622 void ClassTreeBase::slotClassDerivedClasses()
00623 {
00624     ClassToolDialog *dlg = new ClassToolDialog(m_part);
00625     dlg->setClassName(contextItem->scopedText());
00626     dlg->viewChildren();
00627 }
00628 
00629 
00630 void ClassTreeBase::slotClassTool()
00631 {
00632     ClassToolDialog *dlg = new ClassToolDialog(m_part);
00633     dlg->setClassName(contextItem->scopedText());
00634     dlg->viewNone();
00635 }
00636 
00637 #include "classtreebase.moc"
KDE Logo
This file is part of the documentation for KDevelop Version 3.1.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Mar 23 00:03:54 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003