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.
445 lines
12 KiB
445 lines
12 KiB
11 years ago
|
/***************************************************************************
|
||
|
*
|
||
|
* 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 <qapplication.h>
|
||
|
#include <qclipboard.h>
|
||
|
#include <klocale.h>
|
||
|
#include "queryview.h"
|
||
|
#include "queryresultsmenu.h"
|
||
|
#include "queryviewdlg.h"
|
||
|
#include "cscopefrontend.h"
|
||
|
#include "searchresultsdlg.h"
|
||
|
|
||
|
/**
|
||
|
* Class constructor.
|
||
|
* @param pParent The parent widget
|
||
|
* @param szName The name of the widget
|
||
|
*/
|
||
|
QueryView::QueryView(QWidget* pParent, const char* szName) :
|
||
|
QListView(pParent, szName),
|
||
|
m_pLastItem(NULL)
|
||
|
{
|
||
|
// Create the popup-menu
|
||
|
m_pQueryMenu = new QueryResultsMenu(this);
|
||
|
|
||
|
// Initialise the list's columns
|
||
|
setAllColumnsShowFocus(true);
|
||
|
addColumn(i18n("Function"));
|
||
|
addColumn(i18n("File"));
|
||
|
addColumn(i18n("Line"));
|
||
|
addColumn(i18n("Text"));
|
||
|
setColumnAlignment(2, Qt::AlignRight);
|
||
|
|
||
|
setShowSortIndicator(true);
|
||
|
|
||
|
// A record is selected if it is either double-clicked, or the ENTER
|
||
|
// key is pressed while the record is highlighted
|
||
|
connect(this, SIGNAL(doubleClicked(QListViewItem*)), this,
|
||
|
SLOT(slotRecordSelected(QListViewItem*)));
|
||
|
connect(this, SIGNAL(returnPressed(QListViewItem*)), this,
|
||
|
SLOT(slotRecordSelected(QListViewItem*)));
|
||
|
|
||
|
// Show the popup-menu when requested
|
||
|
connect(this,
|
||
|
SIGNAL(contextMenuRequested(QListViewItem*, const QPoint&, int)),
|
||
|
m_pQueryMenu, SLOT(slotShow(QListViewItem*, const QPoint&, int)));
|
||
|
|
||
|
// Handle popup-menu commands
|
||
|
connect(m_pQueryMenu, SIGNAL(viewSource(QListViewItem*)), this,
|
||
|
SLOT(slotRecordSelected(QListViewItem*)));
|
||
|
connect(m_pQueryMenu, SIGNAL(findDef(const QString&)), this,
|
||
|
SLOT(slotFindDef(const QString&)));
|
||
|
connect(m_pQueryMenu, SIGNAL(copy(QListViewItem*, int)), this,
|
||
|
SLOT(slotCopy(QListViewItem*, int)));
|
||
|
connect(m_pQueryMenu, SIGNAL(filter(int)), this, SLOT(slotFilter(int)));
|
||
|
connect(m_pQueryMenu, SIGNAL(showAll()), this,
|
||
|
SLOT(slotShowAll()));
|
||
|
connect(m_pQueryMenu, SIGNAL(remove(QListViewItem*)), this,
|
||
|
SLOT(slotRemoveItem(QListViewItem*)));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Class destructor.
|
||
|
*/
|
||
|
QueryView::~QueryView()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates a new list item showing a query result record.
|
||
|
* @param sFunc The name of the function
|
||
|
* @param sFile The file path
|
||
|
* @param sLine The line number in the above file
|
||
|
* @param sText The line's text
|
||
|
* @param pParent The parent item (ignored)
|
||
|
*/
|
||
|
void QueryView::addRecord(const QString& sFunc, const QString& sFile,
|
||
|
const QString& sLine, const QString& sText, QListViewItem* /* pParent */)
|
||
|
{
|
||
|
QListViewItem* pItem;
|
||
|
|
||
|
pItem = new QueryViewItem(this, m_pLastItem, 2);
|
||
|
pItem->setText(0, sFunc);
|
||
|
pItem->setText(1, sFile);
|
||
|
pItem->setText(2, sLine);
|
||
|
pItem->setText(3, sText);
|
||
|
|
||
|
m_pLastItem = pItem;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Selects an item.
|
||
|
* When an item is selected, it is highlighted and made visible. By
|
||
|
* definition, the lineRequested() signal is also emitted.
|
||
|
* This method is used for selecting records programmatically (@see
|
||
|
* selectNext() for example). It has nothing to do with user selection.
|
||
|
* @param pItem The list item to select
|
||
|
*/
|
||
|
void QueryView::select(QListViewItem* pItem)
|
||
|
{
|
||
|
ensureItemVisible(pItem);
|
||
|
setSelected(pItem, true);
|
||
|
slotRecordSelected(pItem);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Selects the next record in the list (if one exists).
|
||
|
* The function selects the next item as follows:
|
||
|
* - The first item in the list, if there is no current item
|
||
|
* - The current item, if it is not selected
|
||
|
* - The item immediately below the current item, otherwise
|
||
|
*/
|
||
|
void QueryView::selectNext()
|
||
|
{
|
||
|
QListViewItem* pItem;
|
||
|
|
||
|
// Do nothing if the list is empty
|
||
|
if (firstChild() == NULL)
|
||
|
return;
|
||
|
|
||
|
// Find the next record
|
||
|
pItem = currentItem();
|
||
|
if (pItem == NULL) {
|
||
|
pItem = firstChild();
|
||
|
}
|
||
|
else if (pItem->isSelected()) {
|
||
|
pItem = pItem->itemBelow();
|
||
|
if (pItem == NULL)
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Select the new item
|
||
|
select(pItem);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Selects the previous record in the list (if one exists).
|
||
|
* The function selects the previous item as follows:
|
||
|
* - The first item in the list, if there is no current item
|
||
|
* - The current item, if it is not selected
|
||
|
* - The item immediately above the current item, otherwise
|
||
|
*/
|
||
|
void QueryView::selectPrev()
|
||
|
{
|
||
|
QListViewItem* pItem;
|
||
|
|
||
|
// Do nothing if the list is empty
|
||
|
if (firstChild() == NULL)
|
||
|
return;
|
||
|
|
||
|
// Find the item immediately above this one
|
||
|
pItem = currentItem();
|
||
|
if (pItem == NULL) {
|
||
|
pItem = firstChild();
|
||
|
}
|
||
|
else if (pItem->isSelected()) {
|
||
|
pItem = pItem->itemAbove();
|
||
|
if (pItem == NULL)
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Select the new item
|
||
|
select(pItem);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Informs the view that query progress information has been received.
|
||
|
* The view emits the needToShow() signal telling its parent that the widget
|
||
|
* should become visible (if not already so).
|
||
|
*/
|
||
|
void QueryView::queryProgress()
|
||
|
{
|
||
|
if (!isVisible())
|
||
|
emit needToShow();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Called when a query using this view terminates.
|
||
|
* @param nRecords Number of records generated by the query
|
||
|
*/
|
||
|
void QueryView::queryFinished(uint nRecords, QListViewItem*)
|
||
|
{
|
||
|
// Auto-select a single record (no need to emit the show() signal in
|
||
|
// that case)
|
||
|
if (nRecords == 1) {
|
||
|
emit select(firstChild());
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Report a query that has returned an empty record set
|
||
|
if (nRecords == 0)
|
||
|
addRecord(i18n("No results"), "", "", "", NULL);
|
||
|
|
||
|
// Data is available, instruct the owner object to show the view
|
||
|
emit needToShow();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates an iterator and initialises it to point to the first _visible_
|
||
|
* item in the list.
|
||
|
* @return A new iterator initialised to the beginning of the list
|
||
|
*/
|
||
|
QueryView::Iterator QueryView::getIterator()
|
||
|
{
|
||
|
QListViewItem* pItem;
|
||
|
|
||
|
for (pItem = firstChild(); pItem != NULL && !pItem->isVisible();
|
||
|
pItem = pItem->nextSibling());
|
||
|
|
||
|
return Iterator(pItem);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Handles double-click events over the view.
|
||
|
* NOTE: We override this method since the QListView implementation opens
|
||
|
* expandable items. This is undesired for tree-like query views (such as the
|
||
|
* call tree.
|
||
|
* @param pEvent Event description object
|
||
|
*/
|
||
|
void QueryView::contentsMouseDoubleClickEvent(QMouseEvent* pEvent)
|
||
|
{
|
||
|
QListViewItem* pItem;
|
||
|
|
||
|
// Handle only left button double-clicks
|
||
|
if (pEvent == NULL || pEvent->button() != LeftButton)
|
||
|
return;
|
||
|
|
||
|
// Find the clicked item
|
||
|
pItem = itemAt(contentsToViewport(pEvent->pos()));
|
||
|
if (pItem == NULL)
|
||
|
return;
|
||
|
|
||
|
// Emit the doubleClicked() signal
|
||
|
emit doubleClicked(pItem);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Emits the lineRequested() signal when a list item is selected.
|
||
|
* This slot is connected to the doubleClicked() and returnPressed()
|
||
|
* signals of the list view.
|
||
|
* @param pItem The selected item
|
||
|
*/
|
||
|
void QueryView::slotRecordSelected(QListViewItem* pItem)
|
||
|
{
|
||
|
QString sFileName, sLine;
|
||
|
|
||
|
// Get the file name and line number
|
||
|
sFileName = pItem->text(1);
|
||
|
sLine = pItem->text(2);
|
||
|
|
||
|
// Do not process the "No results" item
|
||
|
if (!sLine.isEmpty())
|
||
|
emit lineRequested(sFileName, sLine.toUInt());
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Looks up the definition of a given function.
|
||
|
* Results are displayed in a popup window.
|
||
|
* This slot is connected to the findDef() signal emitted by the results menu.
|
||
|
* @param sFunc The function to look for
|
||
|
*/
|
||
|
void QueryView::slotFindDef(const QString& sFunc)
|
||
|
{
|
||
|
QueryViewDlg* pDlg;
|
||
|
|
||
|
// Create a query view dialogue
|
||
|
pDlg = new QueryViewDlg(QueryViewDlg::DestroyOnSelect, this);
|
||
|
|
||
|
// Display a line when it is selected in the dialogue
|
||
|
connect(pDlg, SIGNAL(lineRequested(const QString&, uint)), this,
|
||
|
SIGNAL(lineRequested(const QString&, uint)));
|
||
|
|
||
|
// Start the query
|
||
|
pDlg->query(CscopeFrontend::Definition, sFunc);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Copies the text of the requested field (item+column) to the clipboard.
|
||
|
* This slot is connected to the copy() signal of the QueryResultsMenu object.
|
||
|
* @param pItem The item from which to copy
|
||
|
* @param nCol The index of the item field to copy
|
||
|
*/
|
||
|
void QueryView::slotCopy(QListViewItem* pItem, int nCol)
|
||
|
{
|
||
|
QApplication::clipboard()->setText(pItem->text(nCol),
|
||
|
QClipboard::Clipboard);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Hides all items in the page that do not meet the given search criteria.
|
||
|
* This slot is connected to the search() signal of the QueryResultsMenu
|
||
|
* object.
|
||
|
* The search is incremental: only visible items are checked, so that a new
|
||
|
* search goes over the results of the previous one.
|
||
|
* @param nCol The list column to search in
|
||
|
*/
|
||
|
void QueryView::slotFilter(int nCol)
|
||
|
{
|
||
|
SearchResultsDlg dlg(this);
|
||
|
QRegExp re;
|
||
|
QListViewItem* pItem;
|
||
|
bool bNegate;
|
||
|
|
||
|
// Prepare the dialogue
|
||
|
dlg.setColumn(nCol);
|
||
|
|
||
|
// Show the dialogue
|
||
|
if (dlg.exec() != QDialog::Accepted)
|
||
|
return;
|
||
|
|
||
|
// Get the selected regular expression
|
||
|
dlg.getPattern(re);
|
||
|
bNegate = dlg.isNegated();
|
||
|
|
||
|
// Disable visual updates while search is in progress
|
||
|
setUpdatesEnabled(false);
|
||
|
|
||
|
// Iterate over all items in the list
|
||
|
pItem = firstChild();
|
||
|
while (pItem != NULL) {
|
||
|
// Filter visible items only
|
||
|
if (pItem->isVisible() &&
|
||
|
(re.search(pItem->text(nCol)) == -1) != bNegate) {
|
||
|
pItem->setVisible(false);
|
||
|
}
|
||
|
|
||
|
pItem = pItem->nextSibling();
|
||
|
}
|
||
|
|
||
|
// Redraw the list
|
||
|
setUpdatesEnabled(true);
|
||
|
triggerUpdate();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Makes all list items visible.
|
||
|
* This slot is connected to the showAll() signal of the QueryResultsMenu
|
||
|
* object.
|
||
|
*/
|
||
|
void QueryView::slotShowAll()
|
||
|
{
|
||
|
QListViewItem* pItem;
|
||
|
|
||
|
// Iterate over all items in the list
|
||
|
pItem = firstChild();
|
||
|
while (pItem != NULL) {
|
||
|
pItem->setVisible(true);
|
||
|
pItem = pItem->nextSibling();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Deletes the item on which a popup-menu has been invoked.
|
||
|
* This slot is connected to the remove() signal of the QueryResultsMenu
|
||
|
* object.
|
||
|
* @param pItem The item to remove
|
||
|
*/
|
||
|
void QueryView::slotRemoveItem(QListViewItem* pItem)
|
||
|
{
|
||
|
delete pItem;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Moves the iterator to the next _visible_ item in the list.
|
||
|
*/
|
||
|
void QueryView::Iterator::next()
|
||
|
{
|
||
|
if (m_pItem == NULL)
|
||
|
return;
|
||
|
|
||
|
do {
|
||
|
m_pItem = m_pItem->nextSibling();
|
||
|
} while (m_pItem != NULL && !m_pItem->isVisible());
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return The function associated with the list item the iterator points to
|
||
|
*/
|
||
|
QString QueryView::Iterator::getFunc()
|
||
|
{
|
||
|
if (m_pItem == NULL)
|
||
|
return "";
|
||
|
|
||
|
return m_pItem->text(0);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return The file associated with the list item the iterator points to
|
||
|
*/
|
||
|
QString QueryView::Iterator::getFile()
|
||
|
{
|
||
|
if (m_pItem == NULL)
|
||
|
return "";
|
||
|
|
||
|
return m_pItem->text(1);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return The line number associated with the list item the iterator points
|
||
|
* to
|
||
|
*/
|
||
|
QString QueryView::Iterator::getLine()
|
||
|
{
|
||
|
if (m_pItem == NULL)
|
||
|
return "";
|
||
|
|
||
|
return m_pItem->text(2);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return The text associated with the list item the iterator points to
|
||
|
*/
|
||
|
QString QueryView::Iterator::getText()
|
||
|
{
|
||
|
if (m_pItem == NULL)
|
||
|
return "";
|
||
|
|
||
|
return m_pItem->text(3);
|
||
|
}
|
||
|
|
||
|
#include "queryview.moc"
|