File indexing completed on 2024-04-28 04:34:21

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 "controlflowgraphview.h"
0021 
0022 #include <QGraphicsView>
0023 #include <QGraphicsScene>
0024 #include <QFontMetricsF>
0025 
0026 #include <KLibLoader>
0027 #include <KMessageBox>
0028 #include <KParts/Part>
0029 #include <KActionCollection>
0030 
0031 #include <interfaces/icore.h>
0032 #include <interfaces/iuicontroller.h>
0033 #include <interfaces/iprojectcontroller.h>
0034 
0035 #include "duchaincontrolflow.h"
0036 #include "dotcontrolflowgraph.h"
0037 #include "controlflowgraphfiledialog.h"
0038 #include "kdevcontrolflowgraphviewplugin.h"
0039 
0040 using namespace KDevelop;
0041 
0042 ControlFlowGraphView::ControlFlowGraphView(KDevControlFlowGraphViewPlugin *plugin, QWidget *parent)
0043 :
0044 QWidget(parent),
0045 m_plugin(plugin),
0046 m_part(0),
0047 m_dotControlFlowGraph(new DotControlFlowGraph),
0048 m_duchainControlFlow(new DUChainControlFlow(m_dotControlFlowGraph)),
0049 m_graphLocked(false)
0050 {
0051     setupUi(this);
0052     KLibFactory *factory = KLibLoader::self()->factory("kgraphviewerpart");
0053     if (factory)
0054     {
0055         m_part = factory->create<KParts::ReadOnlyPart>("kgraphviewerpart", this);
0056         if (m_part)
0057         {
0058             QMetaObject::invokeMethod(m_part, "setReadWrite");
0059 
0060             verticalLayout->addWidget(m_part->widget());
0061 
0062             modeFunctionToolButton->setIcon(KIcon("code-function"));
0063             modeClassToolButton->setIcon(KIcon("code-class"));
0064             modeNamespaceToolButton->setIcon(KIcon("namespace"));
0065             clusteringClassToolButton->setIcon(KIcon("code-class"));
0066             clusteringNamespaceToolButton->setIcon(KIcon("namespace"));
0067             clusteringProjectToolButton->setIcon(KIcon("folder-development"));
0068             useFolderNameToolButton->setIcon(KIcon("folder-favorites"));
0069             drawIncomingArcsToolButton->setIcon(KIcon("draw-arrow-down"));
0070             maxLevelToolButton->setIcon(KIcon("zoom-fit-height"));
0071             exportToolButton->setIcon(KIcon("document-export"));
0072             m_duchainControlFlow->setMaxLevel(2);
0073 
0074             birdseyeToolButton->setIcon(KIcon("edit-find"));
0075             usesHoverToolButton->setIcon(KIcon("input-mouse"));
0076             zoominToolButton->setIcon(KIcon("zoom-in"));
0077             zoomoutToolButton->setIcon(KIcon("zoom-out"));
0078 
0079             if (ICore::self()->projectController()->projectCount() > 0)
0080                 setProjectButtonsEnabled(true);
0081 
0082             useShortNamesToolButton->setIcon(KIcon("application-x-arc"));
0083             updateLockIcon(lockControlFlowGraphToolButton->isChecked());
0084 
0085             // Control flow mode buttons signals
0086             connect(modeFunctionToolButton, SIGNAL(toggled(bool)), SLOT(setControlFlowFunction(bool)));
0087             connect(modeClassToolButton, SIGNAL(toggled(bool)), SLOT(setControlFlowClass(bool)));
0088             connect(modeNamespaceToolButton, SIGNAL(toggled(bool)), SLOT(setControlFlowNamespace(bool)));
0089 
0090             // Clustering buttons signals
0091             connect(clusteringClassToolButton, SIGNAL(toggled(bool)), SLOT(setClusteringClass(bool)));
0092             connect(clusteringNamespaceToolButton, SIGNAL(toggled(bool)), SLOT(setClusteringNamespace(bool)));
0093             connect(clusteringProjectToolButton, SIGNAL(toggled(bool)), SLOT(setClusteringProject(bool)));
0094 
0095             // Configuration buttons signals
0096             connect(maxLevelSpinBox, SIGNAL(valueChanged(int)), SLOT(setMaxLevel(int)));
0097             connect(maxLevelToolButton, SIGNAL(toggled(bool)), SLOT(setUseMaxLevel(bool)));
0098             connect(drawIncomingArcsToolButton, SIGNAL(toggled(bool)), SLOT(setDrawIncomingArcs(bool)));
0099             connect(useFolderNameToolButton, SIGNAL(toggled(bool)), SLOT(setUseFolderName(bool)));
0100             connect(useShortNamesToolButton, SIGNAL(toggled(bool)), SLOT(setUseShortNames(bool)));
0101             connect(lockControlFlowGraphToolButton, SIGNAL(toggled(bool)), SLOT(updateLockIcon(bool)));
0102 
0103             // Left buttons signals
0104             connect(zoomoutToolButton, SIGNAL(clicked()), m_part->actionCollection()->action("view_zoom_out"), SIGNAL(triggered()));
0105             connect(zoominToolButton, SIGNAL(clicked()), m_part->actionCollection()->action("view_zoom_in"), SIGNAL(triggered()));
0106             m_part->actionCollection()->action("view_bev_enabled")->setIcon(KIcon("edit-find.png"));
0107             m_part->actionCollection()->action("view_bev_enabled")->setChecked(false);
0108             birdseyeToolButton->setDefaultAction(m_part->actionCollection()->action("view_bev_enabled"));
0109             connect(m_part, SIGNAL(selectionIs(QList<QString>, QPoint&)),
0110                     m_duchainControlFlow, SLOT(slotGraphElementSelected(QList<QString>,QPoint)));
0111             connect(m_part, SIGNAL(hoverEnter(QString)), m_duchainControlFlow, SLOT(slotEdgeHover(QString)));
0112             connect(exportToolButton, SIGNAL(clicked()), SLOT(exportControlFlowGraph()));
0113             connect(usesHoverToolButton, SIGNAL(toggled(bool)), m_duchainControlFlow, SLOT(setShowUsesOnEdgeHover(bool)));
0114 
0115             // Make sure we have a graph before we hook up signals to act on it
0116             m_dotControlFlowGraph->prepareNewGraph();
0117 
0118             // Graph generation signals
0119             connect(m_dotControlFlowGraph, SIGNAL(loadLibrary(graph_t*)), m_part, SLOT(slotLoadLibrary(graph_t*)));
0120             connect(m_duchainControlFlow, SIGNAL(startingJob()), SLOT(startingJob()));
0121             connect(m_duchainControlFlow, SIGNAL(jobDone()), SLOT(graphDone()));
0122 
0123             m_plugin->registerToolView(this);
0124         }
0125         else
0126             KMessageBox::error((QWidget *) m_plugin->core()->uiController()->activeMainWindow(), i18n("Could not load the KGraphViewer kpart"));
0127     }
0128     else
0129         KMessageBox::error((QWidget *) m_plugin->core()->uiController()->activeMainWindow(), i18n("Could not find the KGraphViewer factory") + ": " + KLibLoader::self()->lastErrorMessage());
0130 }
0131 
0132 ControlFlowGraphView::~ControlFlowGraphView()
0133 {
0134     m_plugin->unRegisterToolView(this);
0135     delete m_duchainControlFlow;
0136     delete m_dotControlFlowGraph;
0137     delete m_part;
0138 }
0139 
0140 void ControlFlowGraphView::refreshGraph()
0141 {
0142     m_duchainControlFlow->refreshGraph();
0143 }
0144 
0145 void ControlFlowGraphView::newGraph()
0146 {
0147     m_duchainControlFlow->newGraph();
0148 }
0149 
0150 void ControlFlowGraphView::setProjectButtonsEnabled(bool enabled)
0151 {
0152     useFolderNameToolButton->setEnabled(enabled);
0153     clusteringProjectToolButton->setEnabled(enabled);
0154 }
0155 
0156 void ControlFlowGraphView::cursorPositionChanged(KTextEditor::View *view, const KTextEditor::Cursor &cursor)
0157 {
0158     m_duchainControlFlow->cursorPositionChanged(view, cursor);
0159 }
0160 
0161 void ControlFlowGraphView::startingJob()
0162 {
0163     setEnabled(false);
0164 }
0165 
0166 void ControlFlowGraphView::graphDone()
0167 {
0168     setEnabled(true);
0169 }
0170 
0171 void ControlFlowGraphView::exportControlFlowGraph()
0172 {
0173     QPointer<ControlFlowGraphFileDialog> fileDialog;
0174     if ((fileDialog = m_plugin->exportControlFlowGraph(ControlFlowGraphFileDialog::NoConfigurationButtons)))
0175     {
0176         m_dotControlFlowGraph->exportGraph(fileDialog->selectedFile());
0177         KMessageBox::information(this, i18n("Control flow graph exported"), i18n("Export Control Flow Graph"));
0178     }
0179 }
0180 
0181 void ControlFlowGraphView::updateLockIcon(bool checked)
0182 {
0183     lockControlFlowGraphToolButton->setIcon(KIcon(checked ? "document-encrypt":"document-decrypt"));
0184     lockControlFlowGraphToolButton->setToolTip(checked ? i18n("Unlock control flow graph"):i18n("Lock control flow graph"));
0185     m_duchainControlFlow->setLocked(checked);
0186     m_graphLocked = checked;
0187     if (!checked)
0188         m_duchainControlFlow->refreshGraph();
0189 }
0190 
0191 void ControlFlowGraphView::setControlFlowClass(bool checked)
0192 {
0193     if (checked)
0194     {
0195         m_duchainControlFlow->setControlFlowMode(DUChainControlFlow::ControlFlowClass);
0196         m_duchainControlFlow->refreshGraph();
0197         clusteringClassToolButton->setChecked(false);
0198         clusteringClassToolButton->setEnabled(false);
0199         clusteringNamespaceToolButton->setEnabled(true);
0200     }
0201 }
0202 
0203 void ControlFlowGraphView::setControlFlowFunction(bool checked)
0204 {
0205     if (checked)
0206     {
0207         m_duchainControlFlow->setControlFlowMode(DUChainControlFlow::ControlFlowFunction);
0208         m_duchainControlFlow->refreshGraph();
0209         clusteringClassToolButton->setEnabled(true);
0210         clusteringNamespaceToolButton->setEnabled(true);
0211     }
0212 }
0213 
0214 void ControlFlowGraphView::setControlFlowNamespace(bool checked)
0215 {
0216     if (checked)
0217     {
0218         m_duchainControlFlow->setControlFlowMode(DUChainControlFlow::ControlFlowNamespace);
0219         m_duchainControlFlow->refreshGraph();
0220         clusteringClassToolButton->setChecked(false);
0221         clusteringClassToolButton->setEnabled(false);
0222         clusteringNamespaceToolButton->setChecked(false);
0223         clusteringNamespaceToolButton->setEnabled(false);
0224     }
0225 }
0226 
0227 void ControlFlowGraphView::setClusteringClass(bool checked)
0228 {
0229     Q_UNUSED(checked);
0230     m_duchainControlFlow->setClusteringModes(m_duchainControlFlow->clusteringModes() ^ DUChainControlFlow::ClusteringClass);
0231     m_duchainControlFlow->refreshGraph();
0232     useShortNamesToolButton->setEnabled(m_duchainControlFlow->clusteringModes() ? true:false);
0233 }
0234 
0235 void ControlFlowGraphView::setClusteringProject(bool checked)
0236 {
0237     Q_UNUSED(checked);
0238     m_duchainControlFlow->setClusteringModes(m_duchainControlFlow->clusteringModes() ^ DUChainControlFlow::ClusteringProject);
0239     m_duchainControlFlow->refreshGraph();
0240     useShortNamesToolButton->setEnabled(m_duchainControlFlow->clusteringModes() ? true:false);
0241 }
0242 
0243 void ControlFlowGraphView::setClusteringNamespace(bool checked)
0244 {
0245     Q_UNUSED(checked);
0246     m_duchainControlFlow->setClusteringModes(m_duchainControlFlow->clusteringModes() ^ DUChainControlFlow::ClusteringNamespace);
0247     m_duchainControlFlow->refreshGraph();
0248     useShortNamesToolButton->setEnabled(m_duchainControlFlow->clusteringModes() ? true:false);
0249 }
0250 
0251 void ControlFlowGraphView::setUseMaxLevel(bool checked)
0252 {
0253     maxLevelSpinBox->setEnabled(checked);
0254     setMaxLevel(checked ? maxLevelSpinBox->value():0);
0255 }
0256 
0257 void ControlFlowGraphView::setMaxLevel(int value)
0258 {
0259     m_duchainControlFlow->setMaxLevel(value);
0260     m_duchainControlFlow->refreshGraph();
0261 }
0262 
0263 void ControlFlowGraphView::setDrawIncomingArcs(bool checked)
0264 {
0265     m_duchainControlFlow->setDrawIncomingArcs(checked);
0266     m_duchainControlFlow->refreshGraph();
0267 }
0268 
0269 void ControlFlowGraphView::setUseFolderName(bool checked)
0270 {
0271     m_duchainControlFlow->setUseFolderName(checked);
0272     m_duchainControlFlow->refreshGraph();
0273 }
0274 
0275 void ControlFlowGraphView::setUseShortNames(bool checked)
0276 {
0277     m_duchainControlFlow->setUseShortNames(checked);
0278     m_duchainControlFlow->refreshGraph();
0279 }
0280 
0281 void ControlFlowGraphView::showEvent(QShowEvent *event)
0282 {
0283     Q_UNUSED(event);
0284     m_plugin->setActiveToolView(this);
0285 }
0286 
0287 void ControlFlowGraphView::hideEvent(QHideEvent *event)
0288 {
0289     Q_UNUSED(event);
0290     m_plugin->setActiveToolView(0);
0291 }