void ClassGraph::getRelatedNodesRecurse(const ModelData &model, const ModelType *type, eAddNodeTypes addType, int maxDepth, std::vector<ClassNode> &nodes) { mBackgroundTaskLevel++; -- maxDepth; if(maxDepth >= 0 && type /* && type->getObjectType() == otClass*/) { const ModelClassifier *classifier = type->getClass(); if(classifier) { addNodeToVector(ClassNode(classifier, getComponentOptions(*type, mGraphOptions)), nodes); if((addType & AN_MemberChildren) > 0) { for(const auto &attr : classifier->getAttributes()) { #if(DEBUG_ADD) DebugAdd("Member", attr->getDeclType()); #endif getRelatedNodesRecurse(model, attr->getDeclType(), addType, maxDepth, nodes); } } if((addType & AN_Superclass) > 0) { for(const auto &assoc : model.mAssociations) { if(assoc->getChild() != nullptr && assoc->getParent() != nullptr) { if(assoc->getChild() == classifier) { #if(DEBUG_ADD) DebugAdd("Super", assoc->getParent()); #endif getRelatedNodesRecurse(model, assoc->getParent(), addType, maxDepth, nodes); } } } } if((addType & AN_Subclass) > 0) { for(const auto &assoc : model.mAssociations) { // Normally the child and parent should not be nullptr. if(assoc->getChild() != nullptr && assoc->getParent() != nullptr) { if(assoc->getParent() == classifier) { #if(DEBUG_ADD) DebugAdd("Subclass", assoc->getChild()); #endif getRelatedNodesRecurse(model, assoc->getChild(), addType, maxDepth, nodes); } } } } if((addType & AN_FuncParamsUsing) > 0) { ConstModelClassifierVector relatedClasses; model.getRelatedFuncInterfaceClasses(*classifier, relatedClasses); for(const auto &cls : relatedClasses) { #if(DEBUG_ADD) DebugAdd("Param Using", cls); #endif getRelatedNodesRecurse(model, cls, addType, maxDepth, nodes); } } if((addType & AN_FuncBodyUsing) > 0) { ConstModelDeclClasses relatedDeclClasses; model.getRelatedBodyVarClasses(*classifier, relatedDeclClasses); for(const auto &rdc : relatedDeclClasses) { #if(DEBUG_ADD) DebugAdd("Body Using", rdc.cl); #endif getRelatedNodesRecurse(model, rdc.getClass(), addType, maxDepth, nodes); } } } if((addType & AN_Templates) > 0) { if(type->isTemplateUseType()) { // Add types pointed to by templates. ConstModelClassifierVector relatedClassifiers; model.getRelatedTypeArgClasses(*type, relatedClassifiers); for(const auto &rc : relatedClassifiers) { #if(DEBUG_ADD) DebugAdd("Templ User", rc); #endif getRelatedNodesRecurse(model, rc, addType, maxDepth, nodes); } addNodeToVector(ClassNode(type, getComponentOptions(*type, mGraphOptions)), nodes); } } int taskId = 0; if(mBackgroundTaskLevel == 1) { taskId = mForegroundTaskStatusListener->startTask("Adding relations.", model.mTypes.size()); } for(size_t i=0; i<model.mTypes.size(); i++) { addRelatedNodesRecurseUserToVector(model, type, model.mTypes[i].get(), addType, maxDepth, nodes); if(mBackgroundTaskLevel == 1) { if(!mForegroundTaskStatusListener->updateProgressIteration( taskId, i, nullptr)) { break; } } } if(mBackgroundTaskLevel == 1) { mForegroundTaskStatusListener->endTask(taskId); } } mBackgroundTaskLevel--; }
void ClassGraph::updateConnections(const ModelData &modelData) { mConnectMap.clear(); // Diagram *node1, Diagram *node2 for(size_t ni=0; ni<mNodes.size(); ni++) { const ModelType *type = mNodes[ni].getType(); if(type) { if(mGraphOptions.drawTemplateRelations) { // Go through templates if(type->isTemplateUseType()) { ConstModelClassifierVector relatedClassifiers; modelData.getRelatedTypeArgClasses(*type, relatedClassifiers); for(auto const &cl : relatedClassifiers) { insertConnection(ni, cl, ClassConnectItem(ctTemplateDependency)); } } } const ModelClassifier *classifier = type->getClass(); if(classifier) { // Get attributes of classifier, and get the decl type for(const auto &attr : classifier->getAttributes()) { insertConnection(ni, attr->getDeclType(), ClassConnectItem(ctAggregation, attr->isConst(), attr->isRefer(), attr->getAccess())); } if(mGraphOptions.drawOperParamRelations) { // Get operations parameters of classifier, and get the decl type ConstModelDeclClasses declClasses; modelData.getRelatedFuncParamClasses(*classifier, declClasses); for(const auto &declCl : declClasses) { const ModelDeclarator *decl = declCl.getDecl(); insertConnection(ni, declCl.getClass(), ClassConnectItem(ctFuncParam, decl->isConst(), decl->isRefer(), Visibility())); } } if(mGraphOptions.drawOperBodyVarRelations) { // Get operations parameters of classifier, and get the decl type ConstModelDeclClasses declClasses; modelData.getRelatedBodyVarClasses(*classifier, declClasses); for(const auto &declCl : declClasses) { const ModelDeclarator *decl = declCl.getDecl(); insertConnection(ni, declCl.getClass(), ClassConnectItem(ctFuncVar, decl->isConst(), decl->isRefer(), Visibility())); } } // Go through associations, and get related classes. for(const auto &assoc : modelData.mAssociations) { size_t n1Index = NO_INDEX; size_t n2Index = NO_INDEX; if(assoc->getChild() == classifier) { n1Index = getNodeIndex(assoc->getParent()); n2Index = ni; } else if(assoc->getParent() == classifier) { n1Index = ni; n2Index = getNodeIndex(assoc->getChild()); } if(n1Index != NO_INDEX && n2Index != NO_INDEX) { insertConnection(n1Index, n2Index, ClassConnectItem(ctIneritance, assoc->getAccess())); } } } } } }
void ClassGraph::addRelatedNodesRecurseUserToVector(const ModelData &model, const ModelType *type, const ModelType *modelType, eAddNodeTypes addType, int maxDepth, std::vector<ClassNode> &nodes) { // Add nodes for template types if they refer to the passed in type. if((addType & AN_Templates) > 0) { if(modelType->isTemplateUseType()) { ConstModelClassifierVector relatedClassifiers; model.getRelatedTypeArgClasses(*modelType, relatedClassifiers); for(const auto &rc : relatedClassifiers) { if(rc == type) { #if(DEBUG_ADD) DebugAdd("Typedef Rel", modelType); #endif getRelatedNodesRecurse(model, modelType, addType, maxDepth, nodes); } } } } // Add nodes if members refer to the passed in type. if((addType & AN_MemberUsers) > 0) { const ModelClassifier*cl = modelType->getClass(); if(cl) { for(const auto &attr : cl->getAttributes()) { const ModelType *attrType = attr->getDeclType(); if(attrType == type) { #if(DEBUG_ADD) DebugAdd("Memb User", cl); #endif getRelatedNodesRecurse(model, cl, addType, maxDepth, nodes); } } } } // Add nodes if func params refer to the passed in type. if((addType & AN_FuncParamsUsers) > 0) { const ModelClassifier*cl = modelType->getClass(); if(cl) { ConstModelClassifierVector relatedClasses; model.getRelatedFuncInterfaceClasses(*cl, relatedClasses); for(auto &cls : relatedClasses) { if(cls == type) { #if(DEBUG_ADD) DebugAdd("Param User", cl); #endif getRelatedNodesRecurse(model, cl, addType, maxDepth, nodes); } } } } // Add nodes if func body variables refer to the passed in type. if((addType & AN_FuncBodyUsers) > 0) { const ModelClassifier*cl = modelType->getClass(); if(cl) { ConstModelDeclClasses relatedDeclClasses; model.getRelatedBodyVarClasses(*cl, relatedDeclClasses); for(auto &rdc : relatedDeclClasses) { if(rdc.getClass() == type) { #if(DEBUG_ADD) DebugAdd("Var User", cl); #endif getRelatedNodesRecurse(model, cl, addType, maxDepth, nodes); } } } } }