00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
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
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
00171 KDevLanguageSupport::Features features = classTree()->m_part->languageSupport()->features();
00172
00173
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
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
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
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
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
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
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
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
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
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
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
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
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
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
00529 if (item->childCount() > 0)
00530 setOpen(item, !isOpen(item));
00531
00532
00533
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
00557
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"