logic: rewrote messages handling token activation for correct restoring on undo
* saving search query to undo stack with MessageSearch * saving node and edge with name to undo stack with MessageActivateNode and MessageActivateEdge * added FeatureController that handels distribution of MessageActivateTokens * clearing views when refreshing or changing project * clearing undo stack when changing project * added StorageCache derived from StorageAccessProxy
This commit is contained in:
@@ -60,14 +60,9 @@ QSize QtSearchBar::sizeHint() const
|
||||
return QSize(400, 100);
|
||||
}
|
||||
|
||||
void QtSearchBar::setText(const std::string& text)
|
||||
void QtSearchBar::setMatches(const std::deque<SearchMatch>& matches)
|
||||
{
|
||||
m_searchBox->setQuery(text);
|
||||
}
|
||||
|
||||
void QtSearchBar::setMatch(const SearchMatch& match)
|
||||
{
|
||||
m_searchBox->setQuery(match);
|
||||
m_searchBox->setMatches(matches);
|
||||
}
|
||||
|
||||
void QtSearchBar::setFocus()
|
||||
|
||||
@@ -22,8 +22,7 @@ public:
|
||||
|
||||
virtual QSize sizeHint() const;
|
||||
|
||||
void setText(const std::string& text);
|
||||
void setMatch(const SearchMatch& match);
|
||||
void setMatches(const std::deque<SearchMatch>& matches);
|
||||
void setFocus();
|
||||
void setAutocompletionList(const std::vector<SearchMatch>& autocompletionList);
|
||||
|
||||
|
||||
@@ -33,8 +33,10 @@ void QtQueryElement::onChecked(bool)
|
||||
void QtSmartSearchBox::search()
|
||||
{
|
||||
editTextToElement();
|
||||
LOG_INFO(utility::join(SearchMatch::searchMatchDequeToStringDeque(m_tokens), "")+ text().toStdString());
|
||||
MessageSearch(utility::join(SearchMatch::searchMatchDequeToStringDeque(m_tokens), "") + text().toStdString()).dispatch();
|
||||
|
||||
LOG_INFO_STREAM(<< "Search query: " << SearchMatch::searchMatchDequeToString(m_tokens) << text().toStdString());
|
||||
|
||||
MessageSearch(m_tokens).dispatch();
|
||||
}
|
||||
|
||||
QtSmartSearchBox::QtSmartSearchBox(QWidget* parent)
|
||||
@@ -80,21 +82,16 @@ void QtSmartSearchBox::setAutocompletionList(const std::vector<SearchMatch>& aut
|
||||
}
|
||||
}
|
||||
|
||||
void QtSmartSearchBox::setQuery(const SearchMatch& match)
|
||||
void QtSmartSearchBox::setMatches(const std::deque<SearchMatch>& matches)
|
||||
{
|
||||
clearLineEdit();
|
||||
m_tokens.clear();
|
||||
m_tokens.push_back(match);
|
||||
m_cursorIndex = m_tokens.size();
|
||||
updateElements();
|
||||
}
|
||||
if (SearchMatch::searchMatchDequeToString(matches) == SearchMatch::searchMatchDequeToString(m_tokens))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void QtSmartSearchBox::setQuery(const std::string& text)
|
||||
{
|
||||
clearLineEdit();
|
||||
m_tokens = SearchMatch::stringDequeToSearchMatchDeque(QueryTree::tokenizeQuery(text));
|
||||
m_tokens = matches;
|
||||
m_cursorIndex = m_tokens.size();
|
||||
|
||||
updateElements();
|
||||
}
|
||||
|
||||
|
||||
@@ -39,8 +39,7 @@ public:
|
||||
virtual ~QtSmartSearchBox();
|
||||
|
||||
void setAutocompletionList(const std::vector<SearchMatch>& autocompletionList);
|
||||
void setQuery(const SearchMatch& match);
|
||||
void setQuery(const std::string& text);
|
||||
void setMatches(const std::deque<SearchMatch>& matches);
|
||||
void setFocus();
|
||||
|
||||
protected:
|
||||
|
||||
@@ -75,6 +75,7 @@ void QtCodeView::defocusToken()
|
||||
void QtCodeView::doRefreshView()
|
||||
{
|
||||
setStyleSheet(m_widget);
|
||||
m_widget->clearCodeSnippets();
|
||||
}
|
||||
|
||||
void QtCodeView::doShowCodeSnippets(const std::vector<CodeSnippetParams>& snippets)
|
||||
|
||||
@@ -65,6 +65,7 @@ void QtGraphView::initView()
|
||||
|
||||
void QtGraphView::refreshView()
|
||||
{
|
||||
clear();
|
||||
resizeView();
|
||||
}
|
||||
|
||||
|
||||
@@ -7,8 +7,7 @@
|
||||
QtSearchView::QtSearchView(ViewLayout* viewLayout)
|
||||
: SearchView(viewLayout)
|
||||
, m_refreshViewFunctor(std::bind(&QtSearchView::doRefreshView, this))
|
||||
, m_setTextFunctor(std::bind(&QtSearchView::doSetText, this, std::placeholders::_1))
|
||||
, m_setMatchFunctor(std::bind(&QtSearchView::doSetMatch, this, std::placeholders::_1))
|
||||
, m_setMatchesFunctor(std::bind(&QtSearchView::doSetMatches, this, std::placeholders::_1))
|
||||
, m_setFocusFunctor(std::bind(&QtSearchView::doSetFocus, this))
|
||||
, m_setAutocompletionListFunctor(std::bind(&QtSearchView::doSetAutocompletionList, this, std::placeholders::_1))
|
||||
{
|
||||
@@ -34,14 +33,9 @@ void QtSearchView::refreshView()
|
||||
m_refreshViewFunctor();
|
||||
}
|
||||
|
||||
void QtSearchView::setText(const std::string& text)
|
||||
void QtSearchView::setMatches(const std::deque<SearchMatch>& matches)
|
||||
{
|
||||
m_setTextFunctor(text);
|
||||
}
|
||||
|
||||
void QtSearchView::setMatch(const SearchMatch& match)
|
||||
{
|
||||
m_setMatchFunctor(match);
|
||||
m_setMatchesFunctor(matches);
|
||||
}
|
||||
|
||||
void QtSearchView::setFocus()
|
||||
@@ -57,16 +51,12 @@ void QtSearchView::setAutocompletionList(const std::vector<SearchMatch>& autocom
|
||||
void QtSearchView::doRefreshView()
|
||||
{
|
||||
setStyleSheet();
|
||||
m_widget->setMatches(std::deque<SearchMatch>());
|
||||
}
|
||||
|
||||
void QtSearchView::doSetMatch(const SearchMatch& match)
|
||||
void QtSearchView::doSetMatches(const std::deque<SearchMatch>& matches)
|
||||
{
|
||||
m_widget->setMatch(match);
|
||||
}
|
||||
|
||||
void QtSearchView::doSetText(const std::string& text)
|
||||
{
|
||||
m_widget->setText(text);
|
||||
m_widget->setMatches(matches);
|
||||
}
|
||||
|
||||
void QtSearchView::doSetFocus()
|
||||
|
||||
@@ -19,23 +19,20 @@ public:
|
||||
virtual void refreshView();
|
||||
|
||||
// SearchView implementation
|
||||
virtual void setText(const std::string& text);
|
||||
virtual void setMatch(const SearchMatch& match);
|
||||
virtual void setMatches(const std::deque<SearchMatch>& matches);
|
||||
virtual void setFocus();
|
||||
virtual void setAutocompletionList(const std::vector<SearchMatch>& autocompletionList);
|
||||
|
||||
private:
|
||||
void doRefreshView();
|
||||
void doSetMatch(const SearchMatch& match);
|
||||
void doSetText(const std::string& text);
|
||||
void doSetMatches(const std::deque<SearchMatch>& matches);
|
||||
void doSetFocus();
|
||||
void doSetAutocompletionList(const std::vector<SearchMatch>& autocompletionList);
|
||||
|
||||
void setStyleSheet();
|
||||
|
||||
QtThreadedFunctor<> m_refreshViewFunctor;
|
||||
QtThreadedFunctor<const std::string&> m_setTextFunctor;
|
||||
QtThreadedFunctor<const SearchMatch&> m_setMatchFunctor;
|
||||
QtThreadedFunctor<const std::deque<SearchMatch>&> m_setMatchesFunctor;
|
||||
QtThreadedFunctor<> m_setFocusFunctor;
|
||||
QtThreadedFunctor<const std::vector<SearchMatch>&> m_setAutocompletionListFunctor;
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <QGraphicsSceneEvent>
|
||||
|
||||
#include "utility/messaging/type/MessageActivateTokens.h"
|
||||
#include "utility/messaging/type/MessageActivateEdge.h"
|
||||
#include "utility/messaging/type/MessageFocusIn.h"
|
||||
#include "utility/messaging/type/MessageFocusOut.h"
|
||||
#include "utility/messaging/type/MessageGraphNodeBundleSplit.h"
|
||||
@@ -123,16 +123,9 @@ void QtGraphEdge::onClick()
|
||||
{
|
||||
MessageGraphNodeBundleSplit(m_target.lock()->getTokenId()).dispatch();
|
||||
}
|
||||
else if (getData()->isType(Edge::EDGE_AGGREGATION))
|
||||
{
|
||||
const std::set<Id>& ids = getData()->getComponent<TokenComponentAggregation>()->getAggregationIds();
|
||||
MessageActivateTokens(std::vector<Id>(ids.begin(), ids.end())).dispatch();
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageActivateTokens message(getData()->getId());
|
||||
message.isEdge = true;
|
||||
message.dispatch();
|
||||
MessageActivateEdge(getData()->getId(), getData()->getType(), getData()->getName()).dispatch();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "qt/view/graphElements/QtGraphNodeData.h"
|
||||
|
||||
#include "utility/messaging/type/MessageActivateTokens.h"
|
||||
#include "utility/messaging/type/MessageActivateNode.h"
|
||||
#include "utility/messaging/type/MessageFocusIn.h"
|
||||
#include "utility/messaging/type/MessageFocusOut.h"
|
||||
#include "utility/messaging/type/MessageGraphNodeMove.h"
|
||||
@@ -37,7 +37,7 @@ void QtGraphNodeData::onClick()
|
||||
{
|
||||
if (!m_data->isType(Node::NODE_UNDEFINED | Node::NODE_NAMESPACE))
|
||||
{
|
||||
MessageActivateTokens(m_data->getId()).dispatch();
|
||||
MessageActivateNode(m_data->getId(), m_data->getType(), m_data->getFullName()).dispatch();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+28
-11
@@ -2,13 +2,13 @@
|
||||
|
||||
#include "utility/logging/logging.h"
|
||||
#include "utility/messaging/MessageQueue.h"
|
||||
#include "utility/messaging/type/MessageActivateTokens.h"
|
||||
#include "utility/messaging/type/MessageActivateNode.h"
|
||||
#include "utility/messaging/type/MessageStatus.h"
|
||||
#include "utility/scheduling/TaskScheduler.h"
|
||||
|
||||
#include "component/view/MainView.h"
|
||||
#include "component/view/ViewFactory.h"
|
||||
#include "data/access/StorageAccessProxy.h"
|
||||
#include "data/StorageCache.h"
|
||||
#include "settings/ApplicationSettings.h"
|
||||
|
||||
std::shared_ptr<Application> Application::create(ViewFactory* viewFactory)
|
||||
@@ -17,9 +17,9 @@ std::shared_ptr<Application> Application::create(ViewFactory* viewFactory)
|
||||
|
||||
std::shared_ptr<Application> ptr(new Application());
|
||||
|
||||
ptr->m_storageAccessProxy = std::make_shared<StorageAccessProxy>();
|
||||
ptr->m_storageCache = std::make_shared<StorageCache>();
|
||||
|
||||
ptr->m_componentManager = ComponentManager::create(viewFactory, ptr->m_storageAccessProxy.get());
|
||||
ptr->m_componentManager = ComponentManager::create(viewFactory, ptr->m_storageCache.get());
|
||||
|
||||
ptr->m_mainView = viewFactory->createMainView();
|
||||
ptr->m_componentManager->setup(ptr->m_mainView.get());
|
||||
@@ -51,7 +51,10 @@ void Application::loadProject(const std::string& projectSettingsFilePath)
|
||||
{
|
||||
MessageStatus("Loading Project: " + projectSettingsFilePath).dispatch();
|
||||
|
||||
m_project = Project::create(m_storageAccessProxy.get());
|
||||
m_storageCache->clear();
|
||||
m_componentManager->refreshViews();
|
||||
|
||||
m_project = Project::create(m_storageCache.get());
|
||||
|
||||
m_project->loadProjectSettings(projectSettingsFilePath);
|
||||
m_project->parseCode();
|
||||
@@ -61,7 +64,10 @@ void Application::loadSource(const std::string& sourceDirectoryPath)
|
||||
{
|
||||
MessageStatus("Loading Source: " + sourceDirectoryPath).dispatch();
|
||||
|
||||
m_project = Project::create(m_storageAccessProxy.get());
|
||||
m_storageCache->clear();
|
||||
m_componentManager->refreshViews();
|
||||
|
||||
m_project = Project::create(m_storageCache.get());
|
||||
|
||||
m_project->clearProjectSettings();
|
||||
m_project->setSourceDirectoryPath(sourceDirectoryPath);
|
||||
@@ -72,12 +78,15 @@ void Application::reloadProject()
|
||||
{
|
||||
MessageStatus("Refreshing Project").dispatch();
|
||||
|
||||
m_storageCache->clear();
|
||||
m_componentManager->refreshViews();
|
||||
|
||||
m_project->parseCode();
|
||||
}
|
||||
|
||||
void Application::saveProject(const std::string& projectSettingsFilePath)
|
||||
{
|
||||
if(!m_project->saveProjectSettings(projectSettingsFilePath))
|
||||
if (!m_project->saveProjectSettings(projectSettingsFilePath))
|
||||
{
|
||||
LOG_ERROR("No Project Settings File defined");
|
||||
}
|
||||
@@ -92,16 +101,24 @@ void Application::handleMessage(MessageFinishedParsing* message)
|
||||
return;
|
||||
}
|
||||
|
||||
Id mainId = m_storageAccessProxy->getIdForNodeWithName("main");
|
||||
Id mainId = m_storageCache->getIdForNodeWithName("main");
|
||||
|
||||
if (!mainId && m_storageAccessProxy->getNameForNodeWithId(1).size() > 0)
|
||||
if (!mainId)
|
||||
{
|
||||
mainId = 1;
|
||||
std::vector<Id> ids = m_storageCache->getTokenIdsForQuery("'file'");
|
||||
if (ids.size())
|
||||
{
|
||||
mainId = ids[0];
|
||||
}
|
||||
}
|
||||
|
||||
if (mainId)
|
||||
{
|
||||
MessageActivateTokens message(mainId);
|
||||
MessageActivateNode message(
|
||||
mainId,
|
||||
m_storageCache->getNodeTypeForNodeWithId(mainId),
|
||||
m_storageCache->getNameForNodeWithId(mainId)
|
||||
);
|
||||
message.isFromSystem = true;
|
||||
message.dispatch();
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
class ViewFactory;
|
||||
class MainView;
|
||||
class StorageAccessProxy;
|
||||
class StorageCache;
|
||||
|
||||
class Application
|
||||
: public MessageListener<MessageFinishedParsing>
|
||||
@@ -44,7 +44,7 @@ private:
|
||||
virtual void handleMessage(MessageSaveProject* message);
|
||||
|
||||
std::shared_ptr<Project> m_project;
|
||||
std::shared_ptr<StorageAccessProxy> m_storageAccessProxy;
|
||||
std::shared_ptr<StorageCache> m_storageCache;
|
||||
|
||||
std::shared_ptr<MainView> m_mainView;
|
||||
std::shared_ptr<ComponentManager> m_componentManager;
|
||||
|
||||
@@ -46,6 +46,8 @@ add_files(
|
||||
component/controller/CodeController.h
|
||||
component/controller/Controller.cpp
|
||||
component/controller/Controller.h
|
||||
component/controller/FeatureController.cpp
|
||||
component/controller/FeatureController.h
|
||||
component/controller/GraphController.cpp
|
||||
component/controller/GraphController.h
|
||||
component/controller/GraphLayouter.cpp
|
||||
@@ -204,6 +206,8 @@ add_files(
|
||||
|
||||
data/Storage.cpp
|
||||
data/Storage.h
|
||||
data/StorageCache.cpp
|
||||
data/StorageCache.h
|
||||
|
||||
settings/ApplicationSettings.cpp
|
||||
settings/ApplicationSettings.h
|
||||
@@ -247,7 +251,9 @@ add_files(
|
||||
utility/math/Vector4.h
|
||||
utility/math/VectorBase.h
|
||||
|
||||
utility/messaging/type/MessageActivateEdge.h
|
||||
utility/messaging/type/MessageActivateFile.h
|
||||
utility/messaging/type/MessageActivateNode.h
|
||||
utility/messaging/type/MessageActivateTokenLocation.h
|
||||
utility/messaging/type/MessageActivateTokens.h
|
||||
utility/messaging/type/MessageAutoRefreshChanged.h
|
||||
|
||||
@@ -7,12 +7,26 @@ Component::Component(std::shared_ptr<View> view, std::shared_ptr<Controller> con
|
||||
: m_controller(controller)
|
||||
, m_view(view)
|
||||
{
|
||||
m_controller->setComponent(this);
|
||||
m_view->setComponent(this);
|
||||
if (m_controller)
|
||||
{
|
||||
m_controller->setComponent(this);
|
||||
}
|
||||
|
||||
if (m_view)
|
||||
{
|
||||
m_view->setComponent(this);
|
||||
}
|
||||
}
|
||||
|
||||
Component::~Component()
|
||||
{
|
||||
m_controller->setComponent(NULL);
|
||||
m_view->setComponent(NULL);
|
||||
if (m_controller)
|
||||
{
|
||||
m_controller->setComponent(NULL);
|
||||
}
|
||||
|
||||
if (m_view)
|
||||
{
|
||||
m_view->setComponent(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "component/Component.h"
|
||||
#include "component/controller/CodeController.h"
|
||||
#include "component/controller/FeatureController.h"
|
||||
#include "component/controller/GraphController.h"
|
||||
#include "component/controller/RefreshController.h"
|
||||
#include "component/controller/SearchController.h"
|
||||
@@ -42,6 +43,13 @@ std::shared_ptr<Component> ComponentFactory::createCodeComponent(ViewLayout* vie
|
||||
return std::make_shared<Component>(view, controller);
|
||||
}
|
||||
|
||||
std::shared_ptr<Component> ComponentFactory::createFeatureComponent()
|
||||
{
|
||||
std::shared_ptr<Controller> controller = std::make_shared<FeatureController>(m_storageAccess);
|
||||
|
||||
return std::make_shared<Component>(nullptr, controller);
|
||||
}
|
||||
|
||||
std::shared_ptr<Component> ComponentFactory::createGraphComponent(ViewLayout* viewLayout)
|
||||
{
|
||||
std::shared_ptr<View> view = m_viewFactory->createGraphView(viewLayout);
|
||||
|
||||
@@ -19,6 +19,7 @@ public:
|
||||
ViewFactory* getViewFactory() const;
|
||||
|
||||
std::shared_ptr<Component> createCodeComponent(ViewLayout* viewLayout);
|
||||
std::shared_ptr<Component> createFeatureComponent();
|
||||
std::shared_ptr<Component> createGraphComponent(ViewLayout* viewLayout);
|
||||
std::shared_ptr<Component> createRefreshComponent(ViewLayout* viewLayout);
|
||||
std::shared_ptr<Component> createSearchComponent(ViewLayout* viewLayout);
|
||||
|
||||
@@ -44,16 +44,24 @@ void ComponentManager::setup(ViewLayout* viewLayout)
|
||||
|
||||
std::shared_ptr<Component> statusBarComponent = m_componentFactory->createStatusBarComponent(viewLayout);
|
||||
m_components.push_back(statusBarComponent);
|
||||
|
||||
std::shared_ptr<Component> featureComponent = m_componentFactory->createFeatureComponent();
|
||||
m_components.push_back(featureComponent);
|
||||
}
|
||||
|
||||
void ComponentManager::refreshViews()
|
||||
{
|
||||
for (std::shared_ptr<Component> component : m_components)
|
||||
{
|
||||
View* view = component->getView<View>();
|
||||
|
||||
if (view)
|
||||
{
|
||||
view->refreshView();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ComponentManager::ComponentManager()
|
||||
{
|
||||
}
|
||||
|
||||
void ComponentManager::handleMessage(MessageRefresh* message)
|
||||
{
|
||||
for (std::shared_ptr<Component> component : m_components)
|
||||
{
|
||||
component->getView<View>()->refreshView();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,6 @@
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "utility/messaging/MessageListener.h"
|
||||
#include "utility/messaging/type/MessageRefresh.h"
|
||||
|
||||
#include "component/Component.h"
|
||||
#include "component/ComponentFactory.h"
|
||||
|
||||
@@ -17,7 +14,6 @@ class ViewFactory;
|
||||
class ViewLayout;
|
||||
|
||||
class ComponentManager
|
||||
: public MessageListener<MessageRefresh>
|
||||
{
|
||||
public:
|
||||
static std::shared_ptr<ComponentManager> create(ViewFactory* viewFactory, StorageAccess* graphAccess);
|
||||
@@ -26,12 +22,12 @@ public:
|
||||
|
||||
void setup(ViewLayout* viewLayout);
|
||||
|
||||
void refreshViews();
|
||||
|
||||
private:
|
||||
ComponentManager();
|
||||
ComponentManager(const ComponentManager&);
|
||||
|
||||
void handleMessage(MessageRefresh* message);
|
||||
|
||||
std::shared_ptr<ComponentFactory> m_componentFactory;
|
||||
|
||||
std::vector<std::shared_ptr<CompositeView>> m_compositeViews;
|
||||
|
||||
@@ -23,20 +23,6 @@ CodeController::~CodeController()
|
||||
|
||||
const uint CodeController::s_lineRadius = 2;
|
||||
|
||||
void CodeController::handleMessage(MessageActivateFile* message)
|
||||
{
|
||||
MessageActivateTokens(std::vector<Id>(1, m_storageAccess->getTokenIdForFileNode(message->filePath))).dispatch();
|
||||
}
|
||||
|
||||
void CodeController::handleMessage(MessageActivateTokenLocation* message)
|
||||
{
|
||||
if (message->locationId)
|
||||
{
|
||||
std::vector<Id> activeTokenIds = m_storageAccess->getActiveTokenIdsForLocationId(message->locationId);
|
||||
MessageActivateTokens(activeTokenIds).dispatch();
|
||||
}
|
||||
}
|
||||
|
||||
void CodeController::handleMessage(MessageActivateTokens* message)
|
||||
{
|
||||
std::vector<Id> activeTokenIds = message->tokenIds;
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
#include <string>
|
||||
|
||||
#include "utility/messaging/MessageListener.h"
|
||||
#include "utility/messaging/type/MessageActivateFile.h"
|
||||
#include "utility/messaging/type/MessageActivateTokenLocation.h"
|
||||
#include "utility/messaging/type/MessageActivateTokens.h"
|
||||
#include "utility/messaging/type/MessageFinishedParsing.h"
|
||||
#include "utility/messaging/type/MessageFocusIn.h"
|
||||
@@ -24,8 +22,6 @@ class TokenLocationFile;
|
||||
|
||||
class CodeController
|
||||
: public Controller
|
||||
, public MessageListener<MessageActivateFile>
|
||||
, public MessageListener<MessageActivateTokenLocation>
|
||||
, public MessageListener<MessageActivateTokens>
|
||||
, public MessageListener<MessageFinishedParsing>
|
||||
, public MessageListener<MessageFocusIn>
|
||||
@@ -39,8 +35,6 @@ public:
|
||||
private:
|
||||
static const uint s_lineRadius;
|
||||
|
||||
virtual void handleMessage(MessageActivateFile* message);
|
||||
virtual void handleMessage(MessageActivateTokenLocation* message);
|
||||
virtual void handleMessage(MessageActivateTokens* message);
|
||||
virtual void handleMessage(MessageFinishedParsing* message);
|
||||
virtual void handleMessage(MessageFocusIn* message);
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
#include "component/controller/FeatureController.h"
|
||||
|
||||
#include "utility/messaging/type/MessageActivateTokens.h"
|
||||
|
||||
#include "data/access/StorageAccess.h"
|
||||
|
||||
FeatureController::FeatureController(StorageAccess* storageAccess)
|
||||
: m_storageAccess(storageAccess)
|
||||
{
|
||||
}
|
||||
|
||||
FeatureController::~FeatureController()
|
||||
{
|
||||
}
|
||||
|
||||
void FeatureController::handleMessage(MessageActivateEdge* message)
|
||||
{
|
||||
Id edgeId = message->tokenId;
|
||||
|
||||
if (!message->isFresh())
|
||||
{
|
||||
edgeId = m_storageAccess->getIdForEdgeWithName(message->name);
|
||||
}
|
||||
|
||||
if (!edgeId)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (message->type == Edge::EDGE_AGGREGATION)
|
||||
{
|
||||
MessageActivateTokens(m_storageAccess->getTokenIdsForAggregationEdge(edgeId)).dispatch();
|
||||
return;
|
||||
}
|
||||
|
||||
MessageActivateTokens msg(std::vector<Id>(1, edgeId));
|
||||
msg.isEdge = true;
|
||||
msg.dispatch();
|
||||
}
|
||||
|
||||
void FeatureController::handleMessage(MessageActivateFile* message)
|
||||
{
|
||||
MessageActivateTokens(std::vector<Id>(1, m_storageAccess->getTokenIdForFileNode(message->filePath))).dispatch();
|
||||
}
|
||||
|
||||
void FeatureController::handleMessage(MessageActivateNode* message)
|
||||
{
|
||||
Id nodeId = message->tokenId;
|
||||
|
||||
if (!message->isFresh())
|
||||
{
|
||||
nodeId = m_storageAccess->getIdForNodeWithName(message->name);
|
||||
}
|
||||
|
||||
if (nodeId)
|
||||
{
|
||||
MessageActivateTokens msg(nodeId);
|
||||
msg.isFromSystem = message->isFromSystem;
|
||||
msg.dispatch();
|
||||
}
|
||||
}
|
||||
|
||||
void FeatureController::handleMessage(MessageActivateTokenLocation* message)
|
||||
{
|
||||
if (message->locationId)
|
||||
{
|
||||
Id nodeId = m_storageAccess->getActiveNodeIdForLocationId(message->locationId);
|
||||
MessageActivateNode(
|
||||
nodeId,
|
||||
m_storageAccess->getNodeTypeForNodeWithId(nodeId),
|
||||
m_storageAccess->getNameForNodeWithId(nodeId)
|
||||
).dispatch();
|
||||
}
|
||||
}
|
||||
|
||||
void FeatureController::handleMessage(MessageSearch* message)
|
||||
{
|
||||
MessageActivateTokens(m_storageAccess->getTokenIdsForQuery(message->getQuery())).dispatch();
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
#ifndef FEATURE_CONTROLLER_H
|
||||
#define FEATURE_CONTROLLER_H
|
||||
|
||||
#include "utility/messaging/MessageListener.h"
|
||||
#include "utility/messaging/type/MessageActivateEdge.h"
|
||||
#include "utility/messaging/type/MessageActivateFile.h"
|
||||
#include "utility/messaging/type/MessageActivateNode.h"
|
||||
#include "utility/messaging/type/MessageActivateTokenLocation.h"
|
||||
#include "utility/messaging/type/MessageSearch.h"
|
||||
|
||||
#include "component/controller/Controller.h"
|
||||
|
||||
class StorageAccess;
|
||||
|
||||
class FeatureController
|
||||
: public Controller
|
||||
, public MessageListener<MessageActivateEdge>
|
||||
, public MessageListener<MessageActivateFile>
|
||||
, public MessageListener<MessageActivateNode>
|
||||
, public MessageListener<MessageActivateTokenLocation>
|
||||
, public MessageListener<MessageSearch>
|
||||
{
|
||||
public:
|
||||
FeatureController(StorageAccess* storageAccess);
|
||||
~FeatureController();
|
||||
|
||||
private:
|
||||
virtual void handleMessage(MessageActivateEdge* message);
|
||||
virtual void handleMessage(MessageActivateFile* message);
|
||||
virtual void handleMessage(MessageActivateNode* message);
|
||||
virtual void handleMessage(MessageActivateTokenLocation* message);
|
||||
virtual void handleMessage(MessageSearch* message);
|
||||
|
||||
StorageAccess* m_storageAccess;
|
||||
};
|
||||
|
||||
#endif // FEATURE_CONTROLLER_H
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
SearchController::SearchController(StorageAccess* storageAccess)
|
||||
: m_storageAccess(storageAccess)
|
||||
, m_ignoreNextMessageActivateTokens(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -13,21 +12,37 @@ SearchController::~SearchController()
|
||||
{
|
||||
}
|
||||
|
||||
void SearchController::handleMessage(MessageActivateTokens* message)
|
||||
void SearchController::handleMessage(MessageActivateEdge* message)
|
||||
{
|
||||
if (!m_ignoreNextMessageActivateTokens && message->tokenIds.size())
|
||||
{
|
||||
SearchMatch match;
|
||||
match.fullName = m_storageAccess->getNameForNodeWithId(message->tokenIds[0]);
|
||||
match.nodeType = m_storageAccess->getNodeTypeForNodeWithId(message->tokenIds[0]);
|
||||
match.tokenIds.insert(message->tokenIds[0]);
|
||||
match.queryNodeType = QueryNode::QUERYNODETYPE_TOKEN;
|
||||
SearchMatch match;
|
||||
match.fullName = message->name;
|
||||
match.nodeType = Node::NODE_CLASS;
|
||||
match.tokenIds.insert(message->tokenId);
|
||||
match.queryNodeType = QueryNode::QUERYNODETYPE_TOKEN;
|
||||
|
||||
getView()->setMatches(std::deque<SearchMatch>(1, match));
|
||||
}
|
||||
|
||||
getView()->setMatch(match);
|
||||
}
|
||||
void SearchController::handleMessage(MessageActivateFile* message)
|
||||
{
|
||||
SearchMatch match;
|
||||
match.fullName = message->filePath.fileName();
|
||||
match.nodeType = Node::NODE_FILE;
|
||||
match.tokenIds.insert(m_storageAccess->getTokenIdForFileNode(message->filePath));
|
||||
match.queryNodeType = QueryNode::QUERYNODETYPE_TOKEN;
|
||||
|
||||
m_ignoreNextMessageActivateTokens = false;
|
||||
getView()->setMatches(std::deque<SearchMatch>(1, match));
|
||||
}
|
||||
|
||||
void SearchController::handleMessage(MessageActivateNode* message)
|
||||
{
|
||||
SearchMatch match;
|
||||
match.fullName = message->name;
|
||||
match.nodeType = message->type;
|
||||
match.tokenIds.insert(message->tokenId);
|
||||
match.queryNodeType = QueryNode::QUERYNODETYPE_TOKEN;
|
||||
|
||||
getView()->setMatches(std::deque<SearchMatch>(1, match));
|
||||
}
|
||||
|
||||
void SearchController::handleMessage(MessageFind* message)
|
||||
@@ -37,28 +52,12 @@ void SearchController::handleMessage(MessageFind* message)
|
||||
|
||||
void SearchController::handleMessage(MessageFinishedParsing* message)
|
||||
{
|
||||
getView()->setText("");
|
||||
getView()->setMatches(std::deque<SearchMatch>());
|
||||
}
|
||||
|
||||
void SearchController::handleMessage(MessageSearch* message)
|
||||
{
|
||||
const std::string& query = message->query;
|
||||
|
||||
LOG_INFO("search string: \"" + query + "\"");
|
||||
|
||||
m_ignoreNextMessageActivateTokens = true;
|
||||
|
||||
std::vector<Id> ids = m_storageAccess->getTokenIdsForQuery(query);
|
||||
if (!ids.size())
|
||||
{
|
||||
Id id = m_storageAccess->getIdForNodeWithName(query);
|
||||
if (id > 0)
|
||||
{
|
||||
ids.push_back(id);
|
||||
}
|
||||
}
|
||||
|
||||
MessageActivateTokens(ids).dispatch();
|
||||
getView()->setMatches(message->getMatches());
|
||||
}
|
||||
|
||||
void SearchController::handleMessage(MessageSearchAutocomplete* message)
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
|
||||
#include "component/controller/Controller.h"
|
||||
#include "utility/messaging/MessageListener.h"
|
||||
#include "utility/messaging/type/MessageActivateTokens.h"
|
||||
#include "utility/messaging/type/MessageActivateEdge.h"
|
||||
#include "utility/messaging/type/MessageActivateFile.h"
|
||||
#include "utility/messaging/type/MessageActivateNode.h"
|
||||
#include "utility/messaging/type/MessageFind.h"
|
||||
#include "utility/messaging/type/MessageFinishedParsing.h"
|
||||
#include "utility/messaging/type/MessageSearch.h"
|
||||
@@ -16,7 +18,9 @@ class SearchView;
|
||||
|
||||
class SearchController
|
||||
: public Controller
|
||||
, public MessageListener<MessageActivateTokens>
|
||||
, public MessageListener<MessageActivateEdge>
|
||||
, public MessageListener<MessageActivateFile>
|
||||
, public MessageListener<MessageActivateNode>
|
||||
, public MessageListener<MessageFind>
|
||||
, public MessageListener<MessageFinishedParsing>
|
||||
, public MessageListener<MessageSearch>
|
||||
@@ -27,7 +31,9 @@ public:
|
||||
~SearchController();
|
||||
|
||||
private:
|
||||
virtual void handleMessage(MessageActivateTokens* message);
|
||||
virtual void handleMessage(MessageActivateEdge* message);
|
||||
virtual void handleMessage(MessageActivateFile* message);
|
||||
virtual void handleMessage(MessageActivateNode* message);
|
||||
virtual void handleMessage(MessageFind* message);
|
||||
virtual void handleMessage(MessageFinishedParsing* message);
|
||||
virtual void handleMessage(MessageSearch* message);
|
||||
@@ -36,8 +42,6 @@ private:
|
||||
SearchView* getView();
|
||||
|
||||
StorageAccess* m_storageAccess;
|
||||
|
||||
bool m_ignoreNextMessageActivateTokens;
|
||||
};
|
||||
|
||||
#endif // SEARCH_CONTROLLER_H
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
#include "component/controller/UndoRedoController.h"
|
||||
|
||||
#include "component/view/UndoRedoView.h"
|
||||
#include "utility/logging/logging.h"
|
||||
|
||||
#include "component/view/UndoRedoView.h"
|
||||
|
||||
UndoRedoController::UndoRedoController()
|
||||
: m_lastCommand(nullptr)
|
||||
{
|
||||
@@ -17,108 +18,153 @@ UndoRedoView* UndoRedoController::getView()
|
||||
return Controller::getView<UndoRedoView>();
|
||||
}
|
||||
|
||||
void UndoRedoController::handleMessage(MessageActivateTokens* message)
|
||||
void UndoRedoController::handleMessage(MessageActivateEdge* message)
|
||||
{
|
||||
if(m_lastCommand && m_lastCommand->getType() == "MessageActivateTokens")
|
||||
{
|
||||
if(static_cast<MessageActivateTokens*>(m_lastCommand.get())->tokenIds == message->tokenIds)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
std::shared_ptr<MessageActivateTokens> m = std::shared_ptr<MessageActivateTokens>(new MessageActivateTokens(*message));
|
||||
std::shared_ptr<MessageBase> msg = m;
|
||||
processMessage(msg);
|
||||
if (m_lastCommand && m_lastCommand->getType() == message->getType() &&
|
||||
static_cast<MessageActivateEdge*>(m_lastCommand.get())->name == message->name)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
processMessage(std::make_shared<MessageActivateEdge>(*message));
|
||||
}
|
||||
|
||||
void UndoRedoController::handleMessage(MessageActivateFile* message)
|
||||
{
|
||||
if (m_lastCommand && m_lastCommand->getType() == message->getType() &&
|
||||
static_cast<MessageActivateFile*>(m_lastCommand.get())->filePath == message->filePath)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
processMessage(std::make_shared<MessageActivateFile>(*message));
|
||||
}
|
||||
|
||||
void UndoRedoController::handleMessage(MessageActivateNode* message)
|
||||
{
|
||||
if (m_lastCommand && m_lastCommand->getType() == message->getType() &&
|
||||
static_cast<MessageActivateNode*>(m_lastCommand.get())->name == message->name)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
processMessage(std::make_shared<MessageActivateNode>(*message));
|
||||
}
|
||||
|
||||
void UndoRedoController::handleMessage(MessageGraphNodeExpand* message)
|
||||
{
|
||||
/*MessageGraphNodeExpand* m = new MessageGraphNodeExpand(message->tokenId,message->access);
|
||||
m->UndoRedoType = message->UndoRedoType;
|
||||
processMessage(m);*/
|
||||
}
|
||||
|
||||
void UndoRedoController::handleMessage(MessageGraphNodeMove* message)
|
||||
{
|
||||
/*MessageGraphNodeMove* m = new MessageGraphNodeMove(message->tokenId,message->position);
|
||||
m->UndoRedoType = message->UndoRedoType;
|
||||
processMessage(m, true);*/
|
||||
}
|
||||
|
||||
void UndoRedoController::handleMessage(MessageLoadProject* message)
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void UndoRedoController::handleMessage(MessageLoadSource* message)
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void UndoRedoController::handleMessage(MessageRedo* message)
|
||||
{
|
||||
if(!m_redo.empty())
|
||||
{
|
||||
std::shared_ptr<MessageBase> m = m_redo.back();
|
||||
m_redo.pop_back();
|
||||
m->UndoRedoType = MessageBase::UndoType_Redo;
|
||||
m->dispatch();
|
||||
}
|
||||
if (!m_redo.empty())
|
||||
{
|
||||
std::shared_ptr<MessageBase> m = m_redo.back();
|
||||
m_redo.pop_back();
|
||||
m->undoRedoType = MessageBase::UndoType_Redo;
|
||||
m->dispatch();
|
||||
}
|
||||
}
|
||||
|
||||
void UndoRedoController::handleMessage(MessageSearch* message)
|
||||
{
|
||||
if (m_lastCommand && m_lastCommand->getType() == message->getType() &&
|
||||
static_cast<MessageSearch*>(m_lastCommand.get())->getQuery() == message->getQuery())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
processMessage(std::make_shared<MessageSearch>(*message));
|
||||
}
|
||||
|
||||
void UndoRedoController::handleMessage(MessageUndo* message)
|
||||
{
|
||||
if(!m_undo.empty())
|
||||
{
|
||||
std::shared_ptr<MessageBase> m = m_undo.back();
|
||||
m_undo.pop_back();
|
||||
m->UndoRedoType = MessageBase::UndoType_Undo;
|
||||
m->dispatch();
|
||||
}
|
||||
if (!m_undo.empty())
|
||||
{
|
||||
std::shared_ptr<MessageBase> m = m_undo.back();
|
||||
m_undo.pop_back();
|
||||
m->undoRedoType = MessageBase::UndoType_Undo;
|
||||
m->dispatch();
|
||||
}
|
||||
}
|
||||
|
||||
void UndoRedoController::processMessage(std::shared_ptr<MessageBase> message)
|
||||
{
|
||||
switch(message->UndoRedoType)
|
||||
{
|
||||
case MessageBase::UndoType_Normal:
|
||||
processNormalMessage(message);;
|
||||
break;
|
||||
case MessageBase::UndoType_Redo:
|
||||
processRedoMessage(message);
|
||||
break;
|
||||
case MessageBase::UndoType_Undo:
|
||||
processUndoMessage(message);
|
||||
break;
|
||||
}
|
||||
switch (message->undoRedoType)
|
||||
{
|
||||
case MessageBase::UndoType_Normal:
|
||||
processNormalMessage(message);;
|
||||
break;
|
||||
case MessageBase::UndoType_Redo:
|
||||
processRedoMessage(message);
|
||||
break;
|
||||
case MessageBase::UndoType_Undo:
|
||||
processUndoMessage(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void UndoRedoController::processNormalMessage(std::shared_ptr<MessageBase> message)
|
||||
{
|
||||
if(m_lastCommand != nullptr)
|
||||
{
|
||||
m_undo.push_back(m_lastCommand);
|
||||
getView()->setUndoButtonEnabled(true);
|
||||
}
|
||||
m_lastCommand = message;
|
||||
while(!m_redo.empty())
|
||||
{
|
||||
std::shared_ptr<MessageBase> m = m_redo.back();
|
||||
m_redo.pop_back();
|
||||
}
|
||||
getView()->setRedoButtonEnabled(false);
|
||||
if (m_lastCommand)
|
||||
{
|
||||
m_undo.push_back(m_lastCommand);
|
||||
getView()->setUndoButtonEnabled(true);
|
||||
}
|
||||
|
||||
m_lastCommand = message;
|
||||
|
||||
m_redo.clear();
|
||||
getView()->setRedoButtonEnabled(false);
|
||||
}
|
||||
|
||||
void UndoRedoController::processRedoMessage(std::shared_ptr<MessageBase> message)
|
||||
{
|
||||
m_undo.push_back(m_lastCommand);
|
||||
getView()->setUndoButtonEnabled(true);
|
||||
m_lastCommand = message;
|
||||
if(m_redo.empty())
|
||||
{
|
||||
getView()->setRedoButtonEnabled(false);
|
||||
}
|
||||
m_undo.push_back(m_lastCommand);
|
||||
m_lastCommand = message;
|
||||
|
||||
getView()->setUndoButtonEnabled(true);
|
||||
|
||||
if (m_redo.empty())
|
||||
{
|
||||
getView()->setRedoButtonEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
void UndoRedoController::processUndoMessage(std::shared_ptr<MessageBase> message)
|
||||
{
|
||||
m_redo.push_back(m_lastCommand);
|
||||
getView()->setRedoButtonEnabled(true);
|
||||
m_lastCommand = message;
|
||||
if(m_undo.empty())
|
||||
{
|
||||
getView()->setUndoButtonEnabled(false);
|
||||
}
|
||||
m_redo.push_back(m_lastCommand);
|
||||
m_lastCommand = message;
|
||||
|
||||
getView()->setRedoButtonEnabled(true);
|
||||
|
||||
if (m_undo.empty())
|
||||
{
|
||||
getView()->setUndoButtonEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
void UndoRedoController::clear()
|
||||
{
|
||||
m_lastCommand = nullptr;
|
||||
|
||||
m_undo.clear();
|
||||
m_redo.clear();
|
||||
|
||||
getView()->setUndoButtonEnabled(false);
|
||||
getView()->setRedoButtonEnabled(false);
|
||||
}
|
||||
|
||||
@@ -2,46 +2,53 @@
|
||||
#define UNDO_REDO_CONTROLLER_H
|
||||
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
#include <stack>
|
||||
#include <string>
|
||||
|
||||
#include "component/controller/Controller.h"
|
||||
|
||||
#include "utility/messaging/MessageBase.h"
|
||||
#include "utility/messaging/MessageListener.h"
|
||||
#include "utility/messaging/type/MessageActivateTokens.h"
|
||||
#include "utility/messaging/type/MessageActivateEdge.h"
|
||||
#include "utility/messaging/type/MessageActivateFile.h"
|
||||
#include "utility/messaging/type/MessageActivateNode.h"
|
||||
#include "utility/messaging/type/MessageGraphNodeExpand.h"
|
||||
#include "utility/messaging/type/MessageGraphNodeMove.h"
|
||||
#include "utility/messaging/type/MessageLoadProject.h"
|
||||
#include "utility/messaging/type/MessageLoadSource.h"
|
||||
#include "utility/messaging/type/MessageRedo.h"
|
||||
#include "utility/messaging/type/MessageSearch.h"
|
||||
#include "utility/messaging/type/MessageUndo.h"
|
||||
|
||||
#include "component/controller/Controller.h"
|
||||
|
||||
class UndoRedoView;
|
||||
|
||||
class UndoRedoController
|
||||
: public Controller
|
||||
, public MessageListener<MessageActivateTokens>
|
||||
, public MessageListener<MessageActivateEdge>
|
||||
, public MessageListener<MessageActivateFile>
|
||||
, public MessageListener<MessageActivateNode>
|
||||
, public MessageListener<MessageGraphNodeExpand>
|
||||
, public MessageListener<MessageGraphNodeMove>
|
||||
, public MessageListener<MessageLoadProject>
|
||||
, public MessageListener<MessageLoadSource>
|
||||
, public MessageListener<MessageRedo>
|
||||
, public MessageListener<MessageSearch>
|
||||
, public MessageListener<MessageUndo>
|
||||
{
|
||||
public:
|
||||
UndoRedoController(void);
|
||||
virtual ~UndoRedoController(void);
|
||||
UndoRedoView* getView();
|
||||
private:
|
||||
enum UndoRedoType
|
||||
{
|
||||
UndoRedoType_Normal,
|
||||
UndoRedoType_Undo,
|
||||
UndoRedoType_Redo
|
||||
};
|
||||
UndoRedoController();
|
||||
virtual ~UndoRedoController();
|
||||
|
||||
virtual void handleMessage(MessageActivateTokens* message);
|
||||
UndoRedoView* getView();
|
||||
|
||||
private:
|
||||
virtual void handleMessage(MessageActivateEdge* message);
|
||||
virtual void handleMessage(MessageActivateFile* message);
|
||||
virtual void handleMessage(MessageActivateNode* message);
|
||||
virtual void handleMessage(MessageGraphNodeExpand* message);
|
||||
virtual void handleMessage(MessageGraphNodeMove* message);
|
||||
virtual void handleMessage(MessageLoadProject* message);
|
||||
virtual void handleMessage(MessageLoadSource* message);
|
||||
virtual void handleMessage(MessageRedo* message);
|
||||
virtual void handleMessage(MessageSearch* message);
|
||||
virtual void handleMessage(MessageUndo* message);
|
||||
|
||||
void processMessage(std::shared_ptr<MessageBase> message);
|
||||
@@ -49,6 +56,8 @@ private:
|
||||
void processRedoMessage(std::shared_ptr<MessageBase> message);
|
||||
void processUndoMessage(std::shared_ptr<MessageBase> message);
|
||||
|
||||
void clear();
|
||||
|
||||
std::shared_ptr<MessageBase> m_lastCommand;
|
||||
|
||||
std::deque<std::shared_ptr<MessageBase>> m_undo;
|
||||
|
||||
@@ -14,8 +14,7 @@ public:
|
||||
|
||||
virtual std::string getName() const;
|
||||
|
||||
virtual void setText(const std::string& s) = 0;
|
||||
virtual void setMatch(const SearchMatch& m) = 0;
|
||||
virtual void setMatches(const std::deque<SearchMatch>& matches) = 0;
|
||||
virtual void setFocus() = 0;
|
||||
virtual void setAutocompletionList(const std::vector<SearchMatch>& autocompletionList) = 0;
|
||||
|
||||
|
||||
+56
-11
@@ -7,6 +7,7 @@
|
||||
#include "utility/file/FileSystem.h"
|
||||
|
||||
#include "data/graph/filter/GraphFilterConductor.h"
|
||||
#include "data/graph/token_component/TokenComponentAggregation.h"
|
||||
#include "data/graph/token_component/TokenComponentConst.h"
|
||||
#include "data/graph/token_component/TokenComponentName.h"
|
||||
#include "data/graph/token_component/TokenComponentStatic.h"
|
||||
@@ -683,6 +684,42 @@ Id Storage::getIdForNodeWithName(const std::string& fullName) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
Id Storage::getIdForEdgeWithName(const std::string& name) const
|
||||
{
|
||||
Edge::EdgeType type;
|
||||
std::string fromName;
|
||||
std::string toName;
|
||||
|
||||
Edge::splitName(name, &type, &fromName, &toName);
|
||||
|
||||
Id fromId = getIdForNodeWithName(fromName);
|
||||
Node* from = m_graph.getNodeById(fromId);
|
||||
|
||||
if (from)
|
||||
{
|
||||
Edge* edge = from->findEdgeOfType(
|
||||
type,
|
||||
[&name](Edge* e)
|
||||
{
|
||||
return (e->getName() == name);
|
||||
}
|
||||
);
|
||||
|
||||
if (edge)
|
||||
{
|
||||
if (!edge->isType(type))
|
||||
{
|
||||
LOG_ERROR_STREAM(<< "Edge: " << name << " is not of type: " << Edge::getTypeString(type));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return edge->getId();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string Storage::getNameForNodeWithId(Id id) const
|
||||
{
|
||||
Token* token = m_graph.getTokenById(id);
|
||||
@@ -890,34 +927,28 @@ std::vector<Id> Storage::getActiveTokenIdsForId(Id tokenId, Id* declarationId) c
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<Id> Storage::getActiveTokenIdsForLocationId(Id locationId) const
|
||||
Id Storage::getActiveNodeIdForLocationId(Id locationId) const
|
||||
{
|
||||
std::vector<Id> ret;
|
||||
|
||||
TokenLocation* location = m_locationCollection.findTokenLocationById(locationId);
|
||||
if (!location)
|
||||
{
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Token* token = m_graph.getTokenById(location->getTokenId());
|
||||
if (!token)
|
||||
{
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (token->isNode())
|
||||
{
|
||||
Node* node = dynamic_cast<Node*>(token);
|
||||
ret.push_back(node->getId());
|
||||
return dynamic_cast<Node*>(token)->getId();
|
||||
}
|
||||
else
|
||||
{
|
||||
Edge* edge = dynamic_cast<Edge*>(token);
|
||||
ret.push_back(edge->getTo()->getId());
|
||||
return dynamic_cast<Edge*>(token)->getTo()->getId();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<Id> Storage::getTokenIdsForQuery(std::string query) const
|
||||
@@ -944,6 +975,20 @@ Id Storage::getTokenIdForFileNode(const FilePath& filePath) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<Id> Storage::getTokenIdsForAggregationEdge(Id aggregationId) const
|
||||
{
|
||||
Edge* edge = m_graph.getEdgeById(aggregationId);
|
||||
std::vector<Id> ids;
|
||||
|
||||
if (edge->isType(Edge::EDGE_AGGREGATION))
|
||||
{
|
||||
std::set<Id> i = edge->getComponent<TokenComponentAggregation>()->getAggregationIds();
|
||||
ids.insert(ids.end(), i.begin(), i.end());
|
||||
}
|
||||
|
||||
return ids;
|
||||
}
|
||||
|
||||
TokenLocationCollection Storage::getTokenLocationsForTokenIds(const std::vector<Id>& tokenIds) const
|
||||
{
|
||||
TokenLocationCollection ret;
|
||||
|
||||
@@ -109,6 +109,8 @@ public:
|
||||
|
||||
// StorageAccess implementation
|
||||
virtual Id getIdForNodeWithName(const std::string& fullName) const;
|
||||
virtual Id getIdForEdgeWithName(const std::string& name) const;
|
||||
|
||||
virtual std::string getNameForNodeWithId(Id id) const;
|
||||
virtual Node::NodeType getNodeTypeForNodeWithId(Id id) const;
|
||||
virtual std::vector<SearchMatch> getAutocompletionMatches(
|
||||
@@ -117,10 +119,11 @@ public:
|
||||
virtual std::shared_ptr<Graph> getGraphForActiveTokenIds(const std::vector<Id>& tokenIds) const;
|
||||
|
||||
virtual std::vector<Id> getActiveTokenIdsForId(Id tokenId, Id* declarationId) const;
|
||||
virtual std::vector<Id> getActiveTokenIdsForLocationId(Id locationId) const;
|
||||
virtual Id getActiveNodeIdForLocationId(Id locationId) const;
|
||||
|
||||
virtual std::vector<Id> getTokenIdsForQuery(std::string query) const;
|
||||
virtual Id getTokenIdForFileNode(const FilePath& filePath) const;
|
||||
virtual std::vector<Id> getTokenIdsForAggregationEdge(Id aggregationId) const;
|
||||
|
||||
virtual TokenLocationCollection getTokenLocationsForTokenIds(const std::vector<Id>& tokenIds) const;
|
||||
virtual std::shared_ptr<TokenLocationFile> getTokenLocationsForFile(const std::string& filePath) const;
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
#include "data/StorageCache.h"
|
||||
|
||||
void StorageCache::clear()
|
||||
{
|
||||
m_queryToTokenIds.clear();
|
||||
}
|
||||
|
||||
std::vector<Id> StorageCache::getTokenIdsForQuery(std::string query) const
|
||||
{
|
||||
std::map<std::string, std::vector<Id>>::const_iterator it = m_queryToTokenIds.find(query);
|
||||
|
||||
if (it != m_queryToTokenIds.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
|
||||
std::vector<Id> ids = StorageAccessProxy::getTokenIdsForQuery(query);
|
||||
|
||||
m_queryToTokenIds.emplace(query, ids);
|
||||
|
||||
return ids;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#ifndef STORAGE_CACHE_H
|
||||
#define STORAGE_CACHE_H
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "data/access/StorageAccessProxy.h"
|
||||
|
||||
class StorageCache
|
||||
: public StorageAccessProxy
|
||||
{
|
||||
public:
|
||||
void clear();
|
||||
|
||||
virtual std::vector<Id> getTokenIdsForQuery(std::string query) const;
|
||||
|
||||
private:
|
||||
mutable std::map<std::string, std::vector<Id>> m_queryToTokenIds;
|
||||
};
|
||||
|
||||
#endif // STORAGE_CACHE_H
|
||||
@@ -22,6 +22,8 @@ public:
|
||||
virtual ~StorageAccess();
|
||||
|
||||
virtual Id getIdForNodeWithName(const std::string& name) const = 0;
|
||||
virtual Id getIdForEdgeWithName(const std::string& name) const = 0;
|
||||
|
||||
virtual std::string getNameForNodeWithId(Id id) const = 0;
|
||||
virtual Node::NodeType getNodeTypeForNodeWithId(Id id) const = 0;
|
||||
virtual std::vector<SearchMatch> getAutocompletionMatches(
|
||||
@@ -30,10 +32,11 @@ public:
|
||||
virtual std::shared_ptr<Graph> getGraphForActiveTokenIds(const std::vector<Id>& tokenIds) const = 0;
|
||||
|
||||
virtual std::vector<Id> getActiveTokenIdsForId(Id tokenId, Id* declarationId) const = 0;
|
||||
virtual std::vector<Id> getActiveTokenIdsForLocationId(Id locationId) const = 0;
|
||||
virtual Id getActiveNodeIdForLocationId(Id locationId) const = 0;
|
||||
|
||||
virtual std::vector<Id> getTokenIdsForQuery(std::string query) const = 0;
|
||||
virtual Id getTokenIdForFileNode(const FilePath& filePath) const = 0;
|
||||
virtual std::vector<Id> getTokenIdsForAggregationEdge(Id aggregationId) const = 0;
|
||||
|
||||
virtual TokenLocationCollection getTokenLocationsForTokenIds(const std::vector<Id>& tokenIds) const = 0;
|
||||
virtual std::shared_ptr<TokenLocationFile> getTokenLocationsForFile(const std::string& filePath) const = 0;
|
||||
|
||||
@@ -41,6 +41,16 @@ Id StorageAccessProxy::getIdForNodeWithName(const std::string& name) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
Id StorageAccessProxy::getIdForEdgeWithName(const std::string& name) const
|
||||
{
|
||||
if (hasSubject())
|
||||
{
|
||||
return m_subject->getIdForEdgeWithName(name);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Node::NodeType StorageAccessProxy::getNodeTypeForNodeWithId(Id id) const
|
||||
{
|
||||
if(hasSubject())
|
||||
@@ -92,14 +102,14 @@ std::vector<Id> StorageAccessProxy::getActiveTokenIdsForId(Id tokenId, Id* delca
|
||||
return std::vector<Id>();
|
||||
}
|
||||
|
||||
std::vector<Id> StorageAccessProxy::getActiveTokenIdsForLocationId(Id locationId) const
|
||||
Id StorageAccessProxy::getActiveNodeIdForLocationId(Id locationId) const
|
||||
{
|
||||
if (hasSubject())
|
||||
{
|
||||
return m_subject->getActiveTokenIdsForLocationId(locationId);
|
||||
return m_subject->getActiveNodeIdForLocationId(locationId);
|
||||
}
|
||||
|
||||
return std::vector<Id>();
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<Id> StorageAccessProxy::getTokenIdsForQuery(std::string query) const
|
||||
@@ -122,6 +132,16 @@ Id StorageAccessProxy::getTokenIdForFileNode(const FilePath& filePath) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<Id> StorageAccessProxy::getTokenIdsForAggregationEdge(Id aggregationId) const
|
||||
{
|
||||
if (hasSubject())
|
||||
{
|
||||
return m_subject->getTokenIdsForAggregationEdge(aggregationId);
|
||||
}
|
||||
|
||||
return std::vector<Id>();
|
||||
}
|
||||
|
||||
TokenLocationCollection StorageAccessProxy::getTokenLocationsForTokenIds(const std::vector<Id>& tokenIds) const
|
||||
{
|
||||
if (hasSubject())
|
||||
|
||||
@@ -14,6 +14,8 @@ public:
|
||||
|
||||
// StorageAccess implementation
|
||||
virtual Id getIdForNodeWithName(const std::string& name) const;
|
||||
virtual Id getIdForEdgeWithName(const std::string& name) const;
|
||||
|
||||
virtual std::string getNameForNodeWithId(Id id) const;
|
||||
virtual Node::NodeType getNodeTypeForNodeWithId(Id id) const;
|
||||
virtual std::vector<SearchMatch> getAutocompletionMatches(
|
||||
@@ -22,10 +24,11 @@ public:
|
||||
virtual std::shared_ptr<Graph> getGraphForActiveTokenIds(const std::vector<Id>& tokenIds) const;
|
||||
|
||||
virtual std::vector<Id> getActiveTokenIdsForId(Id tokenId, Id* declarationId) const;
|
||||
virtual std::vector<Id> getActiveTokenIdsForLocationId(Id locationId) const;
|
||||
virtual Id getActiveNodeIdForLocationId(Id locationId) const;
|
||||
|
||||
virtual std::vector<Id> getTokenIdsForQuery(std::string query) const;
|
||||
virtual Id getTokenIdForFileNode(const FilePath& filePath) const;
|
||||
virtual std::vector<Id> getTokenIdsForAggregationEdge(Id aggregationId) const;
|
||||
|
||||
virtual TokenLocationCollection getTokenLocationsForTokenIds(const std::vector<Id>& tokenIds) const;
|
||||
virtual std::shared_ptr<TokenLocationFile> getTokenLocationsForFile(const std::string& filePath) const;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "data/graph/token_component/TokenComponentAggregation.h"
|
||||
#include "data/graph/token_component/TokenComponentAccess.h"
|
||||
#include "utility/logging/logging.h"
|
||||
#include "utility/utilityString.h"
|
||||
|
||||
Edge::Edge(EdgeType type, Node* from, Node* to)
|
||||
: m_type(type)
|
||||
@@ -67,6 +68,24 @@ std::string Edge::getName() const
|
||||
return getTypeString() + ":" + getFrom()->getFullName() + "->" + getTo()->getFullName();
|
||||
}
|
||||
|
||||
void Edge::splitName(const std::string& name, EdgeType* type, std::string* fromName, std::string* toName)
|
||||
{
|
||||
EdgeTypeMask mask = 1;
|
||||
std::string typeStr = utility::substrBefore(name, ':');
|
||||
|
||||
while (typeStr != getTypeString(static_cast<EdgeType>(mask)))
|
||||
{
|
||||
mask = mask << 1;
|
||||
}
|
||||
|
||||
*type = static_cast<EdgeType>(mask);
|
||||
|
||||
std::string names = utility::substrAfter(name, ':');
|
||||
|
||||
*fromName = utility::substrBefore(names, '-');
|
||||
*toName = utility::substrAfter(utility::substrAfter(names, '-'), '>');
|
||||
}
|
||||
|
||||
bool Edge::isNode() const
|
||||
{
|
||||
return false;
|
||||
@@ -110,7 +129,7 @@ void Edge::addComponentAccess(std::shared_ptr<TokenComponentAccess> component)
|
||||
}
|
||||
}
|
||||
|
||||
std::string Edge::getTypeString(EdgeType type) const
|
||||
std::string Edge::getTypeString(EdgeType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
|
||||
@@ -48,6 +48,7 @@ public:
|
||||
Node* getTo() const;
|
||||
|
||||
std::string getName() const;
|
||||
static void splitName(const std::string& name, EdgeType* type, std::string* fromName, std::string* toName);
|
||||
|
||||
// Token implementation
|
||||
virtual bool isNode() const;
|
||||
@@ -58,7 +59,7 @@ public:
|
||||
void addComponentAccess(std::shared_ptr<TokenComponentAccess> component);
|
||||
|
||||
// Logging.
|
||||
std::string getTypeString(EdgeType type) const;
|
||||
static std::string getTypeString(EdgeType type);
|
||||
virtual std::string getTypeString() const;
|
||||
std::string getAsString() const;
|
||||
|
||||
|
||||
@@ -257,15 +257,27 @@ public:
|
||||
|
||||
virtual void apply(const FilterableGraph* in, FilterableGraph* out)
|
||||
{
|
||||
if (m_tokenIds.size())
|
||||
std::vector<Node*> nodes;
|
||||
|
||||
for (Id tokenId : m_tokenIds)
|
||||
{
|
||||
for (Id tokenId : m_tokenIds)
|
||||
Node* node = in->getNodeById(tokenId);
|
||||
if (node)
|
||||
{
|
||||
Node* node = in->getNodeById(tokenId);
|
||||
if (node)
|
||||
{
|
||||
out->addNode(node);
|
||||
}
|
||||
nodes.push_back(node);
|
||||
}
|
||||
else
|
||||
{
|
||||
nodes.clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (nodes.size())
|
||||
{
|
||||
for (Node* node : nodes)
|
||||
{
|
||||
out->addNode(node);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -129,7 +129,11 @@ std::deque<std::string> SearchMatch::searchMatchDequeToStringDeque(const std::de
|
||||
stringDeque.push_back(match.encodeForQuery());
|
||||
}
|
||||
return stringDeque;
|
||||
}
|
||||
|
||||
std::string SearchMatch::searchMatchDequeToString(const std::deque<SearchMatch>& searchMatchDeque)
|
||||
{
|
||||
return utility::join(searchMatchDequeToStringDeque(searchMatchDeque), "");
|
||||
}
|
||||
|
||||
std::string SearchMatch::getNodeTypeAsString() const
|
||||
|
||||
@@ -16,6 +16,7 @@ struct SearchMatch
|
||||
static void log(const std::vector<SearchMatch>& matches, const std::string& query);
|
||||
static std::deque<SearchMatch> stringDequeToSearchMatchDeque(const std::deque<std::string>& deque);
|
||||
static std::deque<std::string> searchMatchDequeToStringDeque(const std::deque<SearchMatch>& deque);
|
||||
static std::string searchMatchDequeToString(const std::deque<SearchMatch>& deque);
|
||||
|
||||
SearchMatch();
|
||||
SearchMatch(const std::string& query);
|
||||
|
||||
@@ -14,7 +14,7 @@ public:
|
||||
};
|
||||
|
||||
MessageBase()
|
||||
: UndoRedoType(UndoType_Normal)
|
||||
: undoRedoType(UndoType_Normal)
|
||||
, m_sendAsTask(true)
|
||||
{
|
||||
}
|
||||
@@ -36,7 +36,12 @@ public:
|
||||
m_sendAsTask = sendAsTask;
|
||||
}
|
||||
|
||||
UndoType UndoRedoType;
|
||||
bool isFresh() const
|
||||
{
|
||||
return (undoRedoType == UndoType_Normal);
|
||||
}
|
||||
|
||||
UndoType undoRedoType;
|
||||
|
||||
private:
|
||||
bool m_sendAsTask;
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
#ifndef MESSAGE_ACTIVATE_EDGE_H
|
||||
#define MESSAGE_ACTIVATE_EDGE_H
|
||||
|
||||
#include "utility/messaging/Message.h"
|
||||
#include "utility/types.h"
|
||||
|
||||
#include "data/graph/Edge.h"
|
||||
|
||||
class MessageActivateEdge
|
||||
: public Message<MessageActivateEdge>
|
||||
{
|
||||
public:
|
||||
MessageActivateEdge(Id tokenId, Edge::EdgeType type, const std::string& name)
|
||||
: tokenId(tokenId)
|
||||
, type(type)
|
||||
, name(name)
|
||||
{
|
||||
}
|
||||
|
||||
static const std::string getStaticType()
|
||||
{
|
||||
return "MessageActivateEdge";
|
||||
}
|
||||
|
||||
const Id tokenId;
|
||||
const Edge::EdgeType type;
|
||||
const std::string name;
|
||||
};
|
||||
|
||||
#endif // MESSAGE_ACTIVATE_EDGE_H
|
||||
@@ -0,0 +1,33 @@
|
||||
#ifndef MESSAGE_ACTIVATE_NODE_H
|
||||
#define MESSAGE_ACTIVATE_NODE_H
|
||||
|
||||
#include "utility/messaging/Message.h"
|
||||
#include "utility/types.h"
|
||||
|
||||
#include "data/graph/Node.h"
|
||||
|
||||
class MessageActivateNode
|
||||
: public Message<MessageActivateNode>
|
||||
{
|
||||
public:
|
||||
MessageActivateNode(Id tokenId, Node::NodeType type, const std::string& name)
|
||||
: tokenId(tokenId)
|
||||
, type(type)
|
||||
, name(name)
|
||||
, isFromSystem(false)
|
||||
{
|
||||
}
|
||||
|
||||
static const std::string getStaticType()
|
||||
{
|
||||
return "MessageActivateNode";
|
||||
}
|
||||
|
||||
const Id tokenId;
|
||||
const Node::NodeType type;
|
||||
const std::string name;
|
||||
|
||||
bool isFromSystem;
|
||||
};
|
||||
|
||||
#endif // MESSAGE_ACTIVATE_NODE_H
|
||||
@@ -29,7 +29,6 @@ public:
|
||||
const std::vector<Id> tokenIds;
|
||||
|
||||
bool isEdge;
|
||||
bool isBundle;
|
||||
bool isFromSystem;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,14 +1,24 @@
|
||||
#ifndef MESSAGE_SEARCH_H
|
||||
#define MESSAGE_SEARCH_H
|
||||
|
||||
#include "utility/messaging/Message.h"
|
||||
#include "utility/types.h"
|
||||
#include <deque>
|
||||
|
||||
class MessageSearch: public Message<MessageSearch>
|
||||
#include "utility/messaging/Message.h"
|
||||
#include "utility/utilityString.h"
|
||||
|
||||
#include "data/search/SearchMatch.h"
|
||||
|
||||
class MessageSearch
|
||||
: public Message<MessageSearch>
|
||||
{
|
||||
public:
|
||||
MessageSearch(const std::string& query)
|
||||
: query(query)
|
||||
: m_query(query)
|
||||
{
|
||||
}
|
||||
|
||||
MessageSearch(const std::deque<SearchMatch>& matches)
|
||||
: m_matches(matches)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -17,7 +27,24 @@ public:
|
||||
return "MessageSearch";
|
||||
}
|
||||
|
||||
const std::string query;
|
||||
std::string getQuery() const
|
||||
{
|
||||
if (m_query.size())
|
||||
{
|
||||
return m_query;
|
||||
}
|
||||
|
||||
return utility::join(SearchMatch::searchMatchDequeToStringDeque(m_matches), "");
|
||||
}
|
||||
|
||||
const std::deque<SearchMatch>& getMatches() const
|
||||
{
|
||||
return m_matches;
|
||||
}
|
||||
|
||||
private:
|
||||
const std::string m_query;
|
||||
const std::deque<SearchMatch> m_matches;
|
||||
};
|
||||
|
||||
#endif // MESSAGE_SEARCH_H
|
||||
|
||||
@@ -100,6 +100,16 @@ namespace utility
|
||||
return c;
|
||||
}
|
||||
|
||||
std::string substrBefore(const std::string& str, char delimiter)
|
||||
{
|
||||
size_t pos = str.find(delimiter);
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
return str.substr(0, pos);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
std::string substrAfter(const std::string& str, char delimiter)
|
||||
{
|
||||
size_t pos = str.find(delimiter);
|
||||
|
||||
@@ -29,6 +29,7 @@ namespace utility
|
||||
std::deque<std::string> tokenize(const std::deque<std::string>& list, char delimiter);
|
||||
std::deque<std::string> tokenize(const std::deque<std::string>& list, const std::string& delimiter);
|
||||
|
||||
std::string substrBefore(const std::string& str, char delimiter);
|
||||
std::string substrAfter(const std::string& str, char delimiter);
|
||||
|
||||
bool isPrefix(const std::string& prefix, const std::string& text);
|
||||
|
||||
@@ -156,6 +156,31 @@ public:
|
||||
TS_ASSERT_EQUALS(result.at(6), "D");
|
||||
}
|
||||
|
||||
void test_substr_before_with_single_delimiter_occurence()
|
||||
{
|
||||
TS_ASSERT_EQUALS(utility::substrBefore("foo bar", ' '), "foo");
|
||||
}
|
||||
|
||||
void test_substr_before_with_multiple_delimiter_occurences()
|
||||
{
|
||||
TS_ASSERT_EQUALS(utility::substrBefore("foo bar foo", ' '), "foo");
|
||||
}
|
||||
|
||||
void test_substr_before_with_no_delimiter_occurence()
|
||||
{
|
||||
TS_ASSERT_EQUALS(utility::substrBefore("foobar", ' '), "foobar");
|
||||
}
|
||||
|
||||
void test_substr_before_with_delimiter_at_start()
|
||||
{
|
||||
TS_ASSERT_EQUALS(utility::substrBefore(" foobar", ' '), "");
|
||||
}
|
||||
|
||||
void test_substr_before_with_delimiter_at_end()
|
||||
{
|
||||
TS_ASSERT_EQUALS(utility::substrBefore("foobar ", ' '), "foobar");
|
||||
}
|
||||
|
||||
void test_substr_after_with_single_delimiter_occurence()
|
||||
{
|
||||
TS_ASSERT_EQUALS(utility::substrAfter("foo bar", ' '), "bar");
|
||||
|
||||
Reference in New Issue
Block a user