You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kscope/src/symboldlg.cpp

335 lines
9.7 KiB

/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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 <qlabel.h>
#include <qlistview.h>
#include <qpushbutton.h>
#include <qradiobutton.h>
#include <qcheckbox.h>
#include <qgroupbox.h>
#include <kcombobox.h>
#include <klocale.h>
#include "symboldlg.h"
#include "cscopefrontend.h"
#include "kscopeconfig.h"
QStringList SymbolDlg::s_slHistory;
/**
* Class constructor.
* @param pParent Parent widget
* @param szName This widget's name
*/
SymbolDlg::SymbolDlg(QWidget* pParent, const char* szName) :
SymbolLayout(pParent, szName, true, 0),
m_progress(m_pHintList)
{
// Create a persistent Cscope process
m_pCscope = new CscopeFrontend();
// Initialise the hint list (hidden by default)
m_pHintList->addColumn(i18n("Suggested Symbols"));
m_pHintList->hide();
((QWidget*)m_pHintGroup)->hide();
m_pBeginWithRadio->toggle();
adjustSize();
// Close the dialogue when either the "OK" or "Cancel" button are clicked
connect(m_pOKButton, SIGNAL(clicked()), this, SLOT(accept()));
connect(m_pCancelButton, SIGNAL(clicked()), this, SLOT(reject()));
// Run a symbol completion query when the "Hint" button is clicked
connect(m_pHintButton, SIGNAL(clicked()), this, SLOT(slotHintClicked()));
// Add results to the hint list
connect(m_pCscope, SIGNAL(dataReady(FrontendToken*)), this,
SLOT(slotHintDataReady(FrontendToken*)));
// Set hint button availability based on the type of query
connect(m_pTypeCombo, SIGNAL(activated(int)), this,
SLOT(slotTypeChanged(int)));
// Selecting an item in the hint list sets it as the current text
connect(m_pHintList, SIGNAL(selectionChanged(QListViewItem*)), this,
SLOT(slotHintItemSelected(QListViewItem*)));
// Double-clicking an item in the hint list accepts that item as the
// result of the query (i.e., the item is selcted and the dialogue is
// closed)
connect(m_pHintList, SIGNAL(doubleClicked(QListViewItem*)), this,
SLOT(accept()));
// Refresh the hint list when the hint options change
connect(m_pBeginWithRadio, SIGNAL(toggled(bool)), this,
SLOT(slotHintOptionChanged(bool)));
connect(m_pContainRadio, SIGNAL(toggled(bool)), this,
SLOT(slotHintOptionChanged(bool)));
// Show hint query progress information
connect(m_pCscope, SIGNAL(progress(int, int)), this,
SLOT(slotHintProgress(int, int)));
connect(m_pCscope, SIGNAL(finished(uint)), this,
SLOT(slotHintFinished(uint)));
}
/**
* Class destructor.
*/
SymbolDlg::~SymbolDlg()
{
delete m_pCscope;
}
/**
* Displays the requested type of query in the type combo-box.
* @param nType The requested type
*/
void SymbolDlg::setType(uint nType)
{
m_pTypeCombo->setCurrentItem(nType);
slotTypeChanged(nType);
}
/**
* @param sSymbol The initial text of the combo-box
*/
void SymbolDlg::setSymbol(const QString& sSymbol)
{
m_pSymbolHC->setCurrentText(sSymbol);
}
/**
* @param slSymHistory A list of previously queried symbols
*/
void SymbolDlg::setHistory(QStringList& slSymHistory)
{
m_pSymbolHC->setHistoryItems(slSymHistory);
}
/**
* @return The current text of the symbol combo-box
*/
QString SymbolDlg::getSymbol() const
{
QString sResult;
sResult = m_pSymbolHC->currentText().stripWhiteSpace();
if (m_pSubStringCheck->isChecked())
sResult = ".*" + sResult + ".*";
return sResult;
}
/**
* @return The type of query requested by the user
* @note The returned value does not conform to the type used for running
* Cscope queries. Use getQueryType() to translate between these
* values.
*/
uint SymbolDlg::getType() const
{
return m_pTypeCombo->currentItem();
}
bool SymbolDlg::getCase() const
{
return !m_pCaseCheck->isChecked();
}
/**
* A convinience static function for creating and showing SymbolDlg dialogue.
* @param pParent The parent widget
* @param nType The type of query requested by the user (may be
* changed in the dialogue)
* @param sSymbol The initial text of the combo-box
* @return The text entered by the user in the symbol combo-box, or an empty
* string if the dialogue was cancelled
*/
QString SymbolDlg::promptSymbol(QWidget* pParent, uint& nType,
const QString& sSymbol, bool& bCase)
{
SymbolDlg dlg(pParent);
// Initialise the dialogue
dlg.setType(nType);
dlg.setHistory(s_slHistory);
dlg.setSymbol(sSymbol);
// Display the dialogue
if (dlg.exec() != QDialog::Accepted)
return "";
// Return the text entered by the user
nType = dlg.getType();
bCase = dlg.getCase();
dlg.m_pSymbolHC->addToHistory(dlg.getSymbol());
s_slHistory = dlg.m_pSymbolHC->historyItems();
return dlg.getSymbol();
}
/**
* Translates a symbol dialogue type into a Cscope query type.
* @param nType The type to translate
* @return A query type matching the symbol dialogue type
*/
uint SymbolDlg::getQueryType(uint nType)
{
if (nType == CallTree)
return CscopeFrontend::None;
if (nType <= Text)
return nType;
return nType + 1;
}
/**
* Runs a symbol definition query, looking for symbols starting with the
* currently entered text.
* If the hint list is not visible, it is shown first.
* This slot is connected to the clicked() signal of the "Hint" button.
*/
void SymbolDlg::slotHintClicked()
{
QString sText, sRegExp;
// Show the hint list if necessary
if (!m_pHintList->isVisible()) {
m_pHintList->show();
((QWidget*)m_pHintGroup)->show();
adjustSize();
}
// Clear the previous contents
m_pHintList->clear();
// Get the currently entered text (must have at least one character)
sText = m_pSymbolHC->currentText().stripWhiteSpace();
if (sText.isEmpty())
return;
// Create the regular expression
if (m_pBeginWithRadio->isOn())
sRegExp = sText + "[a-zA-Z0-9_]*";
else
sRegExp = "[a-zA-Z0-9_]*" + sText + "[a-zA-Z0-9_]*";
m_reHint.setPattern(sRegExp);
// Run a Cscope symbol definition query using a regular expression
m_pCscope->query(CscopeFrontend::Definition, sRegExp);
}
/**
* Called when a new record is ready to be added to the hint list.
* NOTE: Cscope 15.5 has a bug where the "function" field of the record
* displays the regular expression instead of the matched symbol name. For
* this reason, we need to extract the symbol from the "Text" field.
* @param pToken The head of the record's token list
*/
void SymbolDlg::slotHintDataReady(FrontendToken* pToken)
{
QString sText;
// Get the line text
pToken = pToken->getNext()->getNext()->getNext();
sText = pToken->getData();
// Find the symbol within the line
if (m_reHint.search(sText) == -1)
return;
// Find the symbol within the list, if found - do not add
if (m_pHintList->findItem(m_reHint.capturedTexts().first(), 0))
return;
// Add a list item
(void)new QListViewItem(m_pHintList, m_reHint.capturedTexts().first());
}
/**
* Sets the text of a selected hint list item as the current text of the
* symbol combo-box.
* This slot is connected to the doubleClicked() signal of the hint list-view.
* @param pItem The clicked list item
*/
void SymbolDlg::slotHintItemSelected(QListViewItem* pItem)
{
m_pSymbolHC->setCurrentText(pItem->text(0));
}
/**
* Refreshes the hint list based on the newly selected option.
* This slot is connected to the toggled() signal of the hint options radio
* buttons.
* NOTE: The list is only refreshed if the system profile is set to Fast.
* @param bOn true if the button was toggled on
*/
void SymbolDlg::slotHintOptionChanged(bool bOn)
{
if (bOn && Config().getSysProfile() == KScopeConfig::Fast)
slotHintClicked();
}
/**
* Display a progress bar while the hint query is working.
* This slot is connected to the progress() signal emitted by the Cscope
* frontend object.
* @param nProgress Progress value
* @param nTotal The final expected value
*/
void SymbolDlg::slotHintProgress(int nProgress, int nTotal)
{
m_progress.setProgress(nProgress, nTotal);
}
/**
* Destroys all progress information widget when the query process terminates.
* This slot is connected to the finished() signal emitted by the Cscope
* process.
*/
void SymbolDlg::slotHintFinished(uint /* ignored */)
{
m_progress.finished();
}
/**
* Enables/disables the hint button, based on the newly selected type.
* This slot is connected to the activated() signal of the type combo-box.
* @param nType The newly selected type
*/
void SymbolDlg::slotTypeChanged(int nType)
{
if (nType == FileName || nType == Including)
m_pHintButton->setEnabled(false);
else
m_pHintButton->setEnabled(true);
}
#include "symboldlg.moc"