ui: Added on-screen search feature (issue #79)

* Use menu action "Edit -> Find in View" or Ctrl + D
* UI displayed as search bar at bottom of main window
* Hide search bar with ECS or close button
* Entering a query searches in name of graph nodes and code contents of code view
* Use Enter to iterate through matches, well move match into view in graph and code view
* Checkboxes allow for adding/removing results for certain views
* Create Bookmark shortcut is now CTRL + S

bug id = 79
This commit is contained in:
Eberhard Graether
2017-09-19 14:00:40 +02:00
parent 4731f379f4
commit 95ef8c3eec
64 changed files with 1642 additions and 174 deletions
@@ -2,6 +2,7 @@
#include <QBrush>
#include <QFont>
#include <QFontMetrics>
#include <QGraphicsSceneEvent>
#include <QPen>
@@ -11,6 +12,7 @@
#include "qt/view/graphElements/nodeComponents/QtGraphNodeComponent.h"
#include "qt/view/graphElements/QtGraphEdge.h"
#include "utility/ResourcePaths.h"
#include "utility/utilityString.h"
void QtGraphNode::blendIn()
{
@@ -40,10 +42,6 @@ QFont QtGraphNode::getFontForNodeType(Node::NodeType type)
}
QtGraphNode::QtGraphNode()
: m_icon(nullptr)
, m_isActive(false)
, m_multipleActive(false)
, m_isHovering(false)
{
this->setPen(QPen(Qt::transparent));
@@ -244,6 +242,35 @@ void QtGraphNode::focusOut()
updateStyle();
}
void QtGraphNode::matchNameRecursive(const std::string& query, std::vector<QtGraphNode*>* matchedNodes)
{
matchName(query, matchedNodes);
for (auto subNode : m_subNodes)
{
subNode->matchNameRecursive(query, matchedNodes);
}
}
void QtGraphNode::removeNameMatch()
{
if (m_matchLength)
{
m_matchRect->hide();
m_matchText->hide();
m_matchPos = 0;
m_matchLength = 0;
updateStyle();
}
}
void QtGraphNode::setActiveMatch(bool active)
{
m_isActiveMatch = active;
}
bool QtGraphNode::isDataNode() const
{
return false;
@@ -407,6 +434,40 @@ void QtGraphNode::notifyEdgesAfterMove()
}
}
void QtGraphNode::matchName(const std::string& query, std::vector<QtGraphNode*>* matchedNodes)
{
m_isActiveMatch = false;
std::string name = getName();
size_t pos = utility::toLowerCase(name).find(query);
if (pos != std::string::npos)
{
if (!m_matchText)
{
m_matchRect = new QtRoundedRectItem(this);
m_matchText = new QGraphicsSimpleTextItem(this);
}
m_matchRect->show();
m_matchText->show();
std::string matchName(name.length(), ' ');
matchName.replace(pos, query.length(), name.substr(pos, query.length()));
m_matchText->setText(matchName.c_str());
matchedNodes->push_back(this);
m_matchPos = pos;
m_matchLength = query.length();
updateStyle();
}
else if (m_matchLength)
{
removeNameMatch();
}
}
void QtGraphNode::setStyle(const GraphViewStyle::NodeStyle& style)
{
QPen pen(Qt::transparent);
@@ -462,4 +523,25 @@ void QtGraphNode::setStyle(const GraphViewStyle::NodeStyle& style)
m_text->setFont(font);
m_text->setBrush(QBrush(style.color.text.c_str()));
m_text->setPos(style.iconOffset.x + style.iconSize + style.textOffset.x, style.textOffset.y);
if (m_matchLength)
{
GraphViewStyle::NodeColor color = GraphViewStyle::getScreenMatchColor(m_isActiveMatch);
m_matchText->setFont(font);
m_matchText->setBrush(QBrush(color.text.c_str()));
m_matchText->setPos(style.iconOffset.x + style.iconSize + style.textOffset.x, style.textOffset.y);
float charWidth = QFontMetrics(font).width("QtGraphNode::QtGraphNode::QtGraphNode") / 37.0f;
float charHeight = QFontMetrics(font).height();
m_matchRect->setRect(
style.iconOffset.x + style.iconSize + style.textOffset.x + m_matchPos * charWidth,
style.textOffset.y,
m_matchLength * charWidth,
charHeight
);
m_matchRect->setPen(QPen(color.border.c_str()));
m_matchRect->setBrush(QBrush(color.fill.c_str()));
m_matchRect->setRadius(3);
}
}
@@ -74,6 +74,10 @@ public:
void focusIn();
void focusOut();
void matchNameRecursive(const std::string& query, std::vector<QtGraphNode*>* matchedNodes);
void removeNameMatch();
void setActiveMatch(bool active);
virtual bool isDataNode() const;
virtual bool isAccessNode() const;
virtual bool isExpandToggleNode() const;
@@ -99,6 +103,8 @@ protected:
void notifyEdgesAfterMove();
virtual void matchName(const std::string& query, std::vector<QtGraphNode*>* matchedNodes);
void setStyle(const GraphViewStyle::NodeStyle& style);
std::list<std::shared_ptr<QtGraphEdge>> m_outEdges;
@@ -107,19 +113,26 @@ protected:
std::weak_ptr<QtGraphNode> m_parentNode;
std::list<std::shared_ptr<QtGraphNode>> m_subNodes;
QGraphicsSimpleTextItem* m_text;
QtRoundedRectItem* m_rect;
QtRoundedRectItem* m_undefinedRect;
QGraphicsPixmapItem* m_icon;
QGraphicsSimpleTextItem* m_text = nullptr;
QtRoundedRectItem* m_rect = nullptr;
QtRoundedRectItem* m_undefinedRect = nullptr;
QGraphicsPixmapItem* m_icon = nullptr;
Vec2i m_size;
bool m_isActive;
bool m_multipleActive;
bool m_isHovering;
bool m_isActive = false;
bool m_multipleActive = false;
bool m_isHovering = false;
private:
std::list<std::shared_ptr<QtGraphNodeComponent>> m_components;
// Name match
QGraphicsSimpleTextItem* m_matchText = nullptr;
QtRoundedRectItem* m_matchRect = nullptr;
size_t m_matchPos = 0;
size_t m_matchLength = 0;
bool m_isActiveMatch = false;
};
#endif // QT_GRAPH_NODE_H
@@ -23,6 +23,9 @@ public:
void hideLabel();
protected:
virtual void matchName(const std::string& query, std::vector<QtGraphNode*>* matchedNodes) {}
private:
AccessKind m_accessKind;
@@ -19,6 +19,9 @@ public:
virtual void onClick();
virtual void updateStyle();
protected:
virtual void matchName(const std::string& query, std::vector<QtGraphNode*>* matchedNodes) {}
private:
QGraphicsPixmapItem* m_icon;
bool m_invisibleSubNodeCount;
@@ -26,6 +26,8 @@ protected:
virtual void hoverEnterEvent(QGraphicsSceneHoverEvent* event);
virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent* event);
virtual void matchName(const std::string& query, std::vector<QtGraphNode*>* matchedNodes) {}
private:
const NameHierarchy m_qualifierName;