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
+38 -8
View File
@@ -181,7 +181,7 @@
<fill>#FFFF0000</fill>
</focus>
</error>
<fulltext>
<fulltext_search>
<normal>
<fill>#C2AFEF</fill>
<text>#3D3D3D</text>
@@ -189,7 +189,17 @@
<focus>
<fill>#987CEA</fill>
</focus>
</fulltext>
</fulltext_search>
<screen_search>
<normal>
<border>transparent</border>
<fill>#D2FA6E</fill>
<text>#262626</text>
</normal>
<focus>
<fill>#FA6EF3</fill>
</focus>
</screen_search>
</annotation>
</snippet>
</code>
@@ -436,6 +446,14 @@
</aggregation>
</edge>
</graph>
<tab>
<background>#494949</background>
<active>#D4D4D4</active>
<hover>#878787</hover>
<text>#878787</text>
</tab>
<table>
<background>#494949</background>
<table>#D4D4D4</table>
@@ -452,10 +470,22 @@
<active>#7B7B7B</active>
</table_line_2>
</table>
<tab>
<background>#494949</background>
<active>#D4D4D4</active>
<hover>#878787</hover>
<text>#878787</text>
</tab>
<screen_search>
<background>#808080</background>
<box>
<background>#494949</background>
<text>#D4D4D4</text>
<match_label>#A0A0A0</match_label>
</box>
<filter>white</filter>
<button>
<normal>#494949</normal>
<hover>#606060</hover>
<press>#707070</press>
<disabled>#494949</disabled>
<icon>white</icon>
<icon_disabled>#666666</icon_disabled>
</button>
</screen_search>
</config>
+32 -5
View File
@@ -179,7 +179,7 @@
<fill>#CCFF0000</fill>
</focus>
</error>
<fulltext>
<fulltext_search>
<normal>
<fill>#C7C7E2</fill>
<text>#000000</text>
@@ -187,7 +187,17 @@
<focus>
<fill>#ABABDD</fill>
</focus>
</fulltext>
</fulltext_search>
<screen_search>
<normal>
<border>transparent</border>
<fill>#8ADBBC</fill>
<text>#000000</text>
</normal>
<focus>
<fill>#DB97C2</fill>
</focus>
</screen_search>
</annotation>
</snippet>
</code>
@@ -397,15 +407,14 @@
</aggregation>
</edge>
</graph>
<error>
<background>white</background>
</error>
<tab>
<background>white</background>
<active>black</active>
<hover>#878787</hover>
<text>#878787</text>
</tab>
<table>
<background>white</background>
<table>#aaa</table>
@@ -422,4 +431,22 @@
<active>grey</active>
</table_line_2>
</table>
<screen_search>
<background>#E0E0E0</background>
<box>
<background>white</background>
<text>black</text>
<match_label>#A0A0A0</match_label>
</box>
<filter>black</filter>
<button>
<normal>white</normal>
<hover>#F2F2F2</hover>
<press>#CECECE</press>
<disabled>white</disabled>
<icon>#727272</icon>
<icon_disabled>#CECECE</icon_disabled>
</button>
</screen_search>
</config>
+38 -8
View File
@@ -181,7 +181,7 @@
<fill>#FFFF0000</fill>
</focus>
</error>
<fulltext>
<fulltext_search>
<normal>
<fill>#207EA8</fill>
<text>#F7F7F7</text>
@@ -190,7 +190,17 @@
<border>#006D93</border>
<fill>#134B63</fill>
</focus>
</fulltext>
</fulltext_search>
<screen_search>
<normal>
<border>transparent</border>
<fill>#6EDB42</fill>
<text>#000000</text>
</normal>
<focus>
<fill>#FF52E8</fill>
</focus>
</screen_search>
</annotation>
</snippet>
</code>
@@ -407,6 +417,14 @@
</aggregation>
</edge>
</graph>
<tab>
<background>#272728</background>
<active>white</active>
<hover>#878787</hover>
<text>#878787</text>
</tab>
<table>
<background>#272728</background>
<table>white</table>
@@ -423,10 +441,22 @@
<active>#969696</active>
</table_line_2>
</table>
<tab>
<background>#272728</background>
<active>white</active>
<hover>#878787</hover>
<text>#878787</text>
</tab>
<screen_search>
<background>#777777</background>
<box>
<background>#272728</background>
<text>#F7F7F7</text>
<match_label>#A0A0A0</match_label>
</box>
<filter>#F7F7F7</filter>
<button>
<normal>#272728</normal>
<hover>#333333</hover>
<press>#555555</press>
<disabled>#272728</disabled>
<icon>white</icon>
<icon_disabled>#555555</icon_disabled>
</button>
</screen_search>
</config>
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

