diff options
Diffstat (limited to 'src/calltreedlg.cpp')
-rw-r--r-- | src/calltreedlg.cpp | 336 |
1 files changed, 336 insertions, 0 deletions
diff --git a/src/calltreedlg.cpp b/src/calltreedlg.cpp new file mode 100644 index 0000000..65ee4f8 --- /dev/null +++ b/src/calltreedlg.cpp @@ -0,0 +1,336 @@ +/*************************************************************************** + * + * Copyright (C) 2005 Elad Lahav ([email protected]) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ***************************************************************************/ + +#include <qfile.h> +#include <qtoolbutton.h> +#include <qbuttongroup.h> +#include <qwidgetstack.h> +#include <klocale.h> +#include <kfiledialog.h> +#include "calltreedlg.h" +#include "graphwidget.h" +#include "treewidget.h" +#include "kscopepixmaps.h" +#include "kscopeconfig.h" +#include "graphprefdlg.h" + +/** The currently supported version of saved call-tree files. */ +#define FILE_VERSION 5 + +/** Window flags for call-tree widgets. */ +#define CALL_TREE_W_FLAGS \ + WStyle_Customize | \ + WStyle_NormalBorder | \ + WStyle_Title | \ + WDestructiveClose + +/** File Name index for the file name generation */ +int CallTreeDlg::s_nFileNameIndex = 0; + +/** + * Class constructor. + * @param pParent The parent widget + * @param szName The widget's name + */ +CallTreeDlg::CallTreeDlg(QWidget* pParent, const char* szName) : + CallTreeLayout(pParent, szName, CALL_TREE_W_FLAGS) +{ + // Set button pixmaps + m_pCalledButton->setPixmap(GET_PIXMAP(CalledTree)); + m_pCallingButton->setPixmap(GET_PIXMAP(CallingTree)); + m_pGraphButton->setPixmap(GET_PIXMAP(CallGraph)); + m_pSaveButton->setPixmap(GET_PIXMAP(ButtonSaveAs)); + m_pZoomInButton->setPixmap(GET_PIXMAP(ButtonZoomIn)); + m_pZoomOutButton->setPixmap(GET_PIXMAP(ButtonZoomOut)); + m_pRotateButton->setPixmap(GET_PIXMAP(ButtonRotate)); + m_pPrefButton->setPixmap(GET_PIXMAP(ButtonPref)); + + // Open the location of a call + connect(m_pGraphWidget, SIGNAL(lineRequested(const QString&, uint)), + this, SIGNAL(lineRequested(const QString&, uint))); + connect(m_pCalledWidget, SIGNAL(lineRequested(const QString&, uint)), + this, SIGNAL(lineRequested(const QString&, uint))); + connect(m_pCallingWidget, SIGNAL(lineRequested(const QString&, uint)), + this, SIGNAL(lineRequested(const QString&, uint))); + + m_pCallingWidget->setMode(TreeWidget::Calling); + + // Get the default view from KScope's configuration + m_nDefView = Config().getDefGraphView(); +} + +/** + * Class destructor. + */ +CallTreeDlg::~CallTreeDlg() +{ +} + +/** + * @param sFunc The function to use as the root of the call tree + */ +void CallTreeDlg::setRoot(const QString& sFunc) +{ + m_sRoot = sFunc; + + // Generate unique file name to save call tree later + m_sFileName = sFunc; + m_sFileName.replace(' ', '_'); + m_sFileName += QString::number(++s_nFileNameIndex); + + // Set the root item in all views + m_pGraphWidget->setRoot(sFunc); + m_pCalledWidget->setRoot(sFunc); + m_pCallingWidget->setRoot(sFunc); +} + +/** + * Displays the dialogue. + */ +void CallTreeDlg::show() +{ + // Set the default view. + m_pViewGroup->setButton(m_nDefView); + m_pStack->raiseWidget(m_nDefView); + slotViewChanged(m_nDefView); + + CallTreeLayout::show(); +} + +/** + * Informs the call tree manager that this object should be removed from the + * list of call tree dialogues. + * The close event is received when the dialogue is explicitly closed by the + * user. This dialogue will not appear when the project is reopened, and it + * is therefore safe to delete the graph file at this point. + * @param pEvent Information on the closing event + */ +void CallTreeDlg::closeEvent(QCloseEvent* pEvent) +{ + if (!m_sFilePath.isEmpty()) + QFile::remove(m_sFilePath); + + emit closed(this); + QWidget::closeEvent(pEvent); +} + +extern void yyinit(CallTreeDlg*, FILE*, Encoder*); +extern int yyparse(); + +/** + * Restores a call tree from the given call tree file. + * NOTE: The call tree file is deleted when loading is complete. + * @param sProjPath The full path of the project directory + * @param sFileName The name of the call tree file to load + * @return true if successful, false otherwise + */ +bool CallTreeDlg::load(const QString& sProjPath, const QString& sFileName) +{ + QString sPath; + FILE* pFile; + int nVersion, nView, nResult; + Encoder enc; + + // Create the full path name + sPath = sProjPath + "/" + sFileName; + + // Open the file for reading + pFile = fopen(sPath.latin1(), "r"); + if (pFile == NULL) + return false; + + // Check file version + if ((fscanf(pFile, "VERSION=%d\n", &nVersion) != 1) || + (nVersion != FILE_VERSION)) { + fclose(pFile); + return false; + } + + // Get default view + if ((fscanf(pFile, "View=%d\n", &nView) == 1) && + (nView >= 0) && + (nView <= 2)) { + m_nDefView = nView; + } + + // Read the call trees and the graph stored on this file + yyinit(this, pFile, &enc); + nResult = yyparse(); + + // Close the file + fclose(pFile); + + // Check the result returned by the parser + if (nResult != 0) + return false; + + // Store the file name + m_sFileName = sFileName; + m_sFilePath = sPath; + + // Draw the graph + m_pGraphWidget->draw(); + return true; +} + +/** + * Writes the contents of the call tree dialog to a call tree file. + * This method is called for call trees before the owner project is + * closed. + * @param sProjPath The full path of the project directory + */ +void CallTreeDlg::store(const QString& sProjPath) +{ + QString sPath; + FILE* pFile; + + // Create the full file path + sPath = sProjPath + "/" + m_sFileName; + m_sFilePath = sPath; + + // Open a file for writing (create if necessary) + pFile = fopen(sPath.latin1(), "w+"); + if (pFile == NULL) + return; + + // Write header + fprintf(pFile, "VERSION=%d\n", FILE_VERSION); + fprintf(pFile, "View=%d\n", m_pViewGroup->selectedId()); + + // Save the contents of all widgets + m_pCalledWidget->save(pFile); + m_pCallingWidget->save(pFile); + m_pGraphWidget->save(pFile); + + // Close the file + fclose(pFile); +} + +/** + * Saves the graph to a dot file. + * The user is prompted for a name to use for the file, and then graph + * widget writes its information to this file (using the dot language). + * This slot is connected to the clicked() signal of the "Save As..." button. + */ +void CallTreeDlg::slotSaveClicked() +{ + QString sFile; + + // Prompt the user for a file name + sFile = KFileDialog::getSaveFileName(":kscope"); + + // Save the graph to a file (unless the user did not give a file name) + if (!sFile.isEmpty()) + m_pGraphWidget->save(sFile); +} + +/** + * Increases the zoom factor of the graph. + * This slot is connected to the clicked() signal of the "Zoom In" button. + */ +void CallTreeDlg::slotZoomInClicked() +{ + m_pGraphWidget->zoom(true); + m_pGraphWidget->draw(); +} + +/** + * Decreases the zoom factor of the graph. + * This slot is connected to the clicked() signal of the "Zoom Out" button. + */ +void CallTreeDlg::slotZoomOutClicked() +{ + m_pGraphWidget->zoom(false); + m_pGraphWidget->draw(); +} + +/** + * Changes the graph's layout direction. + * This slot is connected to the clicked() signal of the "Rotate" button. + */ +void CallTreeDlg::slotRotateClicked() +{ + m_pGraphWidget->rotate(); + m_pGraphWidget->draw(); +} + +/** + * Opens the call graph preferences dialogue. + * This slot is connected to the clicked() signal of the "Preferences" button. + */ +void CallTreeDlg::slotPrefClicked() +{ + GraphPrefDlg dlg(this); + int nMaxNodeDegree; + + if (dlg.exec() == QDialog::Accepted) { + nMaxNodeDegree = dlg.getMaxNodeDegree(); + Config().setGraphMaxNodeDegree(nMaxNodeDegree); + m_pGraphWidget->setMaxNodeDegree(nMaxNodeDegree); + } +} + +/** + * Prepares the selected view. + * This slot is called when the user chooses a different view through the + * toggle buttons in the dialogue's toolbar. + * @param nView Identifies the selected view + */ +void CallTreeDlg::slotViewChanged(int nView) +{ + switch (nView) { + case 0: + // Call graph + setCaption(i18n("Call Graph")); + m_pGraphGroup->setEnabled(true); + m_pHelpLabel->setText(i18n("Right-click a function node or an arrow " + "head for more options.")); + break; + + case 1: + // Called functions tree + setCaption(i18n("Called Functions Tree")); + m_pGraphGroup->setEnabled(false); + m_pHelpLabel->setText(i18n("Right-click a tree item for more " + "options.")); + m_pCalledWidget->queryRoot(); + break; + + case 2: + // Calling functions tree + setCaption(i18n("Calling Functions Tree")); + m_pGraphGroup->setEnabled(false); + m_pHelpLabel->setText(i18n("Right-click a tree item for more " + "options.")); + m_pCallingWidget->queryRoot(); + break; + } + + Config().setDefGraphView(nView); +} + +#include "calltreedlg.moc" |