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.
602 lines
16 KiB
602 lines
16 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 <tqtoolbutton.h>
|
|
#include <tqtooltip.h>
|
|
#include <tdelocale.h>
|
|
#include <tdemessagebox.h>
|
|
#include "querywidget.h"
|
|
#include "kscopepixmaps.h"
|
|
#include "kscopeconfig.h"
|
|
|
|
/**
|
|
* Class constructor.
|
|
* @param pParent The parent widget
|
|
* @param szName The widget's name
|
|
*/
|
|
QueryWidget::QueryWidget(TQWidget* pParent, const char* szName) :
|
|
QueryWidgetLayout(pParent, szName),
|
|
m_pPageMenu(NULL),
|
|
m_pLockAction(NULL),
|
|
m_pHistPage(NULL),
|
|
m_bHistEnabled(true),
|
|
m_nQueryPages(0)
|
|
{
|
|
// Pages can be closed by clicking their tabs
|
|
m_pQueryTabs->setHoverCloseButton(true);
|
|
|
|
// Change the lock action state according to the current page
|
|
connect(m_pQueryTabs, SIGNAL(currentChanged(TQWidget*)), this,
|
|
SLOT(slotCurrentChanged(TQWidget*)));
|
|
|
|
// Close a query when its tab button is clicked
|
|
connect(m_pQueryTabs, SIGNAL(closeRequest(TQWidget*)), this,
|
|
SLOT(slotClosePage(TQWidget*)));
|
|
|
|
// Show the menu when requested
|
|
connect(m_pQueryTabs, SIGNAL(contextMenu(const TQPoint&)), this,
|
|
SLOT(slotContextMenu(const TQPoint&)));
|
|
connect(m_pQueryTabs, SIGNAL(contextMenu(TQWidget*, const TQPoint&)), this,
|
|
SLOT(slotContextMenu(TQWidget*, const TQPoint&)));
|
|
}
|
|
|
|
/**
|
|
* Class destructor.
|
|
*/
|
|
QueryWidget::~QueryWidget()
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Runs a query in a query page.
|
|
* A query page is first selected, with a new one created if required. The
|
|
* method then creates a Cscope process and runs the query.
|
|
* @param nType The query's numeric type code
|
|
* @param sText The query's text, as entered by the user
|
|
* @param bCase true for case-sensitive queries, false otherwise
|
|
*/
|
|
void QueryWidget::initQuery(uint nType, const TQString& sText, bool bCase)
|
|
{
|
|
QueryPage* pPage;
|
|
|
|
// Make sure we have a query page
|
|
findQueryPage();
|
|
pPage = (QueryPage*)currentPage();
|
|
|
|
// Use the current page, or a new page if the current one is locked
|
|
if (pPage->isLocked()) {
|
|
addQueryPage();
|
|
pPage = (QueryPage*)currentPage();
|
|
}
|
|
|
|
// Reset the page's results list
|
|
pPage->clear();
|
|
pPage->query(nType, sText, bCase);
|
|
|
|
// Set the page's tab text according to the new query
|
|
setPageCaption(pPage);
|
|
}
|
|
|
|
/**
|
|
* Applies the user's colour and font preferences to all pages.
|
|
*/
|
|
void QueryWidget::applyPrefs()
|
|
{
|
|
QueryPage* pPage;
|
|
int nPages, i;
|
|
|
|
// Iterate query pages
|
|
nPages = m_pQueryTabs->count();
|
|
for (i = 0; i < nPages; i++) {
|
|
pPage = (QueryPage*)m_pQueryTabs->page(i);
|
|
pPage->applyPrefs();
|
|
setPageCaption(pPage);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Loads all pages saved when the project was closed.
|
|
* @param sProjPath The full path of the project directory
|
|
* @param slFiles The list of query file names to load
|
|
*/
|
|
void QueryWidget::loadPages(const TQString& sProjPath,
|
|
const TQStringList& slFiles)
|
|
{
|
|
TQStringList::ConstIterator itr;
|
|
QueryPageBase* pPage;
|
|
TQString sName;
|
|
|
|
// Iterate through query files
|
|
for (itr = slFiles.begin(); itr != slFiles.end(); ++itr) {
|
|
// Set the target page, based on the file type (query or history)
|
|
if ((*itr).startsWith("History")) {
|
|
findHistoryPage();
|
|
pPage = m_pHistPage;
|
|
}
|
|
else {
|
|
findQueryPage();
|
|
pPage = (QueryPage*)currentPage();
|
|
}
|
|
|
|
// Load a query file to this page, and lock the page
|
|
if (pPage->load(sProjPath, *itr)) {
|
|
setPageCaption(pPage);
|
|
setPageLocked(pPage, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Stores all pages marked for saving into files in the project directory.
|
|
* @param sProjPath The full path of the project directory
|
|
* @param slFiles Holds a list of query file names, upon return
|
|
*/
|
|
void QueryWidget::savePages(const TQString& sProjPath, TQStringList& slFiles)
|
|
{
|
|
int nPageCount, i;
|
|
QueryPage* pPage;
|
|
TQString sFileName;
|
|
|
|
// Iterate pages
|
|
nPageCount = m_pQueryTabs->count();
|
|
for (i = 0; i < nPageCount; i++) {
|
|
pPage = (QueryPage*)m_pQueryTabs->page(i);
|
|
if (pPage->shouldSave()) {
|
|
// Store this query page
|
|
if (pPage->save(sProjPath, sFileName) && !sFileName.isEmpty())
|
|
slFiles.append(sFileName);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Adds a new position record to the active history page.
|
|
* @param sFile The file path
|
|
* @param nLine The line number
|
|
* @param sText The contents of the line pointed to by the file path and
|
|
* line number
|
|
*/
|
|
void QueryWidget::addHistoryRecord(const TQString& sFile, uint nLine,
|
|
const TQString& sText)
|
|
{
|
|
// Validate file name and line number
|
|
if (sFile.isEmpty() || nLine == 0)
|
|
return;
|
|
|
|
// Do nothing if history logging is disabled
|
|
if (!m_bHistEnabled)
|
|
return;
|
|
|
|
// Make sure there is an active history page
|
|
findHistoryPage();
|
|
|
|
// Add the position entry to the active page
|
|
m_pHistPage->addRecord(sFile, nLine, sText);
|
|
}
|
|
|
|
/**
|
|
* Sets the tab caption and tool-tip for the given page.
|
|
* @param pPage The page whose tab needs to be changed
|
|
*/
|
|
void QueryWidget::setPageCaption(QueryPageBase* pPage)
|
|
{
|
|
m_pQueryTabs->changeTab(pPage,
|
|
pPage->getCaption(Config().getUseBriefQueryCaptions()));
|
|
m_pQueryTabs->setTabToolTip(pPage, pPage->getCaption());
|
|
}
|
|
|
|
/**
|
|
* Creates a new query page, and adds it to the tab widget.
|
|
* The new page is set as the current one.
|
|
*/
|
|
void QueryWidget::addQueryPage()
|
|
{
|
|
QueryPage* pPage;
|
|
TQString sTitle;
|
|
|
|
// Create the page
|
|
pPage = new QueryPage(this);
|
|
|
|
// Add the page, and set it as the current one
|
|
m_pQueryTabs->insertTab(pPage, GET_PIXMAP(TabUnlocked), "Query",
|
|
m_nQueryPages++);
|
|
setCurrentPage(pPage);
|
|
|
|
// Emit the lineRequested() signal when a query record is selected on
|
|
// this page
|
|
connect(pPage, SIGNAL(lineRequested(const TQString&, uint)), this,
|
|
SLOT(slotRequestLine(const TQString&, uint)));
|
|
}
|
|
|
|
/**
|
|
* Creates a new query page, and emits signal about it.
|
|
*/
|
|
void QueryWidget::slotNewQueryPage()
|
|
{
|
|
addQueryPage();
|
|
emit newQuery();
|
|
}
|
|
|
|
/**
|
|
* Locks or unlocks a query.
|
|
* This slot is connected to the toggled() signal of the lock query button.
|
|
* @param bOn true if the new state of the button is "on", false if it is
|
|
* "off"
|
|
*/
|
|
void QueryWidget::slotLockCurrent(bool bOn)
|
|
{
|
|
QueryPageBase* pPage;
|
|
|
|
pPage = currentPage();
|
|
|
|
if (pPage != NULL)
|
|
setPageLocked(currentPage(), bOn);
|
|
}
|
|
|
|
/**
|
|
* Locks or unlocks a query, by toggling the current state.
|
|
*/
|
|
void QueryWidget::slotLockCurrent()
|
|
{
|
|
QueryPageBase* pPage;
|
|
|
|
pPage = currentPage();
|
|
if (pPage != NULL)
|
|
setPageLocked(pPage, !pPage->isLocked());
|
|
}
|
|
|
|
/**
|
|
* Reruns the query whose results are displayed in the current page.
|
|
*/
|
|
void QueryWidget::slotRefreshCurrent()
|
|
{
|
|
QueryPage* pPage;
|
|
|
|
// Make sure the current page is a valid, non-empty one
|
|
pPage = dynamic_cast<QueryPage*>(currentPage());
|
|
if (pPage == NULL)
|
|
return;
|
|
|
|
// Clear the current page contents
|
|
pPage->refresh();
|
|
}
|
|
|
|
/**
|
|
* Selects the next query result record in the current query page.
|
|
*/
|
|
void QueryWidget::slotNextResult()
|
|
{
|
|
QueryPage* pPage;
|
|
|
|
// Select the next record in the current page
|
|
pPage = dynamic_cast<QueryPage*>(currentPage());
|
|
if (pPage != NULL)
|
|
pPage->selectNext();
|
|
}
|
|
|
|
/**
|
|
* Selects the next query result record in the current query page.
|
|
*/
|
|
void QueryWidget::slotPrevResult()
|
|
{
|
|
QueryPage* pPage;
|
|
|
|
// Select the next record in the current page
|
|
pPage = dynamic_cast<QueryPage*>(currentPage());
|
|
if (pPage != NULL)
|
|
pPage->selectPrev();
|
|
}
|
|
|
|
/**
|
|
* Closes the current query page.
|
|
*/
|
|
void QueryWidget::slotCloseCurrent()
|
|
{
|
|
TQWidget* pPage;
|
|
|
|
// Close the current page
|
|
pPage = currentPage();
|
|
if (pPage != NULL)
|
|
slotClosePage(pPage);
|
|
}
|
|
|
|
/**
|
|
* Closes all query pages.
|
|
*/
|
|
void QueryWidget::slotCloseAll()
|
|
{
|
|
int nPageCount, i;
|
|
QueryPage* pPage;
|
|
|
|
// Close all pages
|
|
nPageCount = m_pQueryTabs->count();
|
|
for (i = 0; i < nPageCount; i++) {
|
|
pPage = (QueryPage*)m_pQueryTabs->page(0);
|
|
m_pQueryTabs->removePage(pPage);
|
|
delete pPage;
|
|
}
|
|
|
|
m_pHistPage = NULL;
|
|
}
|
|
|
|
/**
|
|
* Handles the "Go->Back" menu command.
|
|
* Moves to the previous position in the position history.
|
|
*/
|
|
void QueryWidget::slotHistoryPrev()
|
|
{
|
|
if (m_pHistPage != NULL) {
|
|
m_bHistEnabled = false;
|
|
m_pHistPage->selectPrev();
|
|
m_bHistEnabled = true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handles the "Go->Forward" menu command.
|
|
* Moves to the next position in the position history.
|
|
*/
|
|
void QueryWidget::slotHistoryNext()
|
|
{
|
|
if (m_pHistPage != NULL) {
|
|
m_bHistEnabled = false;
|
|
m_pHistPage->selectNext();
|
|
m_bHistEnabled = true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sets the active history page, if any, as the current page.
|
|
*/
|
|
void QueryWidget::selectActiveHistory()
|
|
{
|
|
if (m_pHistPage)
|
|
setCurrentPage(m_pHistPage);
|
|
}
|
|
|
|
/**
|
|
* Attaches the page operations menu to this widget.
|
|
* The page menu is a popup menu that handles such operations as opening a
|
|
* new page, closing a page, locking a page, etc.
|
|
* @param pMenu Pointer to the popup menu
|
|
* @param pAction Pointer to the "Lock/Unlock" toggle action
|
|
*/
|
|
void QueryWidget::setPageMenu(TQPopupMenu* pMenu, TDEToggleAction* pAction)
|
|
{
|
|
m_pPageMenu = pMenu;
|
|
m_pLockAction = pAction;
|
|
}
|
|
|
|
/**
|
|
* Emits a signal indicating a certain source file and line number are
|
|
* requested.
|
|
* This slot is connected to the recordSelected() signal emitted by any of
|
|
* the query pages. The signal emitted by this slot is used to display an
|
|
* editor page at the requested line.
|
|
* @param sFileName The file's path
|
|
* @param nLine The requested line in the file
|
|
*/
|
|
void QueryWidget::slotRequestLine(const TQString& sFileName, uint nLine)
|
|
{
|
|
// Disable history if the request came from the active history page
|
|
if (currentPage() == m_pHistPage)
|
|
m_bHistEnabled = false;
|
|
|
|
// Emit the signal
|
|
emit lineRequested(sFileName, nLine);
|
|
|
|
// Re-enable history
|
|
if (currentPage() == m_pHistPage)
|
|
m_bHistEnabled = true;
|
|
}
|
|
|
|
/**
|
|
* Update the lock button when the current query page changes.
|
|
* @param pWidget The new current page
|
|
*/
|
|
void QueryWidget::slotCurrentChanged(TQWidget* pWidget)
|
|
{
|
|
QueryPage* pPage;
|
|
|
|
pPage = (QueryPage*)pWidget;
|
|
m_pLockAction->setChecked(pPage->isLocked());
|
|
}
|
|
|
|
/**
|
|
* Removes the given page from the tab widget.
|
|
* This slot is connected to the closeRequest() signal of the KTabBar object.
|
|
* @param pPage The page to close
|
|
*/
|
|
void QueryWidget::slotClosePage(TQWidget* pPage)
|
|
{
|
|
// Prompt the user before closing a locked query
|
|
if (((QueryPage*)pPage)->isLocked()) {
|
|
if (KMessageBox::questionYesNo(NULL, i18n("You about about to close"
|
|
" a locked page.\nAre you sure?")) == KMessageBox::No) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Check if the closed page is the active history page
|
|
if (pPage == m_pHistPage)
|
|
m_pHistPage = NULL;
|
|
// Update the number of open history pages
|
|
else if (dynamic_cast<HistoryPage*>(pPage) == NULL)
|
|
m_nQueryPages--;
|
|
|
|
// Remove the page and delete the object
|
|
m_pQueryTabs->removePage(pPage);
|
|
delete pPage;
|
|
}
|
|
|
|
/**
|
|
* Displays a context menu for page operations.
|
|
* This slot is connected to the contextMenu() signal, emitted by
|
|
* m_pQueryTabs.
|
|
* NOTE: We assume that the first item in the menu is "New".
|
|
* @param pt The point over which the mouse was clicked in request for the
|
|
* context menu
|
|
*/
|
|
void QueryWidget::slotContextMenu(const TQPoint& pt)
|
|
{
|
|
uint i;
|
|
|
|
// Disable everything but the "new" action (clicked outside any widget)
|
|
for (i = 1; i < m_pPageMenu->count(); i++)
|
|
m_pPageMenu->setItemEnabled(m_pPageMenu->idAt(i), false);
|
|
|
|
// Show the menu
|
|
m_pPageMenu->popup(pt);
|
|
}
|
|
|
|
/**
|
|
* Displays a context menu for page operations.
|
|
* This slot is connected to the contextMenu() signal, emitted by
|
|
* m_pQueryTabs.
|
|
* @param pWidget The page under the mouse
|
|
* @param pt The point over which the mouse was clicked in request for
|
|
* the context menu
|
|
*/
|
|
void QueryWidget::slotContextMenu(TQWidget* pWidget, const TQPoint& pt)
|
|
{
|
|
uint i;
|
|
|
|
// Operations are on the current page, so we must ensure the clicked
|
|
// tab becomes the current one
|
|
setCurrentPage(pWidget);
|
|
|
|
// Enable all operations
|
|
for (i = 1; i < m_pPageMenu->count(); i++)
|
|
m_pPageMenu->setItemEnabled(m_pPageMenu->idAt(i), true);
|
|
|
|
// Show the menu
|
|
m_pPageMenu->popup(pt);
|
|
}
|
|
|
|
/**
|
|
* Locks/unlocks the give page.
|
|
* @param pPage The page to lock or unlock
|
|
* @param bLock true to lock the page, false to unlock it
|
|
*/
|
|
void QueryWidget::setPageLocked(QueryPageBase* pPage, bool bLock)
|
|
{
|
|
if (!pPage->canLock())
|
|
return;
|
|
|
|
// Set the locking state of the current page
|
|
pPage->setLocked(bLock);
|
|
m_pQueryTabs->setTabIconSet(pPage, bLock ? GET_PIXMAP(TabLocked) :
|
|
GET_PIXMAP(TabUnlocked));
|
|
|
|
// There can only be one unlocked history page. Check if a non-active
|
|
// query page is being unlocked
|
|
if (isHistoryPage(pPage) && (pPage != m_pHistPage) && !bLock) {
|
|
// Lock the active history page (may be NULL)
|
|
if (m_pHistPage != NULL)
|
|
setPageLocked(m_pHistPage, true);
|
|
|
|
// Set the unlock page as the new active history page
|
|
m_pHistPage = (HistoryPage*)pPage;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Ensures the current page is a query page that is ready to accept new
|
|
* queries.
|
|
* The function first checks the current page. If it is an unlocked query
|
|
* page, then nothing needs to be done. Otherwise, it checks for the first
|
|
* unlocked query page by iterating over all pages in the tab widget. If this
|
|
* fails as well, a new query page is created.
|
|
*/
|
|
void QueryWidget::findQueryPage()
|
|
{
|
|
QueryPage* pPage;
|
|
int nPages, i;
|
|
|
|
// First check if the current page is an unlocked query page
|
|
pPage = dynamic_cast<QueryPage*>(currentPage());
|
|
if (pPage != NULL) {
|
|
if (!pPage->isLocked() && !pPage->isRunning())
|
|
return;
|
|
}
|
|
|
|
// Look for the first unlocked query page
|
|
nPages = m_pQueryTabs->count();
|
|
for (i = 0; i < nPages; i++) {
|
|
pPage = dynamic_cast<QueryPage*>(m_pQueryTabs->page(i));
|
|
if (pPage != NULL) {
|
|
if (!pPage->isLocked() && !pPage->isRunning()) {
|
|
setCurrentPage(pPage);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Couldn't find an unlocked query page, create a new one
|
|
addQueryPage();
|
|
}
|
|
|
|
/**
|
|
* Ensures an active history page exists.
|
|
* The active history page is the only unlocked history page. If one does not
|
|
* exist, it is created.
|
|
*/
|
|
void QueryWidget::findHistoryPage()
|
|
{
|
|
HistoryPage* pPage;
|
|
int nPages, i;
|
|
TQString sTitle;
|
|
|
|
// First check if the active history page is unlocked
|
|
if (m_pHistPage != NULL && !m_pHistPage->isLocked())
|
|
return;
|
|
|
|
// Look for the first unlocked history page
|
|
nPages = m_pQueryTabs->count();
|
|
for (i = 0; i < nPages; i++) {
|
|
pPage = dynamic_cast<HistoryPage*>(m_pQueryTabs->page(i));
|
|
if (pPage != NULL && !pPage->isLocked()) {
|
|
m_pHistPage = pPage;
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Couldn't find an unlocked query page, create a new one
|
|
m_pHistPage = new HistoryPage(this);
|
|
|
|
// Add the page, and set it as the current one
|
|
m_pQueryTabs->insertTab(m_pHistPage, GET_PIXMAP(TabUnlocked), "");
|
|
setPageCaption(m_pHistPage);
|
|
|
|
// Emit the lineRequested() signal when a query record is selected on
|
|
// this page
|
|
connect(m_pHistPage, SIGNAL(lineRequested(const TQString&, uint)), this,
|
|
SLOT(slotRequestLine(const TQString&, uint)));
|
|
}
|
|
|
|
#include "querywidget.moc"
|