@@ -0,0 +1,82 @@
#screen_search_bar {
border: none;
}
#screen_search_box {
padding-left: 10;
border-top: 1px solid #BEBEBE;
background: <color:screen_search/background>;
}
#search_box {
background: <color:screen_search/box/background>;
border: none;
color: <color:screen_search/box/text>;
font-family: <setting:font_name>;
font-size: <setting:font_size>px;
margin: 4px 0;
max-width: <setting:font_size*20>px;
min-height: 20px;
padding: 1px 0px 1px 0px;
}
#match_label {
border: none;
background: <color:screen_search/box/background>;
color: <color:screen_search/box/match_label>;
font-size: <setting:font_size-2>px;
margin: 4px 0;
padding-right: 4px;
text-align: right;
min-width: <setting:font_size*7>px;
min-height: 20px;
max-height: 40px;
}
#search_button, #prev_button, #next_button, #close_button {
background: <color:screen_search/button/normal>;
width: 20px;
min-height: 20px;
max-height: 40px;
border-radius: 0;
margin: 4px 0;
}
#search_button {
border-bottom-left-radius: 10px;
border-top-left-radius: 10px;
padding-left: 2px;
}
#prev_button {
margin: 4px 1px;
}
#next_button {
border-bottom-right-radius: 10px;
border-top-right-radius: 10px;
}
#prev_button:disabled, #next_button:disabled {
background: <color:screen_search/button/disabled>;
}
#prev_button:hover, #next_button:hover {
background: <color:screen_search/button/hover>;
}
#prev_button:pressed, #next_button:pressed {
background: <color:screen_search/button/press>;
}
#close_button {
background: transparent;
margin: 4px 6px;
padding-top: 1px;
}
#filter_checkbox {
color: <color:screen_search/filter>;
margin-left: 20px;
font-size: <setting:font_size-1>px;
}
+5
View File
@@ -10,6 +10,7 @@ add_files(
component/controller/helper/ListLayouter.h
component/controller/helper/NetworkProtocolHelper.cpp
component/controller/helper/NetworkProtocolHelper.h
component/controller/helper/ScreenSearchInterfaces.h
component/controller/helper/SnippetMerger.cpp
component/controller/helper/SnippetMerger.h
component/controller/helper/TrailLayouter.cpp
@@ -32,6 +33,8 @@ add_files(
component/controller/LogController.h
component/controller/RefreshController.cpp
component/controller/RefreshController.h
component/controller/ScreenSearchController.cpp
component/controller/ScreenSearchController.h
component/controller/SearchController.cpp
component/controller/SearchController.h
component/controller/StatusBarController.cpp
@@ -66,6 +69,8 @@ add_files(
component/view/MainView.h
component/view/RefreshView.cpp
component/view/RefreshView.h
component/view/ScreenSearchView.cpp
component/view/ScreenSearchView.h
component/view/SearchView.cpp
component/view/SearchView.h
component/view/StatusBarView.cpp
+10
View File
@@ -30,3 +30,13 @@ Component::~Component()
m_view->setComponent(NULL);
}
}
Controller* Component::getControllerPtr() const
{
return m_controller.get();
}
View* Component::getViewPtr() const
{
return m_view.get();
}
+4
View File
@@ -15,9 +15,13 @@ public:
template <typename ControllerType>
ControllerType* getController() const;
Controller* getControllerPtr() const;
template <typename ViewType>
ViewType* getView() const;
View* getViewPtr() const;
private:
const std::shared_ptr<Controller> m_controller;
const std::shared_ptr<View> m_view;
+32 -22
View File
@@ -8,6 +8,7 @@
#include "component/controller/GraphController.h"
#include "component/controller/LogController.h"
#include "component/controller/RefreshController.h"
#include "component/controller/ScreenSearchController.h"
#include "component/controller/SearchController.h"
#include "component/controller/StatusBarController.h"
#include "component/controller/StatusController.h"
@@ -18,6 +19,7 @@
#include "component/view/ErrorView.h"
#include "component/view/LogView.h"
#include "component/view/RefreshView.h"
#include "component/view/ScreenSearchView.h"
#include "component/view/SearchView.h"
#include "component/view/StatusBarView.h"
#include "component/view/StatusView.h"
@@ -58,14 +60,6 @@ std::shared_ptr<Component> ComponentFactory::createActivationComponent()
return std::make_shared<Component>(nullptr, controller);
}
std::shared_ptr<Component> ComponentFactory::createTooltipComponent(ViewLayout* viewLayout)
{
std::shared_ptr<TooltipView> view = m_viewFactory->createTooltipView(viewLayout);
std::shared_ptr<Controller> controller = std::make_shared<TooltipController>(m_storageAccess);
return std::make_shared<Component>(view, controller);
}
std::shared_ptr<Component> ComponentFactory::createBookmarkComponent(ViewLayout* viewLayout)
{
std::shared_ptr<BookmarkView> view = m_viewFactory->createBookmarkView(viewLayout);
@@ -90,6 +84,14 @@ std::shared_ptr<Component> ComponentFactory::createErrorComponent(ViewLayout* vi
return std::make_shared<Component>(view, controller);
}
std::shared_ptr<Component> ComponentFactory::createGraphComponent(ViewLayout* viewLayout)
{
std::shared_ptr<View> view = m_viewFactory->createGraphView(viewLayout);
std::shared_ptr<GraphController> controller = std::make_shared<GraphController>(m_storageAccess);
return std::make_shared<Component>(view, controller);
}
std::shared_ptr<Component> ComponentFactory::createLogComponent(ViewLayout* viewLayout)
{
std::shared_ptr<LogView> view = m_viewFactory->createLogView(viewLayout);
@@ -100,14 +102,6 @@ std::shared_ptr<Component> ComponentFactory::createLogComponent(ViewLayout* view
return std::make_shared<Component>(view, controller);
}
std::shared_ptr<Component> ComponentFactory::createGraphComponent(ViewLayout* viewLayout)
{
std::shared_ptr<View> view = m_viewFactory->createGraphView(viewLayout);
std::shared_ptr<GraphController> controller = std::make_shared<GraphController>(m_storageAccess);
return std::make_shared<Component>(view, controller);
}
std::shared_ptr<Component> ComponentFactory::createRefreshComponent(ViewLayout* viewLayout)
{
std::shared_ptr<View> view = m_viewFactory->createRefreshView(viewLayout);
@@ -116,18 +110,18 @@ std::shared_ptr<Component> ComponentFactory::createRefreshComponent(ViewLayout*
return std::make_shared<Component>(view, controller);
}
std::shared_ptr<Component> ComponentFactory::createSearchComponent(ViewLayout* viewLayout)
std::shared_ptr<Component> ComponentFactory::createScreenSearchComponent(ViewLayout* viewLayout)
{
std::shared_ptr<SearchView> view = m_viewFactory->createSearchView(viewLayout);
std::shared_ptr<SearchController> controller = std::make_shared<SearchController>(m_storageAccess);
std::shared_ptr<ScreenSearchView> view = m_viewFactory->createScreenSearchView(viewLayout);
std::shared_ptr<ScreenSearchController> controller = std::make_shared<ScreenSearchController>();
return std::make_shared<Component>(view, controller);
}
std::shared_ptr<Component> ComponentFactory::createUndoRedoComponent(ViewLayout* viewLayout)
std::shared_ptr<Component> ComponentFactory::createSearchComponent(ViewLayout* viewLayout)
{
std::shared_ptr<UndoRedoView> view = m_viewFactory->createUndoRedoView(viewLayout);
std::shared_ptr<UndoRedoController> controller = std::make_shared<UndoRedoController>(m_storageAccess);
std::shared_ptr<SearchView> view = m_viewFactory->createSearchView(viewLayout);
std::shared_ptr<SearchController> controller = std::make_shared<SearchController>(m_storageAccess);
return std::make_shared<Component>(view, controller);
}
@@ -148,6 +142,22 @@ std::shared_ptr<Component> ComponentFactory::createStatusComponent(ViewLayout* v
return std::make_shared<Component>(view, controller);
}
std::shared_ptr<Component> ComponentFactory::createTooltipComponent(ViewLayout* viewLayout)
{
std::shared_ptr<TooltipView> view = m_viewFactory->createTooltipView(viewLayout);
std::shared_ptr<Controller> controller = std::make_shared<TooltipController>(m_storageAccess);
return std::make_shared<Component>(view, controller);
}
std::shared_ptr<Component> ComponentFactory::createUndoRedoComponent(ViewLayout* viewLayout)
{
std::shared_ptr<UndoRedoView> view = m_viewFactory->createUndoRedoView(viewLayout);
std::shared_ptr<UndoRedoController> controller = std::make_shared<UndoRedoController>(m_storageAccess);
return std::make_shared<Component>(view, controller);
}
ComponentFactory::ComponentFactory()
{
}
+1
View File
@@ -26,6 +26,7 @@ public:
std::shared_ptr<Component> createGraphComponent(ViewLayout* viewLayout);
std::shared_ptr<Component> createLogComponent(ViewLayout* viewLayout);
std::shared_ptr<Component> createRefreshComponent(ViewLayout* viewLayout);
std::shared_ptr<Component> createScreenSearchComponent(ViewLayout* viewLayout);
std::shared_ptr<Component> createSearchComponent(ViewLayout* viewLayout);
std::shared_ptr<Component> createStatusBarComponent(ViewLayout* viewLayout);
std::shared_ptr<Component> createStatusComponent(ViewLayout* viewLayout);
+7
View File
@@ -1,6 +1,7 @@
#include "component/ComponentManager.h"
#include "component/controller/Controller.h"
#include "component/controller/ScreenSearchController.h"
#include "component/view/CompositeView.h"
#include "component/view/DialogView.h"
#include "component/view/TabbedView.h"
@@ -52,6 +53,12 @@ void ComponentManager::setup(ViewLayout* viewLayout)
std::shared_ptr<Component> tooltipComponent = m_componentFactory->createTooltipComponent(viewLayout);
m_components.push_back(tooltipComponent);
std::shared_ptr<Component> screenSearchComponent = m_componentFactory->createScreenSearchComponent(viewLayout);
ScreenSearchController* screenSearchController = screenSearchComponent->getController<ScreenSearchController>();
screenSearchController->addResponder(dynamic_cast<ScreenSearchResponder*>(graphComponent->getViewPtr()));
screenSearchController->addResponder(dynamic_cast<ScreenSearchResponder*>(codeComponent->getViewPtr()));
m_components.push_back(screenSearchComponent);
m_dialogView = m_componentFactory->getViewFactory()->createDialogView(viewLayout, m_componentFactory->getStorageAccess());
std::shared_ptr<TabbedView> tabbedView =
@@ -0,0 +1,153 @@
#include "component/controller/ScreenSearchController.h"
#include "component/view/ScreenSearchView.h"
ScreenSearchController::ScreenSearchController()
{
}
ScreenSearchController::~ScreenSearchController()
{
}
void ScreenSearchController::clear()
{
}
void ScreenSearchController::foundMatches(ScreenSearchResponder* responder, size_t matchCount)
{
if (matchCount)
{
std::lock_guard<std::mutex> lock(m_matchMutex);
size_t responderId = getResponderId(responder);
if (!responderId)
{
return;
}
std::vector<std::pair<size_t, size_t>> newMatches;
for (size_t i = 0; i < matchCount; i++)
{
newMatches.push_back(std::make_pair(responderId, i));
}
size_t i = 0;
while (i < m_matches.size() && responderId > m_matches[i].first)
{
i++;
}
m_matches.insert(m_matches.begin() + i, newMatches.begin(), newMatches.end());
m_matchIndex = m_matches.size();
}
getView<ScreenSearchView>()->setMatchCount(m_matches.size());
}
void ScreenSearchController::addResponder(ScreenSearchResponder* responder)
{
if (responder)
{
m_responders.push_back(responder);
getView<ScreenSearchView>()->addResponder(responder->getName());
}
}
void ScreenSearchController::search(const std::string& query, const std::set<std::string>& responderNames)
{
{
std::lock_guard<std::mutex> lock(m_matchMutex);
m_matches.clear();
m_matchIndex = 0;
}
getView<ScreenSearchView>()->setMatchCount(0);
for (ScreenSearchResponder* responder : m_responders)
{
if (!responder->isVisible())
{
continue;
}
if (query.size() && responderNames.find(responder->getName()) != responderNames.end())
{
responder->findMatches(this, query);
}
else
{
responder->clearMatches();
}
}
}
void ScreenSearchController::activateMatch(bool next)
{
std::lock_guard<std::mutex> lock(m_matchMutex);
if (!m_matches.size())
{
return;
}
if (m_matchIndex != m_matches.size())
{
auto match = m_matches[m_matchIndex];
m_responders[match.first - 1]->deactivateMatch(match.second);
}
if (next)
{
if (m_matchIndex == m_matches.size())
{
m_matchIndex = 0;
}
else
{
m_matchIndex = (m_matchIndex + 1) % m_matches.size();
}
}
else
{
if (m_matchIndex == 0)
{
m_matchIndex = m_matches.size() - 1;
}
else
{
m_matchIndex--;
}
}
auto match = m_matches[m_matchIndex];
m_responders[match.first - 1]->activateMatch(match.second);
getView<ScreenSearchView>()->setMatchIndex(m_matchIndex + 1);
}
void ScreenSearchController::clearMatches()
{
{
std::lock_guard<std::mutex> lock(m_matchMutex);
m_matches.clear();
m_matchIndex = 0;
}
for (ScreenSearchResponder* responder : m_responders)
{
responder->clearMatches();
}
}
size_t ScreenSearchController::getResponderId(ScreenSearchResponder* responder) const
{
for (size_t i = 0; i < m_responders.size(); i++)
{
if (m_responders[i] == responder)
{
return i + 1;
}
}
return 0;
}
@@ -0,0 +1,40 @@
#ifndef SCREEN_SEARCH_CONTROLLER_H
#define SCREEN_SEARCH_CONTROLLER_H
#include <mutex>
#include <set>
#include "component/controller/Controller.h"
#include "component/controller/helper/ScreenSearchInterfaces.h"
#include "utility/messaging/MessageListener.h"
class ScreenSearchController
: public Controller
, public ScreenSearchSender
{
public:
ScreenSearchController();
virtual ~ScreenSearchController();
// Controller implementation
virtual void clear();
// ScreenSearchSender implementation
virtual void foundMatches(ScreenSearchResponder* responder, size_t matchCount);
void addResponder(ScreenSearchResponder* responder);
void search(const std::string& query, const std::set<std::string>& responderNames);
void activateMatch(bool next);
void clearMatches();
private:
size_t getResponderId(ScreenSearchResponder* responder) const;
std::vector<ScreenSearchResponder*> m_responders;
std::vector<std::pair<size_t, size_t>> m_matches;
size_t m_matchIndex = 0;
std::mutex m_matchMutex;
};
#endif // SCREEN_SEARCH_CONTROLLER_H
@@ -0,0 +1,47 @@
#ifndef CONTROLLER_PROXY_H
#define CONTROLLER_PROXY_H
#include <functional>
#include "utility/scheduling/TaskLambda.h"
#include "component/view/View.h"
class ControllerProxy
{
public:
ControllerProxy(View* view)
: m_view(view)
{
}
template<typename ControllerType>
void execute(std::function<void(ControllerType*)> callback)
{
ControllerType* controller = m_view->getController<ControllerType>();
if (controller)
{
callback(controller);
}
}
template<typename ControllerType>
void executeAsTask(std::function<void(ControllerType*)> callback)
{
ControllerType* controller = m_view->getController<ControllerType>();
if (controller)
{
Task::dispatch(std::make_shared<TaskLambda>(
[callback, controller]()
{
callback(controller);
}
));
}
}
private:
View* m_view;
};
#endif // CONTROLLER_PROXY_H
@@ -0,0 +1,28 @@
#ifndef SCREEN_SEARCH_INTERFACES_H
#define SCREEN_SEARCH_INTERFACES_H
class ScreenSearchResponder;
class ScreenSearchSender
{
public:
virtual ~ScreenSearchSender() {}
virtual void foundMatches(ScreenSearchResponder* responder, size_t matchCount) = 0;
};
class ScreenSearchResponder
{
public:
virtual ~ScreenSearchResponder() {}
virtual std::string getName() const = 0;
virtual bool isVisible() const = 0;
virtual void findMatches(ScreenSearchSender* sender, const std::string& query) = 0;
virtual void activateMatch(size_t matchIndex) = 0;
virtual void deactivateMatch(size_t matchIndex) = 0;
virtual void clearMatches() = 0;
};
#endif // SCREEN_SEARCH_INTERFACES_H
+2
View File
@@ -5,6 +5,7 @@
#include "data/ErrorInfo.h"
#include "component/controller/helper/ScreenSearchInterfaces.h"
#include "component/view/helper/CodeSnippetParams.h"
#include "component/view/View.h"
@@ -14,6 +15,7 @@ class SourceLocationCollection;
class CodeView
: public View
, public ScreenSearchResponder
{
public:
static const char* VIEW_NAME;
+2
View File
@@ -6,6 +6,7 @@
#include "utility/math/Vector2.h"
#include "utility/types.h"
#include "component/controller/helper/ScreenSearchInterfaces.h"
#include "component/view/View.h"
struct DummyEdge;
@@ -14,6 +15,7 @@ class Graph;
class GraphView
: public View
, public ScreenSearchResponder
{
public:
static const char* VIEW_NAME;
+24
View File
@@ -22,6 +22,7 @@ float GraphViewStyle::s_zoomFactor;
std::map<std::string, GraphViewStyle::NodeColor> GraphViewStyle::s_nodeColors;
std::map<std::string, std::string> GraphViewStyle::s_edgeColors;
std::map<bool, GraphViewStyle::NodeColor> GraphViewStyle::s_screenMatchColors;
Vec2i GraphViewStyle::alignOnRaster(Vec2i position)
{
@@ -142,6 +143,7 @@ void GraphViewStyle::loadStyleSettings()
s_nodeColors.clear();
s_edgeColors.clear();
s_screenMatchColors.clear();
s_gridCellPadding = getImpl()->getCharHeightForNodeType(Node::NODE_TYPE) - 8;
s_gridCellSize = s_gridCellPadding / 2;
@@ -713,6 +715,28 @@ const std::string& GraphViewStyle::getEdgeColor(const std::string& typeStr, bool
return s_edgeColors.find(type)->second;
}
const GraphViewStyle::NodeColor& GraphViewStyle::getScreenMatchColor(bool focus)
{
auto it = s_screenMatchColors.find(focus);
if (it != s_screenMatchColors.end())
{
return it->second;
}
NodeColor color;
ColorScheme* scheme = ColorScheme::getInstance().get();
ColorScheme::ColorState state = focus ? ColorScheme::FOCUS : ColorScheme::NORMAL;
color.fill = scheme->getCodeAnnotationTypeColor("screen_search", "fill", state);
color.border = scheme->getCodeAnnotationTypeColor("screen_search", "border", state);
color.text = scheme->getCodeAnnotationTypeColor("screen_search", "text", state);
s_screenMatchColors.emplace(focus, color);
return s_screenMatchColors.find(focus)->second;
}
void GraphViewStyle::addIcon(Node::NodeType type, bool hasChildren, NodeStyle* style)
{
switch (type)
+2
View File
@@ -138,6 +138,7 @@ public:
static const NodeColor& getNodeColor(const std::string& typeStr, bool focus);
static const std::string& getEdgeColor(const std::string& typeStr, bool focus);
static const NodeColor& getScreenMatchColor(bool focus);
static int s_gridCellSize;
static int s_gridCellPadding;
@@ -156,6 +157,7 @@ private:
static std::map<std::string, NodeColor> s_nodeColors;
static std::map<std::string, std::string> s_edgeColors;
static std::map<bool, NodeColor> s_screenMatchColors;
};
#endif // GRAPH_VIEW_STYLE_H
@@ -0,0 +1,15 @@
#include "component/view/ScreenSearchView.h"
ScreenSearchView::ScreenSearchView(ViewLayout* viewLayout)
: View(viewLayout)
{
}
ScreenSearchView::~ScreenSearchView()
{
}
std::string ScreenSearchView::getName() const
{
return "ScreenSearchView";
}
+22
View File
@@ -0,0 +1,22 @@
#ifndef SCREEN_SEARCH_VIEW_H
#define SCREEN_SEARCH_VIEW_H
#include "component/view/View.h"
class ScreenSearchView
: public View
{
public:
ScreenSearchView(ViewLayout* viewLayout);
virtual ~ScreenSearchView();
// View implementation
virtual std::string getName() const;
virtual void setMatchCount(size_t matchCount) = 0;
virtual void setMatchIndex(size_t matchIndex) = 0;
virtual void addResponder(const std::string& name) = 0;
};
#endif // SCREEN_SEARCH_VIEW_H
+3
View File
@@ -8,6 +8,7 @@
#include "component/view/ViewLayout.h"
class ViewWidgetWrapper;
class ControllerProxy;
class View
{
@@ -43,6 +44,8 @@ protected:
void setWidgetWrapper(std::shared_ptr<ViewWidgetWrapper> widgetWrapper);
private:
friend ControllerProxy;
Component* m_component;
ViewLayout* const m_viewLayout;
std::shared_ptr<ViewWidgetWrapper> m_widgetWrapper;
+2
View File
@@ -13,6 +13,7 @@ class GraphView;
class MainView;
class LogView;
class RefreshView;
class ScreenSearchView;
class SearchView;
class StatusBarView;
class StatusView;
@@ -39,6 +40,7 @@ public:
virtual std::shared_ptr<GraphView> createGraphView(ViewLayout* viewLayout) const = 0;
virtual std::shared_ptr<LogView> createLogView(ViewLayout* viewLayout) const = 0;
virtual std::shared_ptr<RefreshView> createRefreshView(ViewLayout* viewLayout) const = 0;
virtual std::shared_ptr<ScreenSearchView> createScreenSearchView(ViewLayout* viewLayout) const = 0;
virtual std::shared_ptr<SearchView> createSearchView(ViewLayout* viewLayout) const = 0;
virtual std::shared_ptr<StatusBarView> createStatusBarView(ViewLayout* viewLayout) const = 0;
virtual std::shared_ptr<StatusView> createStatusView(ViewLayout* viewLayout) const = 0;
+8 -4
View File
@@ -10,10 +10,12 @@ int locationTypeToInt(LocationType type)
return 1;
case LOCATION_LOCAL_SYMBOL:
return 2;
case LOCATION_FULLTEXT:
return 3;
case LOCATION_ERROR:
return 3;
case LOCATION_FULLTEXT_SEARCH:
return 4;
case LOCATION_SCREEN_SEARCH:
return 5;
}
}
@@ -28,9 +30,11 @@ LocationType intToLocationType(int value)
case 2:
return LOCATION_LOCAL_SYMBOL;
case 3:
return LOCATION_FULLTEXT;
case 4:
return LOCATION_ERROR;
case 4:
return LOCATION_FULLTEXT_SEARCH;
case 5:
return LOCATION_SCREEN_SEARCH;
}
return LOCATION_TOKEN;
}
+3 -2
View File
@@ -6,8 +6,9 @@ enum LocationType
LOCATION_TOKEN,
LOCATION_SCOPE,
LOCATION_LOCAL_SYMBOL,
LOCATION_FULLTEXT,
LOCATION_ERROR
LOCATION_ERROR,
LOCATION_FULLTEXT_SEARCH,
LOCATION_SCREEN_SEARCH
};
int locationTypeToInt(LocationType type);
+1 -1
View File
@@ -177,7 +177,7 @@ bool SourceLocation::isScopeLocation() const
bool SourceLocation::isFullTextSearchMatch() const
{
return m_type == LOCATION_FULLTEXT;
return m_type == LOCATION_FULLTEXT_SEARCH;
}
std::ostream& operator<<(std::ostream& ostream, const SourceLocation& location)
+1 -1
View File
@@ -557,7 +557,7 @@ std::shared_ptr<SourceLocationCollection> PersistentStorage::getFullTextSearchLo
Id locationId = ~(~Id(0) >> 1) + collection->getSourceLocationCount() + 1;
collection->addSourceLocation(
LOCATION_FULLTEXT,
LOCATION_FULLTEXT_SEARCH,
locationId,
std::vector<Id>(),
filePath,
+4
View File
@@ -48,6 +48,8 @@ add_files(
qt/element/QtProgressBar.h
qt/element/QtRefreshBar.cpp
qt/element/QtRefreshBar.h
qt/element/QtScreenSearchBox.cpp
qt/element/QtScreenSearchBox.h
qt/element/QtSearchBar.cpp
qt/element/QtSearchBar.h
qt/element/QtSmartSearchBox.cpp
@@ -145,6 +147,8 @@ add_files(
qt/view/QtMainView.h
qt/view/QtRefreshView.cpp
qt/view/QtRefreshView.h
qt/view/QtScreenSearchView.cpp
qt/view/QtScreenSearchView.h
qt/view/QtSearchView.cpp
qt/view/QtSearchView.h
qt/view/QtStatusBarView.cpp
+72
View File
@@ -19,6 +19,7 @@
#include "utility/messaging/type/MessageMoveIDECursor.h"
#include "utility/messaging/type/MessageShowErrors.h"
#include "utility/utility.h"
#include "utility/utilityString.h"
#include "qt/element/QtCodeNavigator.h"
#include "qt/utility/QtContextMenu.h"
@@ -163,6 +164,18 @@ void QtCodeArea::lineNumberAreaPaintEvent(QPaintEvent *event)
}
break;
case LOCATION_ERROR:
case LOCATION_SCREEN_SEARCH:
if (annotation.isFocused || annotation.isActive)
{
focus = true;
}
else
{
active = true;
}
break;
case LOCATION_TOKEN:
case LOCATION_SCOPE:
if (annotation.isFocused && utility::shareElement(activeSymbolIds, annotation.tokenIds))
@@ -356,6 +369,65 @@ QRectF QtCodeArea::getLineRectForLineNumber(uint lineNumber) const
return blockBoundingGeometry(block);
}
void QtCodeArea::findScreenMatches(const std::string& query, std::vector<std::pair<QtCodeArea*, Id>>* screenMatches)
{
const std::string& code = utility::toLowerCase(getCode());
size_t pos = 0;
while (pos != std::string::npos)
{
pos = code.find(query, pos);
if (pos == std::string::npos)
{
break;
}
Annotation matchAnnotation;
matchAnnotation.start = pos;
matchAnnotation.end = pos + query.size();
std::pair<int, int> start = toLineColumn(matchAnnotation.start);
matchAnnotation.startLine = start.first;
matchAnnotation.startCol = start.second;
std::pair<int, int> end = toLineColumn(matchAnnotation.end);
matchAnnotation.endLine = end.first;
matchAnnotation.endCol = end.second;
// Set first 2 bits to 1 to avoid collisions
matchAnnotation.locationId = ~(~Id(0) >> 2) + screenMatches->size() + 1;
matchAnnotation.locationType = LOCATION_SCREEN_SEARCH;
matchAnnotation.isActive = false;
matchAnnotation.isFocused = false;
m_annotations.push_back(matchAnnotation);
screenMatches->push_back(std::make_pair(this, matchAnnotation.locationId));
pos += query.size();
}
if (screenMatches->size() && screenMatches->back().first == this)
{
viewport()->update();
}
}
void QtCodeArea::clearScreenMatches()
{
size_t i = m_annotations.size();
while (i > 0 && m_annotations[i - 1].locationType == LOCATION_SCREEN_SEARCH)
{
i--;
m_linesToRehighlight.push_back(m_annotations[i].startLine - getStartLineNumber());
}
if (i != m_annotations.size())
{
m_annotations.erase(m_annotations.begin() + i, m_annotations.end());
viewport()->update();
}
}
void QtCodeArea::resizeEvent(QResizeEvent *e)
{
QPlainTextEdit::resizeEvent(e);
+3
View File
@@ -83,6 +83,9 @@ public:
QRectF getLineRectForLineNumber(uint lineNumber) const;
void findScreenMatches(const std::string& query, std::vector<std::pair<QtCodeArea*, Id>>* screenMatches);
void clearScreenMatches();
protected:
virtual void resizeEvent(QResizeEvent* event) Q_DECL_OVERRIDE;
virtual void mouseReleaseEvent(QMouseEvent* event) Q_DECL_OVERRIDE;
+6 -2
View File
@@ -549,7 +549,7 @@ const QtCodeField::AnnotationColor& QtCodeField::getAnnotationColorForAnnotation
if (!s_annotationColors.size())
{
ColorScheme* scheme = ColorScheme::getInstance().get();
std::vector<std::string> types = { "token", "local_symbol", "scope", "error", "fulltext" };
std::vector<std::string> types = { "token", "local_symbol", "scope", "error", "fulltext_search", "screen_search" };
std::vector<ColorScheme::ColorState> states = { ColorScheme::NORMAL, ColorScheme::FOCUS, ColorScheme::ACTIVE };
for (const std::string& type : types)
@@ -579,10 +579,14 @@ const QtCodeField::AnnotationColor& QtCodeField::getAnnotationColorForAnnotation
{
i = 9;
}
else if (annotation.locationType == LOCATION_FULLTEXT)
else if (annotation.locationType == LOCATION_FULLTEXT_SEARCH)
{
i = 12;
}
else if (annotation.locationType == LOCATION_SCREEN_SEARCH)
{
i = 15;
}
if (annotation.isActive)
{
+1 -1
View File
@@ -99,6 +99,7 @@ protected:
std::vector<Annotation> m_annotations;
std::vector<const Annotation*> m_hoveredAnnotations;
std::vector<int> m_linesToRehighlight;
private:
static std::vector<AnnotationColor> s_annotationColors;
@@ -113,7 +114,6 @@ private:
QtHighlighter* m_highlighter;
std::vector<int> m_lineLengths;
std::vector<int> m_linesToRehighlight;
int m_endTextEditPosition;
};
+23 -6
View File
@@ -143,13 +143,12 @@ QtCodeSnippet* QtCodeFile::addCodeSnippet(const CodeSnippetParams& params)
}
}
m_isCollapsed = false;
std::shared_ptr<QtCodeSnippet> snippet(new QtCodeSnippet(params, m_navigator, this));
if (params.reduced)
{
m_title->setProject(params.title);
m_isCollapsed = false;
}
m_snippetLayout->addWidget(snippet.get());
@@ -172,10 +171,6 @@ QtCodeSnippet* QtCodeFile::addCodeSnippet(const CodeSnippetParams& params)
return m_fileSnippet.get();
}
else
{
m_isCollapsed = false;
}
m_snippets.push_back(snippet);
@@ -229,6 +224,11 @@ QtCodeSnippet* QtCodeFile::insertCodeSnippet(const CodeSnippetParams& params)
QtCodeSnippet* QtCodeFile::getSnippetForLocationId(Id locationId) const
{
if (m_fileSnippet && m_fileSnippet->isVisible() && m_fileSnippet->getLineNumberForLocationId(locationId))
{
return m_fileSnippet.get();
}
for (const std::shared_ptr<QtCodeSnippet>& snippet : m_snippets)
{
if (snippet->getLineNumberForLocationId(locationId))
@@ -438,6 +438,23 @@ void QtCodeFile::updateTitleBar()
m_title->updateTexts();
}
void QtCodeFile::findScreenMatches(const std::string& query, std::vector<std::pair<QtCodeArea*, Id>>* screenMatches)
{
if (m_fileSnippet && m_fileSnippet->isVisible())
{
m_fileSnippet->findScreenMatches(query, screenMatches);
return;
}
for (const std::shared_ptr<QtCodeSnippet>& snippet : m_snippets)
{
if (snippet->isVisible())
{
snippet->findScreenMatches(query, screenMatches);
}
}
}
void QtCodeFile::clickedMinimizeButton()
{
// overview stats
+3
View File
@@ -14,6 +14,7 @@
class QLabel;
class QPushButton;
class QtCodeArea;
class QtCodeFileTitleButton;
class QtCodeNavigator;
class QtCodeSnippet;
@@ -59,6 +60,8 @@ public:
void updateSnippets();
void updateTitleBar();
void findScreenMatches(const std::string& query, std::vector<std::pair<QtCodeArea*, Id>>* screenMatches);
public slots:
void clickedMinimizeButton();
void clickedSnippetButton();
@@ -199,6 +199,14 @@ void QtCodeFileList::onWindowFocus()
}
}
void QtCodeFileList::findScreenMatches(const std::string& query, std::vector<std::pair<QtCodeArea*, Id>>* screenMatches)
{
for (const std::shared_ptr<QtCodeFile>& filePtr : m_files)
{
filePtr->findScreenMatches(query, screenMatches);
}
}
void QtCodeFileList::setFileMinimized(const FilePath path)
{
getFile(path)->setMinimized();
+2
View File
@@ -43,6 +43,8 @@ public:
virtual void onWindowFocus();
virtual void findScreenMatches(const std::string& query, std::vector<std::pair<QtCodeArea*, Id>>* screenMatches);
void setFileMinimized(const FilePath path);
void setFileSnippets(const FilePath path);
void setFileMaximized(const FilePath path);
@@ -225,6 +225,14 @@ void QtCodeFileSingle::onWindowFocus()
m_title->updateTexts();
}
void QtCodeFileSingle::findScreenMatches(const std::string& query, std::vector<std::pair<QtCodeArea*, Id>>* screenMatches)
{
if (m_area)
{
m_area->findScreenMatches(query, screenMatches);
}
}
const FilePath& QtCodeFileSingle::getCurrentFilePath() const
{
return m_currentFilePath;
@@ -43,6 +43,8 @@ public:
virtual void onWindowFocus() override;
virtual void findScreenMatches(const std::string& query, std::vector<std::pair<QtCodeArea*, Id>>* screenMatches) override;
const FilePath& getCurrentFilePath() const;
bool hasFileCached(const FilePath& filePath) const;
@@ -10,6 +10,7 @@
class FilePath;
class QRectF;
class QAbstractScrollArea;
class QtCodeArea;
class QWidget;
class QtCodeNavigateable
@@ -29,6 +30,8 @@ public:
virtual void onWindowFocus() = 0;
virtual void findScreenMatches(const std::string& query, std::vector<std::pair<QtCodeArea*, Id>>* screenMatches) = 0;
protected:
void ensureWidgetVisibleAnimated(QWidget* parentWidget, QWidget *childWidget, QRectF rect, bool animated, bool onTop);
void ensurePercentVisibleAnimated(double percentA, double percentB, bool animated, bool onTop);
@@ -15,6 +15,7 @@
#include "data/location/SourceLocation.h"
#include "data/location/SourceLocationCollection.h"
#include "data/location/SourceLocationFile.h"
#include "qt/element/QtCodeArea.h"
#include "qt/element/QtCodeFile.h"
#include "qt/element/QtCodeSnippet.h"
#include "qt/utility/utilityQt.h"
@@ -255,6 +256,9 @@ void QtCodeNavigator::clearCodeSnippets()
m_refIndex = 0;
m_singleHasNewFile = false;
m_screenMatches.clear();
m_activeScreenMatchId = 0;
}
void QtCodeNavigator::clearFile()
@@ -549,6 +553,60 @@ void QtCodeNavigator::refreshStyle()
clearCaches();
}
size_t QtCodeNavigator::findScreenMatches(const std::string& query)
{
clearScreenMatches();
m_current->findScreenMatches(query, &m_screenMatches);
return m_screenMatches.size();
}
void QtCodeNavigator::activateScreenMatch(size_t matchIndex)
{
if (matchIndex >= m_screenMatches.size())
{
return;
}
std::pair<QtCodeArea*, Id> p = m_screenMatches[matchIndex];
m_activeScreenMatchId = p.second;
m_currentActiveLocationIds.insert(m_activeScreenMatchId);
p.first->updateContent();
requestScroll(p.first->getSourceLocationFile()->getFilePath(), 0, m_activeScreenMatchId, true, false);
emit scrollRequest();
}
void QtCodeNavigator::deactivateScreenMatch(size_t matchIndex)
{
if (matchIndex >= m_screenMatches.size())
{
return;
}
m_currentActiveLocationIds.erase(m_screenMatches[matchIndex].second);
m_screenMatches[matchIndex].first->updateContent();
m_activeScreenMatchId = 0;
}
void QtCodeNavigator::clearScreenMatches()
{
if (m_activeScreenMatchId)
{
m_currentActiveLocationIds.erase(m_activeScreenMatchId);
m_activeScreenMatchId = 0;
}
for (auto p : m_screenMatches)
{
p.first->clearScreenMatches();
}
m_screenMatches.clear();
}
void QtCodeNavigator::scrollToValue(int value, bool inListMode)
{
if ((m_mode == MODE_LIST) == inListMode)
+8
View File
@@ -83,6 +83,11 @@ public:
void refreshStyle();
size_t findScreenMatches(const std::string& query);
void activateScreenMatch(size_t matchIndex);
void deactivateScreenMatch(size_t matchIndex);
void clearScreenMatches();
void scrollToValue(int value, bool inListMode);
void scrollToLine(const FilePath& filePath, unsigned int line);
void scrollToDefinition(bool animated, bool ignoreActiveReference);
@@ -192,6 +197,9 @@ private:
ScrollRequest m_scrollRequest;
bool m_singleHasNewFile;
std::vector<std::pair<QtCodeArea*, Id>> m_screenMatches;
Id m_activeScreenMatchId = 0;
};
#endif // QT_CODE_NAVIGATOR_H
+5
View File
@@ -187,6 +187,11 @@ std::string QtCodeSnippet::getCode() const
return m_codeArea->getCode();
}
void QtCodeSnippet::findScreenMatches(const std::string& query, std::vector<std::pair<QtCodeArea*, Id>>* screenMatches)
{
m_codeArea->findScreenMatches(query, screenMatches);
}
void QtCodeSnippet::clickedTitle()
{
if (m_titleId > 0)
+2
View File
@@ -51,6 +51,8 @@ public:
std::string getCode() const;
void findScreenMatches(const std::string& query, std::vector<std::pair<QtCodeArea*, Id>>* screenMatches);
private slots:
void clickedTitle();
void clickedFooter();
@@ -0,0 +1,263 @@
#include "qt/element/QtScreenSearchBox.h"
#include <QApplication>
#include <QCheckBox>
#include <QFocusEvent>
#include <QHBoxLayout>
#include <QLineEdit>
#include <QPushButton>
#include <QTimer>
#include "component/controller/helper/ControllerProxy.h"
#include "component/controller/ScreenSearchController.h"
#include "qt/utility/utilityQt.h"
#include "utility/ResourcePaths.h"
QtFocusInFilter::QtFocusInFilter()
{
}
bool QtFocusInFilter::eventFilter(QObject* obj, QEvent* event)
{
QLineEdit* lineEdit = dynamic_cast<QLineEdit*>(obj);
if (lineEdit && event->type() == QEvent::FocusIn && dynamic_cast<QFocusEvent*>(event)->reason() == Qt::MouseFocusReason)
{
emit focusIn();
}
return QObject::eventFilter(obj, event);
}
QtScreenSearchBox::QtScreenSearchBox(ControllerProxy* controllerProxy, QWidget* parent)
: QFrame(parent)
, m_controllerProxy(controllerProxy)
{
setObjectName("screen_search_box");
QHBoxLayout* layout = new QHBoxLayout();
layout->setContentsMargins(0, 0, 0, 0);
layout->setSpacing(0);
setLayout(layout);
// search field
{
m_searchButton = new QPushButton();
m_searchButton->setAttribute(Qt::WA_LayoutUsesWidgetRect); // fixes layouting on Mac
m_searchButton->setObjectName("search_button");
layout->addWidget(m_searchButton);
connect(m_searchButton, &QPushButton::clicked, this, &QtScreenSearchBox::setFocus);
m_searchBox = new QLineEdit(this);
m_searchBox->setObjectName("search_box");
m_searchBox->setAttribute(Qt::WA_LayoutUsesWidgetRect); // fixes layouting on Mac
m_searchBox->setAttribute(Qt::WA_MacShowFocusRect, 0); // remove blue focus box on Mac
layout->addWidget(m_searchBox);
connect(m_searchBox, &QLineEdit::textChanged, this, &QtScreenSearchBox::searchQueryChanged);
connect(m_searchBox, &QLineEdit::returnPressed, this, &QtScreenSearchBox::returnPressed);
QtFocusInFilter* filter = new QtFocusInFilter();
m_searchBox->installEventFilter(filter);
connect(filter, &QtFocusInFilter::focusIn, this, &QtScreenSearchBox::findMatches);
}
// match label
{
m_matchLabel = new QPushButton();
m_matchLabel->setAttribute(Qt::WA_LayoutUsesWidgetRect); // fixes layouting on Mac
m_matchLabel->setObjectName("match_label");
layout->addWidget(m_matchLabel);
connect(m_matchLabel, &QPushButton::clicked, this, &QtScreenSearchBox::setFocus);
}
// buttons
{
m_prevButton = new QPushButton();
m_nextButton = new QPushButton();
m_prevButton->setAttribute(Qt::WA_LayoutUsesWidgetRect); // fixes layouting on Mac
m_nextButton->setAttribute(Qt::WA_LayoutUsesWidgetRect); // fixes layouting on Mac
m_prevButton->setObjectName("prev_button");
m_nextButton->setObjectName("next_button");
layout->addWidget(m_prevButton);
layout->addWidget(m_nextButton);
connect(m_prevButton, &QPushButton::clicked, this, &QtScreenSearchBox::previousPressed);
connect(m_nextButton, &QPushButton::clicked, this, &QtScreenSearchBox::nextPressed);
}
// filter
{
m_checkboxLayout = new QHBoxLayout();
layout->addLayout(m_checkboxLayout);
layout->addStretch();
}
// buttons
{
m_closeButton = new QPushButton();
m_closeButton->setObjectName("close_button");
m_closeButton->setAttribute(Qt::WA_LayoutUsesWidgetRect); // fixes layouting on Mac
layout->addWidget(m_closeButton);
connect(m_closeButton, &QPushButton::clicked, [this](){ emit closePressed(); });
}
m_timer = new QTimer(this);
m_timer->setSingleShot(true);
connect(m_timer, &QTimer::timeout, this, &QtScreenSearchBox::findMatches);
refreshStyle();
setMatchCount(0);
}
QtScreenSearchBox::~QtScreenSearchBox()
{
}
void QtScreenSearchBox::refreshStyle()
{
m_searchButton->setIcon(utility::createButtonIcon(
ResourcePaths::getGuiPath().str() + "search_view/images/search.png",
"screen_search/button"
));
m_prevButton->setIcon(utility::createButtonIcon(
ResourcePaths::getGuiPath().str() + "code_view/images/arrow_left.png",
"screen_search/button"
));
m_nextButton->setIcon(utility::createButtonIcon(
ResourcePaths::getGuiPath().str() + "code_view/images/arrow_right.png",
"screen_search/button"
));
m_closeButton->setIcon(utility::createButtonIcon(
ResourcePaths::getGuiPath().str() + "screen_search_view/images/close.png",
"screen_search/button"
));
m_searchButton->setIconSize(QSize(12, 12));
m_prevButton->setIconSize(QSize(12, 12));
m_nextButton->setIconSize(QSize(12, 12));
m_closeButton->setIconSize(QSize(15, 15));
}
void QtScreenSearchBox::setMatchCount(size_t matchCount)
{
m_matchCount = matchCount;
m_matchIndex = 0;
updateMatchLabel();
m_prevButton->setEnabled(matchCount > 0);
m_nextButton->setEnabled(matchCount > 0);
}
void QtScreenSearchBox::setMatchIndex(size_t matchIndex)
{
m_matchIndex = matchIndex;
updateMatchLabel();
}
void QtScreenSearchBox::addResponder(const std::string& name)
{
QCheckBox* box = new QCheckBox(name.c_str());
box->setObjectName("filter_checkbox");
box->setChecked(true);
m_checkBoxes.push_back(box);
m_checkboxLayout->addWidget(box);
connect(box, &QCheckBox::stateChanged, this, &QtScreenSearchBox::findMatches);
}
void QtScreenSearchBox::setFocus()
{
m_searchBox->setFocus();
if (m_searchBox->text().size())
{
m_searchBox->selectAll();
searchQueryChanged();
}
}
void QtScreenSearchBox::searchQueryChanged()
{
m_timer->stop();
m_timer->start(200);
}
void QtScreenSearchBox::findMatches()
{
m_controllerProxy->executeAsTask<ScreenSearchController>(
[this](ScreenSearchController* controller)
{
std::set<std::string> responderNames;
for (QCheckBox* box : m_checkBoxes)
{
if (box->isChecked())
{
responderNames.insert(box->text().toStdString());
}
}
controller->search(m_searchBox->text().toLower().toStdString(), responderNames);
}
);
}
void QtScreenSearchBox::returnPressed()
{
if (Qt::KeyboardModifier::ShiftModifier & QApplication::keyboardModifiers())
{
previousPressed();
}
else
{
nextPressed();
}
}
void QtScreenSearchBox::previousPressed()
{
activateMatch(false);
}
void QtScreenSearchBox::nextPressed()
{
activateMatch(true);
}
void QtScreenSearchBox::activateMatch(bool next)
{
m_controllerProxy->executeAsTask<ScreenSearchController>(
[next, this](ScreenSearchController* controller)
{
controller->activateMatch(next);
}
);
}
void QtScreenSearchBox::updateMatchLabel()
{
QString text;
if (m_matchIndex > 0)
{
text += QString::number(m_matchIndex) + " of ";
}
text += QString::number(m_matchCount) + " match";
if (m_matchCount != 1)
{
text += "es";
}
m_matchLabel->setText(text);
}
@@ -0,0 +1,84 @@
#ifndef QT_SCREEN_SEARCH_BOX_H
#define QT_SCREEN_SEARCH_BOX_H
#include <QFrame>
class ControllerProxy;
class QCheckBox;
class QHBoxLayout;
class QLineEdit;
class QPushButton;
class QTimer;
class QtFocusInFilter
: public QObject
{
Q_OBJECT
public:
QtFocusInFilter();
signals:
void focusIn();
protected:
bool eventFilter(QObject* obj, QEvent* event);
};
class QtScreenSearchBox
: public QFrame
{
Q_OBJECT
public:
QtScreenSearchBox(ControllerProxy* controllerProxy, QWidget* parent = nullptr);
virtual ~QtScreenSearchBox();
void refreshStyle();
void setMatchCount(size_t matchCount);
void setMatchIndex(size_t matchIndex);
void addResponder(const std::string& name);
signals:
void closePressed();
public slots:
void setFocus();
private slots:
void searchQueryChanged();
void findMatches();
void returnPressed();
void previousPressed();
void nextPressed();
private:
void activateMatch(bool next);
void updateMatchLabel();
ControllerProxy* m_controllerProxy;
QLineEdit* m_searchBox;
QPushButton* m_matchLabel;
QPushButton* m_searchButton;
QPushButton* m_prevButton;
QPushButton* m_nextButton;
QPushButton* m_closeButton;
QHBoxLayout* m_checkboxLayout;
std::vector<QCheckBox*> m_checkBoxes;
size_t m_matchCount = 0;
size_t m_matchIndex = 0;
QTimer* m_timer;
};
#endif // QT_SCREEN_SEARCH_BOX_H
+56 -83
View File
@@ -5,6 +5,7 @@
#include <QTextDocument>
#include "settings/ColorScheme.h"
#include "utility/utility.h"
QVector<QtHighlighter::HighlightingRule> QtHighlighter::s_highlightingRules;
QVector<QtHighlighter::HighlightingRule> QtHighlighter::s_highlightingRulesCpp;
@@ -110,16 +111,16 @@ QtHighlighter::QtHighlighter(QTextDocument *document, LanguageType language)
: m_document(document)
, m_language(language)
{
if (m_language == LANGUAGE_UNKNOWN)
{
return;
}
if (!s_highlightingRules.size())
{
createHighlightingRules();
}
if (m_language == LANGUAGE_UNKNOWN)
{
return;
}
if (m_language == LANGUAGE_JAVA)
{
m_highlightingRules = s_highlightingRulesJava;
@@ -134,11 +135,6 @@ QtHighlighter::QtHighlighter(QTextDocument *document, LanguageType language)
void QtHighlighter::highlightDocument()
{
if (m_language == LANGUAGE_UNKNOWN)
{
return;
}
QTextDocument* doc = document();
int docStart = 0;
@@ -150,26 +146,29 @@ void QtHighlighter::highlightDocument()
docEnd -= 1;
applyFormat(docStart, docEnd, s_textFormat);
m_ranges.clear();
m_highlightedLines.clear();
m_highlightedLines.resize(document()->blockCount(), false);
for (QTextBlock it = doc->begin(); it != doc->end(); it = it.next())
{
formatBlock(it, s_quotationRule, &m_ranges, true);
}
highlightMultiLineComments(&m_ranges);
}
void QtHighlighter::highlightRange(int startLine, int endLine)
{
if (m_language == LANGUAGE_UNKNOWN)
{
return;
}
m_quotationRanges.clear();
m_multiLineCommentRanges.clear();
std::vector<std::pair<int, int>> ranges;
ranges.push_back(std::pair<int, int>(docStart, docEnd));
for (QTextBlock it = doc->begin(); it != doc->end(); it = it.next())
{
utility::append(m_quotationRanges, formatBlockForRule(it, s_quotationRule, &ranges));
}
highlightMultiLineComments();
}
void QtHighlighter::highlightRange(int startLine, int endLine)
{
if (startLine < 0 || endLine < 0 || startLine > endLine || endLine > int(m_highlightedLines.size()))
{
return;
@@ -199,22 +198,19 @@ void QtHighlighter::highlightRange(int startLine, int endLine)
{
if (!m_highlightedLines[index])
{
applyFormatWithoutRanges(it.position(), it.position() + it.length() - 1, s_textFormat, m_ranges);
applyFormat(it.position(), it.position() + it.length() - 1, s_textFormat);
foreach (const HighlightingRule &rule, m_highlightingRules)
if (m_language != LANGUAGE_UNKNOWN)
{
formatBlock(it, rule, &m_ranges, false);
}
}
index++;
}
foreach (const HighlightingRule &rule, m_highlightingRules)
{
formatBlockForRule(it, rule);
}
index = startLine;
for (QTextBlock it = start; it != end; it = it.next())
{
if (!m_highlightedLines[index])
{
formatBlock(it, s_commentRule, &m_ranges, false);
formatBlockIfInRange(it, s_quotationRule.format, &m_quotationRanges);
formatBlockForRule(it, s_commentRule, &m_quotationRanges);
formatBlockIfInRange(it, s_commentRule.format, &m_multiLineCommentRanges);
}
}
index++;
}
@@ -244,40 +240,6 @@ void QtHighlighter::applyFormat(int startPosition, int endPosition, const QTextC
cursor.setCharFormat(format);
}
void QtHighlighter::applyFormatWithoutRanges(
int startPosition, int endPosition, const QTextCharFormat& format, const std::vector<std::pair<int, int>>& ranges
){
std::vector<std::pair<int, int>> highlightRanges;
for (const std::pair<int, int> p : ranges)
{
if (p.first <= startPosition && p.second >= endPosition)
{
return;
}
if (p.first > startPosition && p.first < endPosition)
{
highlightRanges.push_back(std::pair<int, int>(startPosition, p.first - 1));
}
if (p.second > startPosition && p.second < endPosition)
{
highlightRanges.push_back(std::pair<int, int>(p.second + 1, endPosition));
}
}
if (!highlightRanges.size())
{
highlightRanges.push_back(std::pair<int, int>(startPosition, endPosition));
}
for (const std::pair<int, int> p : highlightRanges)
{
applyFormat(p.first, p.second, format);
}
}
QTextCharFormat QtHighlighter::getFormat(int startPosition, int endPosition) const
{
QTextCursor cursor(document());
@@ -285,7 +247,7 @@ QTextCharFormat QtHighlighter::getFormat(int startPosition, int endPosition) con
return cursor.charFormat();
}
void QtHighlighter::highlightMultiLineComments(std::vector<std::pair<int, int>>* ranges)
void QtHighlighter::highlightMultiLineComments()
{
QTextDocument* doc = document();
@@ -305,7 +267,7 @@ void QtHighlighter::highlightMultiLineComments(std::vector<std::pair<int, int>>*
cursorStart.setPosition(cursorStart.selectionEnd() - 2);
}
}
while (isInRange(cursorStart.position(), *ranges));
while (isInRange(cursorStart.position(), m_quotationRanges));
if (cursorStart.isNull())
{
@@ -318,9 +280,7 @@ void QtHighlighter::highlightMultiLineComments(std::vector<std::pair<int, int>>*
break;
}
applyFormat(cursorStart.selectionStart(), cursorEnd.position(), s_commentRule.format);
ranges->push_back(std::pair<int, int>(cursorStart.selectionStart(), cursorEnd.position()));
m_multiLineCommentRanges.push_back(std::pair<int, int>(cursorStart.selectionStart(), cursorEnd.position()));
cursorStart = cursorEnd;
}
}
@@ -348,34 +308,47 @@ bool QtHighlighter::isInRange(int pos, const std::vector<std::pair<int, int>>& r
return false;
}
void QtHighlighter::formatBlock(
const QTextBlock& block, const HighlightingRule& rule, std::vector<std::pair<int, int>>* ranges, bool saveRange
std::vector<std::pair<int, int>> QtHighlighter::formatBlockForRule(
const QTextBlock& block, const HighlightingRule& rule, std::vector<std::pair<int, int>>* ranges
){
QRegExp expression(rule.pattern);
int pos = block.position();
int index = expression.indexIn(block.text());
std::vector<std::pair<int, int>> newRanges;
while (index >= 0)
{
int length = expression.matchedLength();
if (!isInRange(pos + index, *ranges))
if (!ranges || !isInRange(pos + index, *ranges))
{
applyFormat(pos + index, pos + index + length, rule.format);
}
if (saveRange)
{
newRanges.push_back(std::pair<int, int>(pos + index, pos + index + length - 1));
}
newRanges.push_back(std::pair<int, int>(pos + index, pos + index + length));
index = expression.indexIn(block.text(), index + length);
}
if (saveRange)
return newRanges;
}
void QtHighlighter::formatBlockIfInRange(
const QTextBlock& block, const QTextCharFormat& format, std::vector<std::pair<int, int>>* ranges
){
int startPos = block.position();
int endPos = startPos + block.length() - 1;
for (auto range : *ranges)
{
ranges->insert(ranges->end(), newRanges.begin(), newRanges.end());
int start = std::max(range.first, startPos);
int end = std::min(range.second, endPos);
if (start <= end)
{
applyFormat(start, end, format);
}
}
}
+7 -6
View File
@@ -21,8 +21,6 @@ public:
void rehighlightLines(const std::vector<int>& lines);
void applyFormat(int startPosition, int endPosition, const QTextCharFormat& format);
void applyFormatWithoutRanges(
int startPosition, int endPosition, const QTextCharFormat& format, const std::vector<std::pair<int, int>>& ranges);
QTextCharFormat getFormat(int startPosition, int endPosition) const;
@@ -36,11 +34,13 @@ private:
QTextCharFormat format;
};
void highlightMultiLineComments(std::vector<std::pair<int, int>>* ranges);
void highlightMultiLineComments();
bool isInRange(int index, const std::vector<std::pair<int, int>>& ranges) const;
void formatBlock(
const QTextBlock& block, const HighlightingRule& rule, std::vector<std::pair<int, int>>* ranges, bool saveRange);
std::vector<std::pair<int, int>> formatBlockForRule(
const QTextBlock& block, const HighlightingRule& rule, std::vector<std::pair<int, int>>* ranges = nullptr);
void formatBlockIfInRange(
const QTextBlock& block, const QTextCharFormat& format, std::vector<std::pair<int, int>>* ranges);
QTextDocument* document() const;
@@ -56,7 +56,8 @@ private:
LanguageType m_language;
QVector<HighlightingRule> m_highlightingRules;
std::vector<std::pair<int, int>> m_ranges;
std::vector<std::pair<int, int>> m_quotationRanges;
std::vector<std::pair<int, int>> m_multiLineCommentRanges;
std::vector<bool> m_highlightedLines;
};
+46
View File
@@ -45,6 +45,52 @@ void QtCodeView::refreshView()
});
}
bool QtCodeView::isVisible() const
{
return m_widget->isVisible();
}
void QtCodeView::findMatches(ScreenSearchSender* sender, const std::string& query)
{
m_onQtThread(
[sender, query, this]()
{
size_t matchCount = m_widget->findScreenMatches(query);
sender->foundMatches(this, matchCount);
}
);
}
void QtCodeView::activateMatch(size_t matchIndex)
{
m_onQtThread(
[matchIndex, this]()
{
m_widget->activateScreenMatch(matchIndex);
}
);
}
void QtCodeView::deactivateMatch(size_t matchIndex)
{
m_onQtThread(
[matchIndex, this]()
{
m_widget->deactivateScreenMatch(matchIndex);
}
);
}
void QtCodeView::clearMatches()
{
m_onQtThread(
[this]()
{
m_widget->clearScreenMatches();
}
);
}
void QtCodeView::clear()
{
m_onQtThread([=]()
+7
View File
@@ -18,6 +18,13 @@ public:
virtual void initView();
virtual void refreshView();
// ScreenSearchResponder implementation
virtual bool isVisible() const;
virtual void findMatches(ScreenSearchSender* sender, const std::string& query);
virtual void activateMatch(size_t matchIndex);
virtual void deactivateMatch(size_t matchIndex);
virtual void clearMatches();
// CodeView implementation
virtual void clear();
+78
View File
@@ -168,6 +168,80 @@ void QtGraphView::refreshView()
getView()->refreshStyle();
}
bool QtGraphView::isVisible() const
{
return QtViewWidgetWrapper::getWidgetOfView(this)->isVisible();
}
void QtGraphView::findMatches(ScreenSearchSender* sender, const std::string& query)
{
m_onQtThread(
[sender, query, this]()
{
m_matchedNodes.clear();
for (std::shared_ptr<QtGraphNode> node : m_oldNodes)
{
node->matchNameRecursive(query, &m_matchedNodes);
}
sender->foundMatches(this, m_matchedNodes.size());
}
);
}
void QtGraphView::activateMatch(size_t matchIndex)
{
m_onQtThread(
[matchIndex, this]()
{
if (matchIndex >= m_matchedNodes.size())
{
return;
}
QtGraphNode* node = m_matchedNodes[matchIndex];
node->setActiveMatch(true);
node->updateStyle();
centerNode(node);
}
);
}
void QtGraphView::deactivateMatch(size_t matchIndex)
{
m_onQtThread(
[matchIndex, this]()
{
if (matchIndex >= m_matchedNodes.size())
{
return;
}
QtGraphNode* node = m_matchedNodes[matchIndex];
node->setActiveMatch(false);
node->updateStyle();
}
);
}
void QtGraphView::clearMatches()
{
m_onQtThread(
[this]()
{
for (QtGraphNode* node : m_matchedNodes)
{
node->removeNameMatch();
}
m_matchedNodes.clear();
}
);
}
void QtGraphView::rebuildGraph(
std::shared_ptr<Graph> graph,
const std::vector<std::shared_ptr<DummyNode>>& nodes,
@@ -599,6 +673,8 @@ void QtGraphView::doRebuildGraph(
m_graph = graph;
}
m_matchedNodes.clear();
QGraphicsView* view = getView();
@@ -682,6 +758,8 @@ void QtGraphView::doClear()
m_graph.reset();
m_oldGraph.reset();
m_matchedNodes.clear();
}
void QtGraphView::doResize()
+11
View File
@@ -39,6 +39,14 @@ public:
virtual void initView();
virtual void refreshView();
// ScreenSearchResponder implementation
virtual bool isVisible() const;
virtual void findMatches(ScreenSearchSender* sender, const std::string& query);
virtual void activateMatch(size_t matchIndex);
virtual void deactivateMatch(size_t matchIndex);
virtual void clearMatches();
// GraphView implementation
virtual void rebuildGraph(
std::shared_ptr<Graph> graph,
const std::vector<std::shared_ptr<DummyNode>>& nodes,
@@ -164,6 +172,9 @@ private:
QLabel* m_trailDepthLabel;
std::vector<QRectF> m_virtualNodeRects;
// Name matches
std::vector<QtGraphNode*> m_matchedNodes;
};
#endif // QT_GRAPH_VIEW_H
@@ -0,0 +1,98 @@
#include "qt/view/QtScreenSearchView.h"
#include <QToolBar>
#include "component/controller/ScreenSearchController.h"
#include "qt/element/QtScreenSearchBox.h"
#include "qt/utility/utilityQt.h"
#include "qt/view/QtMainView.h"
#include "qt/view/QtViewWidgetWrapper.h"
#include "qt/window/QtMainWindow.h"
#include "utility/ResourcePaths.h"
QtScreenSearchView::QtScreenSearchView(ViewLayout* viewLayout)
: ScreenSearchView(viewLayout)
, m_controllerProxy(this)
{
m_widget = new QtScreenSearchBox(&m_controllerProxy);
m_bar = new QToolBar();
m_bar->setObjectName("screen_search_bar");
m_bar->setMovable(false);
m_bar->addWidget(m_widget);
QtMainWindow* mainWindow = dynamic_cast<QtMainView*>(getViewLayout())->getMainWindow();
QObject::connect(m_widget, &QtScreenSearchBox::closePressed, this, &QtScreenSearchView::hide);
QObject::connect(mainWindow, &QtMainWindow::showScreenSearch, this, &QtScreenSearchView::show);
QObject::connect(mainWindow, &QtMainWindow::hideScreenSearch, this, &QtScreenSearchView::hide);
}
QtScreenSearchView::~QtScreenSearchView()
{
}
void QtScreenSearchView::createWidgetWrapper()
{
setWidgetWrapper(std::make_shared<QtViewWidgetWrapper>(m_widget));
}
void QtScreenSearchView::initView()
{
}
void QtScreenSearchView::refreshView()
{
m_onQtThread([=]()
{
m_bar->setStyleSheet(
utility::getStyleSheet(ResourcePaths::getGuiPath().concat(
FilePath("screen_search_view/screen_search_view.css"))).c_str()
);
m_widget->refreshStyle();
});
}
void QtScreenSearchView::setMatchCount(size_t matchCount)
{
m_onQtThread([=]()
{
m_widget->setMatchCount(matchCount);
});
}
void QtScreenSearchView::setMatchIndex(size_t matchIndex)
{
m_onQtThread([=]()
{
m_widget->setMatchIndex(matchIndex);
});
}
void QtScreenSearchView::addResponder(const std::string& name)
{
m_widget->addResponder(name);
}
void QtScreenSearchView::show()
{
QtMainWindow* mainWindow = dynamic_cast<QtMainView*>(getViewLayout())->getMainWindow();
mainWindow->addToolBar(Qt::BottomToolBarArea, m_bar);
m_bar->show();
m_widget->setFocus();
}
void QtScreenSearchView::hide()
{
m_bar->hide();
m_widget->setMatchCount(0);
m_controllerProxy.executeAsTask<ScreenSearchController>(
[](ScreenSearchController* controller)
{
controller->clearMatches();
}
);
}
+44
View File
@@ -0,0 +1,44 @@
#ifndef QT_SCREEN_SEARCH_VIEW_H
#define QT_SCREEN_SEARCH_VIEW_H
#include "component/controller/helper/ControllerProxy.h"
#include "component/view/ScreenSearchView.h"
#include "qt/utility/QtThreadedFunctor.h"
class QtScreenSearchBox;
class QToolBar;
class QtScreenSearchView
: public QObject
, public ScreenSearchView
{
Q_OBJECT
public:
QtScreenSearchView(ViewLayout* viewLayout);
~QtScreenSearchView();
// View implementation
virtual void createWidgetWrapper() override;
virtual void initView() override;
virtual void refreshView() override;
// ScreenSearchView implementation
virtual void setMatchCount(size_t matchCount) override;
virtual void setMatchIndex(size_t matchIndex) override;
virtual void addResponder(const std::string& name) override;
public slots:
void show();
void hide();
private:
ControllerProxy m_controllerProxy;
QtThreadedLambdaFunctor m_onQtThread;
QtScreenSearchBox* m_widget;
QToolBar* m_bar;
};
#endif // QT_SCREEN_SEARCH_VIEW_H
+4 -10
View File
@@ -5,13 +5,12 @@
#include "qt/view/QtMainView.h"
#include "qt/view/QtViewWidgetWrapper.h"
#include "qt/window/QtMainWindow.h"
#include "settings/ColorScheme.h"
#include "utility/ResourcePaths.h"
QtTooltipView::QtTooltipView(ViewLayout* viewLayout)
: TooltipView(viewLayout)
{
m_widget = new QtTooltip(dynamic_cast<QtMainView*>(getViewLayout())->getMainWindow());
m_widget = new QtTooltip(dynamic_cast<QtMainView*>(viewLayout)->getMainWindow());
}
QtTooltipView::~QtTooltipView()
@@ -31,7 +30,9 @@ void QtTooltipView::refreshView()
{
m_onQtThread([=]()
{
setStyleSheet();
m_widget->setStyleSheet(
utility::getStyleSheet(ResourcePaths::getGuiPath().concat(FilePath("tooltip_view/tooltip_view.css"))).c_str()
);
});
}
@@ -68,10 +69,3 @@ bool QtTooltipView::tooltipVisible() const
{
return m_widget->isVisible();
}
void QtTooltipView::setStyleSheet()
{
m_widget->setStyleSheet(
utility::getStyleSheet(ResourcePaths::getGuiPath().concat(FilePath("tooltip_view/tooltip_view.css"))).c_str()
);
}
-3
View File
@@ -25,9 +25,6 @@ public:
virtual bool tooltipVisible() const;
private:
void setStyleSheet();
void doRefreshView();
QtThreadedLambdaFunctor m_onQtThread;
QtTooltip* m_widget;
+6
View File
@@ -11,6 +11,7 @@
#include "qt/view/QtLogView.h"
#include "qt/view/QtMainView.h"
#include "qt/view/QtRefreshView.h"
#include "qt/view/QtScreenSearchView.h"
#include "qt/view/QtSearchView.h"
#include "qt/view/QtStatusBarView.h"
#include "qt/view/QtStatusView.h"
@@ -84,6 +85,11 @@ std::shared_ptr<RefreshView> QtViewFactory::createRefreshView(ViewLayout* viewLa
return View::createInitAndAddToLayout<QtRefreshView>(viewLayout);
}
std::shared_ptr<ScreenSearchView> QtViewFactory::createScreenSearchView(ViewLayout* viewLayout) const
{
return View::createAndInit<QtScreenSearchView>(viewLayout);
}
std::shared_ptr<SearchView> QtViewFactory::createSearchView(ViewLayout* viewLayout) const
{
return View::createInitAndAddToLayout<QtSearchView>(viewLayout);
+1
View File
@@ -20,6 +20,7 @@ public:
virtual std::shared_ptr<GraphView> createGraphView(ViewLayout* viewLayout) const;
virtual std::shared_ptr<LogView> createLogView(ViewLayout* viewLayout) const;
virtual std::shared_ptr<RefreshView> createRefreshView(ViewLayout* viewLayout) const;
virtual std::shared_ptr<ScreenSearchView> createScreenSearchView(ViewLayout* viewLayout) const;
virtual std::shared_ptr<SearchView> createSearchView(ViewLayout* viewLayout) const;
virtual std::shared_ptr<StatusBarView> createStatusBarView(ViewLayout* viewLayout) const;
virtual std::shared_ptr<StatusView> createStatusView(ViewLayout* viewLayout) const;
@@ -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;
+8 -1
View File
@@ -357,6 +357,7 @@ void QtMainWindow::keyPressEvent(QKeyEvent* event)
case Qt::Key_Escape:
MessageInterruptTasks().dispatch();
emit hideScreenSearch();
break;
case Qt::Key_Space:
@@ -565,6 +566,11 @@ void QtMainWindow::findFulltext()
MessageFind(true).dispatch();
}
void QtMainWindow::findInView()
{
emit showScreenSearch();
}
void QtMainWindow::codeReferencePrevious()
{
MessageCodeReference(MessageCodeReference::REFERENCE_PREVIOUS).dispatch();
@@ -771,6 +777,7 @@ void QtMainWindow::setupEditMenu()
menu->addAction(tr("&Find Symbol"), this, &QtMainWindow::find, QKeySequence::Find);
menu->addAction(tr("&Find Text"), this, &QtMainWindow::findFulltext, QKeySequence(Qt::SHIFT + Qt::CTRL + Qt::Key_F));
menu->addAction(tr("&Find in View"), this, &QtMainWindow::findInView, QKeySequence(Qt::CTRL + Qt::Key_D));
menu->addSeparator();
@@ -858,7 +865,7 @@ void QtMainWindow::setupBookmarksMenu()
m_bookmarksMenu->clear();
}
m_bookmarksMenu->addAction(tr("Bookmark Active Symbol..."), this, &QtMainWindow::showBookmarkCreator, QKeySequence(Qt::CTRL + Qt::Key_D));
m_bookmarksMenu->addAction(tr("Bookmark Active Symbol..."), this, &QtMainWindow::showBookmarkCreator, QKeySequence::Save);
m_bookmarksMenu->addAction(tr("Bookmark Manager"), this, &QtMainWindow::showBookmarkBrowser, QKeySequence(Qt::CTRL + Qt::Key_B));
m_bookmarksMenu->addSeparator();
+5
View File
@@ -78,6 +78,10 @@ public:
void setContentEnabled(bool enabled);
signals:
void showScreenSearch();
void hideScreenSearch();
protected:
void keyPressEvent(QKeyEvent* event);
void contextMenuEvent(QContextMenuEvent* event);
@@ -109,6 +113,7 @@ public slots:
void find();
void findFulltext();
void findInView();
void codeReferencePrevious();
void codeReferenceNext();
void overview();