parent
a9ab84d8b1
commit
7c01382e81
@ -17,6 +17,11 @@ enum {
|
|||||||
PROP_COUNT
|
PROP_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SIGNAL_MODE_CHANGED,
|
||||||
|
SIGNAL_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
static void ag_header_bar_dispose(GObject *gobject);
|
static void ag_header_bar_dispose(GObject *gobject);
|
||||||
static void ag_header_bar_finalize(GObject *gobject);
|
static void ag_header_bar_finalize(GObject *gobject);
|
||||||
|
|
||||||
@ -25,6 +30,7 @@ G_DEFINE_TYPE_WITH_PRIVATE(AgHeaderBar, ag_header_bar, GTK_TYPE_HEADER_BAR);
|
|||||||
#define GET_PRIV(v, o) AgHeaderBarPrivate *v = ag_header_bar_get_instance_private(o);
|
#define GET_PRIV(v, o) AgHeaderBarPrivate *v = ag_header_bar_get_instance_private(o);
|
||||||
|
|
||||||
static GParamSpec *properties[PROP_COUNT];
|
static GParamSpec *properties[PROP_COUNT];
|
||||||
|
static guint signals[SIGNAL_COUNT] = { 0 };
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ag_header_bar_selection_mode_cb(GtkButton *button,
|
ag_header_bar_selection_mode_cb(GtkButton *button,
|
||||||
@ -32,22 +38,58 @@ ag_header_bar_selection_mode_cb(GtkButton *button,
|
|||||||
{
|
{
|
||||||
GET_PRIV(priv, header_bar);
|
GET_PRIV(priv, header_bar);
|
||||||
|
|
||||||
switch (priv->mode) {
|
/* If we are not in list mode, this transition is invalid */
|
||||||
case AG_HEADER_BAR_MODE_LIST:
|
if (priv->mode != AG_HEADER_BAR_MODE_LIST) {
|
||||||
ag_header_bar_set_mode(header_bar, AG_HEADER_BAR_MODE_SELECTION);
|
g_warning("Invalid header bar mode transition!");
|
||||||
|
|
||||||
break;
|
return;
|
||||||
|
|
||||||
case AG_HEADER_BAR_MODE_SELECTION:
|
|
||||||
ag_header_bar_set_mode(header_bar, AG_HEADER_BAR_MODE_LIST);
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
g_warning("Invalid header bar mode transition!");
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_signal_emit(
|
||||||
|
header_bar,
|
||||||
|
signals[SIGNAL_MODE_CHANGED], 0,
|
||||||
|
AG_HEADER_BAR_MODE_SELECTION
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ag_header_bar_selection_cancel_cb(GtkButton *button,
|
||||||
|
AgHeaderBar *header_bar)
|
||||||
|
{
|
||||||
|
GET_PRIV(priv, header_bar);
|
||||||
|
|
||||||
|
/* If we are not in selection mode, this transition is invalid */
|
||||||
|
if (priv->mode != AG_HEADER_BAR_MODE_SELECTION) {
|
||||||
|
g_warning("Invalid header bar mode transition!");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_signal_emit(
|
||||||
|
header_bar,
|
||||||
|
signals[SIGNAL_MODE_CHANGED], 0,
|
||||||
|
AG_HEADER_BAR_MODE_LIST
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ag_header_bar_back_cb(GtkButton *button,
|
||||||
|
AgHeaderBar *header_bar)
|
||||||
|
{
|
||||||
|
GET_PRIV(priv, header_bar);
|
||||||
|
|
||||||
|
/* If we are not in chart mode, this transition is invalid */
|
||||||
|
if (priv->mode != AG_HEADER_BAR_MODE_CHART) {
|
||||||
|
g_warning("Invalid header bar mode transition!");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_signal_emit(
|
||||||
|
header_bar,
|
||||||
|
signals[SIGNAL_MODE_CHANGED], 0,
|
||||||
|
AG_HEADER_BAR_MODE_LIST
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -56,6 +98,10 @@ ag_header_bar_set_selection_mode(AgHeaderBar *header_bar, gboolean state)
|
|||||||
GtkStyleContext *style;
|
GtkStyleContext *style;
|
||||||
GET_PRIV(priv, header_bar);
|
GET_PRIV(priv, header_bar);
|
||||||
|
|
||||||
|
if (state == (priv->mode == AG_HEADER_BAR_MODE_SELECTION)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
style = gtk_widget_get_style_context(GTK_WIDGET(header_bar));
|
style = gtk_widget_get_style_context(GTK_WIDGET(header_bar));
|
||||||
|
|
||||||
if (state) {
|
if (state) {
|
||||||
@ -83,13 +129,15 @@ ag_header_bar_set_mode_internal(AgHeaderBar *header_bar,
|
|||||||
AgHeaderBarMode mode,
|
AgHeaderBarMode mode,
|
||||||
gboolean force)
|
gboolean force)
|
||||||
{
|
{
|
||||||
|
gboolean invalid = FALSE;
|
||||||
|
AgHeaderBarMode old_mode;
|
||||||
GET_PRIV(priv, header_bar);
|
GET_PRIV(priv, header_bar);
|
||||||
|
|
||||||
if (!force && (priv->mode == mode)) {
|
if (!force && (priv->mode == mode)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->mode = mode;
|
old_mode = priv->mode;
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case AG_HEADER_BAR_MODE_LIST:
|
case AG_HEADER_BAR_MODE_LIST:
|
||||||
@ -124,12 +172,18 @@ ag_header_bar_set_mode_internal(AgHeaderBar *header_bar,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
invalid = TRUE;
|
||||||
g_warning("Invalid header bar mode!");
|
g_warning("Invalid header bar mode!");
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_object_notify_by_pspec(G_OBJECT(header_bar), properties[PROP_MODE]);
|
if (invalid) {
|
||||||
|
priv->mode = old_mode;
|
||||||
|
} else {
|
||||||
|
priv->mode = mode;
|
||||||
|
g_object_notify_by_pspec(G_OBJECT(header_bar), properties[PROP_MODE]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -229,6 +283,18 @@ ag_header_bar_class_init(AgHeaderBarClass *klass)
|
|||||||
properties[PROP_MODE]
|
properties[PROP_MODE]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
signals[SIGNAL_MODE_CHANGED] = g_signal_new(
|
||||||
|
"mode-changed",
|
||||||
|
AG_TYPE_HEADER_BAR,
|
||||||
|
G_SIGNAL_RUN_FIRST,
|
||||||
|
0,
|
||||||
|
NULL, NULL,
|
||||||
|
NULL,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
1,
|
||||||
|
AG_TYPE_HEADER_BAR_MODE
|
||||||
|
);
|
||||||
|
|
||||||
gtk_widget_class_set_template_from_resource(
|
gtk_widget_class_set_template_from_resource(
|
||||||
widget_class,
|
widget_class,
|
||||||
"/eu/polonkai/gergely/Astrognome/ui/ag-header-bar.ui"
|
"/eu/polonkai/gergely/Astrognome/ui/ag-header-bar.ui"
|
||||||
@ -254,6 +320,14 @@ ag_header_bar_class_init(AgHeaderBarClass *klass)
|
|||||||
widget_class,
|
widget_class,
|
||||||
ag_header_bar_selection_mode_cb
|
ag_header_bar_selection_mode_cb
|
||||||
);
|
);
|
||||||
|
gtk_widget_class_bind_template_callback(
|
||||||
|
widget_class,
|
||||||
|
ag_header_bar_selection_cancel_cb
|
||||||
|
);
|
||||||
|
gtk_widget_class_bind_template_callback(
|
||||||
|
widget_class,
|
||||||
|
ag_header_bar_back_cb
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -36,25 +36,27 @@ ag_icon_view_set_mode(AgIconView *icon_view, AgIconViewMode mode)
|
|||||||
{
|
{
|
||||||
AgIconViewPrivate *priv = ag_icon_view_get_instance_private(icon_view);
|
AgIconViewPrivate *priv = ag_icon_view_get_instance_private(icon_view);
|
||||||
|
|
||||||
if (priv->mode != mode) {
|
if (priv->mode == mode) {
|
||||||
priv->mode = mode;
|
return;
|
||||||
|
|
||||||
if (mode != AG_ICON_VIEW_MODE_SELECTION) {
|
|
||||||
ag_icon_view_unselect_all(icon_view);
|
|
||||||
}
|
|
||||||
|
|
||||||
ag_chart_renderer_set_toggle_visible(
|
|
||||||
priv->thumb_renderer,
|
|
||||||
(mode == AG_ICON_VIEW_MODE_SELECTION)
|
|
||||||
);
|
|
||||||
|
|
||||||
gtk_widget_queue_draw(GTK_WIDGET(icon_view));
|
|
||||||
|
|
||||||
g_object_notify_by_pspec(
|
|
||||||
G_OBJECT(icon_view),
|
|
||||||
properties[PROP_MODE]
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
priv->mode = mode;
|
||||||
|
|
||||||
|
if (mode != AG_ICON_VIEW_MODE_SELECTION) {
|
||||||
|
ag_icon_view_unselect_all(icon_view);
|
||||||
|
}
|
||||||
|
|
||||||
|
ag_chart_renderer_set_toggle_visible(
|
||||||
|
priv->thumb_renderer,
|
||||||
|
(mode == AG_ICON_VIEW_MODE_SELECTION)
|
||||||
|
);
|
||||||
|
|
||||||
|
gtk_widget_queue_draw(GTK_WIDGET(icon_view));
|
||||||
|
|
||||||
|
g_object_notify_by_pspec(
|
||||||
|
G_OBJECT(icon_view),
|
||||||
|
properties[PROP_MODE]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
AgIconViewMode
|
AgIconViewMode
|
||||||
|
107
src/ag-window.c
107
src/ag-window.c
@ -1299,20 +1299,19 @@ ag_window_set_theme(AgWindow *window, AgDisplayTheme *theme)
|
|||||||
static void
|
static void
|
||||||
ag_window_tab_changed_cb(GtkStack *tabs, GParamSpec *pspec, AgWindow *window)
|
ag_window_tab_changed_cb(GtkStack *tabs, GParamSpec *pspec, AgWindow *window)
|
||||||
{
|
{
|
||||||
GtkWidget *active_tab;
|
|
||||||
const gchar *active_tab_name = gtk_stack_get_visible_child_name(tabs);
|
|
||||||
GET_PRIV(window);
|
GET_PRIV(window);
|
||||||
|
GtkWidget *old_tab = priv->current_tab;
|
||||||
|
GtkWidget *new_tab = gtk_stack_get_visible_child(tabs);
|
||||||
|
const gchar *active_tab_name = gtk_stack_get_visible_child_name(tabs);
|
||||||
|
|
||||||
g_debug("Active tab changed: %s", active_tab_name);
|
if (old_tab == new_tab) {
|
||||||
|
|
||||||
if (active_tab_name == NULL) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
active_tab = gtk_stack_get_visible_child(tabs);
|
g_debug("Active tab changed: %s", active_tab_name);
|
||||||
|
|
||||||
if (strcmp("chart", active_tab_name) == 0) {
|
if (strcmp("chart", active_tab_name) == 0) {
|
||||||
gtk_widget_set_size_request(active_tab, 600, 600);
|
gtk_widget_set_size_request(new_tab, 600, 600);
|
||||||
if (priv->theme == NULL) {
|
if (priv->theme == NULL) {
|
||||||
AgSettings *settings;
|
AgSettings *settings;
|
||||||
GSettings *main_settings;
|
GSettings *main_settings;
|
||||||
@ -1335,6 +1334,8 @@ ag_window_tab_changed_cb(GtkStack *tabs, GParamSpec *pspec, AgWindow *window)
|
|||||||
if (strcmp("list", active_tab_name) == 0) {
|
if (strcmp("list", active_tab_name) == 0) {
|
||||||
ag_header_bar_set_mode(priv->header_bar, AG_HEADER_BAR_MODE_LIST);
|
ag_header_bar_set_mode(priv->header_bar, AG_HEADER_BAR_MODE_LIST);
|
||||||
} else {
|
} else {
|
||||||
|
g_debug("Switching header bar to chart mode");
|
||||||
|
|
||||||
ag_header_bar_set_mode(priv->header_bar, AG_HEADER_BAR_MODE_CHART);
|
ag_header_bar_set_mode(priv->header_bar, AG_HEADER_BAR_MODE_CHART);
|
||||||
|
|
||||||
// Note that priv->current_tab is actually the previously selected tab,
|
// Note that priv->current_tab is actually the previously selected tab,
|
||||||
@ -1345,7 +1346,7 @@ ag_window_tab_changed_cb(GtkStack *tabs, GParamSpec *pspec, AgWindow *window)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->current_tab = active_tab;
|
priv->current_tab = new_tab;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1492,46 +1493,29 @@ ag_window_refresh_action(GSimpleAction *action,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ag_window_set_selection_mode(AgWindow *window, gboolean state)
|
ag_window_header_bar_mode_change_cb(AgHeaderBar *header_bar,
|
||||||
|
AgHeaderBarMode mode,
|
||||||
|
AgWindow *window)
|
||||||
{
|
{
|
||||||
GET_PRIV(window);
|
GET_PRIV(window);
|
||||||
|
|
||||||
if (priv->current_tab != priv->tab_list) {
|
switch (mode) {
|
||||||
g_warning("You can activate selection mode only in the list view!");
|
case AG_HEADER_BAR_MODE_LIST:
|
||||||
|
ag_window_change_tab(window, "list");
|
||||||
|
ag_header_bar_set_mode(header_bar, mode);
|
||||||
|
ag_icon_view_set_mode(priv->chart_list, AG_ICON_VIEW_MODE_NORMAL);
|
||||||
|
|
||||||
return;
|
break;
|
||||||
|
|
||||||
|
case AG_HEADER_BAR_MODE_SELECTION:
|
||||||
|
ag_header_bar_set_mode(header_bar, mode);
|
||||||
|
ag_icon_view_set_mode(priv->chart_list, AG_ICON_VIEW_MODE_SELECTION);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_debug("Set selection mode: %d", state);
|
|
||||||
|
|
||||||
if (state) {
|
|
||||||
ag_header_bar_set_mode(priv->header_bar, AG_HEADER_BAR_MODE_SELECTION);
|
|
||||||
ag_icon_view_set_mode(
|
|
||||||
priv->chart_list,
|
|
||||||
AG_ICON_VIEW_MODE_SELECTION
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
ag_header_bar_set_mode(priv->header_bar, AG_HEADER_BAR_MODE_LIST);
|
|
||||||
ag_icon_view_set_mode(
|
|
||||||
priv->chart_list,
|
|
||||||
AG_ICON_VIEW_MODE_NORMAL
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
ag_window_header_bar_mode_change_cb(AgHeaderBar *header_bar,
|
|
||||||
GParamSpec *pspec,
|
|
||||||
AgWindow *window)
|
|
||||||
{
|
|
||||||
AgHeaderBarMode mode;
|
|
||||||
|
|
||||||
mode = ag_header_bar_get_mode(header_bar);
|
|
||||||
|
|
||||||
ag_window_set_selection_mode(
|
|
||||||
window,
|
|
||||||
(mode == AG_HEADER_BAR_MODE_SELECTION)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1543,29 +1527,21 @@ ag_window_icon_view_mode_cb(AgIconView *icon_view,
|
|||||||
GVariant *state_var = g_variant_new_boolean(
|
GVariant *state_var = g_variant_new_boolean(
|
||||||
(mode == AG_ICON_VIEW_MODE_SELECTION)
|
(mode == AG_ICON_VIEW_MODE_SELECTION)
|
||||||
);
|
);
|
||||||
|
GET_PRIV(window);
|
||||||
|
|
||||||
|
g_debug("IV mode change: %d", (mode == AG_ICON_VIEW_MODE_SELECTION));
|
||||||
|
|
||||||
g_action_group_activate_action(
|
g_action_group_activate_action(
|
||||||
G_ACTION_GROUP(window),
|
G_ACTION_GROUP(window),
|
||||||
"selection",
|
"selection",
|
||||||
state_var
|
state_var
|
||||||
);
|
);
|
||||||
}
|
ag_header_bar_set_mode(
|
||||||
|
priv->header_bar,
|
||||||
static void
|
(mode == AG_ICON_VIEW_MODE_SELECTION)
|
||||||
ag_window_selection_mode_action(GSimpleAction *action,
|
? AG_HEADER_BAR_MODE_SELECTION
|
||||||
GVariant *parameter,
|
: AG_HEADER_BAR_MODE_LIST
|
||||||
gpointer user_data)
|
);
|
||||||
{
|
|
||||||
GVariant *state;
|
|
||||||
gboolean new_state;
|
|
||||||
AgWindow *window = AG_WINDOW(user_data);
|
|
||||||
|
|
||||||
state = g_action_get_state(G_ACTION(action));
|
|
||||||
new_state = !g_variant_get_boolean(state);
|
|
||||||
g_action_change_state(G_ACTION(action), g_variant_new_boolean(new_state));
|
|
||||||
g_variant_unref(state);
|
|
||||||
|
|
||||||
ag_window_set_selection_mode(window, new_state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1680,7 +1656,6 @@ static GActionEntry win_entries[] = {
|
|||||||
{ "new-chart", ag_window_new_chart_action, NULL, NULL, NULL },
|
{ "new-chart", ag_window_new_chart_action, NULL, NULL, NULL },
|
||||||
{ "back", ag_window_back_action, NULL, NULL, NULL },
|
{ "back", ag_window_back_action, NULL, NULL, NULL },
|
||||||
{ "refresh", ag_window_refresh_action, NULL, NULL, NULL },
|
{ "refresh", ag_window_refresh_action, NULL, NULL, NULL },
|
||||||
{ "selection", ag_window_selection_mode_action, "b", "false", NULL },
|
|
||||||
{ "delete", ag_window_delete_action, NULL, NULL, NULL },
|
{ "delete", ag_window_delete_action, NULL, NULL, NULL },
|
||||||
{ "connection", ag_window_connection_action, "s", "'aspects'", NULL },
|
{ "connection", ag_window_connection_action, "s", "'aspects'", NULL },
|
||||||
};
|
};
|
||||||
@ -2012,12 +1987,6 @@ ag_window_destroy(GtkWidget *widget)
|
|||||||
GTK_WIDGET_CLASS(ag_window_parent_class)->destroy(widget);
|
GTK_WIDGET_CLASS(ag_window_parent_class)->destroy(widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
ag_window_selection_mode_cancel_cb(GtkButton *button, AgWindow *window)
|
|
||||||
{
|
|
||||||
ag_window_set_selection_mode(window, FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ag_window_set_property(GObject *gobject,
|
ag_window_set_property(GObject *gobject,
|
||||||
guint prop_id,
|
guint prop_id,
|
||||||
@ -2207,10 +2176,6 @@ ag_window_class_init(AgWindowClass *klass)
|
|||||||
widget_class,
|
widget_class,
|
||||||
ag_window_icon_view_mode_cb
|
ag_window_icon_view_mode_cb
|
||||||
);
|
);
|
||||||
gtk_widget_class_bind_template_callback(
|
|
||||||
widget_class,
|
|
||||||
ag_window_selection_mode_cancel_cb
|
|
||||||
);
|
|
||||||
gtk_widget_class_bind_template_callback(
|
gtk_widget_class_bind_template_callback(
|
||||||
widget_class,
|
widget_class,
|
||||||
ag_window_house_system_changed_cb
|
ag_window_house_system_changed_cb
|
||||||
|
@ -55,6 +55,7 @@
|
|||||||
<object class="GtkButton" id="back_button">
|
<object class="GtkButton" id="back_button">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="action_name">win.back</property>
|
<property name="action_name">win.back</property>
|
||||||
|
<signal name="clicked" handler="ag_header_bar_back_cb" swapped="no" object="AgHeaderBar"/>
|
||||||
<style>
|
<style>
|
||||||
<class name="image-button"/>
|
<class name="image-button"/>
|
||||||
</style>
|
</style>
|
||||||
@ -99,7 +100,7 @@
|
|||||||
<object class="GtkButton" id="selection_cancel_button">
|
<object class="GtkButton" id="selection_cancel_button">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="label" translatable="yes">Cancel</property>
|
<property name="label" translatable="yes">Cancel</property>
|
||||||
<signal name="clicked" handler="ag_header_bar_selection_mode_cb" object="AgHeaderBar" swapped="no"/>
|
<signal name="clicked" handler="ag_header_bar_selection_cancel_cb" object="AgHeaderBar" swapped="no"/>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="name">selection</property>
|
<property name="name">selection</property>
|
||||||
|
@ -83,7 +83,7 @@
|
|||||||
<signal name="delete-event" handler="ag_window_delete_event_callback" swapped="no"/>
|
<signal name="delete-event" handler="ag_window_delete_event_callback" swapped="no"/>
|
||||||
<child type="titlebar">
|
<child type="titlebar">
|
||||||
<object class="AgHeaderBar" id="header_bar">
|
<object class="AgHeaderBar" id="header_bar">
|
||||||
<signal name="notify::mode" handler="ag_window_header_bar_mode_change_cb" swapped="no"/>
|
<signal name="mode-changed" handler="ag_window_header_bar_mode_change_cb" swapped="no"/>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
|
Loading…
Reference in New Issue
Block a user