ui: Added custom trail dialog (issue #249)
* open custom trail dialg via button in top of trail controls * search from symbol to symbol or all referenced/referencing of symbol * define search depth with slider * define horizontal/vertical layout * define node and edge types * renamed depth graph to trail in graph ui * added custom trail UI tests fortune cookie message = A happy surprise is waiting for you.
This commit is contained in:
@@ -593,4 +593,25 @@
|
||||
<icon_disabled>#666666</icon_disabled>
|
||||
</button>
|
||||
</screen_search>
|
||||
|
||||
<custom_trail>
|
||||
<background>#494949</background>
|
||||
<alt_background>#808080</alt_background>
|
||||
<separator>#CCCCCC</separator>
|
||||
<text>#FFFFFF</text>
|
||||
<text_disabled>darkgrey</text_disabled>
|
||||
<background_disabled>#696969</background_disabled>
|
||||
<button>
|
||||
<default>
|
||||
<text>#FFFFFF</text>
|
||||
<background>#494949</background>
|
||||
<border>#FFFFFF</border>
|
||||
</default>
|
||||
<hover>
|
||||
<text>#494949</text>
|
||||
<background>#FFFFFF</background>
|
||||
<border>#FFFFFF</border>
|
||||
</hover>
|
||||
</button>
|
||||
</custom_trail>
|
||||
</config>
|
||||
|
||||
@@ -463,7 +463,7 @@
|
||||
|
||||
<call>
|
||||
<normal>#F4BC3D</normal>
|
||||
<trail_focus>#878787</trail_focus>
|
||||
<trail_focus>#F56B3D</trail_focus>
|
||||
</call>
|
||||
|
||||
<use>
|
||||
@@ -567,4 +567,25 @@
|
||||
<icon_disabled>#CECECE</icon_disabled>
|
||||
</button>
|
||||
</screen_search>
|
||||
|
||||
<custom_trail>
|
||||
<background>white</background>
|
||||
<alt_background>#F5F5F5</alt_background>
|
||||
<separator>#C0C0C0</separator>
|
||||
<text>black</text>
|
||||
<text_disabled>#A0A0A0</text_disabled>
|
||||
<background_disabled>#F2F2F2</background_disabled>
|
||||
<button>
|
||||
<default>
|
||||
<text>black</text>
|
||||
<background>white</background>
|
||||
<border>lightgray</border>
|
||||
</default>
|
||||
<hover>
|
||||
<text>white</text>
|
||||
<background>#2D3C86</background>
|
||||
<border>lightgray</border>
|
||||
</hover>
|
||||
</button>
|
||||
</custom_trail>
|
||||
</config>
|
||||
|
||||
@@ -570,4 +570,25 @@
|
||||
<icon_disabled>#555555</icon_disabled>
|
||||
</button>
|
||||
</screen_search>
|
||||
|
||||
<custom_trail>
|
||||
<background>#272728</background>
|
||||
<alt_background>#555555</alt_background>
|
||||
<separator>#CCC</separator>
|
||||
<text>#F7F7F7</text>
|
||||
<text_disabled>darkgrey</text_disabled>
|
||||
<background_disabled>#474748</background_disabled>
|
||||
<button>
|
||||
<default>
|
||||
<text>#F7F7F7</text>
|
||||
<background>#272728</background>
|
||||
<border>#F7F7F7</border>
|
||||
</default>
|
||||
<hover>
|
||||
<text>#272728</text>
|
||||
<background>#F7F7F7</background>
|
||||
<border>#F7F7F7</border>
|
||||
</hover>
|
||||
</button>
|
||||
</custom_trail>
|
||||
</config>
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
* {
|
||||
color: <color:custom_trail/text>;
|
||||
}
|
||||
|
||||
#panelA {
|
||||
background: <color:custom_trail/background>;
|
||||
}
|
||||
|
||||
#panelB, #panelB2 {
|
||||
background: <color:custom_trail/alt_background>;
|
||||
border-top: 1px solid <color:custom_trail/separator>;
|
||||
border-bottom: 1px solid <color:custom_trail/separator>;
|
||||
}
|
||||
|
||||
#panelB2 {
|
||||
border-bottom: none
|
||||
}
|
||||
|
||||
#search_box_container {
|
||||
border-color: <color:custom_trail/separator>;
|
||||
border-radius: 8px;
|
||||
border-width: 1px;
|
||||
}
|
||||
|
||||
#search_box_container:disabled {
|
||||
background: <color:custom_trail/background_disabled>;
|
||||
border-color: <color:custom_trail/background_disabled>;
|
||||
}
|
||||
|
||||
#search_box:disabled {
|
||||
color: <color:custom_trail/text_disabled>;
|
||||
}
|
||||
|
||||
#button, #button_small {
|
||||
background: <color:custom_trail/button/default/background>;
|
||||
border: 1px solid <color:custom_trail/button/default/border>;
|
||||
border-radius: 8px;
|
||||
color: <color:custom_trail/button/default/text>;
|
||||
padding: 3px 8px 2px;
|
||||
font-size: <setting:font_size+1>px;
|
||||
min-width: 5em;
|
||||
}
|
||||
|
||||
#button_small {
|
||||
border-radius: 6px;
|
||||
font-size: <setting:font_size-1>px;
|
||||
min-width: 4em;
|
||||
}
|
||||
|
||||
#button:hover, #button_small:hover {
|
||||
background: <color:custom_trail/button/hover/background>;
|
||||
border-color: <color:custom_trail/button/hover/border>;
|
||||
color: <color:custom_trail/button/hover/text>;
|
||||
}
|
||||
|
||||
#button:disabled, #button_small:disabled {
|
||||
background: <color:custom_trail/button/disabled/background>;
|
||||
border-color: <color:custom_trail/button/disabled/border>;
|
||||
color: <color:custom_trail/button/disabled/text>;
|
||||
}
|
||||
|
||||
#error {
|
||||
color: red;
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 532 B |
Binary file not shown.
|
After Width: | Height: | Size: 3.1 KiB |
@@ -11,7 +11,7 @@
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
QWidget#search_box_container {
|
||||
#search_box_container {
|
||||
background: <color:search/field/background>;
|
||||
border: 2px solid <color:search/field/border>;
|
||||
border-bottom-left-radius: 12px;
|
||||
@@ -20,19 +20,19 @@ QWidget#search_box_container {
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
QLineEdit#search_box {
|
||||
#search_box {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
color: <color:search/field/text>;
|
||||
selection-background-color: <color:search/field/highlight>;
|
||||
}
|
||||
|
||||
QWidget#search_box_highlight {
|
||||
#search_box_highlight {
|
||||
background-color: <color:search/field/highlight>;
|
||||
border: none;
|
||||
}
|
||||
|
||||
QAbstractItemView#search_box_popup {
|
||||
#search_box_popup {
|
||||
background-color: <color:search/popup/background>;
|
||||
border: 1px solid <color:search/popup/line>;
|
||||
color: <color:search/popup/text>;
|
||||
|
||||
@@ -38,6 +38,8 @@ add_files(
|
||||
component/controller/CodeController.h
|
||||
component/controller/Controller.cpp
|
||||
component/controller/Controller.h
|
||||
component/controller/CustomTrailController.cpp
|
||||
component/controller/CustomTrailController.h
|
||||
component/controller/ErrorController.cpp
|
||||
component/controller/ErrorController.h
|
||||
component/controller/GraphController.cpp
|
||||
@@ -71,6 +73,7 @@ add_files(
|
||||
component/view/CodeView.h
|
||||
component/view/CompositeView.cpp
|
||||
component/view/CompositeView.h
|
||||
component/view/CustomTrailView.h
|
||||
component/view/DialogView.cpp
|
||||
component/view/DialogView.h
|
||||
component/view/ErrorView.cpp
|
||||
@@ -469,6 +472,7 @@ add_files(
|
||||
utility/messaging/filter_types/MessageFilterSearchAutocomplete.h
|
||||
|
||||
utility/messaging/type/activation/MessageActivateLegend.h
|
||||
utility/messaging/type/activation/MessageActivateFullTextSearch.h
|
||||
|
||||
utility/messaging/type/bookmark/MessageBookmarkActivate.h
|
||||
utility/messaging/type/bookmark/MessageBookmarkBrowse.h
|
||||
@@ -479,6 +483,8 @@ add_files(
|
||||
|
||||
utility/messaging/type/code/MessageCodeShowDefinition.h
|
||||
|
||||
utility/messaging/type/custom_trail/MessageCustomTrailShow.h
|
||||
|
||||
utility/messaging/type/error/MessageActivateErrors.h
|
||||
utility/messaging/type/error/MessageErrorCountClear.h
|
||||
utility/messaging/type/error/MessageErrorCountUpdate.h
|
||||
@@ -497,6 +503,9 @@ add_files(
|
||||
utility/messaging/type/indexing/MessageIndexingStarted.h
|
||||
utility/messaging/type/indexing/MessageIndexingStatus.h
|
||||
|
||||
utility/messaging/type/search/MessageSearch.h
|
||||
utility/messaging/type/search/MessageSearchAutocomplete.h
|
||||
|
||||
utility/messaging/type/tab/MessageTabClose.h
|
||||
utility/messaging/type/tab/MessageTabOpen.h
|
||||
utility/messaging/type/tab/MessageTabOpenWith.h
|
||||
@@ -507,7 +516,6 @@ add_files(
|
||||
utility/messaging/type/MessageActivateBase.h
|
||||
utility/messaging/type/MessageActivateEdge.h
|
||||
utility/messaging/type/MessageActivateFile.h
|
||||
utility/messaging/type/MessageActivateFullTextSearch.h
|
||||
utility/messaging/type/MessageActivateLocalSymbols.h
|
||||
utility/messaging/type/MessageActivateNodes.h
|
||||
utility/messaging/type/MessageActivateSourceLocations.h
|
||||
@@ -544,8 +552,6 @@ add_files(
|
||||
utility/messaging/type/MessageScrollCode.h
|
||||
utility/messaging/type/MessageScrollGraph.h
|
||||
utility/messaging/type/MessageScrollToLine.h
|
||||
utility/messaging/type/MessageSearch.h
|
||||
utility/messaging/type/MessageSearchAutocomplete.h
|
||||
utility/messaging/type/MessageShowReference.h
|
||||
utility/messaging/type/MessageShowScope.h
|
||||
utility/messaging/type/MessageShowStatus.h
|
||||
|
||||
@@ -3,27 +3,30 @@
|
||||
#include "Component.h"
|
||||
#include "ActivationController.h"
|
||||
#include "BookmarkController.h"
|
||||
#include "CodeController.h"
|
||||
#include "ErrorController.h"
|
||||
#include "GraphController.h"
|
||||
#include "RefreshController.h"
|
||||
#include "ScreenSearchController.h"
|
||||
#include "SearchController.h"
|
||||
#include "StatusBarController.h"
|
||||
#include "StatusController.h"
|
||||
#include "TabsController.h"
|
||||
#include "TooltipController.h"
|
||||
#include "UndoRedoController.h"
|
||||
#include "BookmarkView.h"
|
||||
#include "CodeController.h"
|
||||
#include "CodeView.h"
|
||||
#include "CustomTrailController.h"
|
||||
#include "CustomTrailView.h"
|
||||
#include "ErrorController.h"
|
||||
#include "ErrorView.h"
|
||||
#include "GraphController.h"
|
||||
#include "GraphView.h"
|
||||
#include "RefreshController.h"
|
||||
#include "RefreshView.h"
|
||||
#include "ScreenSearchController.h"
|
||||
#include "ScreenSearchView.h"
|
||||
#include "SearchController.h"
|
||||
#include "SearchView.h"
|
||||
#include "StatusBarController.h"
|
||||
#include "StatusBarView.h"
|
||||
#include "StatusController.h"
|
||||
#include "StatusView.h"
|
||||
#include "TabsController.h"
|
||||
#include "TabsView.h"
|
||||
#include "TooltipController.h"
|
||||
#include "TooltipView.h"
|
||||
#include "UndoRedoController.h"
|
||||
#include "UndoRedoView.h"
|
||||
#include "ViewFactory.h"
|
||||
|
||||
@@ -66,6 +69,14 @@ std::shared_ptr<Component> ComponentFactory::createCodeComponent(ViewLayout* vie
|
||||
return std::make_shared<Component>(view, controller);
|
||||
}
|
||||
|
||||
std::shared_ptr<Component> ComponentFactory::createCustomTrailComponent()
|
||||
{
|
||||
std::shared_ptr<CustomTrailView> view = m_viewFactory->createCustomTrailView();
|
||||
std::shared_ptr<CustomTrailController> controller = std::make_shared<CustomTrailController>(m_storageAccess);
|
||||
|
||||
return std::make_shared<Component>(view, controller);
|
||||
}
|
||||
|
||||
std::shared_ptr<Component> ComponentFactory::createErrorComponent(ViewLayout* viewLayout)
|
||||
{
|
||||
std::shared_ptr<ErrorView> view = m_viewFactory->createErrorView(viewLayout);
|
||||
|
||||
@@ -21,6 +21,7 @@ public:
|
||||
std::shared_ptr<Component> createActivationComponent();
|
||||
std::shared_ptr<Component> createBookmarkComponent(ViewLayout* viewLayout);
|
||||
std::shared_ptr<Component> createCodeComponent(ViewLayout* viewLayout);
|
||||
std::shared_ptr<Component> createCustomTrailComponent();
|
||||
std::shared_ptr<Component> createErrorComponent(ViewLayout* viewLayout);
|
||||
std::shared_ptr<Component> createGraphComponent(ViewLayout* viewLayout);
|
||||
std::shared_ptr<Component> createRefreshComponent(ViewLayout* viewLayout);
|
||||
|
||||
@@ -98,6 +98,9 @@ void ComponentManager::setupMain(ViewLayout* viewLayout, Id appId)
|
||||
|
||||
std::shared_ptr<Component> statusBarComponent = m_componentFactory.createStatusBarComponent(viewLayout);
|
||||
m_components.push_back(statusBarComponent);
|
||||
|
||||
std::shared_ptr<Component> customTrailComponent = m_componentFactory.createCustomTrailComponent();
|
||||
m_components.push_back(customTrailComponent);
|
||||
}
|
||||
|
||||
void ComponentManager::setupTab(ViewLayout* viewLayout, Id tabId, ScreenSearchSender* screenSearchSender)
|
||||
|
||||
@@ -240,6 +240,17 @@ void CodeController::handleMessage(MessageActivateTokens* message)
|
||||
MessageStatus(status).dispatch();
|
||||
}
|
||||
|
||||
void CodeController::handleMessage(MessageActivateTrail* message)
|
||||
{
|
||||
if (message->custom)
|
||||
{
|
||||
getView()->clear();
|
||||
Id nodeId = { message->originId ? message->originId : message->targetId };
|
||||
MessageCodeShowDefinition msg(nodeId);
|
||||
handleMessage(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
void CodeController::handleMessage(MessageActivateTrailEdge* message)
|
||||
{
|
||||
TRACE("trail edge activate");
|
||||
@@ -375,6 +386,11 @@ void CodeController::handleMessage(MessageCodeShowDefinition* message)
|
||||
}
|
||||
|
||||
snippets[0].insertSnippet = true;
|
||||
|
||||
if (!m_collection)
|
||||
{
|
||||
m_collection = std::make_shared<SourceLocationCollection>();
|
||||
}
|
||||
m_collection->addSourceLocationCopies(collection.get());
|
||||
|
||||
saveOrRestoreViewMode(message);
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "MessageActivateFullTextSearch.h"
|
||||
#include "MessageActivateLocalSymbols.h"
|
||||
#include "MessageActivateTokens.h"
|
||||
#include "MessageActivateTrail.h"
|
||||
#include "MessageActivateTrailEdge.h"
|
||||
#include "MessageChangeFileView.h"
|
||||
#include "MessageDeactivateEdge.h"
|
||||
@@ -43,6 +44,7 @@ class CodeController
|
||||
, public MessageListener<MessageActivateLegend>
|
||||
, public MessageListener<MessageActivateLocalSymbols>
|
||||
, public MessageListener<MessageActivateTokens>
|
||||
, public MessageListener<MessageActivateTrail>
|
||||
, public MessageListener<MessageActivateTrailEdge>
|
||||
, public MessageListener<MessageChangeFileView>
|
||||
, public MessageListener<MessageCodeShowDefinition>
|
||||
@@ -69,6 +71,7 @@ private:
|
||||
void handleMessage(MessageActivateLegend* message) override;
|
||||
void handleMessage(MessageActivateLocalSymbols* message) override;
|
||||
void handleMessage(MessageActivateTokens* message) override;
|
||||
void handleMessage(MessageActivateTrail* message) override;
|
||||
void handleMessage(MessageActivateTrailEdge* message) override;
|
||||
void handleMessage(MessageChangeFileView* message) override;
|
||||
void handleMessage(MessageCodeShowDefinition* message) override;
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
#include "CustomTrailController.h"
|
||||
|
||||
#include "CustomTrailView.h"
|
||||
#include "NodeTypeSet.h"
|
||||
#include "StorageAccess.h"
|
||||
|
||||
CustomTrailController::CustomTrailController(StorageAccess* storageAccess)
|
||||
: m_storageAccess(storageAccess)
|
||||
{
|
||||
}
|
||||
|
||||
void CustomTrailController::clear()
|
||||
{
|
||||
getView()->clearView();
|
||||
getView()->setAvailableNodeAndEdgeTypes(
|
||||
m_storageAccess->getAvailableNodeTypes(), m_storageAccess->getAvailableEdgeTypes()
|
||||
);
|
||||
}
|
||||
|
||||
void CustomTrailController::autocomplete(const std::wstring query, bool from)
|
||||
{
|
||||
NodeTypeSet nodeTypes = NodeTypeSet::all();
|
||||
nodeTypes.remove(NodeType(NodeType::NODE_MODULE));
|
||||
nodeTypes.remove(NodeType(NodeType::NODE_NAMESPACE));
|
||||
nodeTypes.remove(NodeType(NodeType::NODE_PACKAGE));
|
||||
|
||||
getView()->showAutocompletions(m_storageAccess->getAutocompletionMatches(query, nodeTypes, false), from);
|
||||
}
|
||||
|
||||
void CustomTrailController::activateTrail(MessageActivateTrail message)
|
||||
{
|
||||
Id nodeId = message.originId ? message.originId : message.targetId;
|
||||
message.searchMatches = m_storageAccess->getSearchMatchesForTokenIds({ nodeId });
|
||||
message.dispatch();
|
||||
}
|
||||
|
||||
void CustomTrailController::handleMessage(MessageCustomTrailShow* message)
|
||||
{
|
||||
getView()->showView();
|
||||
}
|
||||
|
||||
void CustomTrailController::handleMessage(MessageIndexingFinished* message)
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void CustomTrailController::handleMessage(MessageWindowClosed* message)
|
||||
{
|
||||
getView()->hideView();
|
||||
}
|
||||
|
||||
CustomTrailView* CustomTrailController::getView()
|
||||
{
|
||||
return Controller::getView<CustomTrailView>();
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
#ifndef CUSTOM_TRAIL_CONTROLLER_H
|
||||
#define CUSTOM_TRAIL_CONTROLLER_H
|
||||
|
||||
#include "Controller.h"
|
||||
#include "MessageCustomTrailShow.h"
|
||||
#include "MessageListener.h"
|
||||
#include "MessageWindowClosed.h"
|
||||
#include "MessageIndexingFinished.h"
|
||||
#include "MessageActivateTrail.h"
|
||||
|
||||
class CustomTrailView;
|
||||
class StorageAccess;
|
||||
|
||||
class CustomTrailController
|
||||
: public Controller
|
||||
, public MessageListener<MessageCustomTrailShow>
|
||||
, public MessageListener<MessageIndexingFinished>
|
||||
, public MessageListener<MessageWindowClosed>
|
||||
{
|
||||
public:
|
||||
CustomTrailController(StorageAccess* storageAccess);
|
||||
~CustomTrailController() = default;
|
||||
|
||||
// Controller implementation
|
||||
void clear() override;
|
||||
|
||||
void autocomplete(const std::wstring query, bool from);
|
||||
void activateTrail(MessageActivateTrail message);
|
||||
|
||||
private:
|
||||
void handleMessage(MessageCustomTrailShow* message) override;
|
||||
void handleMessage(MessageIndexingFinished* message) override;
|
||||
void handleMessage(MessageWindowClosed* message) override;
|
||||
|
||||
CustomTrailView* getView();
|
||||
|
||||
StorageAccess* m_storageAccess;
|
||||
};
|
||||
|
||||
#endif // CUSTOM_TRAIL_CONTROLLER_H
|
||||
@@ -215,10 +215,11 @@ void GraphController::handleMessage(MessageActivateTrail* message)
|
||||
m_activeEdgeIds.clear();
|
||||
|
||||
std::shared_ptr<Graph> graph = m_storageAccess->getGraphForTrail(
|
||||
message->originId, message->targetId, message->trailType, message->depth);
|
||||
message->originId, message->targetId, message->nodeTypes, message->edgeTypes, message->nodeNonIndexed, message->depth,
|
||||
true /* !message->custom || (message->originId && message->targetId) */);
|
||||
|
||||
// remove non-indexed files from include graph if indexed file is origin
|
||||
if (message->trailType & Edge::EDGE_INCLUDE)
|
||||
if (!message->custom && message->edgeTypes & Edge::EDGE_INCLUDE)
|
||||
{
|
||||
Node* fileNode = graph->getNodeById(message->originId ? message->originId : message->targetId);
|
||||
if (fileNode && fileNode->isDefined())
|
||||
@@ -262,11 +263,13 @@ void GraphController::handleMessage(MessageActivateTrail* message)
|
||||
m_graph->setTrailMode(message->horizontalLayout ? Graph::TRAIL_HORIZONTAL : Graph::TRAIL_VERTICAL);
|
||||
m_graph->setHasTrailOrigin(message->originId);
|
||||
|
||||
setVisibility(setActive(m_activeNodeIds, true));
|
||||
m_activeNodeIds = { message->originId ? message->originId : message->targetId };
|
||||
setActive(m_activeNodeIds, true);
|
||||
setVisibility(true);
|
||||
|
||||
MessageStatus(L"Layouting depth graph", false, true).dispatch();
|
||||
|
||||
if (message->trailType & Edge::EDGE_INHERITANCE)
|
||||
if (!message->custom && message->edgeTypes & Edge::EDGE_INHERITANCE)
|
||||
{
|
||||
groupTrailNodes(GroupType::INHERITANCE);
|
||||
}
|
||||
@@ -274,6 +277,15 @@ void GraphController::handleMessage(MessageActivateTrail* message)
|
||||
layoutNesting();
|
||||
layoutTrail(message->horizontalLayout, message->originId);
|
||||
|
||||
if (message->originId && message->targetId)
|
||||
{
|
||||
DummyNode* targetNode = getDummyGraphNodeById(message->targetId).get();
|
||||
if (targetNode)
|
||||
{
|
||||
targetNode->active = true;
|
||||
}
|
||||
}
|
||||
|
||||
MessageStatus(L"Displaying depth graph", false, true).dispatch();
|
||||
|
||||
GraphView::GraphParams params;
|
||||
|
||||
@@ -44,6 +44,14 @@ void SearchController::handleMessage(MessageActivateTokens* message)
|
||||
}
|
||||
}
|
||||
|
||||
void SearchController::handleMessage(MessageActivateTrail* message)
|
||||
{
|
||||
if (message->custom)
|
||||
{
|
||||
updateMatches(message);
|
||||
}
|
||||
}
|
||||
|
||||
void SearchController::handleMessage(MessageFind* message)
|
||||
{
|
||||
if (message->findFulltext)
|
||||
@@ -69,7 +77,7 @@ void SearchController::handleMessage(MessageSearchAutocomplete* message)
|
||||
}
|
||||
|
||||
LOG_INFO(L"autocomplete string: \"" + message->query + L"\"");
|
||||
view->setAutocompletionList(m_storageAccess->getAutocompletionMatches(message->query, message->acceptedNodeTypes));
|
||||
view->setAutocompletionList(m_storageAccess->getAutocompletionMatches(message->query, message->acceptedNodeTypes, true));
|
||||
}
|
||||
|
||||
SearchView* SearchController::getView()
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "MessageActivateAll.h"
|
||||
#include "MessageActivateFullTextSearch.h"
|
||||
#include "MessageActivateTokens.h"
|
||||
#include "MessageActivateTrail.h"
|
||||
#include "MessageFind.h"
|
||||
#include "MessageSearchAutocomplete.h"
|
||||
|
||||
@@ -21,6 +22,7 @@ class SearchController
|
||||
, public MessageListener<MessageActivateFullTextSearch>
|
||||
, public MessageListener<MessageActivateLegend>
|
||||
, public MessageListener<MessageActivateTokens>
|
||||
, public MessageListener<MessageActivateTrail>
|
||||
, public MessageListener<MessageFind>
|
||||
, public MessageListener<MessageSearchAutocomplete>
|
||||
{
|
||||
@@ -36,6 +38,7 @@ private:
|
||||
void handleMessage(MessageActivateFullTextSearch* message) override;
|
||||
void handleMessage(MessageActivateLegend* message) override;
|
||||
void handleMessage(MessageActivateTokens* message) override;
|
||||
void handleMessage(MessageActivateTrail* message) override;
|
||||
void handleMessage(MessageFind* message) override;
|
||||
void handleMessage(MessageSearchAutocomplete* message) override;
|
||||
|
||||
|
||||
@@ -132,7 +132,10 @@ void UndoRedoController::handleMessage(MessageActivateTrail* message)
|
||||
return;
|
||||
}
|
||||
|
||||
Command command(std::make_shared<MessageActivateTrail>(*message), Command::ORDER_ADAPT, true);
|
||||
Command command(
|
||||
std::make_shared<MessageActivateTrail>(*message),
|
||||
message->custom ? Command::ORDER_ACTIVATE : Command::ORDER_ADAPT
|
||||
);
|
||||
processCommand(command);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
#ifndef CUSTOM_TRAIL_VIEW_H
|
||||
#define CUSTOM_TRAIL_VIEW_H
|
||||
|
||||
#include "SearchMatch.h"
|
||||
#include "View.h"
|
||||
|
||||
class CustomTrailView
|
||||
: public View
|
||||
{
|
||||
public:
|
||||
CustomTrailView(ViewLayout*)
|
||||
: View(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
virtual std::string getName() const
|
||||
{
|
||||
return "custom trail";
|
||||
}
|
||||
|
||||
virtual void clearView() = 0;
|
||||
virtual void setAvailableNodeAndEdgeTypes(NodeType::TypeMask nodeTypes, Edge::TypeMask edgeTypes) = 0;
|
||||
|
||||
virtual void showView() = 0;
|
||||
virtual void hideView() = 0;
|
||||
virtual void showAutocompletions(const std::vector<SearchMatch>& autocompletions, bool from) = 0;
|
||||
};
|
||||
|
||||
#endif // CUSTOM_TRAIL_VIEW_H
|
||||
@@ -9,6 +9,7 @@
|
||||
class BookmarkButtonsView;
|
||||
class BookmarkView;
|
||||
class CodeView;
|
||||
class CustomTrailView;
|
||||
class ErrorView;
|
||||
class GraphView;
|
||||
class GraphViewStyleImpl;
|
||||
@@ -38,6 +39,7 @@ public:
|
||||
virtual std::shared_ptr<BookmarkButtonsView> createBookmarkButtonsView(ViewLayout* viewLayout) const = 0;
|
||||
virtual std::shared_ptr<BookmarkView> createBookmarkView(ViewLayout* viewLayout) const = 0;
|
||||
virtual std::shared_ptr<CodeView> createCodeView(ViewLayout* viewLayout) const = 0;
|
||||
virtual std::shared_ptr<CustomTrailView> createCustomTrailView() const = 0;
|
||||
virtual std::shared_ptr<ErrorView> createErrorView(ViewLayout* viewLayout) const = 0;
|
||||
virtual std::shared_ptr<GraphView> createGraphView(ViewLayout* viewLayout) const = 0;
|
||||
virtual std::shared_ptr<RefreshView> createRefreshView(ViewLayout* viewLayout) const = 0;
|
||||
|
||||
@@ -139,7 +139,7 @@ std::wstring NodeType::getReadableTypeWString(NodeType::Type type)
|
||||
return std::wstring(str.begin(), str.end());
|
||||
}
|
||||
|
||||
NodeType::Type NodeType::getTypeForReadableTypeString(const std::wstring str)
|
||||
NodeType::Type NodeType::getTypeForReadableTypeString(const std::wstring& str)
|
||||
{
|
||||
for (NodeType::TypeMask mask = 1; mask <= NodeType::NODE_MAX_VALUE; mask *= 2)
|
||||
{
|
||||
|
||||
@@ -84,7 +84,7 @@ public:
|
||||
|
||||
static std::string getReadableTypeString(NodeType::Type type);
|
||||
static std::wstring getReadableTypeWString(NodeType::Type type);
|
||||
static NodeType::Type getTypeForReadableTypeString(const std::wstring str);
|
||||
static NodeType::Type getTypeForReadableTypeString(const std::wstring& str);
|
||||
|
||||
NodeType(Type type);
|
||||
|
||||
|
||||
@@ -168,6 +168,20 @@ std::wstring Edge::getReadableTypeString(EdgeType type)
|
||||
return L"";
|
||||
}
|
||||
|
||||
Edge::EdgeType Edge::getTypeForReadableTypeString(const std::wstring& str)
|
||||
{
|
||||
for (TypeMask mask = 1; mask <= EDGE_MAX_VALUE; mask *= 2)
|
||||
{
|
||||
EdgeType type = intToType(mask);
|
||||
if (getReadableTypeString(type) == str)
|
||||
{
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
return EDGE_UNDEFINED;
|
||||
}
|
||||
|
||||
std::wstring Edge::getReadableTypeString() const
|
||||
{
|
||||
return getReadableTypeString(m_type);
|
||||
|
||||
@@ -31,7 +31,9 @@ public:
|
||||
EDGE_IMPORT = 1 << 12,
|
||||
EDGE_AGGREGATION = 1 << 13,
|
||||
EDGE_MACRO_USAGE = 1 << 14,
|
||||
EDGE_ANNOTATION_USAGE = 1 << 15
|
||||
EDGE_ANNOTATION_USAGE = 1 << 15,
|
||||
|
||||
EDGE_MAX_VALUE = EDGE_ANNOTATION_USAGE
|
||||
};
|
||||
|
||||
static int typeToInt(EdgeType type);
|
||||
@@ -58,6 +60,8 @@ public:
|
||||
|
||||
static std::wstring getUnderscoredTypeString(EdgeType type);
|
||||
static std::wstring getReadableTypeString(EdgeType type);
|
||||
static EdgeType getTypeForReadableTypeString(const std::wstring& str);
|
||||
|
||||
// Logging.
|
||||
virtual std::wstring getReadableTypeString() const override;
|
||||
std::wstring getAsString() const;
|
||||
|
||||
@@ -670,7 +670,7 @@ std::shared_ptr<SourceLocationCollection> PersistentStorage::getFullTextSearchLo
|
||||
return collection;
|
||||
}
|
||||
|
||||
std::vector<SearchMatch> PersistentStorage::getAutocompletionMatches(const std::wstring& query, NodeTypeSet acceptedNodeTypes) const
|
||||
std::vector<SearchMatch> PersistentStorage::getAutocompletionMatches(const std::wstring& query, NodeTypeSet acceptedNodeTypes, bool acceptCommands) const
|
||||
{
|
||||
TRACE();
|
||||
|
||||
@@ -692,7 +692,10 @@ std::vector<SearchMatch> PersistentStorage::getAutocompletionMatches(const std::
|
||||
utility::append(matches, getAutocompletionFileMatches(query, maxResultsCount));
|
||||
}
|
||||
|
||||
utility::append(matches, getAutocompletionCommandMatches(query, acceptedNodeTypes));
|
||||
if (acceptCommands)
|
||||
{
|
||||
utility::append(matches, getAutocompletionCommandMatches(query, acceptedNodeTypes));
|
||||
}
|
||||
|
||||
// Rescore search matches to check if better score is achieved with higher indices
|
||||
std::vector<SearchMatch> rescoredMatches;
|
||||
@@ -1233,19 +1236,37 @@ std::shared_ptr<Graph> PersistentStorage::getGraphForChildrenOfNodeId(Id nodeId)
|
||||
}
|
||||
|
||||
std::shared_ptr<Graph> PersistentStorage::getGraphForTrail(
|
||||
Id originId, Id targetId, Edge::TypeMask trailType, size_t depth) const
|
||||
Id originId, Id targetId, NodeType::TypeMask nodeTypes, Edge::TypeMask edgeTypes, bool nodeNonIndexed,
|
||||
size_t depth, bool directed) const
|
||||
{
|
||||
TRACE();
|
||||
|
||||
std::set<Id> nodeIds;
|
||||
std::set<Id> edgeIds;
|
||||
|
||||
std::vector<Id> nodeIdsToProcess;
|
||||
nodeIdsToProcess.push_back(originId ? originId : targetId);
|
||||
nodeIds.insert(originId ? originId : targetId);
|
||||
bool forward = originId;
|
||||
size_t currentDepth = 0;
|
||||
|
||||
nodeIds.insert(nodeIdsToProcess.back());
|
||||
std::vector<Id> nodeIdsToProcess = { *nodeIds.begin() };
|
||||
|
||||
struct TrailNode
|
||||
{
|
||||
Id id = 0;
|
||||
std::set<TrailNode*> parents;
|
||||
std::set<Id> edgeIds;
|
||||
};
|
||||
|
||||
bool isTerminatedTrail = originId && targetId;
|
||||
std::map<Id, TrailNode> trailNodes;
|
||||
|
||||
if (isTerminatedTrail)
|
||||
{
|
||||
TrailNode root;
|
||||
root.id = originId;
|
||||
trailNodes.emplace(originId, root);
|
||||
}
|
||||
|
||||
while (nodeIdsToProcess.size() && (!depth || currentDepth < depth))
|
||||
{
|
||||
std::vector<StorageEdge> edges =
|
||||
@@ -1253,7 +1274,7 @@ std::shared_ptr<Graph> PersistentStorage::getGraphForTrail(
|
||||
m_sqliteIndexStorage.getEdgesBySourceIds(nodeIdsToProcess) :
|
||||
m_sqliteIndexStorage.getEdgesByTargetIds(nodeIdsToProcess);
|
||||
|
||||
if (trailType & Edge::LAYOUT_VERTICAL)
|
||||
if (!directed || edgeTypes & Edge::LAYOUT_VERTICAL)
|
||||
{
|
||||
utility::append(edges,
|
||||
forward ?
|
||||
@@ -1262,33 +1283,165 @@ std::shared_ptr<Graph> PersistentStorage::getGraphForTrail(
|
||||
);
|
||||
}
|
||||
|
||||
nodeIdsToProcess.clear();
|
||||
std::vector<Id> nodeIdsToCheck;
|
||||
std::map<Id, std::vector<StorageEdge>> edgesToInsert;
|
||||
|
||||
for (const StorageEdge& edge : edges)
|
||||
{
|
||||
if (Edge::intToType(edge.type) & trailType)
|
||||
if (Edge::intToType(edge.type) & edgeTypes &&
|
||||
edgeIds.find(edge.id) == edgeIds.end())
|
||||
{
|
||||
bool isForward = forward == !(Edge::intToType(edge.type) & Edge::LAYOUT_VERTICAL);
|
||||
|
||||
const Id nodeId = isForward ? edge.targetNodeId : edge.sourceNodeId;
|
||||
const Id otherNodeId = isForward ? edge.sourceNodeId : edge.targetNodeId;
|
||||
const Id targetNodeId = isForward ? edge.targetNodeId : edge.sourceNodeId;
|
||||
const Id sourceNodeId = isForward ? edge.sourceNodeId : edge.targetNodeId;
|
||||
|
||||
if (nodeIds.find(nodeId) == nodeIds.end())
|
||||
if (nodeIds.find(targetNodeId) == nodeIds.end())
|
||||
{
|
||||
nodeIdsToProcess.push_back(nodeId);
|
||||
nodeIds.insert(nodeId);
|
||||
edgeIds.insert(edge.id);
|
||||
nodeIdsToCheck.push_back(targetNodeId);
|
||||
edgesToInsert[targetNodeId].push_back(edge);
|
||||
}
|
||||
else if (nodeIds.find(otherNodeId) != nodeIds.end())
|
||||
else if (nodeIds.find(sourceNodeId) == nodeIds.end())
|
||||
{
|
||||
if (!directed)
|
||||
{
|
||||
nodeIdsToCheck.push_back(sourceNodeId);
|
||||
edgesToInsert[sourceNodeId].push_back(edge);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
edgeIds.insert(edge.id);
|
||||
|
||||
if (isTerminatedTrail)
|
||||
{
|
||||
TrailNode& target = trailNodes[targetNodeId];
|
||||
TrailNode& origin = trailNodes[sourceNodeId];
|
||||
target.id = targetNodeId;
|
||||
origin.id = sourceNodeId;
|
||||
target.parents.insert(&origin);
|
||||
target.edgeIds.insert(edge.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nodeIdsToProcess.clear();
|
||||
|
||||
if (nodeTypes != 0)
|
||||
{
|
||||
for (const StorageNode& node : m_sqliteIndexStorage.getAllByIds<StorageNode>(nodeIdsToCheck))
|
||||
{
|
||||
NodeType::Type type = NodeType::intToType(node.type);
|
||||
if (type & nodeTypes || (type == NodeType::NODE_SYMBOL && nodeNonIndexed))
|
||||
{
|
||||
if (!nodeNonIndexed)
|
||||
{
|
||||
if (type == NodeType::NODE_FILE)
|
||||
{
|
||||
auto it = m_fileNodeIndexed.find(node.id);
|
||||
if (it == m_fileNodeIndexed.end() || !it->second)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto it = m_symbolDefinitionKinds.find(node.id);
|
||||
if (it == m_symbolDefinitionKinds.end() || it->second == DEFINITION_NONE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: don't add namespace nodes to the graph, because it destroys trail layouting
|
||||
// Remove when namespaces are proper nodes with children
|
||||
if ((type & (NodeType::NODE_MODULE | NodeType::NODE_NAMESPACE | NodeType::NODE_PACKAGE)) == 0)
|
||||
{
|
||||
nodeIds.insert(node.id);
|
||||
for (const StorageEdge& edge : edgesToInsert[node.id])
|
||||
{
|
||||
if ((Edge::intToType(edge.type) & Edge::EDGE_MEMBER) == 0)
|
||||
{
|
||||
edgeIds.insert(edge.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
nodeIdsToProcess.push_back(node.id);
|
||||
|
||||
if (isTerminatedTrail)
|
||||
{
|
||||
TrailNode& targetNode = trailNodes[node.id];
|
||||
targetNode.id = node.id;
|
||||
|
||||
for (const StorageEdge& edge : edgesToInsert[node.id])
|
||||
{
|
||||
targetNode.edgeIds.insert(edge.id);
|
||||
|
||||
Id sourceNodeId = (edge.targetNodeId == node.id ? edge.sourceNodeId : edge.targetNodeId);
|
||||
TrailNode& oldNode = trailNodes[sourceNodeId];
|
||||
targetNode.parents.insert(&oldNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const Id nodeId : nodeIdsToCheck)
|
||||
{
|
||||
nodeIds.insert(nodeId);
|
||||
nodeIdsToProcess.push_back(nodeId);
|
||||
|
||||
for (const StorageEdge& edge : edgesToInsert[nodeId])
|
||||
{
|
||||
edgeIds.insert(edge.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
edgesToInsert.clear();
|
||||
|
||||
currentDepth++;
|
||||
}
|
||||
|
||||
if (isTerminatedTrail)
|
||||
{
|
||||
nodeIds.clear();
|
||||
edgeIds.clear();
|
||||
|
||||
if (trailNodes.find(targetId) != trailNodes.end())
|
||||
{
|
||||
std::queue<TrailNode*> nodesToProcess;
|
||||
nodesToProcess.push(&trailNodes[targetId]);
|
||||
|
||||
while (nodesToProcess.size())
|
||||
{
|
||||
TrailNode* currentNode = nodesToProcess.front();
|
||||
nodesToProcess.pop();
|
||||
|
||||
if (nodeIds.find(currentNode->id) != nodeIds.end())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
nodeIds.insert(currentNode->id);
|
||||
edgeIds.insert(currentNode->edgeIds.begin(), currentNode->edgeIds.end());
|
||||
|
||||
for (TrailNode* parent : currentNode->parents)
|
||||
{
|
||||
nodesToProcess.push(parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nodeIds.insert(originId);
|
||||
nodeIds.insert(targetId);
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Graph> graph = std::make_shared<Graph>();
|
||||
|
||||
addNodesWithParentsAndEdgesToGraph(utility::toVector(nodeIds), utility::toVector(edgeIds), graph.get(), false);
|
||||
@@ -1298,6 +1451,30 @@ std::shared_ptr<Graph> PersistentStorage::getGraphForTrail(
|
||||
return graph;
|
||||
}
|
||||
|
||||
NodeType::TypeMask PersistentStorage::getAvailableNodeTypes() const
|
||||
{
|
||||
TRACE();
|
||||
|
||||
NodeType::TypeMask mask = 0;
|
||||
for (int type : m_sqliteIndexStorage.getAvailableNodeTypes())
|
||||
{
|
||||
mask |= NodeType::intToType(type);
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
||||
Edge::TypeMask PersistentStorage::getAvailableEdgeTypes() const
|
||||
{
|
||||
TRACE();
|
||||
|
||||
Edge::TypeMask mask = 0;
|
||||
for (int type : m_sqliteIndexStorage.getAvailableEdgeTypes())
|
||||
{
|
||||
mask |= Edge::intToType(type);
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
||||
// TODO: rename: getActiveElementIdsForId; TODO: make separate function for declarationId
|
||||
std::vector<Id> PersistentStorage::getActiveTokenIdsForId(Id tokenId, Id* declarationId) const
|
||||
{
|
||||
|
||||
@@ -104,7 +104,7 @@ public:
|
||||
std::shared_ptr<SourceLocationCollection> getFullTextSearchLocations(
|
||||
const std::wstring& searchTerm, bool caseSensitive) const override;
|
||||
|
||||
std::vector<SearchMatch> getAutocompletionMatches(const std::wstring& query, NodeTypeSet acceptedNodeTypes) const override;
|
||||
std::vector<SearchMatch> getAutocompletionMatches(const std::wstring& query, NodeTypeSet acceptedNodeTypes, bool acceptCommands) const override;
|
||||
std::vector<SearchMatch> getAutocompletionSymbolMatches(
|
||||
const std::wstring& query, const NodeTypeSet& acceptedNodeTypes, size_t maxResultsCount, size_t maxBestScoredResultsLength) const;
|
||||
std::vector<SearchMatch> getAutocompletionFileMatches(const std::wstring& query, size_t maxResultsCount) const;
|
||||
@@ -116,7 +116,11 @@ public:
|
||||
std::shared_ptr<Graph> getGraphForActiveTokenIds(
|
||||
const std::vector<Id>& tokenIds, const std::vector<Id>& expandedNodeIds, bool* isActiveNamespace = nullptr) const override;
|
||||
std::shared_ptr<Graph> getGraphForChildrenOfNodeId(Id nodeId) const override;
|
||||
std::shared_ptr<Graph> getGraphForTrail(Id originId, Id targetId, Edge::TypeMask trailType, size_t depth) const override;
|
||||
std::shared_ptr<Graph> getGraphForTrail(
|
||||
Id originId, Id targetId, NodeType::TypeMask nodeTypes, Edge::TypeMask trailType, bool nodeNonIndexed, size_t depth, bool directed) const override;
|
||||
|
||||
NodeType::TypeMask getAvailableNodeTypes() const override;
|
||||
Edge::TypeMask getAvailableEdgeTypes() const override;
|
||||
|
||||
std::vector<Id> getActiveTokenIdsForId(Id tokenId, Id* declarationId) const override;
|
||||
std::vector<Id> getNodeIdsForLocationIds(const std::vector<Id>& locationIds) const override;
|
||||
|
||||
@@ -49,7 +49,7 @@ public:
|
||||
|
||||
virtual std::shared_ptr<SourceLocationCollection> getFullTextSearchLocations(
|
||||
const std::wstring& searchTerm, bool caseSensitive) const = 0;
|
||||
virtual std::vector<SearchMatch> getAutocompletionMatches(const std::wstring& query, NodeTypeSet acceptedNodeTypes) const = 0;
|
||||
virtual std::vector<SearchMatch> getAutocompletionMatches(const std::wstring& query, NodeTypeSet acceptedNodeTypes, bool acceptCommands) const = 0;
|
||||
virtual std::vector<SearchMatch> getSearchMatchesForTokenIds(const std::vector<Id>& tokenIds) const = 0;
|
||||
|
||||
virtual std::shared_ptr<Graph> getGraphForAll() const = 0;
|
||||
@@ -57,7 +57,10 @@ public:
|
||||
virtual std::shared_ptr<Graph> getGraphForActiveTokenIds(
|
||||
const std::vector<Id>& tokenIds, const std::vector<Id>& expandedNodeIds, bool* isActiveNamespace = nullptr) const = 0;
|
||||
virtual std::shared_ptr<Graph> getGraphForChildrenOfNodeId(Id nodeId) const = 0;
|
||||
virtual std::shared_ptr<Graph> getGraphForTrail(Id originId, Id targetId, Edge::TypeMask trailType, size_t depth) const = 0;
|
||||
virtual std::shared_ptr<Graph> getGraphForTrail(Id originId, Id targetId, NodeType::TypeMask nodeTypes, Edge::TypeMask edgeTypes, bool nodeNonIndexed, size_t depth, bool directed) const = 0;
|
||||
|
||||
virtual NodeType::TypeMask getAvailableNodeTypes() const = 0;
|
||||
virtual Edge::TypeMask getAvailableEdgeTypes() const = 0;
|
||||
|
||||
virtual std::vector<Id> getActiveTokenIdsForId(Id tokenId, Id* declarationId) const = 0;
|
||||
virtual std::vector<Id> getNodeIdsForLocationIds(const std::vector<Id>& locationIds) const = 0;
|
||||
|
||||
@@ -66,6 +66,35 @@ void StorageAccessProxy::setSubject(std::weak_ptr<StorageAccess> subject)
|
||||
return _DEFAULT_VALUE_; \
|
||||
}
|
||||
|
||||
#define DEF_GETTER_5(_METHOD_NAME_, _PARAM_1_TYPE_, _PARAM_2_TYPE_, _PARAM_3_TYPE_, _PARAM_4_TYPE_, _PARAM_5_TYPE_, _RETURN_TYPE_, _DEFAULT_VALUE_) \
|
||||
UNWRAP(_RETURN_TYPE_) StorageAccessProxy::_METHOD_NAME_(_PARAM_1_TYPE_ p1, _PARAM_2_TYPE_ p2, _PARAM_3_TYPE_ p3, _PARAM_4_TYPE_ p4, _PARAM_5_TYPE_ p5) const \
|
||||
{ \
|
||||
if (std::shared_ptr<StorageAccess> subject = m_subject.lock()) \
|
||||
{ \
|
||||
return subject->_METHOD_NAME_(p1, p2, p3, p4, p5); \
|
||||
} \
|
||||
return _DEFAULT_VALUE_; \
|
||||
}
|
||||
|
||||
#define DEF_GETTER_6(_METHOD_NAME_, _PARAM_1_TYPE_, _PARAM_2_TYPE_, _PARAM_3_TYPE_, _PARAM_4_TYPE_, _PARAM_5_TYPE_, _PARAM_6_TYPE_, _RETURN_TYPE_, _DEFAULT_VALUE_) \
|
||||
UNWRAP(_RETURN_TYPE_) StorageAccessProxy::_METHOD_NAME_(_PARAM_1_TYPE_ p1, _PARAM_2_TYPE_ p2, _PARAM_3_TYPE_ p3, _PARAM_4_TYPE_ p4, _PARAM_5_TYPE_ p5, _PARAM_6_TYPE_ p6) const \
|
||||
{ \
|
||||
if (std::shared_ptr<StorageAccess> subject = m_subject.lock()) \
|
||||
{ \
|
||||
return subject->_METHOD_NAME_(p1, p2, p3, p4, p5, p6); \
|
||||
} \
|
||||
return _DEFAULT_VALUE_; \
|
||||
}
|
||||
|
||||
#define DEF_GETTER_7(_METHOD_NAME_, _PARAM_1_TYPE_, _PARAM_2_TYPE_, _PARAM_3_TYPE_, _PARAM_4_TYPE_, _PARAM_5_TYPE_, _PARAM_6_TYPE_, _PARAM_7_TYPE_, _RETURN_TYPE_, _DEFAULT_VALUE_) \
|
||||
UNWRAP(_RETURN_TYPE_) StorageAccessProxy::_METHOD_NAME_(_PARAM_1_TYPE_ p1, _PARAM_2_TYPE_ p2, _PARAM_3_TYPE_ p3, _PARAM_4_TYPE_ p4, _PARAM_5_TYPE_ p5, _PARAM_6_TYPE_ p6, _PARAM_7_TYPE_ p7) const \
|
||||
{ \
|
||||
if (std::shared_ptr<StorageAccess> subject = m_subject.lock()) \
|
||||
{ \
|
||||
return subject->_METHOD_NAME_(p1, p2, p3, p4, p5, p6, p7); \
|
||||
} \
|
||||
return _DEFAULT_VALUE_; \
|
||||
}
|
||||
|
||||
DEF_GETTER_1(getNodeIdForFileNode, const FilePath&, Id, 0)
|
||||
DEF_GETTER_1(getNodeIdForNameHierarchy, const NameHierarchy&, Id, 0)
|
||||
@@ -79,13 +108,15 @@ DEF_GETTER_1(getNodeIdToParentFileMap, const std::vector<Id>&, NodeIdToParentFil
|
||||
DEF_GETTER_1(getNodeTypeForNodeWithId, Id, NodeType, NodeType(NodeType::NODE_SYMBOL))
|
||||
DEF_GETTER_1(getEdgeById, Id, StorageEdge, StorageEdge())
|
||||
DEF_GETTER_2(getFullTextSearchLocations, const std::wstring &, bool, std::shared_ptr<SourceLocationCollection>, std::make_shared<SourceLocationCollection>())
|
||||
DEF_GETTER_2(getAutocompletionMatches, const std::wstring &, NodeTypeSet, std::vector<SearchMatch>, std::vector<SearchMatch>())
|
||||
DEF_GETTER_3(getAutocompletionMatches, const std::wstring &, NodeTypeSet, bool, std::vector<SearchMatch>, std::vector<SearchMatch>())
|
||||
DEF_GETTER_1(getSearchMatchesForTokenIds, const std::vector<Id>&, std::vector<SearchMatch>, std::vector<SearchMatch>())
|
||||
DEF_GETTER_0(getGraphForAll, std::shared_ptr<Graph>, std::make_shared<Graph>())
|
||||
DEF_GETTER_1(getGraphForNodeTypes, NodeTypeSet, std::shared_ptr<Graph>, std::make_shared<Graph>())
|
||||
DEF_GETTER_3(getGraphForActiveTokenIds, const std::vector<Id>&, const std::vector<Id>&, bool*, std::shared_ptr<Graph>, std::make_shared<Graph>())
|
||||
DEF_GETTER_1(getGraphForChildrenOfNodeId, Id, std::shared_ptr<Graph>, std::make_shared<Graph>())
|
||||
DEF_GETTER_4(getGraphForTrail, Id, Id, Edge::TypeMask, size_t, std::shared_ptr<Graph>, std::make_shared<Graph>())
|
||||
DEF_GETTER_7(getGraphForTrail, Id, Id, NodeType::TypeMask, Edge::TypeMask, bool, size_t, bool, std::shared_ptr<Graph>, std::make_shared<Graph>())
|
||||
DEF_GETTER_0(getAvailableNodeTypes, NodeType::TypeMask, 0);
|
||||
DEF_GETTER_0(getAvailableEdgeTypes, Edge::TypeMask, 0);
|
||||
DEF_GETTER_2(getActiveTokenIdsForId, Id, Id*, std::vector<Id>, {})
|
||||
DEF_GETTER_1(getNodeIdsForLocationIds, const std::vector<Id>&, std::vector<Id>, {})
|
||||
DEF_GETTER_1(getSourceLocationsForTokenIds, const std::vector<Id>&, std::shared_ptr<SourceLocationCollection>, std::make_shared<SourceLocationCollection>())
|
||||
|
||||
@@ -28,7 +28,7 @@ public:
|
||||
|
||||
std::shared_ptr<SourceLocationCollection> getFullTextSearchLocations(
|
||||
const std::wstring& searchTerm, bool caseSensitive) const override;
|
||||
std::vector<SearchMatch> getAutocompletionMatches(const std::wstring& query, NodeTypeSet acceptedNodeTypes) const override;
|
||||
std::vector<SearchMatch> getAutocompletionMatches(const std::wstring& query, NodeTypeSet acceptedNodeTypes, bool acceptCommands) const override;
|
||||
std::vector<SearchMatch> getSearchMatchesForTokenIds(const std::vector<Id>& tokenIds) const override;
|
||||
|
||||
std::shared_ptr<Graph> getGraphForAll() const override;
|
||||
@@ -36,7 +36,10 @@ public:
|
||||
std::shared_ptr<Graph> getGraphForActiveTokenIds(
|
||||
const std::vector<Id>& tokenIds, const std::vector<Id>& expandedNodeIds, bool* isActiveNamespace = nullptr) const override;
|
||||
std::shared_ptr<Graph> getGraphForChildrenOfNodeId(Id nodeId) const override;
|
||||
std::shared_ptr<Graph> getGraphForTrail(Id originId, Id targetId, Edge::TypeMask trailType, size_t depth) const override;
|
||||
std::shared_ptr<Graph> getGraphForTrail(Id originId, Id targetId, NodeType::TypeMask nodeTypes, Edge::TypeMask edgeTypes, bool nodeNonIndexed, size_t depth, bool directed) const override;
|
||||
|
||||
NodeType::TypeMask getAvailableNodeTypes() const override;
|
||||
Edge::TypeMask getAvailableEdgeTypes() const override;
|
||||
|
||||
std::vector<Id> getActiveTokenIdsForId(Id tokenId, Id* declarationId) const override;
|
||||
std::vector<Id> getNodeIdsForLocationIds(const std::vector<Id>& locationIds) const override;
|
||||
|
||||
@@ -758,6 +758,46 @@ StorageNode SqliteIndexStorage::getNodeBySerializedName(const std::wstring& seri
|
||||
return StorageNode();
|
||||
}
|
||||
|
||||
std::vector<int> SqliteIndexStorage::getAvailableNodeTypes() const
|
||||
{
|
||||
CppSQLite3Query q = executeQuery("SELECT DISTINCT type FROM node;");
|
||||
|
||||
std::vector<int> types;
|
||||
|
||||
while (!q.eof())
|
||||
{
|
||||
const int type = q.getIntField(0, -1);
|
||||
if (type != -1)
|
||||
{
|
||||
types.push_back(type);
|
||||
}
|
||||
|
||||
q.nextRow();
|
||||
}
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
std::vector<int> SqliteIndexStorage::getAvailableEdgeTypes() const
|
||||
{
|
||||
CppSQLite3Query q = executeQuery("SELECT DISTINCT type FROM edge;");
|
||||
|
||||
std::vector<int> types;
|
||||
|
||||
while (!q.eof())
|
||||
{
|
||||
const int type = q.getIntField(0, -1);
|
||||
if (type != -1)
|
||||
{
|
||||
types.push_back(type);
|
||||
}
|
||||
|
||||
q.nextRow();
|
||||
}
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
StorageFile SqliteIndexStorage::getFileByPath(const std::wstring& filePath) const
|
||||
{
|
||||
return doGetFirst<StorageFile>("WHERE file.path == '" + utility::encodeToUtf8(filePath) + "'");
|
||||
|
||||
@@ -98,6 +98,9 @@ public:
|
||||
StorageNode getNodeById(Id id) const;
|
||||
StorageNode getNodeBySerializedName(const std::wstring& serializedName) const;
|
||||
|
||||
std::vector<int> getAvailableNodeTypes() const;
|
||||
std::vector<int> getAvailableEdgeTypes() const;
|
||||
|
||||
StorageFile getFileByPath(const std::wstring& filePath) const;
|
||||
|
||||
std::vector<StorageFile> getFilesByPaths(const std::vector<FilePath>& filePaths) const;
|
||||
|
||||
@@ -2,19 +2,48 @@
|
||||
#define MESSAGE_ACTIVATE_TRAIL_H
|
||||
|
||||
#include "Message.h"
|
||||
#include "types.h"
|
||||
#include "MessageActivateBase.h"
|
||||
#include "NodeType.h"
|
||||
#include "TabId.h"
|
||||
#include "types.h"
|
||||
|
||||
class MessageActivateTrail
|
||||
: public Message<MessageActivateTrail>
|
||||
, public MessageActivateBase
|
||||
{
|
||||
public:
|
||||
MessageActivateTrail(Id originId, Id targetId, Edge::TypeMask trailType, size_t depth, bool horizontalLayout)
|
||||
MessageActivateTrail(
|
||||
Id originId, Id targetId, Edge::TypeMask edgeTypes, size_t depth, bool horizontalLayout
|
||||
)
|
||||
: originId(originId)
|
||||
, targetId(targetId)
|
||||
, trailType(trailType)
|
||||
, nodeTypes(0)
|
||||
, edgeTypes(edgeTypes)
|
||||
, nodeNonIndexed(false)
|
||||
, depth(depth)
|
||||
, horizontalLayout(horizontalLayout)
|
||||
, custom(false)
|
||||
{
|
||||
setSchedulerId(TabId::currentTab());
|
||||
}
|
||||
|
||||
MessageActivateTrail(
|
||||
Id originId,
|
||||
Id targetId,
|
||||
NodeType::TypeMask nodeTypes,
|
||||
Edge::TypeMask edgeTypes,
|
||||
bool nodeNonIndexed,
|
||||
size_t depth,
|
||||
bool horizontalLayout
|
||||
)
|
||||
: originId(originId)
|
||||
, targetId(targetId)
|
||||
, nodeTypes(nodeTypes)
|
||||
, edgeTypes(edgeTypes)
|
||||
, nodeNonIndexed(nodeNonIndexed)
|
||||
, depth(depth)
|
||||
, horizontalLayout(horizontalLayout)
|
||||
, custom(true)
|
||||
{
|
||||
setSchedulerId(TabId::currentTab());
|
||||
}
|
||||
@@ -24,11 +53,21 @@ public:
|
||||
return "MessageActivateTrail";
|
||||
}
|
||||
|
||||
std::vector<SearchMatch> getSearchMatches() const override
|
||||
{
|
||||
return searchMatches;
|
||||
}
|
||||
|
||||
std::vector<SearchMatch> searchMatches;
|
||||
|
||||
const Id originId;
|
||||
const Id targetId;
|
||||
const Edge::TypeMask trailType;
|
||||
const NodeType::TypeMask nodeTypes;
|
||||
const Edge::TypeMask edgeTypes;
|
||||
const bool nodeNonIndexed;
|
||||
const size_t depth;
|
||||
const bool horizontalLayout;
|
||||
const bool custom;
|
||||
};
|
||||
|
||||
#endif // MESSAGE_ACTIVATE_TRAIL_H
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
#ifndef MESSAGE_CUSTOM_TRAIL_SHOW_H
|
||||
#define MESSAGE_CUSTOM_TRAIL_SHOW_H
|
||||
|
||||
#include "Message.h"
|
||||
|
||||
class MessageCustomTrailShow
|
||||
: public Message<MessageCustomTrailShow>
|
||||
{
|
||||
public:
|
||||
MessageCustomTrailShow()
|
||||
{
|
||||
}
|
||||
|
||||
static const std::string getStaticType()
|
||||
{
|
||||
return "MessageCustomTrailShow";
|
||||
}
|
||||
};
|
||||
|
||||
#endif // MESSAGE_CUSTOM_TRAIL_SHOW_H
|
||||
@@ -246,6 +246,8 @@ add_files(
|
||||
qt/view/QtCodeView.h
|
||||
qt/view/QtCompositeView.cpp
|
||||
qt/view/QtCompositeView.h
|
||||
qt/view/QtCustomTrailView.cpp
|
||||
qt/view/QtCustomTrailView.h
|
||||
qt/view/QtDialogView.cpp
|
||||
qt/view/QtDialogView.h
|
||||
qt/view/QtErrorView.cpp
|
||||
|
||||
@@ -3,10 +3,12 @@
|
||||
#include <QHBoxLayout>
|
||||
|
||||
#include "MessageActivateAll.h"
|
||||
#include "ResourcePaths.h"
|
||||
|
||||
#include "MessageActivateFullTextSearch.h"
|
||||
#include "MessageSearch.h"
|
||||
#include "MessageSearchAutocomplete.h"
|
||||
#include "QtSearchBarButton.h"
|
||||
#include "QtSmartSearchBox.h"
|
||||
#include "ResourcePaths.h"
|
||||
|
||||
QtSearchBar::QtSearchBar()
|
||||
{
|
||||
@@ -33,19 +35,21 @@ QtSearchBar::QtSearchBar()
|
||||
innerLayout->setContentsMargins(12, 3, 5, 2);
|
||||
m_searchBoxContainer->setLayout(innerLayout);
|
||||
|
||||
m_searchBox = new QtSmartSearchBox(m_searchBoxContainer);
|
||||
m_searchBox->setObjectName("search_box");
|
||||
m_searchBox->setAttribute(Qt::WA_MacShowFocusRect, 0); // remove blue focus box on Mac
|
||||
m_searchBox = new QtSmartSearchBox("Search", true, m_searchBoxContainer);
|
||||
m_searchBox->setMinimumWidth(100);
|
||||
m_searchBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
|
||||
innerLayout->addWidget(m_searchBox);
|
||||
|
||||
connect(m_searchBox, &QtSmartSearchBox::autocomplete, this, &QtSearchBar::requestAutocomplete);
|
||||
connect(m_searchBox, &QtSmartSearchBox::search, this, &QtSearchBar::requestSearch);
|
||||
connect(m_searchBox, &QtSmartSearchBox::fullTextSearch, this, &QtSearchBar::requestFullTextSearch);
|
||||
|
||||
m_searchButton = new QtSearchBarButton(ResourcePaths::getGuiPath().concatenate(L"search_view/images/search.png"));
|
||||
m_searchButton->setObjectName("search_button");
|
||||
m_searchButton->setToolTip("search");
|
||||
layout->addWidget(m_searchButton);
|
||||
|
||||
connect(m_searchButton, &QPushButton::clicked, m_searchBox, &QtSmartSearchBox::search);
|
||||
connect(m_searchButton, &QPushButton::clicked, m_searchBox, &QtSmartSearchBox::startSearch);
|
||||
|
||||
refreshStyle();
|
||||
}
|
||||
@@ -98,3 +102,18 @@ void QtSearchBar::homeButtonClicked()
|
||||
{
|
||||
MessageActivateAll().dispatch();
|
||||
}
|
||||
|
||||
void QtSearchBar::requestAutocomplete(const std::wstring& query, NodeTypeSet acceptedNodeTypes)
|
||||
{
|
||||
MessageSearchAutocomplete(query, acceptedNodeTypes).dispatch();
|
||||
}
|
||||
|
||||
void QtSearchBar::requestSearch(const std::vector<SearchMatch>& matches, NodeTypeSet acceptedNodeTypes)
|
||||
{
|
||||
MessageSearch(matches, acceptedNodeTypes).dispatch();
|
||||
}
|
||||
|
||||
void QtSearchBar::requestFullTextSearch(const std::wstring& query, bool caseSensitive)
|
||||
{
|
||||
MessageActivateFullTextSearch(query, caseSensitive).dispatch();
|
||||
}
|
||||
|
||||
@@ -36,6 +36,10 @@ public:
|
||||
private slots:
|
||||
void homeButtonClicked();
|
||||
|
||||
void requestAutocomplete(const std::wstring& query, NodeTypeSet acceptedNodeTypes);
|
||||
void requestSearch(const std::vector<SearchMatch>& matches, NodeTypeSet acceptedNodeTypes);
|
||||
void requestFullTextSearch(const std::wstring& query, bool caseSensitive);
|
||||
|
||||
private:
|
||||
QWidget* m_searchBoxContainer; // used for correct clipping inside the search box
|
||||
|
||||
|
||||
@@ -11,9 +11,6 @@
|
||||
#include "GraphViewStyle.h"
|
||||
#include "NodeTypeSet.h"
|
||||
#include "ColorScheme.h"
|
||||
#include "MessageActivateFullTextSearch.h"
|
||||
#include "MessageSearch.h"
|
||||
#include "MessageSearchAutocomplete.h"
|
||||
#include "utility.h"
|
||||
#include "utilityString.h"
|
||||
|
||||
@@ -30,7 +27,7 @@ void QtSearchElement::onChecked(bool)
|
||||
emit wasChecked(this);
|
||||
}
|
||||
|
||||
void QtSmartSearchBox::search()
|
||||
void QtSmartSearchBox::startSearch()
|
||||
{
|
||||
editTextToElement();
|
||||
|
||||
@@ -53,7 +50,7 @@ void QtSmartSearchBox::search()
|
||||
else
|
||||
{
|
||||
QString text = QString::fromStdWString(match.name);
|
||||
if (!text.startsWith(SearchMatch::FULLTEXT_SEARCH_CHARACTER))
|
||||
if (m_supportsFullTextSearch && !text.startsWith(SearchMatch::FULLTEXT_SEARCH_CHARACTER))
|
||||
{
|
||||
text = QChar(SearchMatch::FULLTEXT_SEARCH_CHARACTER) + text;
|
||||
}
|
||||
@@ -62,46 +59,28 @@ void QtSmartSearchBox::search()
|
||||
updateElements();
|
||||
|
||||
setEditText(text);
|
||||
fullTextSearch();
|
||||
startFullTextSearch();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MessageSearch(utility::toVector(m_matches), getMatchAcceptedNodeTypes()).dispatch();
|
||||
emit search(utility::toVector(m_matches), getMatchAcceptedNodeTypes());
|
||||
}
|
||||
|
||||
void QtSmartSearchBox::fullTextSearch()
|
||||
{
|
||||
std::wstring term = text().toStdWString().substr(1);
|
||||
if (term.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool caseSensitive = false;
|
||||
if (term.at(0) == SearchMatch::FULLTEXT_SEARCH_CHARACTER)
|
||||
{
|
||||
term = term.substr(1);
|
||||
if (term.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
caseSensitive = true;
|
||||
}
|
||||
|
||||
MessageActivateFullTextSearch(term, caseSensitive).dispatch();
|
||||
}
|
||||
|
||||
QtSmartSearchBox::QtSmartSearchBox(QWidget* parent)
|
||||
QtSmartSearchBox::QtSmartSearchBox(const QString& placeholder, bool supportsFullTextSearch, QWidget* parent)
|
||||
: QLineEdit(parent)
|
||||
, m_placeholder(placeholder)
|
||||
, m_supportsFullTextSearch(supportsFullTextSearch)
|
||||
, m_allowTextChange(false)
|
||||
, m_cursorIndex(0)
|
||||
, m_shiftKeyDown(false)
|
||||
, m_mousePressed(false)
|
||||
, m_ignoreNextMousePress(false)
|
||||
{
|
||||
setObjectName("search_box");
|
||||
setAttribute(Qt::WA_MacShowFocusRect, 0); // remove blue focus box on Mac
|
||||
|
||||
m_highlightRect = new QWidget(this);
|
||||
m_highlightRect->setGeometry(0, 0, 0, 0);
|
||||
m_highlightRect->setObjectName("search_box_highlight");
|
||||
@@ -124,6 +103,11 @@ QCompleter* QtSmartSearchBox::getCompleter() const
|
||||
return m_completer;
|
||||
}
|
||||
|
||||
std::vector<SearchMatch> QtSmartSearchBox::getMatches() const
|
||||
{
|
||||
return utility::toVector(m_matches);
|
||||
}
|
||||
|
||||
void QtSmartSearchBox::setAutocompletionList(const std::vector<SearchMatch>& autocompletionList)
|
||||
{
|
||||
// Save the cursor position, because after activating the completer the cursor gets set to the end position.
|
||||
@@ -208,8 +192,8 @@ bool QtSmartSearchBox::event(QEvent *event)
|
||||
setEditText(QString::fromStdWString(m_highlightedMatch.getFullName()));
|
||||
requestAutoCompletions();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (keyEvent->key() == Qt::Key_Escape)
|
||||
{
|
||||
@@ -271,12 +255,12 @@ void QtSmartSearchBox::keyPressEvent(QKeyEvent* event)
|
||||
{
|
||||
if (text().startsWith(SearchMatch::FULLTEXT_SEARCH_CHARACTER))
|
||||
{
|
||||
fullTextSearch();
|
||||
startFullTextSearch();
|
||||
return;
|
||||
}
|
||||
else if (!m_completer->popup()->isVisible())
|
||||
{
|
||||
search();
|
||||
startSearch();
|
||||
}
|
||||
}
|
||||
else if (event->key() == Qt::Key_Backspace)
|
||||
@@ -646,7 +630,7 @@ void QtSmartSearchBox::onAutocompletionActivated(const SearchMatch& match)
|
||||
|
||||
if (!match.name.empty())
|
||||
{
|
||||
search();
|
||||
startSearch();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1034,7 +1018,7 @@ void QtSmartSearchBox::updatePlaceholder()
|
||||
{
|
||||
if (text().isEmpty() && m_elements.empty())
|
||||
{
|
||||
setPlaceholderText("Search");
|
||||
setPlaceholderText(m_placeholder);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1052,7 +1036,7 @@ void QtSmartSearchBox::requestAutoCompletions()
|
||||
{
|
||||
if (!text().isEmpty() && !text().startsWith(SearchMatch::FULLTEXT_SEARCH_CHARACTER))
|
||||
{
|
||||
MessageSearchAutocomplete(text().toStdWString(), getMatchAcceptedNodeTypes()).dispatch();
|
||||
emit autocomplete(text().toStdWString(), getMatchAcceptedNodeTypes());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1065,6 +1049,34 @@ void QtSmartSearchBox::hideAutoCompletions()
|
||||
m_completer->popup()->hide();
|
||||
}
|
||||
|
||||
void QtSmartSearchBox::startFullTextSearch()
|
||||
{
|
||||
if (!m_supportsFullTextSearch)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::wstring term = text().toStdWString().substr(1);
|
||||
if (term.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool caseSensitive = false;
|
||||
if (term.at(0) == SearchMatch::FULLTEXT_SEARCH_CHARACTER)
|
||||
{
|
||||
term = term.substr(1);
|
||||
if (term.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
caseSensitive = true;
|
||||
}
|
||||
|
||||
emit fullTextSearch(term, caseSensitive);
|
||||
}
|
||||
|
||||
std::deque<SearchMatch> QtSmartSearchBox::getMatchesForInput(const std::wstring& text) const
|
||||
{
|
||||
std::deque<SearchMatch> matches;
|
||||
|
||||
@@ -33,15 +33,20 @@ class QtSmartSearchBox
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
signals:
|
||||
void autocomplete(const std::wstring& query, NodeTypeSet acceptedNodeTypes);
|
||||
void search(const std::vector<SearchMatch>& matches, NodeTypeSet acceptedNodeTypes);
|
||||
void fullTextSearch(const std::wstring& query, bool caseSensitive);
|
||||
|
||||
public slots:
|
||||
void search();
|
||||
void fullTextSearch();
|
||||
void startSearch();
|
||||
|
||||
public:
|
||||
QtSmartSearchBox(QWidget* parent);
|
||||
QtSmartSearchBox(const QString& placeholder, bool supportsFullTextSearch, QWidget* parent = nullptr);
|
||||
virtual ~QtSmartSearchBox();
|
||||
|
||||
QCompleter* getCompleter() const;
|
||||
std::vector<SearchMatch> getMatches() const;
|
||||
|
||||
void setAutocompletionList(const std::vector<SearchMatch>& autocompletionList);
|
||||
void setMatches(const std::vector<SearchMatch>& matches);
|
||||
@@ -99,11 +104,16 @@ private:
|
||||
void requestAutoCompletions();
|
||||
void hideAutoCompletions();
|
||||
|
||||
void startFullTextSearch();
|
||||
|
||||
std::deque<SearchMatch> getMatchesForInput(const std::wstring& text) const;
|
||||
|
||||
NodeTypeSet getMatchAcceptedNodeTypes() const;
|
||||
bool lastMatchIsNoFilter() const;
|
||||
|
||||
const QString m_placeholder;
|
||||
const bool m_supportsFullTextSearch;
|
||||
|
||||
bool m_allowTextChange;
|
||||
QString m_oldText;
|
||||
|
||||
|
||||
@@ -120,20 +120,20 @@ QtGraphicsView::QtGraphicsView(QWidget* parent)
|
||||
"", ResourcePaths::getGuiPath().concatenate(L"graph_view/images/zoom_in.png"), "search/button", this);
|
||||
m_zoomInButton->setObjectName("zoom_in_button");
|
||||
m_zoomInButton->setAutoRepeat(true);
|
||||
m_zoomInButton->setToolTip("Zoom in (" + modifierName + " + Mousewheel forward)");
|
||||
m_zoomInButton->setToolTip("zoom in (" + modifierName + " + Mousewheel forward)");
|
||||
connect(m_zoomInButton, &QPushButton::pressed, this, &QtGraphicsView::zoomInPressed);
|
||||
|
||||
m_zoomOutButton = new QtSelfRefreshIconButton(
|
||||
"", ResourcePaths::getGuiPath().concatenate(L"graph_view/images/zoom_out.png"), "search/button", this);
|
||||
m_zoomOutButton->setObjectName("zoom_out_button");
|
||||
m_zoomOutButton->setAutoRepeat(true);
|
||||
m_zoomOutButton->setToolTip("Zoom out (" + modifierName + " + Mousewheel back)");
|
||||
m_zoomOutButton->setToolTip("zoom out (" + modifierName + " + Mousewheel back)");
|
||||
connect(m_zoomOutButton, &QPushButton::pressed, this, &QtGraphicsView::zoomOutPressed);
|
||||
|
||||
m_legendButton = new QtSelfRefreshIconButton(
|
||||
"", ResourcePaths::getGuiPath().concatenate(L"graph_view/images/legend.png"), "search/button", this);
|
||||
m_legendButton->setObjectName("legend_button");
|
||||
m_legendButton->setToolTip("Show graph legend");
|
||||
m_legendButton->setToolTip("show legend");
|
||||
connect(m_legendButton, &QPushButton::clicked, this, &QtGraphicsView::legendClicked);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,644 @@
|
||||
#include "QtCustomTrailView.h"
|
||||
|
||||
#include <QBoxLayout>
|
||||
#include <QButtonGroup>
|
||||
#include <QCheckBox>
|
||||
#include <QGridLayout>
|
||||
#include <QGroupBox>
|
||||
#include <QKeyEvent>
|
||||
#include <QLabel>
|
||||
#include <QRadioButton>
|
||||
#include <QSlider>
|
||||
|
||||
#include "ColorScheme.h"
|
||||
#include "MessageActivateTrail.h"
|
||||
#include "NodeTypeSet.h"
|
||||
#include "QtSmartSearchBox.h"
|
||||
#include "ResourcePaths.h"
|
||||
#include "TabId.h"
|
||||
#include "utilityQt.h"
|
||||
|
||||
QtCustomTrailView::QtCustomTrailView(ViewLayout*)
|
||||
: QWidget(nullptr)
|
||||
, CustomTrailView(nullptr)
|
||||
, m_controllerProxy(this, TabId::app())
|
||||
{
|
||||
setWindowTitle("Custom Trail");
|
||||
|
||||
QGridLayout* mainLayout = new QGridLayout();
|
||||
mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||
mainLayout->setSpacing(0);
|
||||
setLayout(mainLayout);
|
||||
|
||||
QWidget* panelA1 = new QWidget();
|
||||
QWidget* panelA2 = new QWidget();
|
||||
QWidget* panelB1 = new QWidget();
|
||||
QWidget* panelB2 = new QWidget();
|
||||
QWidget* panelC1 = new QWidget();
|
||||
QWidget* panelC2 = new QWidget();
|
||||
QWidget* panelD = new QWidget();
|
||||
|
||||
panelA1->setObjectName("panelA");
|
||||
panelA2->setObjectName("panelA");
|
||||
panelB1->setObjectName("panelB");
|
||||
panelB2->setObjectName("panelB");
|
||||
panelC1->setObjectName("panelA");
|
||||
panelC2->setObjectName("panelA");
|
||||
panelD->setObjectName("panelB2");
|
||||
|
||||
mainLayout->addWidget(panelA1, 0, 0);
|
||||
mainLayout->addWidget(panelA2, 0, 1);
|
||||
mainLayout->addWidget(panelB1, 1, 0);
|
||||
mainLayout->addWidget(panelB2, 1, 1);
|
||||
mainLayout->addWidget(panelC1, 2, 0);
|
||||
mainLayout->addWidget(panelC2, 2, 1);
|
||||
mainLayout->addWidget(panelD, 3, 0, 1, 2);
|
||||
|
||||
// search boxes
|
||||
{
|
||||
QHBoxLayout* hLayout = new QHBoxLayout();
|
||||
hLayout->setContentsMargins(25, 10, 10, 10);
|
||||
panelA1->setLayout(hLayout);
|
||||
|
||||
m_searchBoxFrom = new QtSmartSearchBox("Start Symbol", false);
|
||||
m_searchBoxTo = new QtSmartSearchBox("Target Symbol", false);
|
||||
|
||||
hLayout->addWidget(new QLabel("From:"));
|
||||
hLayout->addWidget(createSearchBox(m_searchBoxFrom));
|
||||
hLayout->addSpacing(15);
|
||||
|
||||
QVBoxLayout* optionsLayout = new QVBoxLayout();
|
||||
optionsLayout->setContentsMargins(10, 10, 25, 10);
|
||||
panelA2->setLayout(optionsLayout);
|
||||
|
||||
m_optionTo = new QRadioButton(QString::fromUtf8("\xe2\x86\x92") + " To:");
|
||||
m_optionReferenced = new QRadioButton(QString::fromUtf8("\xe2\x86\x92") + " All Referenced");
|
||||
m_optionReferencing = new QRadioButton(QString::fromUtf8("\xe2\x86\x90") + " All Referencing");
|
||||
|
||||
m_optionTo->setAttribute(Qt::WA_LayoutUsesWidgetRect); // fixes layouting on Mac
|
||||
m_optionReferenced->setAttribute(Qt::WA_LayoutUsesWidgetRect); // fixes layouting on Mac
|
||||
m_optionReferencing->setAttribute(Qt::WA_LayoutUsesWidgetRect); // fixes layouting on Mac
|
||||
|
||||
m_optionTo->setChecked(true);
|
||||
|
||||
QButtonGroup* options = new QButtonGroup();
|
||||
options->addButton(m_optionTo);
|
||||
options->addButton(m_optionReferenced);
|
||||
options->addButton(m_optionReferencing);
|
||||
|
||||
QWidget* searchBoxToContainer = createSearchBox(m_searchBoxTo);
|
||||
QHBoxLayout* toLayout = new QHBoxLayout();
|
||||
toLayout->setContentsMargins(0, 0, 0, 0);
|
||||
toLayout->addWidget(m_optionTo);
|
||||
toLayout->addWidget(searchBoxToContainer);
|
||||
|
||||
optionsLayout->addLayout(toLayout);
|
||||
optionsLayout->addWidget(m_optionReferenced);
|
||||
optionsLayout->addSpacing(7);
|
||||
optionsLayout->addWidget(m_optionReferencing);
|
||||
|
||||
connect(options, QOverload<QAbstractButton *>::of(&QButtonGroup::buttonClicked),
|
||||
[this, searchBoxToContainer](QAbstractButton* button)
|
||||
{
|
||||
searchBoxToContainer->setEnabled(button == m_optionTo);
|
||||
}
|
||||
);
|
||||
|
||||
connect(m_searchBoxFrom, &QtSmartSearchBox::autocomplete,
|
||||
[this](const std::wstring& query, NodeTypeSet acceptedNodeTypes)
|
||||
{
|
||||
m_controllerProxy.executeAsTaskWithArgs(&CustomTrailController::autocomplete, query, true);
|
||||
}
|
||||
);
|
||||
|
||||
connect(m_searchBoxTo, &QtSmartSearchBox::autocomplete,
|
||||
[this](const std::wstring& query, NodeTypeSet acceptedNodeTypes)
|
||||
{
|
||||
m_controllerProxy.executeAsTaskWithArgs(&CustomTrailController::autocomplete, query, false);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// depth slider
|
||||
{
|
||||
QHBoxLayout* hLayout = new QHBoxLayout();
|
||||
hLayout->setContentsMargins(25, 10, 10, 10);
|
||||
panelB1->setLayout(hLayout);
|
||||
|
||||
hLayout->addWidget(new QLabel("Max Depth:"));
|
||||
|
||||
m_slider = new QSlider(Qt::Horizontal);
|
||||
m_slider->setObjectName("depth_slider");
|
||||
m_slider->setToolTip("adjust graph depth");
|
||||
m_slider->setMinimum(1);
|
||||
m_slider->setMaximum(51);
|
||||
m_slider->setMinimumWidth(150);
|
||||
m_slider->setValue(INITIAL_GRAPH_DEPTH);
|
||||
|
||||
hLayout->addWidget(m_slider);
|
||||
|
||||
QLabel* valueLabel = new QLabel(QString::number(INITIAL_GRAPH_DEPTH));
|
||||
valueLabel->setMinimumWidth(20);
|
||||
hLayout->addWidget(valueLabel);
|
||||
|
||||
connect(m_slider, &QSlider::valueChanged,
|
||||
[this, valueLabel](int)
|
||||
{
|
||||
if (m_slider->value() == m_slider->maximum())
|
||||
{
|
||||
valueLabel->setText("inf");
|
||||
}
|
||||
else
|
||||
{
|
||||
valueLabel->setText(QString::number(m_slider->value()));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
hLayout->addStretch();
|
||||
}
|
||||
|
||||
// layout direction
|
||||
{
|
||||
QHBoxLayout* hLayout = new QHBoxLayout();
|
||||
hLayout->setContentsMargins(10, 10, 25, 10);
|
||||
hLayout->setSpacing(15);
|
||||
panelB2->setLayout(hLayout);
|
||||
|
||||
m_horizontalButton = new QRadioButton("Horizontal");
|
||||
m_verticalButton = new QRadioButton("Vertical");
|
||||
|
||||
m_horizontalButton->setChecked(true);
|
||||
|
||||
hLayout->addWidget(new QLabel("Layout Direction:"));
|
||||
hLayout->addWidget(m_horizontalButton);
|
||||
hLayout->addWidget(m_verticalButton);
|
||||
|
||||
QButtonGroup* layouts = new QButtonGroup();
|
||||
layouts->addButton(m_horizontalButton);
|
||||
layouts->addButton(m_verticalButton);
|
||||
|
||||
hLayout->addStretch();
|
||||
}
|
||||
|
||||
ColorScheme* scheme = ColorScheme::getInstance().get();
|
||||
|
||||
// node filters
|
||||
{
|
||||
std::vector<QString> nodeFilters;
|
||||
std::vector<QColor> nodeColors;
|
||||
|
||||
std::vector<NodeType::Type> nodeTypes = {
|
||||
// NodeType::NODE_SYMBOL,
|
||||
NodeType::NODE_TYPE,
|
||||
NodeType::NODE_BUILTIN_TYPE,
|
||||
// NodeType::NODE_MODULE,
|
||||
// NodeType::NODE_NAMESPACE,
|
||||
// NodeType::NODE_PACKAGE,
|
||||
NodeType::NODE_CLASS,
|
||||
NodeType::NODE_STRUCT,
|
||||
NodeType::NODE_UNION,
|
||||
NodeType::NODE_INTERFACE,
|
||||
NodeType::NODE_TYPEDEF,
|
||||
NodeType::NODE_TEMPLATE_PARAMETER,
|
||||
NodeType::NODE_TYPE_PARAMETER,
|
||||
NodeType::NODE_ENUM,
|
||||
NodeType::NODE_ENUM_CONSTANT,
|
||||
NodeType::NODE_GLOBAL_VARIABLE,
|
||||
NodeType::NODE_FIELD,
|
||||
NodeType::NODE_FUNCTION,
|
||||
NodeType::NODE_METHOD,
|
||||
NodeType::NODE_FILE,
|
||||
NodeType::NODE_MACRO,
|
||||
NodeType::NODE_ANNOTATION
|
||||
};
|
||||
|
||||
for (NodeType::Type t : nodeTypes)
|
||||
{
|
||||
nodeFilters.push_back(QString::fromStdString(NodeType::getReadableTypeString(t)));
|
||||
nodeColors.push_back(QColor(scheme->getNodeTypeColor(t, "fill", ColorScheme::FOCUS).c_str()));
|
||||
}
|
||||
|
||||
QVBoxLayout* filterLayout = addFilters("Nodes:", nodeFilters, nodeColors, &m_nodeFilters, 11);
|
||||
filterLayout->setContentsMargins(25, 10, 25, 10);
|
||||
panelC1->setLayout(filterLayout);
|
||||
}
|
||||
|
||||
// edge filters
|
||||
{
|
||||
std::vector<QString> edgeFilters;
|
||||
std::vector<QColor> edgeColors;
|
||||
|
||||
std::vector<Edge::EdgeType> edgeTypes = {
|
||||
// Edge::EDGE_UNDEFINED,
|
||||
Edge::EDGE_TYPE_USAGE,
|
||||
Edge::EDGE_INHERITANCE,
|
||||
Edge::EDGE_USAGE,
|
||||
Edge::EDGE_CALL,
|
||||
Edge::EDGE_OVERRIDE,
|
||||
// Edge::EDGE_TEMPLATE_ARGUMENT, // merged with type use
|
||||
// Edge::EDGE_TEMPLATE_DEFAULT_ARGUMENT, // merged with type use
|
||||
Edge::EDGE_TEMPLATE_SPECIALIZATION,
|
||||
// Edge::EDGE_TEMPLATE_MEMBER_SPECIALIZATION, // merged with above
|
||||
Edge::EDGE_TYPE_ARGUMENT,
|
||||
Edge::EDGE_INCLUDE,
|
||||
Edge::EDGE_IMPORT,
|
||||
// Edge::EDGE_AGGREGATION,
|
||||
Edge::EDGE_MACRO_USAGE,
|
||||
Edge::EDGE_ANNOTATION_USAGE
|
||||
// Edge::EDGE_MEMBER // has separate checkbox
|
||||
};
|
||||
|
||||
for (Edge::EdgeType t : edgeTypes)
|
||||
{
|
||||
edgeFilters.push_back(QString::fromStdWString(Edge::getReadableTypeString(t)));
|
||||
edgeColors.push_back(QColor(scheme->getEdgeTypeColor(t, ColorScheme::FOCUS).c_str()));
|
||||
}
|
||||
|
||||
QVBoxLayout* filterLayout = addFilters("Edges:", edgeFilters, edgeColors, &m_edgeFilters, 5);
|
||||
filterLayout->setContentsMargins(10, 10, 25, 10);
|
||||
panelC2->setLayout(filterLayout);
|
||||
}
|
||||
|
||||
// controls
|
||||
{
|
||||
QPushButton* cancelButton = new QPushButton("Cancel");
|
||||
QPushButton* searchButton = new QPushButton("Search");
|
||||
|
||||
cancelButton->setObjectName("button");
|
||||
searchButton->setObjectName("button");
|
||||
|
||||
cancelButton->setAttribute(Qt::WA_LayoutUsesWidgetRect); // fixes layouting on Mac
|
||||
searchButton->setAttribute(Qt::WA_LayoutUsesWidgetRect); // fixes layouting on Mac
|
||||
|
||||
m_errorLabel = new QLabel();
|
||||
m_errorLabel->setObjectName("error");
|
||||
|
||||
QHBoxLayout* hLayout = new QHBoxLayout();
|
||||
hLayout->setContentsMargins(25, 15, 25, 15);
|
||||
hLayout->addWidget(cancelButton);
|
||||
hLayout->addStretch();
|
||||
hLayout->addWidget(m_errorLabel);
|
||||
hLayout->addSpacing(10);
|
||||
hLayout->addWidget(searchButton);
|
||||
panelD->setLayout(hLayout);
|
||||
|
||||
connect(cancelButton, &QPushButton::clicked,
|
||||
[this]()
|
||||
{
|
||||
hide();
|
||||
}
|
||||
);
|
||||
|
||||
connect(searchButton, &QPushButton::clicked,
|
||||
[this]()
|
||||
{
|
||||
if (m_searchBoxFrom->getMatches().size() == 0 ||
|
||||
m_searchBoxFrom->getMatches().front().tokenIds.size() == 0)
|
||||
{
|
||||
setError("No 'Start Symbol' symbol found.");
|
||||
return;
|
||||
}
|
||||
|
||||
Id startId = m_searchBoxFrom->getMatches().front().tokenIds.front();
|
||||
Id endId = 0;
|
||||
|
||||
if (m_optionReferencing->isChecked())
|
||||
{
|
||||
std::swap(startId, endId);
|
||||
}
|
||||
else if (m_optionTo->isChecked())
|
||||
{
|
||||
if (m_searchBoxTo->getMatches().size() && m_searchBoxTo->getMatches().front().tokenIds.size())
|
||||
{
|
||||
endId = m_searchBoxTo->getMatches().front().tokenIds.front();
|
||||
}
|
||||
else
|
||||
{
|
||||
setError("No 'Target Symbol' symbol found.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
NodeType::TypeMask nodeTypes = getCheckedNodeTypes();
|
||||
Edge::TypeMask edgeTypes = getCheckedEdgeTypes();
|
||||
|
||||
if (!nodeTypes)
|
||||
{
|
||||
setError("No 'Nodes' selected.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!edgeTypes)
|
||||
{
|
||||
setError("No 'Edges' selected.");
|
||||
return;
|
||||
}
|
||||
|
||||
MessageActivateTrail message(
|
||||
startId,
|
||||
endId,
|
||||
nodeTypes,
|
||||
edgeTypes,
|
||||
m_nodeNonIndexed->isChecked(),
|
||||
m_slider->value() == m_slider->maximum() ? 0 : m_slider->value(),
|
||||
m_horizontalButton->isChecked()
|
||||
);
|
||||
|
||||
m_controllerProxy.executeAsTaskWithArgs(&CustomTrailController::activateTrail, message);
|
||||
|
||||
setError("");
|
||||
|
||||
hide();
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void QtCustomTrailView::createWidgetWrapper()
|
||||
{
|
||||
}
|
||||
|
||||
void QtCustomTrailView::refreshView()
|
||||
{
|
||||
m_onQtThread([this]()
|
||||
{
|
||||
updateStyleSheet();
|
||||
m_searchBoxFrom->refreshStyle();
|
||||
m_searchBoxTo->refreshStyle();
|
||||
});
|
||||
}
|
||||
|
||||
void QtCustomTrailView::clearView()
|
||||
{
|
||||
m_onQtThread([this]()
|
||||
{
|
||||
m_searchBoxFrom->setMatches({});
|
||||
m_searchBoxTo->setMatches({});
|
||||
});
|
||||
}
|
||||
|
||||
void QtCustomTrailView::setAvailableNodeAndEdgeTypes(NodeType::TypeMask nodeTypes, Edge::TypeMask edgeTypes)
|
||||
{
|
||||
m_onQtThread([this, nodeTypes, edgeTypes]()
|
||||
{
|
||||
for (QCheckBox* filter : m_nodeFilters)
|
||||
{
|
||||
if (filter == m_nodeNonIndexed)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
bool enabled = nodeTypes & NodeType::getTypeForReadableTypeString(filter->text().toStdWString());
|
||||
filter->setEnabled(enabled);
|
||||
filter->setVisible(enabled);
|
||||
}
|
||||
|
||||
for (QCheckBox* filter : m_edgeFilters)
|
||||
{
|
||||
bool enabled = false;
|
||||
if (filter == m_edgeMember)
|
||||
{
|
||||
enabled = edgeTypes & Edge::EDGE_MEMBER;
|
||||
}
|
||||
else
|
||||
{
|
||||
enabled = edgeTypes & Edge::getTypeForReadableTypeString(filter->text().toStdWString());
|
||||
}
|
||||
|
||||
filter->setEnabled(enabled);
|
||||
filter->setVisible(enabled);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void QtCustomTrailView::showView()
|
||||
{
|
||||
m_onQtThread([this]()
|
||||
{
|
||||
show();
|
||||
raise();
|
||||
});
|
||||
}
|
||||
|
||||
void QtCustomTrailView::hideView()
|
||||
{
|
||||
m_onQtThread([this]()
|
||||
{
|
||||
hide();
|
||||
});
|
||||
}
|
||||
|
||||
void QtCustomTrailView::showAutocompletions(const std::vector<SearchMatch>& autocompletions, bool from)
|
||||
{
|
||||
m_onQtThread([this, autocompletions, from]()
|
||||
{
|
||||
if (from)
|
||||
{
|
||||
m_searchBoxFrom->setAutocompletionList(autocompletions);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_searchBoxTo->setAutocompletionList(autocompletions);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void QtCustomTrailView::keyPressEvent(QKeyEvent* event)
|
||||
{
|
||||
if (event->key() == Qt::Key_Escape)
|
||||
{
|
||||
hide();
|
||||
return;
|
||||
}
|
||||
|
||||
QWidget::keyPressEvent(event);
|
||||
}
|
||||
|
||||
void QtCustomTrailView::updateStyleSheet()
|
||||
{
|
||||
std::string css = utility::getStyleSheet(ResourcePaths::getGuiPath().concatenate(L"search_view/search_view.css"));
|
||||
css += utility::getStyleSheet(ResourcePaths::getGuiPath().concatenate(L"custom_trail_view/custom_trail_view.css"));
|
||||
|
||||
setStyleSheet(css.c_str());
|
||||
|
||||
QAbstractItemView* popup = m_searchBoxFrom->getCompleter()->popup();
|
||||
if (popup)
|
||||
{
|
||||
popup->setStyleSheet(css.c_str());
|
||||
}
|
||||
|
||||
popup = m_searchBoxTo->getCompleter()->popup();
|
||||
if (popup)
|
||||
{
|
||||
popup->setStyleSheet(css.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
QWidget* QtCustomTrailView::createSearchBox(QtSmartSearchBox* searchBox) const
|
||||
{
|
||||
QWidget* searchBoxContainer = new QWidget();
|
||||
searchBoxContainer->setObjectName("search_box_container");
|
||||
searchBoxContainer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
|
||||
searchBox->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Maximum);
|
||||
|
||||
QBoxLayout* innerLayout = new QVBoxLayout();
|
||||
innerLayout->setContentsMargins(12, 3, 5, 2);
|
||||
innerLayout->addWidget(searchBox);
|
||||
searchBoxContainer->setLayout(innerLayout);
|
||||
|
||||
return searchBoxContainer;
|
||||
}
|
||||
|
||||
QVBoxLayout* QtCustomTrailView::addFilters(
|
||||
QString name,
|
||||
const std::vector<QString>& filters,
|
||||
const std::vector<QColor>& colors,
|
||||
std::vector<QCheckBox*>* checkBoxes,
|
||||
size_t filtersInFirstColumn)
|
||||
{
|
||||
QVBoxLayout* vLayout = new QVBoxLayout();
|
||||
vLayout->addWidget(new QLabel(name));
|
||||
|
||||
QHBoxLayout* mainLayout = new QHBoxLayout();
|
||||
vLayout->addLayout(mainLayout);
|
||||
|
||||
QVBoxLayout* filterALayout = new QVBoxLayout();
|
||||
QVBoxLayout* filterBLayout = new QVBoxLayout();
|
||||
|
||||
mainLayout->addLayout(filterALayout);
|
||||
mainLayout->addLayout(filterBLayout);
|
||||
|
||||
QPixmap pixmap(QString::fromStdString(ResourcePaths::getGuiPath().concatenate(L"custom_trail_view/images/circle.png").str()));
|
||||
for (size_t i = 0; i < filters.size(); i++)
|
||||
{
|
||||
QCheckBox* checkBox = new QCheckBox(filters[i]);
|
||||
checkBox->setChecked(true);
|
||||
checkBox->setIcon(QIcon(utility::colorizePixmap(pixmap, colors[i])));
|
||||
checkBoxes->push_back(checkBox);
|
||||
|
||||
if (i < filtersInFirstColumn)
|
||||
{
|
||||
filterALayout->addWidget(checkBox);
|
||||
}
|
||||
else
|
||||
{
|
||||
filterBLayout->addWidget(checkBox);
|
||||
}
|
||||
}
|
||||
|
||||
if (checkBoxes == &m_nodeFilters)
|
||||
{
|
||||
m_nodeNonIndexed = new QCheckBox("non-indexed");
|
||||
m_nodeNonIndexed->setChecked(true);
|
||||
checkBoxes->push_back(m_nodeNonIndexed);
|
||||
|
||||
filterBLayout->addSpacing(7);
|
||||
filterBLayout->addWidget(m_nodeNonIndexed);
|
||||
}
|
||||
else if (checkBoxes == &m_edgeFilters)
|
||||
{
|
||||
m_edgeMember = new QCheckBox("member");
|
||||
m_edgeMember->setChecked(true);
|
||||
checkBoxes->push_back(m_edgeMember);
|
||||
|
||||
filterBLayout->addSpacing(5);
|
||||
filterBLayout->addWidget(m_edgeMember);
|
||||
}
|
||||
|
||||
filterALayout->addStretch();
|
||||
filterBLayout->addStretch();
|
||||
|
||||
vLayout->addLayout(addCheckButtons(*checkBoxes));
|
||||
vLayout->addStretch();
|
||||
|
||||
return vLayout;
|
||||
}
|
||||
|
||||
QHBoxLayout* QtCustomTrailView::addCheckButtons(const std::vector<QCheckBox*>& checkBoxes) const
|
||||
{
|
||||
QHBoxLayout* buttonLayout = new QHBoxLayout();
|
||||
|
||||
QPushButton* checkButton = new QPushButton("Check All");
|
||||
QPushButton* uncheckButton = new QPushButton("Uncheck All");
|
||||
|
||||
checkButton->setObjectName("button_small");
|
||||
uncheckButton->setObjectName("button_small");
|
||||
|
||||
buttonLayout->addWidget(checkButton);
|
||||
buttonLayout->addWidget(uncheckButton);
|
||||
buttonLayout->addStretch();
|
||||
|
||||
connect(checkButton, &QPushButton::clicked,
|
||||
[&checkBoxes]()
|
||||
{
|
||||
for (QCheckBox* box : checkBoxes)
|
||||
{
|
||||
if (box->isEnabled())
|
||||
{
|
||||
box->setChecked(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
connect(uncheckButton, &QPushButton::clicked,
|
||||
[&checkBoxes]()
|
||||
{
|
||||
for (QCheckBox* box : checkBoxes)
|
||||
{
|
||||
box->setChecked(false);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return buttonLayout;
|
||||
}
|
||||
|
||||
NodeType::TypeMask QtCustomTrailView::getCheckedNodeTypes() const
|
||||
{
|
||||
NodeType::TypeMask nodeTypes = 0;
|
||||
for (const QCheckBox* filter : m_nodeFilters)
|
||||
{
|
||||
if (filter->isEnabled() && filter->isChecked() && filter != m_nodeNonIndexed)
|
||||
{
|
||||
nodeTypes |= NodeType::getTypeForReadableTypeString(filter->text().toStdWString());
|
||||
}
|
||||
}
|
||||
return nodeTypes;
|
||||
}
|
||||
|
||||
Edge::TypeMask QtCustomTrailView::getCheckedEdgeTypes() const
|
||||
{
|
||||
Edge::TypeMask edgeTypes = 0;
|
||||
for (const QCheckBox* filter : m_edgeFilters)
|
||||
{
|
||||
if (filter->isEnabled() && filter->isChecked() && filter != m_edgeMember)
|
||||
{
|
||||
Edge::EdgeType type = Edge::getTypeForReadableTypeString(filter->text().toStdWString());
|
||||
|
||||
edgeTypes |= type;
|
||||
|
||||
if (type == Edge::EDGE_TYPE_USAGE)
|
||||
{
|
||||
edgeTypes |= Edge::EDGE_TEMPLATE_ARGUMENT | Edge::EDGE_TEMPLATE_DEFAULT_ARGUMENT;
|
||||
}
|
||||
else if (type == Edge::EDGE_TEMPLATE_SPECIALIZATION)
|
||||
{
|
||||
edgeTypes |= Edge::EDGE_TEMPLATE_MEMBER_SPECIALIZATION;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_edgeMember->isChecked())
|
||||
{
|
||||
edgeTypes |= Edge::EDGE_MEMBER;
|
||||
}
|
||||
|
||||
return edgeTypes;
|
||||
}
|
||||
|
||||
void QtCustomTrailView::setError(const QString& error)
|
||||
{
|
||||
m_errorLabel->setText(error);
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
#ifndef QT_CUSTOM_TRAIL_VIEW_H
|
||||
#define QT_CUSTOM_TRAIL_VIEW_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "ControllerProxy.h"
|
||||
#include "CustomTrailController.h"
|
||||
#include "CustomTrailView.h"
|
||||
#include "QtThreadedFunctor.h"
|
||||
|
||||
class QCheckBox;
|
||||
class QHBoxLayout;
|
||||
class QLabel;
|
||||
class QSlider;
|
||||
class QRadioButton;
|
||||
class QtSmartSearchBox;
|
||||
class QVBoxLayout;
|
||||
|
||||
class QtCustomTrailView
|
||||
: public QWidget
|
||||
, public CustomTrailView
|
||||
{
|
||||
public:
|
||||
QtCustomTrailView(ViewLayout*);
|
||||
|
||||
// View implementation
|
||||
void createWidgetWrapper() override;
|
||||
void refreshView() override;
|
||||
|
||||
// TrailView implementation
|
||||
void clearView() override;
|
||||
void setAvailableNodeAndEdgeTypes(NodeType::TypeMask nodeTypes, Edge::TypeMask edgeTypes) override;
|
||||
|
||||
void showView() override;
|
||||
void hideView() override;
|
||||
void showAutocompletions(const std::vector<SearchMatch>& autocompletions, bool from) override;
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent* event) override;
|
||||
|
||||
private:
|
||||
void updateStyleSheet();
|
||||
|
||||
QWidget* createSearchBox(QtSmartSearchBox* searchBox) const;
|
||||
QVBoxLayout* addFilters(
|
||||
QString name,
|
||||
const std::vector<QString>& filters,
|
||||
const std::vector<QColor>& colors,
|
||||
std::vector<QCheckBox*>* checkBoxes,
|
||||
size_t filtersInFirstColumn);
|
||||
QHBoxLayout* addCheckButtons(const std::vector<QCheckBox*>& checkBoxes) const;
|
||||
|
||||
NodeType::TypeMask getCheckedNodeTypes() const;
|
||||
Edge::TypeMask getCheckedEdgeTypes() const;
|
||||
|
||||
void setError(const QString& error);
|
||||
|
||||
static const size_t INITIAL_GRAPH_DEPTH = 5;
|
||||
static const size_t FILTERS_PER_COLUMN = 10;
|
||||
|
||||
QtThreadedLambdaFunctor m_onQtThread;
|
||||
|
||||
ControllerProxy<CustomTrailController> m_controllerProxy;
|
||||
|
||||
QtSmartSearchBox* m_searchBoxFrom;
|
||||
QtSmartSearchBox* m_searchBoxTo;
|
||||
|
||||
QRadioButton* m_optionReferenced;
|
||||
QRadioButton* m_optionReferencing;
|
||||
QRadioButton* m_optionTo;
|
||||
|
||||
QSlider* m_slider;
|
||||
|
||||
QRadioButton* m_horizontalButton;
|
||||
QRadioButton* m_verticalButton;
|
||||
|
||||
std::vector<QCheckBox*> m_nodeFilters;
|
||||
std::vector<QCheckBox*> m_edgeFilters;
|
||||
|
||||
QCheckBox* m_nodeNonIndexed;
|
||||
QCheckBox* m_edgeMember;
|
||||
|
||||
QLabel* m_errorLabel;
|
||||
};
|
||||
|
||||
#endif // QT_CUSTOM_TRAIL_VIEW_H
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "DummyNode.h"
|
||||
#include "GraphViewStyle.h"
|
||||
#include "MessageActivateTrail.h"
|
||||
#include "MessageCustomTrailShow.h"
|
||||
#include "MessageDeactivateEdge.h"
|
||||
#include "MessageRefreshUI.h"
|
||||
#include "MessageScrollGraph.h"
|
||||
@@ -81,7 +82,7 @@ QtGraphView::QtGraphView(ViewLayout* viewLayout)
|
||||
m_expandButton = new QtSelfRefreshIconButton(
|
||||
"", ResourcePaths::getGuiPath().concatenate(L"graph_view/images/graph.png"), "search/button");
|
||||
m_expandButton->setObjectName("expand_button");
|
||||
m_expandButton->setToolTip("show depth graph controls");
|
||||
m_expandButton->setToolTip("show trail controls");
|
||||
m_expandButton->setIconSize(QSize(16, 16));
|
||||
m_expandButton->setGeometry(0, 0, 26, 26);
|
||||
connect(m_expandButton, &QPushButton::clicked, this, &QtGraphView::clickedExpand);
|
||||
@@ -96,10 +97,17 @@ QtGraphView::QtGraphView(ViewLayout* viewLayout)
|
||||
m_collapseButton = new QtSelfRefreshIconButton(
|
||||
"", ResourcePaths::getGuiPath().concatenate(L"graph_view/images/graph_arrow.png"), "search/button", ui);
|
||||
m_collapseButton->setObjectName("collapse_button");
|
||||
m_collapseButton->setToolTip("hide depth graph controls");
|
||||
m_collapseButton->setToolTip("hide trail controls");
|
||||
m_collapseButton->setIconSize(QSize(16, 16));
|
||||
connect(m_collapseButton, &QPushButton::clicked, this, &QtGraphView::clickedCollapse);
|
||||
|
||||
m_customTrailButton = new QtSelfRefreshIconButton("", FilePath(), "search/button", ui);
|
||||
m_customTrailButton->setObjectName("trail_button");
|
||||
m_customTrailButton->setIconSize(QSize(16, 16));
|
||||
m_customTrailButton->setToolTip("custom trail");
|
||||
m_customTrailButton->setIconPath(ResourcePaths::getGuiPath().concatenate(L"graph_view/images/graph_custom.png"));
|
||||
connect(m_customTrailButton, &QPushButton::clicked, this, &QtGraphView::clickedCustomTrail);
|
||||
|
||||
m_forwardTrailButton = new QtSelfRefreshIconButton("", FilePath(), "search/button", ui);
|
||||
m_forwardTrailButton->setObjectName("trail_button");
|
||||
m_forwardTrailButton->setIconSize(QSize(16, 16));
|
||||
@@ -112,12 +120,12 @@ QtGraphView::QtGraphView(ViewLayout* viewLayout)
|
||||
|
||||
m_trailDepthLabel = new QLabel(ui);
|
||||
m_trailDepthLabel->setObjectName("depth_label");
|
||||
m_trailDepthLabel->setToolTip("adjust graph depth");
|
||||
m_trailDepthLabel->setToolTip("adjust trail depth");
|
||||
m_trailDepthLabel->setAlignment(Qt::AlignCenter);
|
||||
|
||||
m_trailDepthSlider = new QSlider(Qt::Vertical, ui);
|
||||
m_trailDepthSlider->setObjectName("depth_slider");
|
||||
m_trailDepthSlider->setToolTip("adjust graph depth");
|
||||
m_trailDepthSlider->setToolTip("adjust trail depth");
|
||||
m_trailDepthSlider->setMinimum(1);
|
||||
m_trailDepthSlider->setMaximum(26);
|
||||
m_trailDepthSlider->setValue(5);
|
||||
@@ -125,14 +133,15 @@ QtGraphView::QtGraphView(ViewLayout* viewLayout)
|
||||
connect(m_trailDepthSlider, &QSlider::sliderReleased, this, &QtGraphView::trailDepthUpdated);
|
||||
|
||||
m_collapseButton->setGeometry(0, 0, 26, 20);
|
||||
m_backwardTrailButton->setGeometry(0, 22, 26, 26);
|
||||
m_forwardTrailButton->setGeometry(0, 50, 26, 26);
|
||||
m_trailDepthLabel->setGeometry(0, 78, 26, 26);
|
||||
m_trailDepthSlider->setGeometry(0, 104, 26, 100);
|
||||
m_customTrailButton->setGeometry(0, 22, 26, 26);
|
||||
m_backwardTrailButton->setGeometry(0, 50, 26, 26);
|
||||
m_forwardTrailButton->setGeometry(0, 78, 26, 26);
|
||||
m_trailDepthLabel->setGeometry(0, 106, 26, 26);
|
||||
m_trailDepthSlider->setGeometry(0, 132, 26, 100);
|
||||
}
|
||||
|
||||
m_trailWidget = new QWidget(widget);
|
||||
m_trailWidget->setGeometry(8, 8, 26, 210);
|
||||
m_trailWidget->setGeometry(8, 8, 26, 238);
|
||||
m_trailWidget->setLayout(stack);
|
||||
|
||||
if (ApplicationSettings::getInstance()->getGraphControlsVisible())
|
||||
@@ -720,6 +729,11 @@ void QtGraphView::clickedExpand()
|
||||
ApplicationSettings::getInstance()->save();
|
||||
}
|
||||
|
||||
void QtGraphView::clickedCustomTrail()
|
||||
{
|
||||
MessageCustomTrailShow().dispatch();
|
||||
}
|
||||
|
||||
void QtGraphView::clickedBackwardTrail()
|
||||
{
|
||||
activateTrail(false);
|
||||
@@ -768,22 +782,22 @@ MessageActivateTrail QtGraphView::getMessageActivateTrail(bool forward)
|
||||
QtGraphNodeData* node = dynamic_cast<QtGraphNodeData*>(m_oldActiveNode);
|
||||
if (node)
|
||||
{
|
||||
Edge::TypeMask trailType;
|
||||
Edge::TypeMask edgeTypes;
|
||||
bool horizontalLayout = true;
|
||||
|
||||
if (node->getData()->getType().isInheritable())
|
||||
{
|
||||
trailType = Edge::EDGE_INHERITANCE | Edge::EDGE_TEMPLATE_SPECIALIZATION;
|
||||
edgeTypes = Edge::EDGE_INHERITANCE | Edge::EDGE_TEMPLATE_SPECIALIZATION;
|
||||
horizontalLayout = false;
|
||||
}
|
||||
else if (node->getData()->getType().isCallable())
|
||||
{
|
||||
trailType = Edge::EDGE_CALL | Edge::EDGE_OVERRIDE;
|
||||
edgeTypes = Edge::EDGE_CALL | Edge::EDGE_OVERRIDE;
|
||||
horizontalLayout = true;
|
||||
}
|
||||
else if (node->getData()->getType().isFile())
|
||||
{
|
||||
trailType = Edge::EDGE_INCLUDE;
|
||||
edgeTypes = Edge::EDGE_INCLUDE;
|
||||
horizontalLayout = true;
|
||||
}
|
||||
else
|
||||
@@ -801,7 +815,7 @@ MessageActivateTrail QtGraphView::getMessageActivateTrail(bool forward)
|
||||
depth = 0;
|
||||
}
|
||||
|
||||
return MessageActivateTrail(originId, targetId, trailType, depth, horizontalLayout);
|
||||
return MessageActivateTrail(originId, targetId, edgeTypes, depth, horizontalLayout);
|
||||
}
|
||||
|
||||
return message;
|
||||
@@ -810,7 +824,7 @@ MessageActivateTrail QtGraphView::getMessageActivateTrail(bool forward)
|
||||
void QtGraphView::activateTrail(bool forward)
|
||||
{
|
||||
MessageActivateTrail message = getMessageActivateTrail(forward);
|
||||
if (message.trailType)
|
||||
if (message.edgeTypes)
|
||||
{
|
||||
message.dispatch();
|
||||
}
|
||||
@@ -820,20 +834,20 @@ void QtGraphView::updateTrailButtons()
|
||||
{
|
||||
MessageActivateTrail message = getMessageActivateTrail(false);
|
||||
|
||||
m_backwardTrailButton->setEnabled(message.trailType);
|
||||
m_forwardTrailButton->setEnabled(message.trailType);
|
||||
m_trailDepthLabel->setEnabled(message.trailType);
|
||||
m_trailDepthSlider->setEnabled(message.trailType);
|
||||
m_backwardTrailButton->setEnabled(message.edgeTypes);
|
||||
m_forwardTrailButton->setEnabled(message.edgeTypes);
|
||||
m_trailDepthLabel->setEnabled(message.edgeTypes);
|
||||
m_trailDepthSlider->setEnabled(message.edgeTypes);
|
||||
|
||||
std::wstring backwardImagePath = L"graph_left.png";
|
||||
std::wstring forwardImagePath = L"graph_right.png";
|
||||
|
||||
if (message.trailType & Edge::EDGE_CALL)
|
||||
if (message.edgeTypes & Edge::EDGE_CALL)
|
||||
{
|
||||
m_backwardTrailButton->setToolTip("show caller graph");
|
||||
m_forwardTrailButton->setToolTip("show callee graph");
|
||||
}
|
||||
else if (message.trailType & Edge::EDGE_INHERITANCE)
|
||||
else if (message.edgeTypes & Edge::EDGE_INHERITANCE)
|
||||
{
|
||||
m_backwardTrailButton->setToolTip("show base hierarchy");
|
||||
m_forwardTrailButton->setToolTip("show derived hierarchy");
|
||||
@@ -841,15 +855,15 @@ void QtGraphView::updateTrailButtons()
|
||||
backwardImagePath = L"graph_up.png";
|
||||
forwardImagePath = L"graph_down.png";
|
||||
}
|
||||
else if (message.trailType & Edge::EDGE_INCLUDE)
|
||||
else if (message.edgeTypes & Edge::EDGE_INCLUDE)
|
||||
{
|
||||
m_backwardTrailButton->setToolTip("show including files hierarchy");
|
||||
m_forwardTrailButton->setToolTip("show included files hierarchy");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_backwardTrailButton->setToolTip("no depth graph available for active symbol");
|
||||
m_forwardTrailButton->setToolTip("no depth graph available for active symbol");
|
||||
m_backwardTrailButton->setToolTip("no trail for active symbol");
|
||||
m_forwardTrailButton->setToolTip("no trail for active symbol");
|
||||
}
|
||||
|
||||
m_forwardTrailButton->setIconPath(ResourcePaths::getGuiPath().concatenate(L"graph_view/images/" + forwardImagePath));
|
||||
|
||||
@@ -81,6 +81,7 @@ private slots:
|
||||
void clickedCollapse();
|
||||
void clickedExpand();
|
||||
|
||||
void clickedCustomTrail();
|
||||
void clickedBackwardTrail();
|
||||
void clickedForwardTrail();
|
||||
|
||||
@@ -152,6 +153,7 @@ private:
|
||||
QWidget* m_trailWidget;
|
||||
QtSelfRefreshIconButton* m_expandButton;
|
||||
QtSelfRefreshIconButton* m_collapseButton;
|
||||
QtSelfRefreshIconButton* m_customTrailButton;
|
||||
QtSelfRefreshIconButton* m_forwardTrailButton;
|
||||
QtSelfRefreshIconButton* m_backwardTrailButton;
|
||||
QSlider* m_trailDepthSlider;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "QtBookmarkView.h"
|
||||
#include "QtCodeView.h"
|
||||
#include "QtCompositeView.h"
|
||||
#include "QtCustomTrailView.h"
|
||||
#include "QtDialogView.h"
|
||||
#include "QtErrorView.h"
|
||||
#include "QtGraphView.h"
|
||||
@@ -51,6 +52,11 @@ std::shared_ptr<CodeView> QtViewFactory::createCodeView(ViewLayout* viewLayout)
|
||||
return View::createAndAddToLayout<QtCodeView>(viewLayout);
|
||||
}
|
||||
|
||||
std::shared_ptr<CustomTrailView> QtViewFactory::createCustomTrailView() const
|
||||
{
|
||||
return View::create<QtCustomTrailView>(nullptr);
|
||||
}
|
||||
|
||||
std::shared_ptr<ErrorView> QtViewFactory::createErrorView(ViewLayout* viewLayout) const
|
||||
{
|
||||
return View::createAndAddToLayout<QtErrorView>(viewLayout);
|
||||
|
||||
@@ -18,6 +18,7 @@ public:
|
||||
std::shared_ptr<BookmarkButtonsView> createBookmarkButtonsView(ViewLayout* viewLayout) const override;
|
||||
std::shared_ptr<BookmarkView> createBookmarkView(ViewLayout* viewLayout) const override;
|
||||
std::shared_ptr<CodeView> createCodeView(ViewLayout* viewLayout) const override;
|
||||
std::shared_ptr<CustomTrailView> createCustomTrailView() const override;
|
||||
std::shared_ptr<ErrorView> createErrorView(ViewLayout* viewLayout) const override;
|
||||
std::shared_ptr<GraphView> createGraphView(ViewLayout* viewLayout) const override;
|
||||
std::shared_ptr<RefreshView> createRefreshView(ViewLayout* viewLayout) const override;
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "MessageBookmarkBrowse.h"
|
||||
#include "MessageBookmarkCreate.h"
|
||||
#include "MessageCodeReference.h"
|
||||
#include "MessageCustomTrailShow.h"
|
||||
#include "MessageFind.h"
|
||||
#include "MessageIndexingShowDialog.h"
|
||||
#include "MessageLoadProject.h"
|
||||
@@ -755,6 +756,11 @@ void QtMainWindow::codeLocalReferenceNext()
|
||||
MessageCodeReference(MessageCodeReference::REFERENCE_NEXT, true).dispatch();
|
||||
}
|
||||
|
||||
void QtMainWindow::customTrail()
|
||||
{
|
||||
MessageCustomTrailShow().dispatch();
|
||||
}
|
||||
|
||||
void QtMainWindow::overview()
|
||||
{
|
||||
MessageActivateAll().dispatch();
|
||||
@@ -963,6 +969,10 @@ void QtMainWindow::setupEditMenu()
|
||||
|
||||
menu->addSeparator();
|
||||
|
||||
menu->addAction(tr("Custom Trail..."), this, &QtMainWindow::customTrail, QKeySequence(Qt::CTRL + Qt::Key_L));
|
||||
|
||||
menu->addSeparator();
|
||||
|
||||
menu->addAction(tr("&To overview"), this, &QtMainWindow::overview, QKeySequence::MoveToStartOfDocument);
|
||||
|
||||
menu->addSeparator();
|
||||
|
||||
@@ -137,6 +137,7 @@ public slots:
|
||||
void codeReferenceNext();
|
||||
void codeLocalReferencePrevious();
|
||||
void codeLocalReferenceNext();
|
||||
void customTrail();
|
||||
void overview();
|
||||
|
||||
void closeWindow();
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
void func()
|
||||
{
|
||||
int m;
|
||||
}
|
||||
|
||||
void func2()
|
||||
{
|
||||
func();
|
||||
}
|
||||
|
||||
class CustomA
|
||||
{
|
||||
public:
|
||||
void method()
|
||||
{
|
||||
func();
|
||||
}
|
||||
|
||||
int i;
|
||||
};
|
||||
|
||||
class CustomB
|
||||
{
|
||||
public:
|
||||
void method()
|
||||
{
|
||||
a.method();
|
||||
}
|
||||
|
||||
CustomA a;
|
||||
};
|
||||
|
||||
class CustomC
|
||||
{
|
||||
public:
|
||||
int method()
|
||||
{
|
||||
func2();
|
||||
bool a;
|
||||
char c;
|
||||
}
|
||||
|
||||
CustomA a;
|
||||
};
|
||||
|
||||
class CustomD
|
||||
{
|
||||
public:
|
||||
void method()
|
||||
{
|
||||
b.method();
|
||||
}
|
||||
|
||||
CustomB b;
|
||||
CustomC c;
|
||||
};
|
||||
@@ -0,0 +1,85 @@
|
||||
|
||||
#define CUSTOM_TRAIL_TESTS
|
||||
|
||||
#include "custom_trail_files/custom.h"
|
||||
|
||||
// TEST: open and close dialog
|
||||
// START ----------------------------------------------------------------------
|
||||
|
||||
// ACTION 1: Click on custom trail button in graph
|
||||
// RESULT 1: dialog opens on top of window
|
||||
|
||||
// ACTION 2: Close with click on Cancel
|
||||
// RESULT 2: dialog closes
|
||||
|
||||
// ACTION 3: Use custom trail shortcut Ctrl + L
|
||||
// RESULT 3: dialog opens on top of window
|
||||
|
||||
// ACTION 4: click on main window
|
||||
// ACTION 5: open again
|
||||
// RESULT 5: dialog opens on top of window
|
||||
|
||||
// ACTION 6: press ESC
|
||||
// RESULT 6: dialog closes
|
||||
|
||||
// END ------------------------------------------------------------------------
|
||||
|
||||
|
||||
// TEST: from -> to
|
||||
// START ----------------------------------------------------------------------
|
||||
|
||||
// ACTION 1: search from "CustomD"
|
||||
// ACTION 2: search to int
|
||||
// ACTION 3: select infinite depth
|
||||
// ACTION 4: select horizontal layout
|
||||
// ACTION 5: select all node and edge types
|
||||
// Action 6: click search
|
||||
|
||||
// RESULTS 6:
|
||||
// - Graph shows multiple paths
|
||||
// - Graph contains: CustomD -> CustomB, CustomC -> CustomA -> func -> int
|
||||
|
||||
// Action 7: Repeat search with:
|
||||
// - select vertical layout
|
||||
// - uncheck node field
|
||||
|
||||
// RESULTS 7:
|
||||
// - Graph one call chain to func
|
||||
// - Graph goes top to bottom
|
||||
// - Graph contains: CustomD -> CustomB -> CustomA, func2 -> func -> int
|
||||
|
||||
// END ------------------------------------------------------------------------
|
||||
|
||||
|
||||
// TEST: from -> all referenced
|
||||
// START ----------------------------------------------------------------------
|
||||
|
||||
// ACTION 1: search from "CustomD::c"
|
||||
// ACTION 2: select all referenced
|
||||
// ACTION 3: select depth 3
|
||||
// ACTION 4: select horizontal layout
|
||||
// ACTION 5: select all node and edge types
|
||||
// Action 6: click search
|
||||
|
||||
// RESULTS 6:
|
||||
// - Graph shows multiple paths
|
||||
// - Graph contains: CustomD -> CustomC -> int, char, bool, func2, CustomA
|
||||
|
||||
// END ------------------------------------------------------------------------
|
||||
|
||||
|
||||
// TEST: from <- all referencing
|
||||
// START ----------------------------------------------------------------------
|
||||
|
||||
// ACTION 1: search from "func"
|
||||
// ACTION 2: select all referencing
|
||||
// ACTION 3: select depth infinite
|
||||
// ACTION 4: select horizontal layout
|
||||
// ACTION 5: select all node and edge types
|
||||
// Action 6: click search
|
||||
|
||||
// RESULTS 6:
|
||||
// - Graph shows multiple paths
|
||||
// - Graph contains: CustomB, CustomC -> CustomA, func2 -> func
|
||||
|
||||
// END ------------------------------------------------------------------------
|
||||
@@ -7,6 +7,7 @@ Test Suites:\n\n
|
||||
[::\tmOVERVIEW_TESTS\ts\tp]\n
|
||||
[::\tmLAYOUT_TESTS\ts\tp]\n
|
||||
[::\tmDEPTH_GRAPH_TESTS\ts\tp]\n
|
||||
[::\tmCUSTOM_TRAIL_TESTS\ts\tp]\n
|
||||
[::\tmGROUPING_TESTS\ts\tp]\n
|
||||
</description>
|
||||
<source_groups>
|
||||
@@ -37,5 +38,5 @@ Test Suites:\n\n
|
||||
<type>C++ Source Group</type>
|
||||
</source_group_475571d1-b082-4fff-81c5-d099c19f957d>
|
||||
</source_groups>
|
||||
<version>7</version>
|
||||
<version>8</version>
|
||||
</config>
|
||||
|
||||
Reference in New Issue
Block a user