commit caac18bd08717c140ca6189f5616e40867c57f98
parent b24c64652b121643b0ed12c91e0869f0b0bd9865
Author: Jacki <jacki@thejackimonster.de>
Date: Sat, 21 Sep 2024 03:22:21 +0200
Add list of tags to contact info
Signed-off-by: Jacki <jacki@thejackimonster.de>
Diffstat:
3 files changed, 401 insertions(+), 5 deletions(-)
diff --git a/resources/ui/contact_info.ui b/resources/ui/contact_info.ui
@@ -46,6 +46,12 @@ Author: Tobias Frisch
<column type="gboolean"/>
</columns>
</object>
+ <object class="GtkListStore" id="tags_list">
+ <columns>
+ <!-- column-name name -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
<object class="GtkDialog" id="contact_info_dialog">
<property name="can-focus">False</property>
<property name="title" translatable="yes">Contact Information</property>
@@ -338,6 +344,50 @@ Author: Tobias Frisch
</packing>
</child>
<child>
+ <object class="GtkButton" id="list_tags_button">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="spacing">4</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="icon-name">user-bookmarks-symbolic</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-end">16</property>
+ <property name="label" translatable="yes">List Tags</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">7</property>
+ </packing>
+ </child>
+ <child>
<object class="GtkStack" id="block_stack">
<property name="visible">True</property>
<property name="can-focus">False</property>
@@ -434,7 +484,7 @@ Author: Tobias Frisch
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
- <property name="position">7</property>
+ <property name="position">8</property>
</packing>
</child>
<child>
@@ -479,7 +529,7 @@ Author: Tobias Frisch
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
- <property name="position">8</property>
+ <property name="position">9</property>
</packing>
</child>
</object>
@@ -807,6 +857,167 @@ Author: Tobias Frisch
<property name="position">3</property>
</packing>
</child>
+ <child>
+ <object class="GtkBox" id="tags_box">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">4</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes">Tags:</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkTreeView" id="tags_tree">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="model">tags_list</property>
+ <property name="headers-visible">False</property>
+ <property name="reorderable">True</property>
+ <property name="search-column">0</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection"/>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn">
+ <property name="resizable">True</property>
+ <property name="spacing">4</property>
+ <property name="min-width">120</property>
+ <property name="title" translatable="yes">Name:</property>
+ <property name="clickable">True</property>
+ <property name="sort-indicator">True</property>
+ <property name="sort-column-id">0</property>
+ <child>
+ <object class="GtkCellRendererText">
+ <property name="ellipsize">end</property>
+ </object>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="new_tag_box">
+ <property name="width-request">250</property>
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="halign">center</property>
+ <property name="margin-top">8</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">4</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes">New Tag:</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="spacing">4</property>
+ <child>
+ <object class="GtkEntry" id="tag_name_entry">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can-focus">True</property>
+ <property name="placeholder-text" translatable="yes">Tag</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="remove_tag_button">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="icon-name">list-remove-symbolic</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack-type">end</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="add_tag_button">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="icon-name">list-add-symbolic</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack-type">end</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack-type">end</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack-type">end</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="name">page0</property>
+ <property name="title" translatable="yes">page0</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
</object>
</child>
</object>
diff --git a/src/ui/contact_info.c b/src/ui/contact_info.c
@@ -254,6 +254,17 @@ handle_share_attributes_button_click(UNUSED GtkButton *button,
}
static void
+handle_list_tags_button_click(UNUSED GtkButton *button,
+ gpointer user_data)
+{
+ g_assert(user_data);
+
+ struct UI_CONTACT_INFO_Handle *handle = (UI_CONTACT_INFO_Handle*) user_data;
+
+ _contact_info_switch_stack_to(handle, handle->tags_box);
+}
+
+static void
handle_block_button_click(UNUSED GtkButton *button,
gpointer user_data)
{
@@ -768,8 +779,8 @@ handle_add_attribute_button_click(UNUSED GtkButton *button,
}
static void
-handle_attribute_value_entry_activate(UNUSED GtkEntry *entry,
- gpointer user_data)
+handle_attribute_entry_activate(UNUSED GtkEntry *entry,
+ gpointer user_data)
{
g_assert(user_data);
@@ -827,6 +838,81 @@ handle_share_renderer_toggle(GtkCellRendererToggle *renderer,
g_value_unset(&value_shared);
}
+static void
+handle_tag_entry_changed(GtkEditable *editable,
+ gpointer user_data)
+{
+ g_assert((editable) && (user_data));
+
+ GtkEntry *entry = GTK_ENTRY(editable);
+ GtkWidget *target = GTK_WIDGET(user_data);
+
+ const gchar *text = gtk_entry_get_text(entry);
+
+ gtk_widget_set_sensitive(target, (text) && (strlen(text)));
+}
+
+static void
+handle_add_tag_button_click(UNUSED GtkButton *button,
+ gpointer user_data)
+{
+ g_assert(user_data);
+
+ UI_CONTACT_INFO_Handle *handle = (UI_CONTACT_INFO_Handle*) user_data;
+
+ struct GNUNET_CHAT_Handle *chat = handle->app->chat.messenger.handle;
+
+ if (!chat)
+ return;
+
+ const gchar *name = gtk_entry_get_text(handle->tag_name_entry);
+
+ if (name)
+ {
+ application_chat_lock(handle->app);
+ GNUNET_CHAT_contact_tag(handle->contact, name);
+ application_chat_unlock(handle->app);
+
+ gtk_list_store_insert_with_values(
+ handle->tags_list,
+ NULL,
+ -1,
+ 0,
+ name,
+ -1
+ );
+ }
+
+ gtk_entry_set_text(handle->tag_name_entry, "");
+}
+
+static void
+handle_remove_tag_button_click(UNUSED GtkButton *button,
+ gpointer user_data)
+{
+ g_assert(user_data);
+
+ UI_CONTACT_INFO_Handle *handle = (UI_CONTACT_INFO_Handle*) user_data;
+
+ struct GNUNET_CHAT_Handle *chat = handle->app->chat.messenger.handle;
+
+ if (!chat)
+ return;
+
+ // TODO: remove tag from contact
+}
+
+static void
+handle_tag_entry_activate(UNUSED GtkEntry *entry,
+ gpointer user_data)
+{
+ g_assert(user_data);
+
+ UI_CONTACT_INFO_Handle *handle = (UI_CONTACT_INFO_Handle*) user_data;
+
+ handle_add_tag_button_click(handle->add_tag_button, handle);
+}
+
void
ui_contact_info_dialog_init(MESSENGER_Application *app,
UI_CONTACT_INFO_Handle *handle)
@@ -940,6 +1026,17 @@ ui_contact_info_dialog_init(MESSENGER_Application *app,
handle
);
+ handle->list_tags_button = GTK_BUTTON(
+ gtk_builder_get_object(handle->builder, "list_tags_button")
+ );
+
+ g_signal_connect(
+ handle->list_tags_button,
+ "clicked",
+ G_CALLBACK(handle_list_tags_button_click),
+ handle
+ );
+
handle->block_stack = GTK_STACK(
gtk_builder_get_object(handle->builder, "block_stack")
);
@@ -1056,7 +1153,7 @@ ui_contact_info_dialog_init(MESSENGER_Application *app,
g_signal_connect(
handle->attribute_value_entry,
"activate",
- G_CALLBACK(handle_attribute_value_entry_activate),
+ G_CALLBACK(handle_attribute_entry_activate),
handle
);
@@ -1090,6 +1187,62 @@ ui_contact_info_dialog_init(MESSENGER_Application *app,
handle
);
+ handle->tags_box = GTK_WIDGET(
+ gtk_builder_get_object(handle->builder, "tags_box")
+ );
+
+ handle->tags_tree = GTK_TREE_VIEW(
+ gtk_builder_get_object(handle->builder, "tags_tree")
+ );
+
+ handle->tags_list = GTK_LIST_STORE(
+ gtk_builder_get_object(handle->builder, "tags_list")
+ );
+
+ handle->new_tag_box = GTK_WIDGET(
+ gtk_builder_get_object(handle->builder, "new_tag_box")
+ );
+
+ handle->tag_name_entry = GTK_ENTRY(
+ gtk_builder_get_object(handle->builder, "tag_name_entry")
+ );
+
+ handle->add_tag_button = GTK_BUTTON(
+ gtk_builder_get_object(handle->builder, "add_tag_button")
+ );
+
+ handle->remove_tag_button = GTK_BUTTON(
+ gtk_builder_get_object(handle->builder, "remove_tag_button")
+ );
+
+ g_signal_connect(
+ handle->tag_name_entry,
+ "changed",
+ G_CALLBACK(handle_tag_entry_changed),
+ handle->add_tag_button
+ );
+
+ g_signal_connect(
+ handle->tag_name_entry,
+ "activate",
+ G_CALLBACK(handle_tag_entry_activate),
+ handle
+ );
+
+ g_signal_connect(
+ handle->add_tag_button,
+ "clicked",
+ G_CALLBACK(handle_add_tag_button_click),
+ handle
+ );
+
+ g_signal_connect(
+ handle->remove_tag_button,
+ "clicked",
+ G_CALLBACK(handle_remove_tag_button_click),
+ handle
+ );
+
handle->back_button = GTK_BUTTON(
gtk_builder_get_object(handle->builder, "back_button")
);
@@ -1240,6 +1393,16 @@ ui_contact_info_dialog_update(UI_CONTACT_INFO_Handle *handle,
);
gtk_widget_set_sensitive(
+ GTK_WIDGET(handle->list_tags_button),
+ !editable
+ );
+
+ gtk_widget_set_sensitive(
+ GTK_WIDGET(handle->tag_name_entry),
+ !editable
+ );
+
+ gtk_widget_set_sensitive(
GTK_WIDGET(handle->block_button),
!editable
);
@@ -1259,6 +1422,16 @@ ui_contact_info_dialog_update(UI_CONTACT_INFO_Handle *handle,
!editable
);
+ gtk_widget_set_visible(
+ GTK_WIDGET(handle->list_tags_button),
+ !editable
+ );
+
+ gtk_widget_set_visible(
+ GTK_WIDGET(handle->new_tag_box),
+ !editable
+ );
+
gtk_stack_set_visible_child(
handle->block_stack,
GNUNET_YES == GNUNET_CHAT_contact_is_blocked(contact)?
@@ -1273,6 +1446,7 @@ ui_contact_info_dialog_update(UI_CONTACT_INFO_Handle *handle,
gtk_list_store_clear(handle->attributes_list);
gtk_list_store_clear(handle->sharing_list);
+ gtk_list_store_clear(handle->tags_list);
if (editable)
GNUNET_CHAT_get_attributes(
@@ -1300,6 +1474,8 @@ ui_contact_info_dialog_update(UI_CONTACT_INFO_Handle *handle,
cb_contact_info_shared_attributes,
handle
);
+
+ // TODO: iterate contact tags
}
struct GNUNET_CHAT_Context *context = GNUNET_CHAT_contact_get_context(
diff --git a/src/ui/contact_info.h b/src/ui/contact_info.h
@@ -55,6 +55,7 @@ typedef struct UI_CONTACT_INFO_Handle
GtkButton *reveal_identity_button;
GtkButton *list_attributes_button;
GtkButton *share_attributes_button;
+ GtkButton *list_tags_button;
GtkStack *block_stack;
GtkButton *block_button;
GtkButton *unblock_button;
@@ -81,6 +82,14 @@ typedef struct UI_CONTACT_INFO_Handle
GtkListStore *sharing_list;
GtkCellRendererToggle *share_renderer;
+ GtkWidget *tags_box;
+ GtkTreeView *tags_tree;
+ GtkListStore *tags_list;
+ GtkWidget *new_tag_box;
+ GtkEntry *tag_name_entry;
+ GtkButton *add_tag_button;
+ GtkButton *remove_tag_button;
+
GtkButton *back_button;
GtkButton *close_button;