SearchIndex::createScoredResults(const std::vector SearchIndex::createScoredResults(const std::vector
elementIds;
result.indices = path.indices;
- result.score = score(path.text, path.indices);
+ result.score = scoreText(path.text, path.indices);
searchResults.insert(result);
if (maxResultCount && searchResults.size() >= maxResultCount)
@@ -260,9 +259,10 @@ std::multiset SearchIndex::createScoredResults(const std::vector* scoresCache) const
+SearchResult SearchIndex::bestScoredResult(
+ SearchResult result, std::map* scoresCache, size_t maxBestScoredLength)
{
- if (result.text.size() > 100)
+ if (maxBestScoredLength && result.text.size() > maxBestScoredLength)
{
return result;
}
@@ -296,7 +296,7 @@ SearchResult SearchIndex::bestScoredResult(SearchResult result, std::map& indices, const size_t indicesPos,
- std::map* scoresCache, SearchResult* result) const
+ std::map* scoresCache, SearchResult* result)
{
// left for debugging
// std::cout << lowerText << std::endl;
@@ -326,7 +326,7 @@ void SearchIndex::bestScoredResultRecursive(
std::vector newIndices = indices;
newIndices[indicesPos] = i;
- int newScore = score(result->text, newIndices);
+ int newScore = scoreText(result->text, newIndices);
if (newScore > result->score)
{
result->score = newScore;
@@ -362,12 +362,13 @@ void SearchIndex::bestScoredResultRecursive(
}
}
-int SearchIndex::score(const std::string& text, const std::vector& indices) const
+int SearchIndex::scoreText(const std::string& text, const std::vector& indices)
{
const int unmatchedLetterBonus = -1;
const int consecutiveLetterBonus = 5;
const int camelCaseBonus = 4;
const int noLetterBonus = 3;
+ const int firstLetterBonus = 4;
const int delayedStartBonus = -1;
const int minDelayedStartBonus = -20;
@@ -375,6 +376,7 @@ int SearchIndex::score(const std::string& text, const std::vector& indic
int consecutiveLetterScore = 0;
int camelCaseScore = 0;
int noLetterScore = 0;
+ int firstLetterScore = 0;
static std::set noLetters;
if (!noLetters.size())
@@ -386,6 +388,8 @@ int SearchIndex::score(const std::string& text, const std::vector& indic
noLetters.insert(':');
noLetters.insert('<');
noLetters.insert('>');
+ noLetters.insert('/');
+ noLetters.insert('\\');
}
for (size_t i = 0; i < indices.size(); i++)
@@ -399,9 +403,13 @@ int SearchIndex::score(const std::string& text, const std::vector& indic
size_t index = indices[i];
+ // first letter
+ if (index == 0)
+ {
+ firstLetterScore += firstLetterBonus;
+ }
// after no letter
- bool prevIsNoLetter = (index == 0 || noLetters.find(text[index - 1]) != noLetters.end());
- if (prevIsNoLetter)
+ else if ((index != 0 && noLetters.find(text[index - 1]) != noLetters.end()))
{
noLetterScore += noLetterBonus;
}
@@ -416,6 +424,8 @@ int SearchIndex::score(const std::string& text, const std::vector& indic
camelCaseScore += camelCaseBonus;
}
}
+
+
}
int leadingStartScore = std::max(int(indices[0]) * delayedStartBonus, minDelayedStartBonus);
@@ -425,7 +435,66 @@ int SearchIndex::score(const std::string& text, const std::vector& indic
consecutiveLetterScore +
camelCaseScore +
noLetterScore +
+ firstLetterScore +
leadingStartScore;
return score;
}
+
+SearchResult SearchIndex::rescoreText(
+ const std::string& fulltext,
+ const std::string& text,
+ const std::vector& indices,
+ int score,
+ size_t maxBestScoredLength)
+{
+ SearchResult result;
+ result.text = text;
+ result.score = score;
+ result.indices = indices;
+
+ std::vector textIndices;
+
+ // match is already within text
+ int newIdx = indices[0] - (fulltext.size() - text.size());
+ if (newIdx >= 0)
+ {
+ for (size_t idx : indices)
+ {
+ textIndices.push_back(idx - (fulltext.size() - text.size()));
+ }
+ }
+ // try if match is within text
+ else
+ {
+ size_t idx = 0;
+ for (size_t i = 0; i < text.size() && idx < indices.size(); i++)
+ {
+ if (tolower(text[i]) == tolower(fulltext[indices[idx]]))
+ {
+ textIndices.push_back(i);
+ idx++;
+ }
+ }
+
+ // match was not found
+ if (idx != indices.size())
+ {
+ result.score -= 1;
+ return result;
+ }
+ }
+
+ result.score = scoreText(text, textIndices);
+ result.indices = textIndices;
+
+ std::map scoresCache;
+ result = bestScoredResult(result, &scoresCache, maxBestScoredLength);
+
+ for (size_t i = 0; i < result.indices.size(); i++)
+ {
+ result.indices[i] += fulltext.size() - text.size();
+ }
+
+ return result;
+}
diff --git a/src/lib/data/search/SearchIndex.h b/src/lib/data/search/SearchIndex.h
index 46bb6f46..902b1efb 100644
--- a/src/lib/data/search/SearchIndex.h
+++ b/src/lib/data/search/SearchIndex.h
@@ -8,20 +8,19 @@
#include
#include
-#include "data/name/NameHierarchy.h"
#include "utility/types.h"
struct SearchResult
{
- std::string text;
- std::set elementIds;
- std::vector indices;
- int score;
-
bool operator<(const SearchResult& other) const
{
return score > other.score;
}
+
+ std::string text;
+ std::set elementIds;
+ std::vector indices;
+ int score;
};
class SearchIndex
@@ -30,12 +29,12 @@ public:
SearchIndex();
virtual ~SearchIndex();
- void addNode(Id id, const NameHierarchy& nameHierarchy);
+ void addNode(Id id, const std::string& name);
void finishSetup();
void clear();
// maxResultCount == 0 means "no restriction".
- std::vector search(const std::string& query, size_t maxResultCount) const;
+ std::vector search(const std::string& query, size_t maxResultCount, size_t maxBestScoredLength = 0) const;
private:
struct Node;
@@ -65,12 +64,23 @@ private:
void searchRecursive(const Path& path, const std::string& remainingQuery, std::vector* results) const;
std::multiset createScoredResults(const std::vector& paths, size_t maxResultCount) const;
- SearchResult bestScoredResult(SearchResult result, std::map* scoresCache) const;
- void bestScoredResultRecursive(
- const std::string& lowerText, const std::vector& indices, const size_t indicesPos,
- std::map* scoresCache, SearchResult* result) const;
- int score(const std::string& text, const std::vector& indices) const;
+ static SearchResult bestScoredResult(
+ SearchResult result, std::map* scoresCache, size_t maxBestScoredLength);
+ static void bestScoredResultRecursive(
+ const std::string& lowerText, const std::vector& indices, const size_t indicesPos,
+ std::map* scoresCache, SearchResult* result);
+ static int scoreText(const std::string& text, const std::vector& indices);
+
+public:
+ static SearchResult rescoreText(
+ const std::string& fulltext,
+ const std::string& text,
+ const std::vector& indices,
+ int score,
+ size_t maxBestScoredLength = 0);
+
+private:
std::vector> m_nodes;
std::vector> m_edges;
Node* m_root;
diff --git a/src/lib/data/search/SearchMatch.cpp b/src/lib/data/search/SearchMatch.cpp
index 61f1df30..87a2c829 100644
--- a/src/lib/data/search/SearchMatch.cpp
+++ b/src/lib/data/search/SearchMatch.cpp
@@ -49,7 +49,8 @@ std::string SearchMatch::searchMatchesToString(const std::vector& m
SearchMatch SearchMatch::createCommand(CommandType type)
{
SearchMatch match;
- match.text = getCommandName(type);
+ match.name = getCommandName(type);
+ match.text = match.name;
match.typeName = "command";
match.searchType = SEARCH_COMMAND;
return match;
@@ -96,13 +97,60 @@ SearchMatch::SearchMatch()
}
SearchMatch::SearchMatch(const std::string& query)
- : text(query)
+ : name(query)
, typeName("")
, searchType(SEARCH_NONE)
, hasChildren(false)
{
}
+
+bool SearchMatch::operator<(const SearchMatch& other) const
+{
+ // score
+ if (score > other.score)
+ {
+ return true;
+ }
+ else if (score < other.score)
+ {
+ return false;
+ }
+
+ // text size
+ if (text.size() < other.text.size())
+ {
+ return true;
+ }
+ else if (text.size() > other.text.size())
+ {
+ return false;
+ }
+
+ // lower case
+ for (size_t i = 0; i < text.size(); i++)
+ {
+ if (tolower(text[i]) != tolower(other.text[i]))
+ {
+ return tolower(text[i]) < tolower(other.text[i]);
+ }
+ else
+ {
+ // alphabetical
+ if (text[i] < other.text[i])
+ {
+ return true;
+ }
+ else if (text[i] > other.text[i])
+ {
+ return false;
+ }
+ }
+ }
+
+ return false;
+}
+
bool SearchMatch::isValid() const
{
return searchType != SEARCH_NONE;
@@ -110,7 +158,7 @@ bool SearchMatch::isValid() const
void SearchMatch::print(std::ostream& ostream) const
{
- ostream << text << std::endl << '\t';
+ ostream << name << std::endl << '\t';
size_t i = 0;
for (size_t index : indices)
{
@@ -127,7 +175,12 @@ void SearchMatch::print(std::ostream& ostream) const
std::string SearchMatch::getFullName() const
{
- return text;
+ if (searchType == SEARCH_TOKEN && nodeType == Node::NODE_FILE)
+ {
+ return text;
+ }
+
+ return name;
}
std::string SearchMatch::getNodeTypeAsString() const
diff --git a/src/lib/data/search/SearchMatch.h b/src/lib/data/search/SearchMatch.h
index b8768a99..b8684bb8 100644
--- a/src/lib/data/search/SearchMatch.h
+++ b/src/lib/data/search/SearchMatch.h
@@ -41,6 +41,8 @@ struct SearchMatch
SearchMatch();
SearchMatch(const std::string& query);
+ bool operator<(const SearchMatch& other) const;
+
bool isValid() const;
void print(std::ostream& ostream) const;
@@ -49,12 +51,19 @@ struct SearchMatch
std::string getNodeTypeAsString() const;
std::string getSearchTypeName() const;
+ std::string name;
+
std::string text;
+ std::string subtext;
+
std::string typeName;
+
Node::NodeType nodeType;
SearchType searchType;
std::vector indices;
+ int score;
+
std::vector nameHierarchies;
bool hasChildren;
diff --git a/src/lib_gui/qt/element/QtAutocompletionList.cpp b/src/lib_gui/qt/element/QtAutocompletionList.cpp
index 6d3be70b..070aa5e6 100644
--- a/src/lib_gui/qt/element/QtAutocompletionList.cpp
+++ b/src/lib_gui/qt/element/QtAutocompletionList.cpp
@@ -4,8 +4,10 @@
#include
#include "component/view/GraphViewStyle.h"
+#include "qt/utility/QtDeviceScaledPixmap.h"
#include "settings/ApplicationSettings.h"
#include "settings/ColorScheme.h"
+#include "utility/ResourcePaths.h"
QtAutocompletionModel::QtAutocompletionModel(QObject* parent)
: QAbstractTableModel(parent)
@@ -30,7 +32,7 @@ int QtAutocompletionModel::rowCount(const QModelIndex &parent) const
int QtAutocompletionModel::columnCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
- return 4;
+ return 6;
}
QVariant QtAutocompletionModel::data(const QModelIndex &index, int role) const
@@ -45,10 +47,14 @@ QVariant QtAutocompletionModel::data(const QModelIndex &index, int role) const
switch (index.column())
{
case 0:
- return QString::fromStdString(match.getFullName());
+ return QString::fromStdString(match.name);
case 1:
- return QString::fromStdString(match.typeName);
+ return QString::fromStdString(match.text);
case 2:
+ return QString::fromStdString(match.subtext);
+ case 3:
+ return QString::fromStdString(match.typeName);
+ case 4:
{
QList indices;
for (const size_t idx : match.indices)
@@ -57,7 +63,7 @@ QVariant QtAutocompletionModel::data(const QModelIndex &index, int role) const
}
return indices;
}
- case 3:
+ case 5:
return match.nodeType;
default:
return QVariant();
@@ -73,10 +79,52 @@ const SearchMatch* QtAutocompletionModel::getSearchMatchAt(int idx) const
return nullptr;
}
-
-QtAutocompletionDelegate::QtAutocompletionDelegate(QObject* parent)
- : QStyledItemDelegate(parent)
+QString QtAutocompletionModel::longestText() const
{
+ std::string str;
+ for (const SearchMatch& match : m_matchList)
+ {
+ if (match.text.size() > str.size())
+ {
+ str = match.text;
+ }
+ }
+ return QString::fromStdString(str);
+}
+
+QString QtAutocompletionModel::longestSubText() const
+{
+ std::string str;
+ for (const SearchMatch& match : m_matchList)
+ {
+ if (match.subtext.size() > str.size())
+ {
+ str = match.subtext;
+ }
+ }
+ return QString::fromStdString(str);
+}
+
+QString QtAutocompletionModel::longestType() const
+{
+ std::string str;
+ for (const SearchMatch& match : m_matchList)
+ {
+ if (match.typeName.size() > str.size())
+ {
+ str = match.typeName;
+ }
+ }
+ return QString::fromStdString(str);
+}
+
+
+QtAutocompletionDelegate::QtAutocompletionDelegate(QtAutocompletionModel* model, QObject* parent)
+ : QStyledItemDelegate(parent)
+ , m_model(model)
+ , m_arrow()
+{
+ resetCharSizes();
}
QtAutocompletionDelegate::~QtAutocompletionDelegate()
@@ -87,108 +135,219 @@ void QtAutocompletionDelegate::paint(QPainter* painter, const QStyleOptionViewIt
{
painter->save();
- ColorScheme* scheme = ColorScheme::getInstance().get();
-
- if (option.state & QStyle::State_Selected)
- {
- painter->fillRect(option.rect, option.palette.color(QPalette::Highlight));
- }
- else
- {
- painter->fillRect(option.rect, option.palette.color(QPalette::Base));
- }
-
+ // get data
QString name = index.data().toString();
+ QString text = index.sibling(index.row(), index.column() + 1).data().toString();
+ QString subtext = index.sibling(index.row(), index.column() + 2).data().toString();
+ QString type = index.sibling(index.row(), index.column() + 3).data().toString();
+ QList indices = index.sibling(index.row(), index.column() + 4).data().toList();
+ Node::NodeType nodeType = static_cast(index.sibling(index.row(), index.column() + 5).data().toInt());
-
- QString type = index.sibling(index.row(), index.column() + 1).data().toString();
- QColor color("#FFFFFF");
+ // define highlight colors
+ ColorScheme* scheme = ColorScheme::getInstance().get();
+ QColor fillColor("#FFFFFF");
QColor textColor("#000000");
- Node::NodeType nodeType = static_cast(index.sibling(index.row(), index.column() + 3).data().toInt());
if (type.size() && type != "command")
{
const GraphViewStyle::NodeColor& nodeColor = GraphViewStyle::getNodeColor(Node::getTypeString(nodeType), false);
- color = QColor(nodeColor.fill.c_str());
+ fillColor = QColor(nodeColor.fill.c_str());
textColor = QColor(nodeColor.text.c_str());
}
else
{
- color = QColor(scheme->getSearchTypeColor(SearchMatch::getSearchTypeName(SearchMatch::SEARCH_COMMAND), "fill").c_str());
+ fillColor = QColor(scheme->getSearchTypeColor(SearchMatch::getSearchTypeName(SearchMatch::SEARCH_COMMAND), "fill").c_str());
textColor = QColor(scheme->getSearchTypeColor(SearchMatch::getSearchTypeName(SearchMatch::SEARCH_COMMAND), "text").c_str());
}
- float charWidth = option.fontMetrics.width(
- "----------------------------------------------------------------------------------------------------"
- "----------------------------------------------------------------------------------------------------"
- "----------------------------------------------------------------------------------------------------"
- "----------------------------------------------------------------------------------------------------"
- "----------------------------------------------------------------------------------------------------"
- ) / 500.0f;
+ int top1 = 6;
+ int top2 = m_charHeight1 + 3;
- QString highlightName(name.size(), ' ');
+ // draw background
+ QColor backgroundColor = option.palette.color((option.state & QStyle::State_Selected ? QPalette::Highlight : QPalette::Base));
+ painter->fillRect(option.rect, backgroundColor);
- QList indices = index.sibling(index.row(), index.column() + 2).data().toList();
+ // draw highlights at indices
+ QString highlightText(text.size(), ' ');
if (indices.size())
{
for (int i = 0; i < indices.size(); i++)
{
- int idx = indices[i].toInt();
+ int idx = indices[i].toInt() - (name.size() - text.size());
+ if (idx < 0)
+ {
+ continue;
+ }
- QRect rect = option.rect.adjusted(charWidth * (idx + 1) + 2, 2, 0, -1);
- rect.setWidth(charWidth + 1);
- painter->fillRect(rect, color);
+ QRect rect(
+ option.rect.left() + m_charWidth1 * (idx + 1) + 2,
+ option.rect.top() + top1 - 1,
+ m_charWidth1 + 1,
+ m_charHeight1 - 1
+ );
+ painter->fillRect(rect, fillColor);
- highlightName[idx] = name.at(idx);
- name[idx] = ' ';
+ highlightText[idx] = text.at(idx);
+ text[idx] = ' ';
}
}
else
{
- QRect rect = option.rect.adjusted(0, 2, 0, -1);
- rect.setWidth(charWidth - 1);
- painter->fillRect(rect, color);
+ QRect rect(option.rect.left(), option.rect.top() + top1, m_charWidth1 - 1, m_charHeight1 - 2);
+ painter->fillRect(rect, fillColor);
}
- painter->drawText(option.rect.adjusted(charWidth + 2, -1, 0, 0), Qt::AlignLeft, name);
+ // draw text normal
+ painter->drawText(option.rect.adjusted(m_charWidth1 + 2, top1 - 3, 0, 0), Qt::AlignLeft, text);
+ // draw text highlighted
painter->save();
QPen highlightPen = painter->pen();
highlightPen.setColor(textColor);
painter->setPen(highlightPen);
- painter->drawText(option.rect.adjusted(charWidth + 2, -1, 0, 0), Qt::AlignLeft, highlightName);
+ painter->drawText(option.rect.adjusted(m_charWidth1 + 2, top1 - 3, 0, 0), Qt::AlignLeft, highlightText);
painter->restore();
- if (type.size())
+ // draw subtext
+ if (subtext.size())
{
- QFont font = painter->font();
- font.setPixelSize(ApplicationSettings::getInstance()->getFontSize() - 4);
- painter->setFont(font);
+ // draw arrow icon
+ painter->drawPixmap(
+ option.rect.left() + m_charWidth2 * 2,
+ option.rect.top() + top2 + 1 + (m_charHeight2 - m_arrow.height()) / 2,
+ m_arrow.pixmap()
+ );
+
+ painter->setFont(m_font2);
+
+ QString highlightSubtext(subtext.size(), ' ');
+ if (indices.size())
+ {
+ for (int i = 0; i < indices.size(); i++)
+ {
+ int idx = indices[i].toInt();
+ if (idx >= subtext.size())
+ {
+ continue;
+ }
+
+ QRect rect(
+ option.rect.left() + m_charWidth2 * (idx + 3) + 2,
+ option.rect.top() + top2 + 1,
+ m_charWidth2 + 1,
+ m_charHeight2
+ );
+ painter->fillRect(rect, fillColor);
+
+ highlightSubtext[idx] = subtext.at(idx);
+ subtext[idx] = ' ';
+ }
+ }
QPen typePen = painter->pen();
typePen.setColor(scheme->getColor("search/popup/by_text").c_str());
painter->setPen(typePen);
- painter->drawText(option.rect.adjusted(0, 3, -charWidth, 0), Qt::AlignRight, type);
+ // draw subtext normal
+ painter->drawText(option.rect.adjusted((3 * m_charWidth2) + 2, top2, 0, 0), Qt::AlignLeft, subtext);
+
+ // draw subtext highlighted
+ painter->save();
+ QPen highlightPen = painter->pen();
+ highlightPen.setColor(textColor);
+ painter->setPen(highlightPen);
+ painter->drawText(option.rect.adjusted((3 * m_charWidth2) + 2, top2, 0, 0), Qt::AlignLeft, highlightSubtext);
+ painter->restore();
}
+ // draw type
+ if (type.size())
+ {
+ painter->setFont(m_font2);
+
+ QPen typePen = painter->pen();
+ typePen.setColor(scheme->getColor("search/popup/by_text").c_str());
+ painter->setPen(typePen);
+
+ int width = m_charWidth2 * type.size();
+ int x = painter->viewport().right() - width - m_charWidth2;
+ int y = option.rect.top() + top2;
+
+ painter->fillRect(QRect(x - m_charWidth2, y, width + m_charWidth2 * 3, m_charHeight2 + 2), backgroundColor);
+ painter->drawText(QRect(x, y, width, m_charHeight2), Qt::AlignRight, type);
+ }
+
+ // draw bottom line
+ QRect rect(0, option.rect.bottom(), option.rect.width(), 1);
+ painter->fillRect(rect, scheme->getColor("search/popup/line").c_str());
+
painter->restore();
}
QSize QtAutocompletionDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
{
- QString name = index.data().toString();
- QString type = index.sibling(index.row(), index.column() + 1).data().toString();
- return QSize(option.fontMetrics.width(name + type) + 5, option.fontMetrics.height());
+ const_cast(this)->calculateCharSizes(option.font);
+
+ QString text = m_model->longestText();
+ QString subtext = m_model->longestSubText();
+ QString type = m_model->longestType();
+
+ return QSize(
+ std::max((text.size() + 2) * m_charWidth1, (subtext.size() + type.size() + 6) * m_charWidth2),
+ m_charHeight1 * 2 + 3
+ );
}
+void QtAutocompletionDelegate::calculateCharSizes(QFont font)
+{
+ if (m_charWidth1 > 0)
+ {
+ return;
+ }
+
+ m_font1 = font;
+
+ QFontMetrics metrics1(font);
+ m_charWidth1 = metrics1.width(
+ "----------------------------------------------------------------------------------------------------"
+ "----------------------------------------------------------------------------------------------------"
+ "----------------------------------------------------------------------------------------------------"
+ "----------------------------------------------------------------------------------------------------"
+ "----------------------------------------------------------------------------------------------------"
+ ) / 500.0f;
+ m_charHeight1 = metrics1.height();
+
+ font.setPixelSize(ApplicationSettings::getInstance()->getFontSize() - 3);
+ m_font2 = font;
+
+ QFontMetrics metrics2(font);
+ m_charWidth2 = metrics2.width(
+ "----------------------------------------------------------------------------------------------------"
+ "----------------------------------------------------------------------------------------------------"
+ "----------------------------------------------------------------------------------------------------"
+ "----------------------------------------------------------------------------------------------------"
+ "----------------------------------------------------------------------------------------------------"
+ ) / 500.0f;
+ m_charHeight2 = metrics2.height();
+
+ m_arrow = QtDeviceScaledPixmap(QString::fromStdString(ResourcePaths::getGuiPath() + "search_view/images/arrow.png"));
+ m_arrow.scaleToWidth(m_charWidth2);
+ m_arrow.colorize(ColorScheme::getInstance()->getColor("search/popup/by_text").c_str());
+}
+
+void QtAutocompletionDelegate::resetCharSizes()
+{
+ m_charWidth1 = m_charHeight1 = m_charWidth2 = m_charHeight2 = 0.0f;
+}
+
+
QtAutocompletionList::QtAutocompletionList(QWidget* parent)
: QCompleter(parent)
{
m_model = std::make_shared(this);
setModel(m_model.get());
- m_delegate = std::make_shared(this);
+ m_delegate = std::make_shared(m_model.get(), this);
QListView* list = new QListView(parent);
list->setItemDelegateForColumn(0, m_delegate.get());
@@ -201,7 +360,7 @@ QtAutocompletionList::QtAutocompletionList(QWidget* parent)
setCompletionMode(QCompleter::UnfilteredPopupCompletion);
setModelSorting(QCompleter::UnsortedModel);
setCompletionPrefix("");
- setMaxVisibleItems(20);
+ setMaxVisibleItems(8);
m_scrollSpeedChangeListenerHorizontal.setScrollBar(list->horizontalScrollBar());
m_scrollSpeedChangeListenerVertical.setScrollBar(list->verticalScrollBar());
@@ -222,6 +381,8 @@ void QtAutocompletionList::completeAt(const QPoint& pos, const std::vectorresetCharSizes();
+
disconnect(); // must be done because of a bug where signals are no longer received by QtSmartSearchBox
connect(this, SIGNAL(highlighted(const QModelIndex&)), this, SLOT(onHighlighted(const QModelIndex&)), Qt::DirectConnection);
connect(this, SIGNAL(activated(const QModelIndex&)), this, SLOT(onActivated(const QModelIndex&)), Qt::DirectConnection);
diff --git a/src/lib_gui/qt/element/QtAutocompletionList.h b/src/lib_gui/qt/element/QtAutocompletionList.h
index bdbd690e..ad811c46 100644
--- a/src/lib_gui/qt/element/QtAutocompletionList.h
+++ b/src/lib_gui/qt/element/QtAutocompletionList.h
@@ -10,6 +10,7 @@
#include
#include "data/search/SearchMatch.h"
+#include "qt/utility/QtDeviceScaledPixmap.h"
#include "qt/utility/QtScrollSpeedChangeListener.h"
class QtAutocompletionModel
@@ -30,6 +31,10 @@ public:
const SearchMatch* getSearchMatchAt(int idx) const;
+ QString longestText() const;
+ QString longestSubText() const;
+ QString longestType() const;
+
private:
std::vector m_matchList;
};
@@ -39,11 +44,27 @@ class QtAutocompletionDelegate
: public QStyledItemDelegate
{
public:
- explicit QtAutocompletionDelegate(QObject* parent = 0);
+ explicit QtAutocompletionDelegate(QtAutocompletionModel* model, QObject* parent = 0);
virtual ~QtAutocompletionDelegate();
virtual void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
virtual QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const;
+
+ void calculateCharSizes(QFont font);
+ void resetCharSizes();
+
+private:
+ QtAutocompletionModel* m_model;
+
+ QFont m_font1;
+ QFont m_font2;
+
+ float m_charWidth1;
+ float m_charHeight1;
+ float m_charWidth2;
+ float m_charHeight2;
+
+ QtDeviceScaledPixmap m_arrow;
};
diff --git a/src/lib_gui/qt/element/QtSmartSearchBox.cpp b/src/lib_gui/qt/element/QtSmartSearchBox.cpp
index 6e48ad1f..22caa824 100644
--- a/src/lib_gui/qt/element/QtSmartSearchBox.cpp
+++ b/src/lib_gui/qt/element/QtSmartSearchBox.cpp
@@ -146,11 +146,11 @@ bool QtSmartSearchBox::event(QEvent *event)
{
if (m_highlightedMatch.hasChildren)
{
- setEditText((m_highlightedMatch.text + NameHierarchy::getDelimiter()).c_str());
+ setEditText((m_highlightedMatch.getFullName() + NameHierarchy::getDelimiter()).c_str());
}
else
{
- setEditText(m_highlightedMatch.text.c_str());
+ setEditText(m_highlightedMatch.getFullName().c_str());
}
requestAutoCompletions();
@@ -456,7 +456,7 @@ void QtSmartSearchBox::onTextEdited(const QString& text)
}
}
- if (match.text.size() && !m_allowMultipleElements)
+ if (match.name.size() && !m_allowMultipleElements)
{
if (m_matches.size())
{
@@ -475,7 +475,7 @@ void QtSmartSearchBox::onTextEdited(const QString& text)
layoutElements();
}
- if (match.text.size() || m_elements.size())
+ if (match.name.size() || m_elements.size())
{
requestAutoCompletions();
}
@@ -510,7 +510,7 @@ void QtSmartSearchBox::onAutocompletionActivated(const SearchMatch& match)
{
addMatchAndUpdate(match);
- if (match.text.size())
+ if (match.name.size())
{
search();
}
@@ -580,7 +580,7 @@ void QtSmartSearchBox::moveCursorTo(int target)
void QtSmartSearchBox::addMatch(const SearchMatch& match)
{
- if (!match.text.size())
+ if (!match.name.size())
{
return;
}
@@ -607,7 +607,7 @@ void QtSmartSearchBox::addMatch(const SearchMatch& match)
void QtSmartSearchBox::addMatchAndUpdate(const SearchMatch& match)
{
- if (match.text.size())
+ if (match.name.size())
{
m_oldText.clear();
clearLineEdit();
diff --git a/src/lib_gui/qt/utility/QtDeviceScaledPixmap.cpp b/src/lib_gui/qt/utility/QtDeviceScaledPixmap.cpp
index 8beaa0e6..bb83d3ad 100644
--- a/src/lib_gui/qt/utility/QtDeviceScaledPixmap.cpp
+++ b/src/lib_gui/qt/utility/QtDeviceScaledPixmap.cpp
@@ -2,12 +2,18 @@
#include
+#include "qt/utility/utilityQt.h"
+
qreal QtDeviceScaledPixmap::devicePixelRatio()
{
QApplication* app = dynamic_cast(QCoreApplication::instance());
return app->devicePixelRatio();
}
+QtDeviceScaledPixmap::QtDeviceScaledPixmap()
+{
+}
+
QtDeviceScaledPixmap::QtDeviceScaledPixmap(QString filePath)
: m_pixmap(filePath)
{
@@ -48,3 +54,8 @@ void QtDeviceScaledPixmap::mirror(bool horizontal, bool vertical)
m_pixmap = QPixmap::fromImage(m_pixmap.toImage().mirrored(horizontal, vertical));
m_pixmap.setDevicePixelRatio(devicePixelRatio());
}
+
+void QtDeviceScaledPixmap::colorize(QColor color)
+{
+ m_pixmap = utility::colorizePixmap(m_pixmap, color);
+}
diff --git a/src/lib_gui/qt/utility/QtDeviceScaledPixmap.h b/src/lib_gui/qt/utility/QtDeviceScaledPixmap.h
index 706ae607..1b7371e9 100644
--- a/src/lib_gui/qt/utility/QtDeviceScaledPixmap.h
+++ b/src/lib_gui/qt/utility/QtDeviceScaledPixmap.h
@@ -8,7 +8,8 @@ class QtDeviceScaledPixmap
public:
static qreal devicePixelRatio();
- explicit QtDeviceScaledPixmap(QString filePath);
+ QtDeviceScaledPixmap();
+ QtDeviceScaledPixmap(QString filePath);
virtual ~QtDeviceScaledPixmap();
const QPixmap& pixmap() const;
@@ -20,6 +21,7 @@ public:
void scaleToHeight(int height);
void mirror(bool horizontal = false, bool vertical = true);
+ void colorize(QColor color);
private:
QPixmap m_pixmap;
diff --git a/src/test/SearchIndexTestSuite.h b/src/test/SearchIndexTestSuite.h
index 31ff1d74..211c7ef3 100644
--- a/src/test/SearchIndexTestSuite.h
+++ b/src/test/SearchIndexTestSuite.h
@@ -11,7 +11,7 @@ public:
void test_search_index_finds_id_of_element_added()
{
SearchIndex index;
- index.addNode(1, NameHierarchy::deserialize("foo\tsvoid\tp() const"));
+ index.addNode(1, NameHierarchy::deserialize("foo\tsvoid\tp() const").getQualifiedName());
index.finishSetup();
std::vector results = index.search("oo", 0);
@@ -23,7 +23,7 @@ public:
void test_search_index_finds_correct_indices_for_query()
{
SearchIndex index;
- index.addNode(1, NameHierarchy::deserialize("foo\tsvoid\tp() const"));
+ index.addNode(1, NameHierarchy::deserialize("foo\tsvoid\tp() const").getQualifiedName());
index.finishSetup();
std::vector results = index.search("oo", 0);
@@ -36,8 +36,8 @@ public:
void test_search_index_finds_ids_for_ambiguous_query()
{
SearchIndex index;
- index.addNode(1, NameHierarchy::deserialize("for\tsvoid\tp() const"));
- index.addNode(2, NameHierarchy::deserialize("fos\tsvoid\tp() const"));
+ index.addNode(1, NameHierarchy::deserialize("for\tsvoid\tp() const").getQualifiedName());
+ index.addNode(2, NameHierarchy::deserialize("fos\tsvoid\tp() const").getQualifiedName());
index.finishSetup();
std::vector results = index.search("fo", 0);
@@ -51,7 +51,7 @@ public:
void test_search_index_does_not_find_anything_after_clear()
{
SearchIndex index;
- index.addNode(1, NameHierarchy::deserialize("foo\tsvoid\tp() const"));
+ index.addNode(1, NameHierarchy::deserialize("foo\tsvoid\tp() const").getQualifiedName());
index.finishSetup();
index.clear();
std::vector results = index.search("oo", 0);
@@ -62,8 +62,8 @@ public:
void test_search_index_does_not_find_all_results_when_max_amount_is_limited()
{
SearchIndex index;
- index.addNode(1, NameHierarchy::deserialize("foo1\tsvoid\tp() const"));
- index.addNode(2, NameHierarchy::deserialize("foo2\tsvoid\tp() const"));
+ index.addNode(1, NameHierarchy::deserialize("foo1\tsvoid\tp() const").getQualifiedName());
+ index.addNode(2, NameHierarchy::deserialize("foo2\tsvoid\tp() const").getQualifiedName());
index.finishSetup();
std::vector results = index.search("oo", 1);
@@ -73,8 +73,8 @@ public:
void test_search_index_query_is_case_insensitive()
{
SearchIndex index;
- index.addNode(1, NameHierarchy::deserialize("foo1\tsvoid\tp() const"));
- index.addNode(2, NameHierarchy::deserialize("FOO2\tsvoid\tp() const"));
+ index.addNode(1, NameHierarchy::deserialize("foo1\tsvoid\tp() const").getQualifiedName());
+ index.addNode(2, NameHierarchy::deserialize("FOO2\tsvoid\tp() const").getQualifiedName());
index.finishSetup();
std::vector results = index.search("oo", 0);
@@ -85,8 +85,8 @@ public:
{
SearchIndex index;
- index.addNode(1, NameHierarchy::deserialize("oaabbcc\tsvoid\tp() const"));
- index.addNode(2, NameHierarchy::deserialize("ocbcabc\tsvoid\tp() const"));
+ index.addNode(1, NameHierarchy::deserialize("oaabbcc\tsvoid\tp() const").getQualifiedName());
+ index.addNode(2, NameHierarchy::deserialize("ocbcabc\tsvoid\tp() const").getQualifiedName());
index.finishSetup();
std::vector results = index.search("abc", 0);