File indexing completed on 2024-04-28 04:34:22
0001 /*************************************************************************** 0002 * Copyright 2009 Sandro Andrade <sandroandrade@kde.org> * 0003 * * 0004 * This program is free software; you can redistribute it and/or modify * 0005 * it under the terms of the GNU Library General Public License as * 0006 * published by the Free Software Foundation; either version 2 of the * 0007 * License, or (at your option) any later version. * 0008 * * 0009 * This program is distributed in the hope that it will be useful, * 0010 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0012 * GNU General Public License for more details. * 0013 * * 0014 * You should have received a copy of the GNU Library General Public * 0015 * License along with this program; if not, write to the * 0016 * Free Software Foundation, Inc., * 0017 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 0018 ***************************************************************************/ 0019 0020 #include "kdevcontrolflowgraphviewplugin.h" 0021 0022 #include <QAction> 0023 0024 #include <KLocale> 0025 #include <KAboutData> 0026 #include <KMessageBox> 0027 #include <KGenericFactory> 0028 0029 #include <interfaces/icore.h> 0030 #include <interfaces/context.h> 0031 #include <interfaces/iproject.h> 0032 #include <interfaces/idocument.h> 0033 #include <interfaces/iuicontroller.h> 0034 #include <interfaces/iruncontroller.h> 0035 #include <interfaces/iprojectcontroller.h> 0036 #include <interfaces/ilanguagecontroller.h> 0037 #include <interfaces/idocumentcontroller.h> 0038 #include <interfaces/contextmenuextension.h> 0039 0040 #include <language/duchain/codemodel.h> 0041 #include <language/duchain/declaration.h> 0042 #include <language/duchain/classdeclaration.h> 0043 #include <language/duchain/types/functiontype.h> 0044 #include <language/duchain/functiondefinition.h> 0045 #include <language/duchain/persistentsymboltable.h> 0046 #include <language/duchain/classfunctiondeclaration.h> 0047 0048 #include <language/interfaces/codecontext.h> 0049 0050 #include <language/backgroundparser/parsejob.h> 0051 #include <language/backgroundparser/backgroundparser.h> 0052 0053 #include <project/projectmodel.h> 0054 0055 #include <KTextEditor/Document> 0056 0057 #include "duchaincontrolflow.h" 0058 #include "dotcontrolflowgraph.h" 0059 #include "controlflowgraphview.h" 0060 #include "duchaincontrolflowjob.h" 0061 0062 using namespace KDevelop; 0063 0064 K_PLUGIN_FACTORY(ControlFlowGraphViewFactory, registerPlugin<KDevControlFlowGraphViewPlugin>();) 0065 K_EXPORT_PLUGIN(ControlFlowGraphViewFactory(KAboutData("kdevcontrolflowgraphview","kdevcontrolflowgraph", ki18n("Control Flow Graph"), "0.1", ki18n("Control flow graph support in KDevelop"), KAboutData::License_GPL))) 0066 0067 class KDevControlFlowGraphViewFactory: public KDevelop::IToolViewFactory{ 0068 public: 0069 KDevControlFlowGraphViewFactory(KDevControlFlowGraphViewPlugin *plugin) : m_plugin(plugin) {} 0070 virtual QWidget* create(QWidget *parent = 0) 0071 { 0072 return new ControlFlowGraphView(m_plugin, parent); 0073 } 0074 virtual Qt::DockWidgetArea defaultPosition() 0075 { 0076 return Qt::BottomDockWidgetArea; 0077 } 0078 virtual QString id() const 0079 { 0080 return "org.kdevelop.ControlFlowGraphView"; 0081 } 0082 private: 0083 KDevControlFlowGraphViewPlugin *m_plugin; 0084 }; 0085 0086 KDevControlFlowGraphViewPlugin::KDevControlFlowGraphViewPlugin (QObject *parent, const QVariantList &) 0087 : 0088 KDevelop::IPlugin (ControlFlowGraphViewFactory::componentData(), parent), 0089 m_toolViewFactory(new KDevControlFlowGraphViewFactory(this)), 0090 m_activeToolView(0), 0091 m_project(0), 0092 m_abort(false) 0093 { 0094 core()->uiController()->addToolView(i18n("Control Flow Graph"), m_toolViewFactory); 0095 0096 QObject::connect(core()->documentController(), SIGNAL(textDocumentCreated(KDevelop::IDocument*)), 0097 SLOT(textDocumentCreated(KDevelop::IDocument*))); 0098 QObject::connect(core()->projectController(), SIGNAL(projectOpened(KDevelop::IProject*)), 0099 SLOT(projectOpened(KDevelop::IProject*))); 0100 QObject::connect(core()->projectController(), SIGNAL(projectClosed(KDevelop::IProject*)), 0101 SLOT(projectClosed(KDevelop::IProject*))); 0102 QObject::connect(core()->languageController()->backgroundParser(), SIGNAL(parseJobFinished(KDevelop::ParseJob*)), 0103 SLOT(parseJobFinished(KDevelop::ParseJob*))); 0104 0105 m_exportControlFlowGraph = new QAction(i18n("Export Control Flow Graph"), this); 0106 connect(m_exportControlFlowGraph, SIGNAL(triggered(bool)), SLOT(slotExportControlFlowGraph(bool)), Qt::UniqueConnection); 0107 0108 m_exportClassControlFlowGraph = new QAction(i18n("Export Class Control Flow Graph"), this); 0109 connect(m_exportClassControlFlowGraph, SIGNAL(triggered(bool)), SLOT(slotExportClassControlFlowGraph(bool)), Qt::UniqueConnection); 0110 0111 m_exportProjectControlFlowGraph = new QAction(i18n("Export Project Control Flow Graph"), this); 0112 connect(m_exportProjectControlFlowGraph, SIGNAL(triggered(bool)), SLOT(slotExportProjectControlFlowGraph(bool)), Qt::UniqueConnection); 0113 } 0114 0115 KDevControlFlowGraphViewPlugin::~KDevControlFlowGraphViewPlugin() 0116 { 0117 } 0118 0119 QString KDevControlFlowGraphViewPlugin::statusName() const 0120 { 0121 return i18n("Control Flow Graph"); 0122 } 0123 0124 void KDevControlFlowGraphViewPlugin::unload() 0125 { 0126 // When calling removeToolView all existing views are destroyed and their destructor invoke unRegisterToolView. 0127 core()->uiController()->removeToolView(m_toolViewFactory); 0128 } 0129 0130 void KDevControlFlowGraphViewPlugin::registerToolView(ControlFlowGraphView *view) 0131 { 0132 m_toolViews << view; 0133 } 0134 0135 void KDevControlFlowGraphViewPlugin::unRegisterToolView(ControlFlowGraphView *view) 0136 { 0137 m_toolViews.removeAll(view); 0138 } 0139 0140 QPointer<ControlFlowGraphFileDialog> KDevControlFlowGraphViewPlugin::exportControlFlowGraph(ControlFlowGraphFileDialog::OpeningMode mode) 0141 { 0142 QPointer<ControlFlowGraphFileDialog> fileDialog = new ControlFlowGraphFileDialog(KUrl(), "*.png|PNG (Portable Network Graphics)\n*.jpg *.jpeg|JPG \\/ JPEG (Joint Photographic Expert Group)\n*.gif|GIF (Graphics Interchange Format)\n*.svg *.svgz|SVG (Scalable Vector Graphics)\n*.dia|DIA (Dia Structured Diagrams)\n*.fig|FIG\n*.pdf|PDF (Portable Document Format)\n*.dot|DOT (Graph Description Language)", (QWidget *) ICore::self()->uiController()->activeMainWindow(), i18n("Export Control Flow Graph"), mode); 0143 if (fileDialog->exec() == QDialog::Accepted) 0144 { 0145 if (fileDialog) 0146 { 0147 QString fileName = fileDialog->selectedFile(); 0148 if (!fileName.isEmpty()) 0149 return fileDialog; 0150 } 0151 } 0152 return 0; 0153 } 0154 0155 KDevelop::ContextMenuExtension 0156 KDevControlFlowGraphViewPlugin::contextMenuExtension(KDevelop::Context* context) 0157 { 0158 KDevelop::ContextMenuExtension extension; 0159 0160 if (context->hasType(Context::CodeContext) || context->hasType(Context::EditorContext)) 0161 { 0162 KDevelop::DeclarationContext *codeContext = dynamic_cast<KDevelop::DeclarationContext*>(context); 0163 0164 if (!codeContext) 0165 return extension; 0166 0167 DUChainReadLocker readLock(DUChain::lock()); 0168 Declaration *declaration(codeContext->declaration().data()); 0169 0170 // Insert action for generating control flow graph from method 0171 if (declaration && declaration->type<KDevelop::FunctionType>() && (declaration->isDefinition() || FunctionDefinition::definition(declaration))) 0172 { 0173 m_exportControlFlowGraph->setData(QVariant::fromValue(DUChainBasePointer(declaration))); 0174 extension.addAction(KDevelop::ContextMenuExtension::ExtensionGroup, m_exportControlFlowGraph); 0175 } 0176 // Insert action for generating control flow graph for the whole class 0177 else if (declaration && declaration->kind() == Declaration::Type && 0178 declaration->internalContext() && 0179 declaration->internalContext()->type() == DUContext::Class) 0180 { 0181 m_exportClassControlFlowGraph->setData(QVariant::fromValue(DUChainBasePointer(declaration))); 0182 extension.addAction(KDevelop::ContextMenuExtension::ExtensionGroup, m_exportClassControlFlowGraph); 0183 } 0184 } 0185 else if (context->hasType(Context::ProjectItemContext)) 0186 { 0187 KDevelop::ProjectItemContext *projectItemContext = dynamic_cast<KDevelop::ProjectItemContext*>(context); 0188 if (projectItemContext) 0189 { 0190 QList<ProjectBaseItem *> items = projectItemContext->items(); 0191 foreach(ProjectBaseItem *item, items) 0192 { 0193 ProjectFolderItem *folder = item->folder(); 0194 if (folder && !folder->parent()) 0195 { 0196 m_exportProjectControlFlowGraph->setData(QVariant::fromValue(folder->project()->name())); 0197 extension.addAction(KDevelop::ContextMenuExtension::ExtensionGroup, m_exportProjectControlFlowGraph); 0198 } 0199 } 0200 } 0201 } 0202 return extension; 0203 } 0204 0205 void KDevControlFlowGraphViewPlugin::projectOpened(KDevelop::IProject* project) 0206 { 0207 Q_UNUSED(project); 0208 foreach (ControlFlowGraphView *controlFlowGraphView, m_toolViews) 0209 controlFlowGraphView->setProjectButtonsEnabled(true); 0210 refreshActiveToolView(); 0211 } 0212 0213 void KDevControlFlowGraphViewPlugin::projectClosed(KDevelop::IProject* project) 0214 { 0215 Q_UNUSED(project); 0216 if (core()->projectController()->projectCount() == 0) 0217 { 0218 foreach (ControlFlowGraphView *controlFlowGraphView, m_toolViews) 0219 { 0220 controlFlowGraphView->setProjectButtonsEnabled(false); 0221 controlFlowGraphView->newGraph(); 0222 } 0223 } 0224 refreshActiveToolView(); 0225 } 0226 0227 void KDevControlFlowGraphViewPlugin::parseJobFinished(KDevelop::ParseJob* parseJob) 0228 { 0229 if (core()->documentController()->activeDocument() && 0230 parseJob->document().toUrl() == core()->documentController()->activeDocument()->url()) 0231 refreshActiveToolView(); 0232 } 0233 0234 void KDevControlFlowGraphViewPlugin::textDocumentCreated(KDevelop::IDocument *document) 0235 { 0236 connect(document->textDocument(), SIGNAL(viewCreated(KTextEditor::Document*, KTextEditor::View*)), 0237 SLOT(viewCreated(KTextEditor::Document*, KTextEditor::View*))); 0238 } 0239 0240 void KDevControlFlowGraphViewPlugin::viewCreated(KTextEditor::Document *document, KTextEditor::View *view) 0241 { 0242 Q_UNUSED(document); 0243 connect(view, SIGNAL(cursorPositionChanged(KTextEditor::View*, KTextEditor::Cursor)), 0244 SLOT(cursorPositionChanged(KTextEditor::View*, KTextEditor::Cursor))); 0245 connect(view, SIGNAL(destroyed(QObject*)), SLOT(viewDestroyed(QObject*))); 0246 connect(view, SIGNAL(focusIn(KTextEditor::View*)), SLOT(focusIn(KTextEditor::View*))); 0247 } 0248 0249 void KDevControlFlowGraphViewPlugin::viewDestroyed(QObject *object) 0250 { 0251 Q_UNUSED(object); 0252 if (!core()->documentController()->activeDocument() && m_activeToolView) 0253 m_activeToolView->newGraph(); 0254 } 0255 0256 void KDevControlFlowGraphViewPlugin::focusIn(KTextEditor::View *view) 0257 { 0258 if (view) 0259 cursorPositionChanged(view, view->cursorPosition()); 0260 } 0261 0262 void KDevControlFlowGraphViewPlugin::cursorPositionChanged(KTextEditor::View *view, const KTextEditor::Cursor &cursor) 0263 { 0264 if (m_activeToolView) 0265 m_activeToolView->cursorPositionChanged(view, cursor); 0266 } 0267 0268 void KDevControlFlowGraphViewPlugin::refreshActiveToolView() 0269 { 0270 if (m_activeToolView) 0271 m_activeToolView->refreshGraph(); 0272 } 0273 0274 void KDevControlFlowGraphViewPlugin::slotExportControlFlowGraph(bool value) 0275 { 0276 // Export graph for a given function 0277 Q_UNUSED(value); 0278 0279 if (m_duchainControlFlow || m_dotControlFlowGraph) 0280 { 0281 KMessageBox::error((QWidget *) core()->uiController()->activeMainWindow(), i18n("There is a graph being currently exported. Please stop it before requiring a new one")); 0282 return; 0283 } 0284 0285 DUChainReadLocker lock(DUChain::lock()); 0286 0287 Q_ASSERT(qobject_cast<QAction *>(sender())); 0288 QAction *action = static_cast<QAction *>(sender()); 0289 Q_ASSERT(action->data().canConvert<DUChainBasePointer>()); 0290 DeclarationPointer declarationPointer = qvariant_cast<DUChainBasePointer>(action->data()).dynamicCast<Declaration>(); 0291 0292 Declaration *declaration = declarationPointer.data(); 0293 if (!declaration) 0294 { 0295 KMessageBox::error((QWidget *) core()->uiController()->activeMainWindow(), i18n("Could not generate function control flow graph")); 0296 return; 0297 } 0298 0299 if (!declaration->isDefinition()) 0300 { 0301 declaration = FunctionDefinition::definition(declaration); 0302 if (!declaration || !declaration->internalContext()) 0303 { 0304 KMessageBox::error((QWidget *) core()->uiController()->activeMainWindow(), i18n("Could not generate control flow graph")); 0305 return; 0306 } 0307 } 0308 if ((m_fileDialog = exportControlFlowGraph())) 0309 { 0310 DUChainControlFlowJob *job = new DUChainControlFlowJob(declaration->qualifiedIdentifier().toString(), this); 0311 job->setControlFlowJobType(DUChainControlFlowInternalJob::ControlFlowJobBatchForFunction); 0312 m_ideclaration = IndexedDeclaration(declaration); 0313 connect (job, SIGNAL(result(KJob*)), SLOT(generationDone(KJob*))); 0314 ICore::self()->runController()->registerJob(job); 0315 } 0316 action->setData(QVariant::fromValue(DUChainBasePointer())); 0317 } 0318 0319 void KDevControlFlowGraphViewPlugin::slotExportClassControlFlowGraph(bool value) 0320 { 0321 // Export graph for all functions of a given class - individual per-function graphs will be merged 0322 Q_UNUSED(value); 0323 0324 if (m_duchainControlFlow || m_dotControlFlowGraph) 0325 { 0326 KMessageBox::error((QWidget *) core()->uiController()->activeMainWindow(), i18n("There is a graph being currently exported. Please stop it before requiring a new one")); 0327 return; 0328 } 0329 0330 DUChainReadLocker lock(DUChain::lock()); 0331 0332 Q_ASSERT(qobject_cast<QAction *>(sender())); 0333 QAction *action = static_cast<QAction *>(sender()); 0334 Q_ASSERT(action->data().canConvert<DUChainBasePointer>()); 0335 DeclarationPointer declarationPointer = qvariant_cast<DUChainBasePointer>(action->data()).dynamicCast<Declaration>(); 0336 0337 Declaration *declaration = declarationPointer.data(); 0338 if (!declaration) 0339 { 0340 KMessageBox::error((QWidget *) core()->uiController()->activeMainWindow(), i18n("Could not generate class control flow graph")); 0341 return; 0342 } 0343 0344 if ((m_fileDialog = exportControlFlowGraph(ControlFlowGraphFileDialog::ForClassConfigurationButtons))) 0345 { 0346 DUChainControlFlowJob *job = new DUChainControlFlowJob(declaration->qualifiedIdentifier().toString(), this); 0347 job->setControlFlowJobType(DUChainControlFlowInternalJob::ControlFlowJobBatchForClass); 0348 m_ideclaration = IndexedDeclaration(declaration); 0349 connect (job, SIGNAL(result(KJob*)), SLOT(generationDone(KJob*))); 0350 ICore::self()->runController()->registerJob(job); 0351 } 0352 action->setData(QVariant::fromValue(DUChainBasePointer())); 0353 } 0354 0355 void KDevControlFlowGraphViewPlugin::slotExportProjectControlFlowGraph(bool value) 0356 { 0357 // Export graph for all classes of a given project - individual per-class graphs will be merged 0358 Q_UNUSED(value); 0359 0360 if (m_duchainControlFlow || m_dotControlFlowGraph) 0361 { 0362 KMessageBox::error((QWidget *) core()->uiController()->activeMainWindow(), i18n("There is a graph being currently exported. Please stop it before requiring a new one")); 0363 return; 0364 } 0365 0366 Q_ASSERT(qobject_cast<QAction *>(sender())); 0367 QAction *action = static_cast<QAction *>(sender()); 0368 Q_ASSERT(action->data().canConvert<QString>()); 0369 QString projectName = qvariant_cast<QString>(action->data()); 0370 0371 if (projectName.isEmpty()) 0372 { 0373 KMessageBox::error((QWidget *) core()->uiController()->activeMainWindow(), i18n("Could not generate project control flow graph - project name empty")); 0374 return; 0375 } 0376 0377 IProject *project = core()->projectController()->findProjectByName(projectName); 0378 0379 if (!project) 0380 { 0381 KMessageBox::error((QWidget *) core()->uiController()->activeMainWindow(), i18n("Could not generate project control flow graph - project not found")); 0382 return; 0383 } 0384 0385 if ((m_fileDialog = exportControlFlowGraph(ControlFlowGraphFileDialog::ForClassConfigurationButtons))) 0386 { 0387 DUChainControlFlowJob *job = new DUChainControlFlowJob(projectName, this); 0388 job->setControlFlowJobType(DUChainControlFlowInternalJob::ControlFlowJobBatchForProject); 0389 m_project = project; 0390 connect (job, SIGNAL(result(KJob*)), SLOT(generationDone(KJob*))); 0391 ICore::self()->runController()->registerJob(job); 0392 } 0393 action->setData(QVariant::fromValue(QString())); 0394 } 0395 0396 void KDevControlFlowGraphViewPlugin::generateControlFlowGraph() 0397 { 0398 DUChainReadLocker readLock(DUChain::lock()); 0399 0400 Declaration *declaration = m_ideclaration.data(); 0401 if (!declaration) 0402 return; 0403 0404 m_abort = false; 0405 m_dotControlFlowGraph = new DotControlFlowGraph; 0406 m_duchainControlFlow = new DUChainControlFlow(m_dotControlFlowGraph); 0407 0408 configureDuchainControlFlow(m_duchainControlFlow, m_dotControlFlowGraph, m_fileDialog); 0409 0410 m_duchainControlFlow->generateControlFlowForDeclaration(m_ideclaration, IndexedTopDUContext(declaration->topContext()), IndexedDUContext(declaration->internalContext())); 0411 exportGraph(); 0412 } 0413 0414 void KDevControlFlowGraphViewPlugin::generateClassControlFlowGraph() 0415 { 0416 DUChainReadLocker readLock(DUChain::lock()); 0417 0418 Declaration *declaration = m_ideclaration.data(); 0419 if (!declaration) 0420 return; 0421 0422 m_abort = false; 0423 m_dotControlFlowGraph = new DotControlFlowGraph; 0424 m_duchainControlFlow = new DUChainControlFlow(m_dotControlFlowGraph); 0425 0426 configureDuchainControlFlow(m_duchainControlFlow, m_dotControlFlowGraph, m_fileDialog); 0427 0428 if (!declaration->isForwardDeclaration() && declaration->internalContext()) 0429 { 0430 int i = 0; 0431 int max = declaration->internalContext()->localDeclarations().size(); 0432 // For each function declaration 0433 ClassFunctionDeclaration *functionDeclaration; 0434 foreach (Declaration *decl, declaration->internalContext()->localDeclarations()) 0435 { 0436 if (m_abort) 0437 break; 0438 0439 emit showProgress(this, 0, max-1, i); 0440 emit showMessage(this, i18n("Generating graph for function %1", decl->identifier().toString())); 0441 ++i; 0442 if ((functionDeclaration = dynamic_cast<ClassFunctionDeclaration *>(decl))) 0443 { 0444 Declaration *functionDefinition = FunctionDefinition::definition(functionDeclaration); 0445 if (functionDefinition) 0446 m_duchainControlFlow->generateControlFlowForDeclaration(IndexedDeclaration(functionDefinition), IndexedTopDUContext(functionDefinition->topContext()), IndexedDUContext(functionDefinition->internalContext())); 0447 } 0448 } 0449 } 0450 if (!m_abort) 0451 { 0452 emit showMessage(this, i18n("Saving file %1", m_fileDialog->selectedFile())); 0453 exportGraph(); 0454 } 0455 emit hideProgress(this); 0456 emit clearMessage(this); 0457 } 0458 0459 void KDevControlFlowGraphViewPlugin::generateProjectControlFlowGraph() 0460 { 0461 if (!m_project) 0462 return; 0463 0464 m_abort = false; 0465 m_dotControlFlowGraph = new DotControlFlowGraph; 0466 m_duchainControlFlow = new DUChainControlFlow(m_dotControlFlowGraph); 0467 0468 configureDuchainControlFlow(m_duchainControlFlow, m_dotControlFlowGraph, m_fileDialog); 0469 0470 DUChainReadLocker readLock(DUChain::lock()); 0471 0472 int i = 0; 0473 int max = m_project->fileSet().size(); 0474 // For each source file 0475 foreach(const IndexedString &file, m_project->fileSet()) 0476 { 0477 emit showProgress(this, 0, max-1, i); 0478 ++i; 0479 0480 uint codeModelItemCount = 0; 0481 const CodeModelItem *codeModelItems = 0; 0482 CodeModel::self().items(file, codeModelItemCount, codeModelItems); 0483 0484 for (uint codeModelItemIndex = 0; codeModelItemIndex < codeModelItemCount; ++codeModelItemIndex) 0485 { 0486 const CodeModelItem &item = codeModelItems[codeModelItemIndex]; 0487 0488 if ((item.kind & CodeModelItem::Class) && !item.id.identifier().last().toString().isEmpty()) 0489 { 0490 uint declarationCount = 0; 0491 const IndexedDeclaration *declarations = 0; 0492 PersistentSymbolTable::self().declarations(item.id.identifier(), declarationCount, declarations); 0493 // For each class declaration 0494 for (uint j = 0; j < declarationCount; ++j) 0495 { 0496 Declaration *declaration = dynamic_cast<Declaration *>(declarations[j].declaration()); 0497 if (declaration && !declaration->isForwardDeclaration() && declaration->internalContext()) 0498 { 0499 // For each function declaration 0500 ClassFunctionDeclaration *functionDeclaration; 0501 foreach (Declaration *decl, declaration->internalContext()->localDeclarations()) 0502 { 0503 emit showMessage(this, i18n("Generating graph for %1 - %2", file.str(), decl->qualifiedIdentifier().toString())); 0504 if ((functionDeclaration = dynamic_cast<ClassFunctionDeclaration *>(decl))) 0505 { 0506 if (m_abort) 0507 break; 0508 0509 Declaration *functionDefinition = FunctionDefinition::definition(functionDeclaration); 0510 if (functionDefinition) 0511 m_duchainControlFlow->generateControlFlowForDeclaration(IndexedDeclaration(functionDefinition), IndexedTopDUContext(functionDefinition->topContext()), IndexedDUContext(functionDefinition->internalContext())); 0512 } 0513 } 0514 if (m_abort) 0515 break; 0516 } 0517 } 0518 if (m_abort) 0519 break; 0520 } 0521 } 0522 if (m_abort) 0523 break; 0524 } 0525 if (!m_abort) 0526 { 0527 emit showMessage(this, i18n("Saving file %1", m_fileDialog->selectedFile())); 0528 exportGraph(); 0529 } 0530 m_project = 0; 0531 emit hideProgress(this); 0532 emit clearMessage(this); 0533 } 0534 0535 void KDevControlFlowGraphViewPlugin::requestAbort() 0536 { 0537 m_abort = true; 0538 } 0539 0540 void KDevControlFlowGraphViewPlugin::setActiveToolView(ControlFlowGraphView *activeToolView) 0541 { 0542 m_activeToolView = activeToolView; 0543 refreshActiveToolView(); 0544 } 0545 0546 void KDevControlFlowGraphViewPlugin::generationDone(KJob *job) 0547 { 0548 job->deleteLater(); 0549 0550 delete m_dotControlFlowGraph; 0551 delete m_duchainControlFlow; 0552 0553 if (!m_abort) 0554 KMessageBox::information((QWidget *) (core()->uiController()->activeMainWindow()), 0555 i18n("Control flow graph exported"), 0556 i18n("Export Control Flow Graph")); 0557 } 0558 0559 void KDevControlFlowGraphViewPlugin::exportGraph() 0560 { 0561 DotControlFlowGraph::mutex.lock(); 0562 m_dotControlFlowGraph->exportGraph(m_fileDialog->selectedFile()); 0563 DotControlFlowGraph::mutex.unlock(); 0564 } 0565 0566 void KDevControlFlowGraphViewPlugin::configureDuchainControlFlow(DUChainControlFlow *duchainControlFlow, DotControlFlowGraph *dotControlFlowGraph, ControlFlowGraphFileDialog *fileDialog) 0567 { 0568 duchainControlFlow->setControlFlowMode(fileDialog->controlFlowMode()); 0569 duchainControlFlow->setClusteringModes(fileDialog->clusteringModes()); 0570 duchainControlFlow->setMaxLevel(fileDialog->maxLevel()); 0571 duchainControlFlow->setUseFolderName(fileDialog->useFolderName()); 0572 duchainControlFlow->setUseShortNames(fileDialog->useShortNames()); 0573 duchainControlFlow->setDrawIncomingArcs(fileDialog->drawIncomingArcs()); 0574 0575 dotControlFlowGraph->prepareNewGraph(); 0576 }