diff options
author | Slávek Banko <slavek.banko@axis.cz> | 2013-10-07 23:28:24 +0200 |
---|---|---|
committer | Slávek Banko <slavek.banko@axis.cz> | 2013-10-08 05:14:51 +0200 |
commit | 3af5832abe7c802a384cd58d34f7cc4433595ced (patch) | |
tree | cc300d6fae4cb5798f0cf5db3ece63026f34379a /src/ctagslist.cpp | |
download | kscope-3af5832abe7c802a384cd58d34f7cc4433595ced.tar.gz kscope-3af5832abe7c802a384cd58d34f7cc4433595ced.zip |
Initial import of kscope 1.6.2
Diffstat (limited to 'src/ctagslist.cpp')
-rw-r--r-- | src/ctagslist.cpp | 446 |
1 files changed, 446 insertions, 0 deletions
diff --git a/src/ctagslist.cpp b/src/ctagslist.cpp new file mode 100644 index 0000000..687e9fb --- /dev/null +++ b/src/ctagslist.cpp @@ -0,0 +1,446 @@ +/*************************************************************************** + * + * 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 <qheader.h> +#include <klocale.h> +#include "ctagslist.h" +#include "kscopeconfig.h" +#include "kscopepixmaps.h" + +/** + * Defines a special list item for the tag list. + * This special definition allows the tag list to be sorted according to + * symbol line numbers. By default, all items are treated as text, hence the + * comparison of line numbers such as "123" and "24" sets "24" to be the + * larger item. By overriding the comparison function, this class allows for + * correct sorting. + * @author Elad Lahav + */ +class CtagsListItem : public QListViewItem +{ +public: + /** + * Class constructor. + * @param pParent The owning list view widget + * @param sName The name of the tag + * @param sLine The line in which the tag is defined + * @param sType The type of the tag + */ + CtagsListItem(QListView* pParent, QString sName, QString sLine, + QString sType) : QListViewItem(pParent, sName, sLine, sType), + m_nPendLine (sLine.toUInt()) {} + + /** + * Compares two tag list items, and determines their order. + * If comparison is based on a text-column, the default behaviour is + * used. Otherwise, the text is converted to unsigned integers, and then + * compared as numbers. + * @param pItem The item to compare against the local object + * @param nCol The column index by which to compare + * @param bAscend true if sorting in ascending order, false otherwise + * @return 0 if the items are equal, 1 if the local item is greater, -1 + * if the local item is lesser + */ + virtual int compare(QListViewItem* pItem, int nCol, bool bAscend) const { + if (nCol == 1) { + uint nLineCur, nLineOther; + int nResult; + + // Get the line numbers of each item + nLineCur = text(1).toUInt(); + nLineOther = pItem->text(1).toUInt(); + + // Compare the line numbers + nResult = nLineCur - nLineOther; + if (nResult == 0) + return 0; // Items are equal + else if (nResult > 0) + return 1; // The first item is greater + else + return -1; // The second item is greater + } + + // Use default comparison for text columns + return QListViewItem::compare(pItem, nCol, bAscend); + } + + /** + * @return The line number associated with this item + */ + inline uint getLine() { return m_nPendLine; } + +private: + /** The numeric value of the line number column of this item. */ + uint m_nPendLine; +}; + +/** + * Class constructor. + * @param pParent The parent widget + * @param szName The widget's name + */ +CtagsList::CtagsList(QWidget* pParent, const char* szName) : + SearchList(0, pParent, szName), + m_arrLines(16), + m_nItems(0), + m_nCurItem(0), + m_bReady(false), + m_nCurLine(0), + m_nPendLine(0) +{ + m_pList->setShowSortIndicator(true); + connect(m_pList->header(), SIGNAL(clicked(int)), this, + SLOT(slotSortChanged(int))); + + // Determine the default sorting order + switch (Config().getCtagSortOrder()) { + case KScopeConfig::NameAsc: + m_pList->setSorting(0, true); + break; + + case KScopeConfig::NameDes: + m_pList->setSorting(0, false); + break; + + case KScopeConfig::LineAsc: + m_pList->setSorting(1, true); + break; + + case KScopeConfig::LineDes: + m_pList->setSorting(1, false); + break; + + case KScopeConfig::TypeAsc: + m_pList->setSorting(2, true); + break; + + case KScopeConfig::TypeDes: + m_pList->setSorting(2, false); + break; + } + + // Add the list columns + m_pList->addColumn(i18n("Name")); + m_pList->addColumn(i18n("Line")); + m_pList->addColumn(i18n("Type")); + m_pList->setColumnAlignment(1, Qt::AlignRight); + + // Set colours and font + applyPrefs(); +} + +/** + * Class destructor. + */ +CtagsList::~CtagsList() +{ +} + +/** + * Adds a Ctags output entry to the list. + * This slot is connected to the dataReady() signal of a CtagsFrontend object. + * @param pToken The first token in the entry + */ +void CtagsList::slotDataReady(FrontendToken* pToken) +{ + QString sName, sType, sLine; + CtagsListItem* pItem; + KScopePixmaps::PixName pix; + + // Get the name of the symbol + sName = pToken->getData(); + pToken = pToken->getNext(); + + // Get the line number + sLine = pToken->getData(); + pToken = pToken->getNext(); + + // Get the type of the symbol + sType = pToken->getData(); + pToken = pToken->getNext(); + + // Set the appropriate pixmap + switch (sType[0].latin1()) { + case 'f': + sType = i18n("Function"); + pix = KScopePixmaps::SymFunc; + break; + + case 'v': + sType = i18n("Variable"); + pix = KScopePixmaps::SymVar; + break; + + case 's': + sType = i18n("Struct"); + pix = KScopePixmaps::SymStruct; + break; + + case 'd': + sType = i18n("Macro"); + pix = KScopePixmaps::SymMacro; + break; + + case 'm': + sType = i18n("Member"); + pix = KScopePixmaps::SymMember; + break; + + case 'g': + sType = i18n("Enum"); + pix = KScopePixmaps::SymEnum; + break; + + case 'e': + sType = i18n("Enumerator"); + pix = KScopePixmaps::SymEnumerator; + break; + + case 't': + sType = i18n("Typedef"); + pix = KScopePixmaps::SymTypedef; + break; + + case 'l': + sType = i18n("Label"); + pix = KScopePixmaps::SymLabel; + break; + + case 'i': + sType = i18n("Include"); + pix = KScopePixmaps::SymInclude; + break; + + default: + sType = "Unknown"; + pix = KScopePixmaps::SymUnknown; + } + + // Add a new item to the list + pItem = new CtagsListItem(m_pList, sName, sLine, sType); + pItem->setPixmap(0, Pixmaps().getPixmap(pix)); + m_nItems++; + + // Resize the line array, if required + if (m_arrLines.size() < m_nItems) + m_arrLines.resize(m_nItems, QGArray::SpeedOptim); + + // Add the new item to the line array + m_arrLines[m_nItems - 1] = pItem; +} + +/** + * Handles the "resize" event, which occurs when the size of the widget + * changes. + * @param pEvent The event data + */ +void CtagsList::resizeEvent(QResizeEvent* pEvent) +{ + SearchList::resizeEvent(pEvent); + emit resized(); +} + +/** + * Emits the lineRequested() signal when a list item is selected. + * This function is called if either an item is double-clicked, or an item is + * highlighted and the ENTER key is pressed. + * @param pItem The selected list item + */ +void CtagsList::processItemSelected(QListViewItem* pItem) +{ + QString sLine; + + sLine = pItem->text(1); + emit lineRequested(sLine.toUInt()); +} + +/** + * Constructs a tool-tip for the given item. + * @param pItem The item for which a tip is required + * @param sTip The constructed tip string (on return) + * @return Always true + */ +bool CtagsList::getTip(QListViewItem* pItem, QString& sTip) +{ + sTip = QString("Type: <b>%1</b><br>Name: <b>%2</b><br>Line: <b>%3</b>"). + arg(pItem->text(2)).arg(pItem->text(0)).arg(pItem->text(1)); + return true; +} + +/** + * Sets the list's colours and font, according the user's preferences. + */ +void CtagsList::applyPrefs() +{ + // Apply colour settings + m_pList->setPaletteBackgroundColor(Config().getColor( + KScopeConfig::TagListBack)); + m_pList->setPaletteForegroundColor(Config().getColor( + KScopeConfig::TagListFore)); + m_pList->setFont(Config().getFont(KScopeConfig::TagList)); +} + +/** + * Selects the symbol that dominates the given line in the source file. + * @param nLine The requested line + */ +void CtagsList::gotoLine(uint nLine) +{ + CtagsListItem* pItem; + int nFrom, nTo, nItem, nDiff; + + // Wait until Ctags finishes + if (!m_bReady) { + m_nPendLine = nLine; + return; + } + + // Do nothing if no tags are available + if (m_nItems == 0) + return; + + // Calculate the difference from the current line + nDiff = (int)(nLine - m_nCurLine); + m_nCurLine = nLine; + + // In most cases, all the user does is move to the next or prevuious lines + // Handle these simple cases first + if (nDiff == 1) { + if ((m_nCurItem < m_nItems - 1) && + (m_arrLines[m_nCurItem + 1]->getLine() == nLine)) { + m_nCurItem++; + } + else { + return; // New line corresponds to the same tag + } + } + else if (nDiff == -1) { + if ((m_nCurItem > 0) && + (m_arrLines[m_nCurItem]->getLine() > nLine)) { + m_nCurItem--; + } + else { + return; // New line corresponds to the same tag + } + } + else { + // Initialise binary search + nFrom = 0; + nTo = m_nItems - 1; + m_nCurItem = 0; // use the first item if nothing else works + + // Perform a binary search + // This algorithm finds the greatest line that is smaller or equal to + // the requested line + do { + nItem = (nFrom + nTo) / 2; + pItem = m_arrLines[nItem]; + + if (pItem->getLine() == nLine) { + m_nCurItem = nItem; + break; + } + else if (nLine > pItem->getLine()) { + m_nCurItem = nItem; + nFrom = nItem + 1; + } + else { + nTo = nItem - 1; + } + } while (nFrom <= nTo); + } + + // Mark the selected item + pItem = m_arrLines[m_nCurItem]; + m_pList->setSelected(pItem, true); + m_pList->ensureItemVisible(pItem); + + m_nPendLine = 0; +} + +/** + * Deletes all items in the list. + */ +void CtagsList::clear() +{ + m_pList->clear(); + m_nItems = 0; + m_nCurItem = 0; + m_nCurLine = 0; + m_nPendLine = 0; + m_bReady = false; +} + +/** + * Indicates Ctags has finished processing the current file. + * If a goto operation has been scheduled, it is processed. + * @param nRecords The number of records generated by Ctags + */ +void CtagsList::slotCtagsFinished(uint nRecords) +{ + if (nRecords) { + m_bReady = true; + if (m_nPendLine) + gotoLine(m_nPendLine); + } +} + +/** + * Determines the new sort order in the tags list. + * This slot is connected to the clicked() signal of the tag list's header. + * @param nSection Identifies the column whose header button was clicked. + */ +void CtagsList::slotSortChanged(int nSection) +{ + Qt::SortOrder order; + + // Determine whether the new order is ascending or descending + order = m_pList->sortOrder(); + + // Translate the section number into the order constant + switch (nSection) { + case 0: + // Sort by name + Config().setCtagSortOrder(order == Qt::Ascending ? + KScopeConfig::NameAsc : KScopeConfig::NameDes); + break; + + case 1: + // Sort by line + Config().setCtagSortOrder(order == Qt::Ascending ? + KScopeConfig::LineAsc : KScopeConfig::LineDes); + break; + + case 2: + // Sort by type + Config().setCtagSortOrder(order == Qt::Ascending ? + KScopeConfig::TypeAsc : KScopeConfig::TypeDes); + break; + } +} + +#include "ctagslist.moc" |