ui: search view autocompletion
- Implemented autocompletion for the QtSearchView. - Added: MessageFinishedParsing that will be dispatched by the Project after the parsing step is done. - Moved the initial MessageActivateToken from the Project to the Application. - Added getNamesForNodesWithNamePrefix() to GraphAccess.
This commit is contained in:
@@ -37,8 +37,9 @@ const std::string& QtCodeFile::getFileName() const
|
||||
void QtCodeFile::addCodeSnippet(
|
||||
const std::string& str, const TokenLocationFile& locationFile, int startLineNumber, Id activeTokenId
|
||||
){
|
||||
std::shared_ptr<QtCodeSnippet> snippet =
|
||||
std::make_shared<QtCodeSnippet>(m_parentView, str, locationFile, startLineNumber, activeTokenId, this);
|
||||
std::shared_ptr<QtCodeSnippet> snippet(
|
||||
new QtCodeSnippet(m_parentView, str, locationFile, startLineNumber, activeTokenId, this)
|
||||
);
|
||||
layout()->addWidget(snippet.get());
|
||||
m_snippets.push_back(snippet);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
#include "qt/element/QtEditBox.h"
|
||||
#include "utility/logging/logging.h"
|
||||
|
||||
QtEditBox::QtEditBox(QWidget *parent)
|
||||
: QLineEdit(parent)
|
||||
, m_onReturnPressed(nullptr)
|
||||
, m_onTextEdited(nullptr)
|
||||
{
|
||||
connect(this, SIGNAL(returnPressed()), this, SLOT(slotOnReturnPressed()));
|
||||
connect(this, SIGNAL(textEdited(const QString&)), this, SLOT(slotOnTextEdited(const QString&)));
|
||||
}
|
||||
|
||||
QtEditBox::~QtEditBox()
|
||||
@@ -16,8 +19,23 @@ void QtEditBox::setCallbackOnReturnPressed(std::function<void(void)> callback)
|
||||
m_onReturnPressed = callback;
|
||||
}
|
||||
|
||||
void QtEditBox::setCallbackOnTextEdited(std::function<void(const std::string&)> callback)
|
||||
{
|
||||
m_onTextEdited = callback;
|
||||
}
|
||||
|
||||
void QtEditBox::slotOnReturnPressed()
|
||||
{
|
||||
if (m_onReturnPressed)
|
||||
{
|
||||
m_onReturnPressed();
|
||||
}
|
||||
}
|
||||
|
||||
void QtEditBox::slotOnTextEdited(const QString& text)
|
||||
{
|
||||
if (m_onTextEdited)
|
||||
{
|
||||
m_onTextEdited(text.toStdString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,12 +14,15 @@ public:
|
||||
~QtEditBox();
|
||||
|
||||
void setCallbackOnReturnPressed(std::function<void(void)> callback);
|
||||
void setCallbackOnTextEdited(std::function<void(const std::string&)> callback);
|
||||
|
||||
private slots:
|
||||
void slotOnReturnPressed();
|
||||
void slotOnTextEdited(const QString& text);
|
||||
|
||||
private:
|
||||
std::function<void(void)> m_onReturnPressed;
|
||||
std::function<void(const std::string&)> m_onTextEdited;
|
||||
};
|
||||
|
||||
#endif // QT_EDIT_BOX_H
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
|
||||
QtSearchView::QtSearchView(ViewLayout* viewLayout)
|
||||
: SearchView(viewLayout)
|
||||
, m_setTextFunctor(std::bind(&QtSearchView::doSetText, this, std::placeholders::_1))
|
||||
, m_setAutocompletionListFunctor(std::bind(&QtSearchView::doSetAutocompletionList, this, std::placeholders::_1))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -36,6 +38,11 @@ void QtSearchView::initGui()
|
||||
m_searchBox->setPlaceholderText("Please enter your search string.");
|
||||
m_searchBox->setCallbackOnReturnPressed(std::bind(&QtSearchView::onSeachButtonClick, this));
|
||||
|
||||
std::vector<std::string> autocompletionList;
|
||||
autocompletionList.push_back("tralala");
|
||||
autocompletionList.push_back("lalila");
|
||||
setAutocompletionList(autocompletionList);
|
||||
|
||||
m_searchButton = new QtButton(widget);
|
||||
m_searchButton->setText("Search");
|
||||
m_searchButton->setCallbackOnClick(std::bind(&QtSearchView::onSeachButtonClick, this));
|
||||
@@ -44,7 +51,26 @@ void QtSearchView::initGui()
|
||||
widget->layout()->addWidget(m_searchButton);
|
||||
}
|
||||
|
||||
void QtSearchView::setText(const std::string& s) const
|
||||
void QtSearchView::setText(const std::string& s)
|
||||
{
|
||||
m_setTextFunctor(s);
|
||||
}
|
||||
|
||||
void QtSearchView::setAutocompletionList(const std::vector<std::string>& autocompletionList)
|
||||
{
|
||||
m_setAutocompletionListFunctor(autocompletionList);
|
||||
}
|
||||
|
||||
void QtSearchView::onSeachButtonClick()
|
||||
{
|
||||
SearchController* controller = getController();
|
||||
if (controller)
|
||||
{
|
||||
controller->search(m_searchBox->text().toStdString());
|
||||
}
|
||||
}
|
||||
|
||||
void QtSearchView::doSetText(const std::string& s)
|
||||
{
|
||||
if (m_searchBox->text() != s.c_str())
|
||||
{
|
||||
@@ -52,7 +78,12 @@ void QtSearchView::setText(const std::string& s) const
|
||||
}
|
||||
}
|
||||
|
||||
void QtSearchView::onSeachButtonClick()
|
||||
void QtSearchView::doSetAutocompletionList(const std::vector<std::string>& autocompletionList)
|
||||
{
|
||||
getController()->search(m_searchBox->text().toStdString());
|
||||
QStringList wordList;
|
||||
for (const std::string& s: autocompletionList)
|
||||
wordList << s.c_str();
|
||||
QCompleter *completer = new QCompleter(wordList, m_searchBox);
|
||||
completer->setCaseSensitivity(Qt::CaseInsensitive);
|
||||
m_searchBox->setCompleter(completer);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
#ifndef QT_SEARCH_VIEW_H
|
||||
#define QT_SEARCH_VIEW_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "component/view/SearchView.h"
|
||||
#include "qt/utility/QtThreadedFunctor.h"
|
||||
|
||||
class QtEditBox;
|
||||
class QtButton;
|
||||
@@ -17,13 +20,19 @@ public:
|
||||
virtual void initGui();
|
||||
|
||||
// SearchView implementation
|
||||
virtual void setText(const std::string& s) const;
|
||||
virtual void setText(const std::string& s);
|
||||
virtual void setAutocompletionList(const std::vector<std::string>& autocompletionList);
|
||||
|
||||
private:
|
||||
void onSeachButtonClick();
|
||||
|
||||
void doSetText(const std::string& s);
|
||||
void doSetAutocompletionList(const std::vector<std::string>& autocompletionList);
|
||||
|
||||
QtEditBox* m_searchBox;
|
||||
QtButton* m_searchButton;
|
||||
QtThreadedFunctor<const std::string&> m_setTextFunctor;
|
||||
QtThreadedFunctor<const std::vector<std::string>&> m_setAutocompletionListFunctor;
|
||||
};
|
||||
|
||||
# endif // QT_SEARCH_VIEW_H
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "utility/logging/ConsoleLogger.h"
|
||||
#include "utility/logging/LogManager.h"
|
||||
#include "utility/messaging/MessageQueue.h"
|
||||
#include "utility/messaging/type/MessageActivateToken.h"
|
||||
|
||||
std::shared_ptr<Application> Application::create(GuiFactory* guiFactory)
|
||||
{
|
||||
@@ -42,4 +43,7 @@ void Application::loadProject()
|
||||
|
||||
m_project->loadProjectSettings("data/ProjectSettings.xml");
|
||||
m_project->parseCode();
|
||||
|
||||
MessageActivateToken message(1);
|
||||
message.dispatch();
|
||||
}
|
||||
|
||||
+2
-2
@@ -5,7 +5,7 @@
|
||||
|
||||
#include "data/parser/cxx/CxxParser.h"
|
||||
#include "utility/FileSystem.h"
|
||||
#include "utility/messaging/type/MessageActivateToken.h"
|
||||
#include "utility/messaging/type/MessageFinishedParsing.h"
|
||||
#include "utility/logging/logging.h"
|
||||
|
||||
std::shared_ptr<Project> Project::create(
|
||||
@@ -46,7 +46,7 @@ void Project::parseCode()
|
||||
m_storage->logGraph();
|
||||
m_storage->logLocations();
|
||||
|
||||
MessageActivateToken message(1);
|
||||
MessageFinishedParsing message;
|
||||
message.dispatch();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#include "component/view/SearchView.h"
|
||||
#include "data/access/GraphAccess.h"
|
||||
#include "utility/messaging/type/MessageActivateToken.h"
|
||||
|
||||
SearchController::SearchController(std::shared_ptr<GraphAccess> graphAccess)
|
||||
: m_graphAccess(graphAccess)
|
||||
@@ -34,6 +33,11 @@ void SearchController::handleMessage(MessageActivateToken* message)
|
||||
getView()->setText(m_graphAccess->getNameForNodeWithId(message->tokenId));
|
||||
}
|
||||
|
||||
void SearchController::handleMessage(MessageFinishedParsing* message)
|
||||
{
|
||||
getView()->setAutocompletionList(m_graphAccess->getNamesForNodesWithNamePrefix(""));
|
||||
}
|
||||
|
||||
SearchView* SearchController::getView()
|
||||
{
|
||||
return Controller::getView<SearchView>();
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "component/controller/Controller.h"
|
||||
#include "utility/messaging/MessageListener.h"
|
||||
#include "utility/messaging/type/MessageActivateToken.h"
|
||||
#include "utility/messaging/type/MessageFinishedParsing.h"
|
||||
|
||||
class GraphAccess;
|
||||
class SearchView;
|
||||
@@ -13,6 +14,7 @@ class SearchView;
|
||||
class SearchController
|
||||
: public Controller
|
||||
, public MessageListener<MessageActivateToken>
|
||||
, public MessageListener<MessageFinishedParsing>
|
||||
{
|
||||
public:
|
||||
SearchController(std::shared_ptr<GraphAccess> graphAccess);
|
||||
@@ -23,6 +25,7 @@ public:
|
||||
|
||||
private:
|
||||
virtual void handleMessage(MessageActivateToken* message);
|
||||
virtual void handleMessage(MessageFinishedParsing* message);
|
||||
SearchView* getView();
|
||||
|
||||
std::shared_ptr<GraphAccess> m_graphAccess;
|
||||
|
||||
@@ -13,7 +13,8 @@ public:
|
||||
|
||||
virtual std::string getName() const;
|
||||
|
||||
virtual void setText(const std::string& s) const = 0;
|
||||
virtual void setText(const std::string& s) = 0;
|
||||
virtual void setAutocompletionList(const std::vector<std::string>& autocompletionList) = 0;
|
||||
|
||||
protected:
|
||||
SearchController* getController();
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "data/parser/ParseLocation.h"
|
||||
#include "data/parser/ParseVariable.h"
|
||||
#include "utility/logging/logging.h"
|
||||
#include "utility/utilityString.h"
|
||||
|
||||
Storage::Storage()
|
||||
{
|
||||
@@ -191,6 +192,20 @@ std::string Storage::getNameForNodeWithId(Id id) const
|
||||
return (node ? node->getName() : "");
|
||||
}
|
||||
|
||||
std::vector<std::string> Storage::getNamesForNodesWithNamePrefix(const std::string& prefix) const
|
||||
{
|
||||
std::vector<std::string> names;
|
||||
m_graph.forEachNode([&](Node* node){
|
||||
const std::string& nodeName = node->getName();
|
||||
if (utility::isPrefix(prefix, nodeName))
|
||||
{
|
||||
names.push_back(nodeName);
|
||||
}
|
||||
});
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
TokenLocationCollection Storage::getTokenLocationsForTokenId(Id id) const
|
||||
{
|
||||
TokenLocationCollection ret;
|
||||
|
||||
@@ -48,6 +48,7 @@ public:
|
||||
// GraphAccess implementation
|
||||
virtual Id getIdForNodeWithName(const std::string& name) const;
|
||||
virtual std::string getNameForNodeWithId(Id id) const;
|
||||
virtual std::vector<std::string> getNamesForNodesWithNamePrefix(const std::string& prefix) const;
|
||||
|
||||
// LocationAccess implementation
|
||||
virtual TokenLocationCollection getTokenLocationsForTokenId(Id locationId) const;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define GRAPH_ACCESS_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "utility/types.h"
|
||||
|
||||
@@ -14,6 +15,7 @@ public:
|
||||
|
||||
virtual Id getIdForNodeWithName(const std::string& name) const = 0;
|
||||
virtual std::string getNameForNodeWithId(Id id) const = 0;
|
||||
virtual std::vector<std::string> getNamesForNodesWithNamePrefix(const std::string& prefix) const = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ public:
|
||||
return "MessageActivateToken";
|
||||
}
|
||||
|
||||
public:
|
||||
const Id tokenId;
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef MESSAGE_FINISHED_PARSING_H
|
||||
#define MESSAGE_FINISHED_PARSING_H
|
||||
|
||||
#include "utility/messaging/Message.h"
|
||||
|
||||
class MessageFinishedParsing: public Message<MessageFinishedParsing>
|
||||
{
|
||||
public:
|
||||
MessageFinishedParsing()
|
||||
{
|
||||
}
|
||||
|
||||
static const std::string getStaticType()
|
||||
{
|
||||
return "MessageFinishedParsing";
|
||||
}
|
||||
};
|
||||
|
||||
#endif // MESSAGE_FINISHED_PARSING_H
|
||||
@@ -23,4 +23,12 @@ namespace utility
|
||||
|
||||
return vec;
|
||||
}
|
||||
|
||||
bool isPrefix(const std::string& prefix, const std::string& text)
|
||||
{
|
||||
typedef std::pair<std::string::const_iterator, std::string::const_iterator> ResType;
|
||||
ResType res = std::mismatch(prefix.begin(), prefix.end(), text.begin());
|
||||
|
||||
return res.first == prefix.end();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ namespace utility
|
||||
{
|
||||
std::vector<std::string> split(const std::string& str, char delimiter);
|
||||
std::vector<std::string> split(const std::string& str, const std::string& delimiter);
|
||||
|
||||
bool isPrefix(const std::string& prefix, const std::string& text);
|
||||
}
|
||||
|
||||
#endif // UTILITY_STRING_H
|
||||
|
||||
@@ -50,4 +50,35 @@ public:
|
||||
TS_ASSERT_EQUALS(result[2], "B");
|
||||
TS_ASSERT_EQUALS(result[3], "C");
|
||||
}
|
||||
|
||||
void test_empty_string_is_detected_as_prefix_of_any_other_string()
|
||||
{
|
||||
const std::string foo = "foo";
|
||||
|
||||
TS_ASSERT(utility::isPrefix("", foo));
|
||||
}
|
||||
|
||||
void test_prefix_of_bigger_text_is_detected_as_prefix()
|
||||
{
|
||||
const std::string foobar = "foobar";
|
||||
const std::string foo = "foo";
|
||||
|
||||
TS_ASSERT(utility::isPrefix(foo, foobar));
|
||||
}
|
||||
|
||||
void test_prefix_is_detected_as_prefix_of_self()
|
||||
{
|
||||
const std::string foo = "foo";
|
||||
|
||||
TS_ASSERT(utility::isPrefix(foo, foo));
|
||||
}
|
||||
|
||||
void test_different_texts_are_not_detected_of_prefixes_of_each_other()
|
||||
{
|
||||
const std::string foo = "foo";
|
||||
const std::string bar = "bar";
|
||||
|
||||
TS_ASSERT(!utility::isPrefix(foo, bar));
|
||||
TS_ASSERT(!utility::isPrefix(bar, foo));
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user