ui: added shortcut to refresh view
Added a refresh shortcut to the new View menu, that causes stylesheets to be refreshed by dispatching a MessageRefresh.
This commit is contained in:
@@ -13,6 +13,7 @@
|
|||||||
#include "utility/messaging/type/MessageFind.h"
|
#include "utility/messaging/type/MessageFind.h"
|
||||||
#include "utility/messaging/type/MessageLoadProject.h"
|
#include "utility/messaging/type/MessageLoadProject.h"
|
||||||
#include "utility/messaging/type/MessageLoadSource.h"
|
#include "utility/messaging/type/MessageLoadSource.h"
|
||||||
|
#include "utility/messaging/type/MessageRefresh.h"
|
||||||
|
|
||||||
QtMainWindow::QtMainWindow()
|
QtMainWindow::QtMainWindow()
|
||||||
{
|
{
|
||||||
@@ -21,6 +22,7 @@ QtMainWindow::QtMainWindow()
|
|||||||
|
|
||||||
setupProjectMenu();
|
setupProjectMenu();
|
||||||
setupFindMenu();
|
setupFindMenu();
|
||||||
|
setupViewMenu();
|
||||||
setupHelpMenu();
|
setupHelpMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,6 +76,11 @@ void QtMainWindow::find()
|
|||||||
MessageFind().dispatch();
|
MessageFind().dispatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QtMainWindow::refresh()
|
||||||
|
{
|
||||||
|
MessageRefresh().dispatch();
|
||||||
|
}
|
||||||
|
|
||||||
void QtMainWindow::addView(View* view)
|
void QtMainWindow::addView(View* view)
|
||||||
{
|
{
|
||||||
QDockWidget* dock = new QDockWidget(tr(view->getName().c_str()), this);
|
QDockWidget* dock = new QDockWidget(tr(view->getName().c_str()), this);
|
||||||
@@ -177,6 +184,14 @@ void QtMainWindow::setupFindMenu()
|
|||||||
menu->addAction(tr("&Find"), this, SLOT(find()), QKeySequence::Find);
|
menu->addAction(tr("&Find"), this, SLOT(find()), QKeySequence::Find);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QtMainWindow::setupViewMenu()
|
||||||
|
{
|
||||||
|
QMenu *menu = new QMenu(tr("&View"), this);
|
||||||
|
menuBar()->addMenu(menu);
|
||||||
|
|
||||||
|
menu->addAction(tr("&Refresh"), this, SLOT(refresh()), QKeySequence::Refresh);
|
||||||
|
}
|
||||||
|
|
||||||
void QtMainWindow::setupHelpMenu()
|
void QtMainWindow::setupHelpMenu()
|
||||||
{
|
{
|
||||||
QMenu *menu = new QMenu(tr("&Help"), this);
|
QMenu *menu = new QMenu(tr("&Help"), this);
|
||||||
|
|||||||
@@ -31,10 +31,12 @@ public slots:
|
|||||||
void newProject();
|
void newProject();
|
||||||
void openProject(const QString &path = QString());
|
void openProject(const QString &path = QString());
|
||||||
void find();
|
void find();
|
||||||
|
void refresh();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setupProjectMenu();
|
void setupProjectMenu();
|
||||||
void setupFindMenu();
|
void setupFindMenu();
|
||||||
|
void setupViewMenu();
|
||||||
void setupHelpMenu();
|
void setupHelpMenu();
|
||||||
|
|
||||||
QDockWidget* getDockWidgetForView(View* view) const;
|
QDockWidget* getDockWidgetForView(View* view) const;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
QtCodeView::QtCodeView(ViewLayout* viewLayout)
|
QtCodeView::QtCodeView(ViewLayout* viewLayout)
|
||||||
: CodeView(viewLayout)
|
: CodeView(viewLayout)
|
||||||
|
, m_refreshViewFunctor(std::bind(&QtCodeView::doRefreshView, this))
|
||||||
, m_clearCodeSnippetsFunctor(std::bind(&QtCodeView::doClearCodeSnippets, this))
|
, m_clearCodeSnippetsFunctor(std::bind(&QtCodeView::doClearCodeSnippets, this))
|
||||||
, m_addCodeSnippetFunctor(std::bind(&QtCodeView::doAddCodeSnippet, this, std::placeholders::_1))
|
, m_addCodeSnippetFunctor(std::bind(&QtCodeView::doAddCodeSnippet, this, std::placeholders::_1))
|
||||||
{
|
{
|
||||||
@@ -31,7 +32,6 @@ void QtCodeView::createWidgetWrapper()
|
|||||||
void QtCodeView::initView()
|
void QtCodeView::initView()
|
||||||
{
|
{
|
||||||
QWidget* widget = QtViewWidgetWrapper::getWidgetOfView(this);
|
QWidget* widget = QtViewWidgetWrapper::getWidgetOfView(this);
|
||||||
widget->setStyleSheet(TextAccess::createFromFile("data/gui/code_view/code_view.css")->getText().c_str());
|
|
||||||
widget->setObjectName("code_view");
|
widget->setObjectName("code_view");
|
||||||
|
|
||||||
QScrollArea* scroll = dynamic_cast<QScrollArea*>(widget);
|
QScrollArea* scroll = dynamic_cast<QScrollArea*>(widget);
|
||||||
@@ -45,6 +45,13 @@ void QtCodeView::initView()
|
|||||||
|
|
||||||
scroll->setWidgetResizable(true);
|
scroll->setWidgetResizable(true);
|
||||||
scroll->setWidget(m_frame.get());
|
scroll->setWidget(m_frame.get());
|
||||||
|
|
||||||
|
setStyleSheet();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QtCodeView::refreshView()
|
||||||
|
{
|
||||||
|
m_refreshViewFunctor();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtCodeView::addCodeSnippet(const CodeSnippetParams params)
|
void QtCodeView::addCodeSnippet(const CodeSnippetParams params)
|
||||||
@@ -63,6 +70,11 @@ void QtCodeView::activateToken(Id tokenId) const
|
|||||||
message.dispatch();
|
message.dispatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QtCodeView::doRefreshView()
|
||||||
|
{
|
||||||
|
setStyleSheet();
|
||||||
|
}
|
||||||
|
|
||||||
void QtCodeView::doAddCodeSnippet(const CodeSnippetParams params)
|
void QtCodeView::doAddCodeSnippet(const CodeSnippetParams params)
|
||||||
{
|
{
|
||||||
std::string fileName = FileSystem::fileName(params.locationFile.getFilePath());
|
std::string fileName = FileSystem::fileName(params.locationFile.getFilePath());
|
||||||
@@ -94,3 +106,9 @@ void QtCodeView::doClearCodeSnippets()
|
|||||||
{
|
{
|
||||||
m_files.clear();
|
m_files.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QtCodeView::setStyleSheet()
|
||||||
|
{
|
||||||
|
QWidget* widget = QtViewWidgetWrapper::getWidgetOfView(this);
|
||||||
|
widget->setStyleSheet(TextAccess::createFromFile("data/gui/code_view/code_view.css")->getText().c_str());
|
||||||
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ public:
|
|||||||
// View implementation
|
// View implementation
|
||||||
virtual void createWidgetWrapper();
|
virtual void createWidgetWrapper();
|
||||||
virtual void initView();
|
virtual void initView();
|
||||||
|
virtual void refreshView();
|
||||||
|
|
||||||
// CodeView implementation
|
// CodeView implementation
|
||||||
virtual void addCodeSnippet(const CodeSnippetParams params);
|
virtual void addCodeSnippet(const CodeSnippetParams params);
|
||||||
@@ -28,13 +29,17 @@ public:
|
|||||||
void activateToken(Id tokenId) const;
|
void activateToken(Id tokenId) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void doRefreshView();
|
||||||
void doAddCodeSnippet(const CodeSnippetParams params);
|
void doAddCodeSnippet(const CodeSnippetParams params);
|
||||||
void doClearCodeSnippets();
|
void doClearCodeSnippets();
|
||||||
|
|
||||||
|
void setStyleSheet();
|
||||||
|
|
||||||
std::shared_ptr<QFrame> m_frame;
|
std::shared_ptr<QFrame> m_frame;
|
||||||
std::vector<std::shared_ptr<QtCodeFile> > m_files;
|
std::vector<std::shared_ptr<QtCodeFile> > m_files;
|
||||||
|
|
||||||
QtThreadedFunctor<void> m_clearCodeSnippetsFunctor;
|
QtThreadedFunctor<> m_refreshViewFunctor;
|
||||||
|
QtThreadedFunctor<> m_clearCodeSnippetsFunctor;
|
||||||
QtThreadedFunctor<const CodeSnippetParams> m_addCodeSnippetFunctor;
|
QtThreadedFunctor<const CodeSnippetParams> m_addCodeSnippetFunctor;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -51,6 +51,10 @@ void QtGraphView::initView()
|
|||||||
widget->layout()->addWidget(view);
|
widget->layout()->addWidget(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QtGraphView::refreshView()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void QtGraphView::rebuildGraph(const std::vector<DummyNode>& nodes, const std::vector<DummyEdge>& edges)
|
void QtGraphView::rebuildGraph(const std::vector<DummyNode>& nodes, const std::vector<DummyEdge>& edges)
|
||||||
{
|
{
|
||||||
m_rebuildGraph(nodes, edges);
|
m_rebuildGraph(nodes, edges);
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ public:
|
|||||||
// View implementation
|
// View implementation
|
||||||
virtual void createWidgetWrapper();
|
virtual void createWidgetWrapper();
|
||||||
virtual void initView();
|
virtual void initView();
|
||||||
|
virtual void refreshView();
|
||||||
|
|
||||||
virtual void rebuildGraph(const std::vector<DummyNode>& nodes, const std::vector<DummyEdge>& edges);
|
virtual void rebuildGraph(const std::vector<DummyNode>& nodes, const std::vector<DummyEdge>& edges);
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
QtSearchView::QtSearchView(ViewLayout* viewLayout)
|
QtSearchView::QtSearchView(ViewLayout* viewLayout)
|
||||||
: SearchView(viewLayout)
|
: SearchView(viewLayout)
|
||||||
|
, m_refreshViewFunctor(std::bind(&QtSearchView::doRefreshView, this))
|
||||||
, m_setTextFunctor(std::bind(&QtSearchView::doSetText, this, std::placeholders::_1))
|
, m_setTextFunctor(std::bind(&QtSearchView::doSetText, this, std::placeholders::_1))
|
||||||
, m_setFocusFunctor(std::bind(&QtSearchView::doSetFocus, this))
|
, m_setFocusFunctor(std::bind(&QtSearchView::doSetFocus, this))
|
||||||
, m_setAutocompletionListFunctor(std::bind(&QtSearchView::doSetAutocompletionList, this, std::placeholders::_1))
|
, m_setAutocompletionListFunctor(std::bind(&QtSearchView::doSetAutocompletionList, this, std::placeholders::_1))
|
||||||
@@ -30,7 +31,6 @@ void QtSearchView::initView()
|
|||||||
{
|
{
|
||||||
QWidget* widget = QtViewWidgetWrapper::getWidgetOfView(this);
|
QWidget* widget = QtViewWidgetWrapper::getWidgetOfView(this);
|
||||||
widget->setObjectName("search_view");
|
widget->setObjectName("search_view");
|
||||||
widget->setStyleSheet(TextAccess::createFromFile("data/gui/search_view/search_view.css")->getText().c_str());
|
|
||||||
|
|
||||||
QBoxLayout* layout = new QBoxLayout(QBoxLayout::LeftToRight);
|
QBoxLayout* layout = new QBoxLayout(QBoxLayout::LeftToRight);
|
||||||
layout->setSpacing(0);
|
layout->setSpacing(0);
|
||||||
@@ -53,6 +53,13 @@ void QtSearchView::initView()
|
|||||||
m_caseSensitiveButton->setCheckable(true);
|
m_caseSensitiveButton->setCheckable(true);
|
||||||
m_caseSensitiveButton->setToolTip("case sensitive");
|
m_caseSensitiveButton->setToolTip("case sensitive");
|
||||||
widget->layout()->addWidget(m_caseSensitiveButton);
|
widget->layout()->addWidget(m_caseSensitiveButton);
|
||||||
|
|
||||||
|
setStyleSheet();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QtSearchView::refreshView()
|
||||||
|
{
|
||||||
|
m_refreshViewFunctor();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtSearchView::setText(const std::string& s)
|
void QtSearchView::setText(const std::string& s)
|
||||||
@@ -79,6 +86,11 @@ void QtSearchView::onSearchButtonClick()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QtSearchView::doRefreshView()
|
||||||
|
{
|
||||||
|
setStyleSheet();
|
||||||
|
}
|
||||||
|
|
||||||
void QtSearchView::doSetText(const std::string& s)
|
void QtSearchView::doSetText(const std::string& s)
|
||||||
{
|
{
|
||||||
if (m_searchBox->text() != s.c_str())
|
if (m_searchBox->text() != s.c_str())
|
||||||
@@ -105,5 +117,18 @@ void QtSearchView::doSetAutocompletionList(const std::vector<std::string>& autoc
|
|||||||
completer->popup()->setObjectName("search_box_popup");
|
completer->popup()->setObjectName("search_box_popup");
|
||||||
completer->setCaseSensitivity(Qt::CaseInsensitive);
|
completer->setCaseSensitivity(Qt::CaseInsensitive);
|
||||||
m_searchBox->setCompleter(completer);
|
m_searchBox->setCompleter(completer);
|
||||||
completer->popup()->setStyleSheet(TextAccess::createFromFile("data/gui/search_view/search_view.css")->getText().c_str());
|
setStyleSheet();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QtSearchView::setStyleSheet()
|
||||||
|
{
|
||||||
|
std::string css = TextAccess::createFromFile("data/gui/search_view/search_view.css")->getText();
|
||||||
|
|
||||||
|
QWidget* widget = QtViewWidgetWrapper::getWidgetOfView(this);
|
||||||
|
widget->setStyleSheet(css.c_str());
|
||||||
|
|
||||||
|
if (m_searchBox->completer())
|
||||||
|
{
|
||||||
|
m_searchBox->completer()->popup()->setStyleSheet(css.c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ public:
|
|||||||
// View implementation
|
// View implementation
|
||||||
virtual void createWidgetWrapper();
|
virtual void createWidgetWrapper();
|
||||||
virtual void initView();
|
virtual void initView();
|
||||||
|
virtual void refreshView();
|
||||||
|
|
||||||
// SearchView implementation
|
// SearchView implementation
|
||||||
virtual void setText(const std::string& s);
|
virtual void setText(const std::string& s);
|
||||||
@@ -27,14 +28,18 @@ public:
|
|||||||
private:
|
private:
|
||||||
void onSearchButtonClick();
|
void onSearchButtonClick();
|
||||||
|
|
||||||
|
void doRefreshView();
|
||||||
void doSetText(const std::string& s);
|
void doSetText(const std::string& s);
|
||||||
void doSetFocus();
|
void doSetFocus();
|
||||||
void doSetAutocompletionList(const std::vector<std::string>& autocompletionList);
|
void doSetAutocompletionList(const std::vector<std::string>& autocompletionList);
|
||||||
|
|
||||||
|
void setStyleSheet();
|
||||||
|
|
||||||
QtEditBox* m_searchBox;
|
QtEditBox* m_searchBox;
|
||||||
QtButton* m_searchButton;
|
QtButton* m_searchButton;
|
||||||
QtButton* m_caseSensitiveButton;
|
QtButton* m_caseSensitiveButton;
|
||||||
|
|
||||||
|
QtThreadedFunctor<> m_refreshViewFunctor;
|
||||||
QtThreadedFunctor<const std::string&> m_setTextFunctor;
|
QtThreadedFunctor<const std::string&> m_setTextFunctor;
|
||||||
QtThreadedFunctor<> m_setFocusFunctor;
|
QtThreadedFunctor<> m_setFocusFunctor;
|
||||||
QtThreadedFunctor<const std::vector<std::string>&> m_setAutocompletionListFunctor;
|
QtThreadedFunctor<const std::vector<std::string>&> m_setAutocompletionListFunctor;
|
||||||
|
|||||||
@@ -153,6 +153,7 @@ add_files(
|
|||||||
utility/messaging/type/MessageFinishedParsing.h
|
utility/messaging/type/MessageFinishedParsing.h
|
||||||
utility/messaging/type/MessageLoadProject.h
|
utility/messaging/type/MessageLoadProject.h
|
||||||
utility/messaging/type/MessageLoadSource.h
|
utility/messaging/type/MessageLoadSource.h
|
||||||
|
utility/messaging/type/MessageRefresh.h
|
||||||
|
|
||||||
utility/messaging/Message.h
|
utility/messaging/Message.h
|
||||||
utility/messaging/MessageBase.h
|
utility/messaging/MessageBase.h
|
||||||
|
|||||||
@@ -59,6 +59,11 @@ void CodeController::handleMessage(MessageActivateToken* message)
|
|||||||
setActiveTokenId(message->tokenId);
|
setActiveTokenId(message->tokenId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CodeController::handleMessage(MessageRefresh* message)
|
||||||
|
{
|
||||||
|
getView()->refreshView();
|
||||||
|
}
|
||||||
|
|
||||||
CodeView* CodeController::getView()
|
CodeView* CodeController::getView()
|
||||||
{
|
{
|
||||||
return Controller::getView<CodeView>();
|
return Controller::getView<CodeView>();
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "component/controller/Controller.h"
|
#include "component/controller/Controller.h"
|
||||||
#include "utility/messaging/MessageListener.h"
|
#include "utility/messaging/MessageListener.h"
|
||||||
#include "utility/messaging/type/MessageActivateToken.h"
|
#include "utility/messaging/type/MessageActivateToken.h"
|
||||||
|
#include "utility/messaging/type/MessageRefresh.h"
|
||||||
#include "utility/types.h"
|
#include "utility/types.h"
|
||||||
|
|
||||||
class CodeView;
|
class CodeView;
|
||||||
@@ -20,6 +21,7 @@ struct AnnotatedText
|
|||||||
class CodeController
|
class CodeController
|
||||||
: public Controller
|
: public Controller
|
||||||
, public MessageListener<MessageActivateToken>
|
, public MessageListener<MessageActivateToken>
|
||||||
|
, public MessageListener<MessageRefresh>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CodeController(LocationAccess* locationAccess);
|
CodeController(LocationAccess* locationAccess);
|
||||||
@@ -29,6 +31,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void handleMessage(MessageActivateToken* message);
|
virtual void handleMessage(MessageActivateToken* message);
|
||||||
|
virtual void handleMessage(MessageRefresh* message);
|
||||||
CodeView* getView();
|
CodeView* getView();
|
||||||
|
|
||||||
LocationAccess* m_locationAccess;
|
LocationAccess* m_locationAccess;
|
||||||
|
|||||||
@@ -43,6 +43,11 @@ void SearchController::handleMessage(MessageFinishedParsing* message)
|
|||||||
getView()->setAutocompletionList(m_graphAccess->getNamesForNodesWithNamePrefix(""));
|
getView()->setAutocompletionList(m_graphAccess->getNamesForNodesWithNamePrefix(""));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SearchController::handleMessage(MessageRefresh* message)
|
||||||
|
{
|
||||||
|
getView()->refreshView();
|
||||||
|
}
|
||||||
|
|
||||||
SearchView* SearchController::getView()
|
SearchView* SearchController::getView()
|
||||||
{
|
{
|
||||||
return Controller::getView<SearchView>();
|
return Controller::getView<SearchView>();
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "utility/messaging/type/MessageActivateToken.h"
|
#include "utility/messaging/type/MessageActivateToken.h"
|
||||||
#include "utility/messaging/type/MessageFind.h"
|
#include "utility/messaging/type/MessageFind.h"
|
||||||
#include "utility/messaging/type/MessageFinishedParsing.h"
|
#include "utility/messaging/type/MessageFinishedParsing.h"
|
||||||
|
#include "utility/messaging/type/MessageRefresh.h"
|
||||||
|
|
||||||
class GraphAccess;
|
class GraphAccess;
|
||||||
class SearchView;
|
class SearchView;
|
||||||
@@ -17,6 +18,7 @@ class SearchController
|
|||||||
, public MessageListener<MessageActivateToken>
|
, public MessageListener<MessageActivateToken>
|
||||||
, public MessageListener<MessageFind>
|
, public MessageListener<MessageFind>
|
||||||
, public MessageListener<MessageFinishedParsing>
|
, public MessageListener<MessageFinishedParsing>
|
||||||
|
, public MessageListener<MessageRefresh>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SearchController(GraphAccess* graphAccess);
|
SearchController(GraphAccess* graphAccess);
|
||||||
@@ -29,6 +31,7 @@ private:
|
|||||||
virtual void handleMessage(MessageActivateToken* message);
|
virtual void handleMessage(MessageActivateToken* message);
|
||||||
virtual void handleMessage(MessageFind* message);
|
virtual void handleMessage(MessageFind* message);
|
||||||
virtual void handleMessage(MessageFinishedParsing* message);
|
virtual void handleMessage(MessageFinishedParsing* message);
|
||||||
|
virtual void handleMessage(MessageRefresh* message);
|
||||||
SearchView* getView();
|
SearchView* getView();
|
||||||
|
|
||||||
GraphAccess* m_graphAccess;
|
GraphAccess* m_graphAccess;
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ public:
|
|||||||
virtual std::string getName() const = 0;
|
virtual std::string getName() const = 0;
|
||||||
virtual void createWidgetWrapper() = 0;
|
virtual void createWidgetWrapper() = 0;
|
||||||
virtual void initView() = 0;
|
virtual void initView() = 0;
|
||||||
|
virtual void refreshView() = 0;
|
||||||
|
|
||||||
void setComponent(Component* component);
|
void setComponent(Component* component);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
#ifndef MESSAGE_REFRESH_H
|
||||||
|
#define MESSAGE_REFRESH_H
|
||||||
|
|
||||||
|
#include "utility/messaging/Message.h"
|
||||||
|
#include "utility/types.h"
|
||||||
|
|
||||||
|
class MessageRefresh: public Message<MessageRefresh>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MessageRefresh()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static const std::string getStaticType()
|
||||||
|
{
|
||||||
|
return "MessageRefresh";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MESSAGE_REFRESH_H
|
||||||
Reference in New Issue
Block a user