From 1b3387031891a18041a8e89dac67eca1b0f9fb09 Mon Sep 17 00:00:00 2001 From: Mohammed Sadiq Date: Wed, 5 Jan 2022 18:30:33 +0530 Subject: [PATCH 1/8] new-chat-dialog: Use a single variable for account We have been using ChattyAccount in every block within the function. So let's declare it once at the top of function --- src/dialogs/chatty-new-chat-dialog.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/dialogs/chatty-new-chat-dialog.c b/src/dialogs/chatty-new-chat-dialog.c index c0dd950e..ca8cfb18 100644 --- a/src/dialogs/chatty-new-chat-dialog.c +++ b/src/dialogs/chatty-new-chat-dialog.c @@ -133,13 +133,14 @@ static gboolean dialog_filter_item_cb (ChattyItem *item, ChattyNewChatDialog *self) { + ChattyAccount *account; + g_return_val_if_fail (CHATTY_IS_NEW_CHAT_DIALOG (self), FALSE); if (self->multi_selection) { - ChattyAccount *mm_account; - mm_account = chatty_manager_get_mm_account (self->manager); - if (chatty_account_get_status (mm_account) == CHATTY_CONNECTED) { + account = chatty_manager_get_mm_account (self->manager); + if (chatty_account_get_status (account) == CHATTY_CONNECTED) { if (chatty_item_matches (item, self->search_str, CHATTY_PROTOCOL_MMS_SMS, TRUE) && !new_chat_dialog_contact_is_selected (CHATTY_CONTACT (item))) return TRUE; @@ -151,8 +152,6 @@ dialog_filter_item_cb (ChattyItem *item, #ifdef PURPLE_ENABLED if (CHATTY_IS_PP_BUDDY (item)) { - ChattyAccount *account; - account = chatty_pp_buddy_get_account (CHATTY_PP_BUDDY (item)); if (chatty_account_get_status (account) != CHATTY_CONNECTED) @@ -161,8 +160,6 @@ dialog_filter_item_cb (ChattyItem *item, #endif if (CHATTY_IS_CHAT (item)) { - ChattyAccount *account; - #ifdef PURPLE_ENABLED /* Hide chat if it's buddy chat as the buddy is shown separately */ if (CHATTY_IS_PP_CHAT (item) && -- GitLab From 611bc3f25a8964361bfc9ac72edb92bb087eb7de Mon Sep 17 00:00:00 2001 From: Mohammed Sadiq Date: Fri, 7 Jan 2022 17:50:44 +0530 Subject: [PATCH 2/8] contact: Add API to create dummy contact --- src/users/chatty-contact.c | 14 ++++++++++++++ src/users/chatty-contact.h | 2 ++ 2 files changed, 16 insertions(+) diff --git a/src/users/chatty-contact.c b/src/users/chatty-contact.c index 8b5d3209..da178b16 100644 --- a/src/users/chatty-contact.c +++ b/src/users/chatty-contact.c @@ -269,6 +269,20 @@ chatty_contact_new (EContact *contact, return self; } +ChattyContact * +chatty_contact_dummy_new (const char *name, + const char *value) +{ + ChattyContact *self; + + self = g_object_new (CHATTY_TYPE_CONTACT, NULL); + self->name = g_strdup (name); + self->value = g_strdup (value); + g_object_set_data (G_OBJECT (self), "dummy", GINT_TO_POINTER (TRUE)); + + return self; +} + void chatty_contact_set_name (ChattyContact *self, const char *name) diff --git a/src/users/chatty-contact.h b/src/users/chatty-contact.h index 3d3962c6..99ef0ee8 100644 --- a/src/users/chatty-contact.h +++ b/src/users/chatty-contact.h @@ -26,6 +26,8 @@ G_DECLARE_FINAL_TYPE (ChattyContact, chatty_contact, CHATTY, CONTACT, ChattyItem ChattyContact *chatty_contact_new (EContact *contact, EVCardAttribute *attr, ChattyProtocol protocol); +ChattyContact *chatty_contact_dummy_new (const char *name, + const char *value); void chatty_contact_set_name (ChattyContact *self, const char *name); void chatty_contact_set_value (ChattyContact *self, -- GitLab From 1bb0c92e00916e45c1c5965681c9b030a0e2be50 Mon Sep 17 00:00:00 2001 From: Mohammed Sadiq Date: Fri, 7 Jan 2022 17:52:45 +0530 Subject: [PATCH 3/8] Add chatty-contact-list This has been modified and ripped off from new-chat-dialog. As per the design[0] we shall have to use contact list in more than one place, so let's better move it to a separate class so that it's easier to include it where ever we need. [0] https://gitlab.gnome.org/Teams/Design/app-mockups/raw/d214c06090433c1795ef1b2c861fd3851a44ec58/messages/compose.png --- po/POTFILES.in | 1 + src/chatty-contact-list.c | 509 ++++++++++++++++++++++++++++++++++ src/chatty-contact-list.h | 33 +++ src/chatty.gresource.xml | 1 + src/meson.build | 1 + src/ui/chatty-contact-list.ui | 80 ++++++ 6 files changed, 625 insertions(+) create mode 100644 src/chatty-contact-list.c create mode 100644 src/chatty-contact-list.h create mode 100644 src/ui/chatty-contact-list.ui diff --git a/po/POTFILES.in b/po/POTFILES.in index 08af6977..746b003a 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -9,6 +9,7 @@ src/chatty-chat-list.c src/chatty-chat-view.c src/chatty-chat.c src/chatty-chat.h +src/chatty-contact-list.c src/chatty-contact-provider.c src/chatty-contact-provider.h src/chatty-history.c diff --git a/src/chatty-contact-list.c b/src/chatty-contact-list.c new file mode 100644 index 00000000..a8681435 --- /dev/null +++ b/src/chatty-contact-list.c @@ -0,0 +1,509 @@ +/* + * Copyright (C) 2022 Purism SPC + * + * Authors: + * Mohammed Sadiq + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#define G_LOG_DOMAIN "chatty-contact-list" + +#include "config.h" + +#include +#include "contrib/gtk.h" + +#include "chatty-chat.h" +#include "chatty-purple.h" +#include "chatty-list-row.h" +#include "chatty-manager.h" +#include "chatty-contact-list.h" + +#define ITEMS_COUNT 50 + +struct _ChattyContactList +{ + GtkBox parent_instance; + + GtkWidget *scrolled_window; + GtkWidget *main_stack; + GtkWidget *empty_view; + GtkWidget *contact_list_view; + + GtkWidget *selected_contact_list; + GtkWidget *new_contact_list; + GtkWidget *new_contact_row; + GtkWidget *contact_list; + + ChattyItem *dummy_contact; + GListStore *selection_store; + GtkSliceListModel *slice_model; + GtkFilter *filter; + char *search_str; + + ChattyManager *manager; + + ChattyProtocol active_protocols; + ChattyProtocol filter_protocols; + gboolean can_multi_select; +}; + +G_DEFINE_TYPE (ChattyContactList, chatty_contact_list, GTK_TYPE_BOX) + +enum { + DELETE_ROW, + SELECTION_CHANGED, + N_SIGNALS +}; + +static guint signals[N_SIGNALS]; + +static GtkWidget * +new_chat_contact_row_new (ChattyItem *item, + ChattyContactList *self) +{ + GtkWidget *row; + + row = chatty_list_contact_row_new (item); + chatty_list_row_set_selectable (CHATTY_LIST_ROW (row), self->can_multi_select); + + return row; +} + +static GtkWidget * +new_selected_contact_row_new (ChattyItem *item, + ChattyContactList *self) +{ + GtkWidget *row; + + row = new_chat_contact_row_new (item, self); + chatty_list_row_select (CHATTY_LIST_ROW (row), TRUE); + + if (!gtk_widget_is_visible (self->contact_list)) + chatty_list_row_show_delete_button (CHATTY_LIST_ROW (row)); + + return row; +} + +static gboolean +new_chat_dialog_contact_is_selected (ChattyContact *contact) +{ + g_return_val_if_fail (CHATTY_IS_CONTACT (contact), FALSE); + + return !!g_object_get_data (G_OBJECT (contact), "selected"); +} + +static void +update_new_contact_row (ChattyContactList *self) +{ + const char *dummy_value; + guint end_len, n_items; + gboolean valid = FALSE; + + chatty_contact_set_value (CHATTY_CONTACT (self->dummy_contact), self->search_str); + chatty_list_row_set_item (CHATTY_LIST_ROW (self->new_contact_row), self->dummy_contact); + + if (!self->search_str || !*self->search_str || + !(self->active_protocols & CHATTY_PROTOCOL_MMS_SMS)) { + gtk_widget_hide (self->new_contact_row); + return; + } + + end_len = strspn (self->search_str, "0123456789"); + valid = end_len == strlen (self->search_str); + valid = valid || !!chatty_utils_username_is_valid (self->search_str, CHATTY_PROTOCOL_MMS_SMS); + gtk_widget_set_visible (self->new_contact_row, valid); + + if (!self->can_multi_select) + return; + + dummy_value = chatty_item_get_username (self->dummy_contact); + n_items = g_list_model_get_n_items (G_LIST_MODEL (self->selection_store)); + + /* If new custom contact row match any of the selected contact, hide it */ + for (guint i = 0; i < n_items; i++) { + g_autoptr(ChattyItem) item = NULL; + const char *value; + + item = g_list_model_get_item (G_LIST_MODEL (self->selection_store), i); + value = chatty_item_get_username (item); + + if (g_strcmp0 (value, dummy_value) == 0) { + gtk_widget_hide (self->new_contact_row); + break; + } + } +} + +static gboolean +contact_list_filter_item_cb (ChattyItem *item, + ChattyContactList *self) +{ + ChattyAccount *account; + ChattyProtocol protocols; + + g_return_val_if_fail (CHATTY_IS_CONTACT_LIST (self), FALSE); + + if (self->can_multi_select) { + account = chatty_manager_get_mm_account (self->manager); + + if (chatty_account_get_status (account) == CHATTY_CONNECTED) { + /* Show only non-selected items, selected items are shown elsewhere */ + if (CHATTY_IS_CONTACT (item) && + !new_chat_dialog_contact_is_selected (CHATTY_CONTACT (item)) && + chatty_item_matches (item, self->search_str, CHATTY_PROTOCOL_MMS_SMS, TRUE)) + return TRUE; + } + + return FALSE; + } + +#ifdef PURPLE_ENABLED + if (CHATTY_IS_PP_BUDDY (item)) { + account = chatty_pp_buddy_get_account (CHATTY_PP_BUDDY (item)); + + if (chatty_account_get_status (account) != CHATTY_CONNECTED) + return FALSE; + } +#endif + + if (CHATTY_IS_CHAT (item)) { +#ifdef PURPLE_ENABLED + /* Hide chat if it's buddy chat as the buddy is shown separately */ + if (CHATTY_IS_PP_CHAT (item) && + chatty_pp_chat_get_purple_buddy (CHATTY_PP_CHAT (item))) + return FALSE; +#endif + + account = chatty_chat_get_account (CHATTY_CHAT (item)); + + if (!account || chatty_account_get_status (account) != CHATTY_CONNECTED) + return FALSE; + } + + protocols = self->active_protocols & self->filter_protocols; + + return chatty_item_matches (item, self->search_str, protocols, TRUE); +} + +static void +contact_list_edge_reached_cb (ChattyContactList *self, + GtkPositionType position) +{ + g_assert (CHATTY_IS_CONTACT_LIST (self)); + + if (position != GTK_POS_BOTTOM || + gtk_stack_get_visible_child (GTK_STACK (self->main_stack)) != self->contact_list_view) + return; + + gtk_slice_list_model_set_size (self->slice_model, + gtk_slice_list_model_get_size (self->slice_model) + ITEMS_COUNT); +} + +static void +selected_contact_row_activated_cb (ChattyContactList *self, + ChattyListRow *row, + GtkListBox *list) +{ + ChattyItem *item; + + item = chatty_list_row_get_item (row); + g_object_set_data (G_OBJECT (item), "selected", GINT_TO_POINTER (FALSE)); + + if (chatty_contact_is_dummy (CHATTY_CONTACT (item))) { + /* If the deselected item value matches the search string, show new contact row */ + if (self->search_str && + g_strcmp0 (chatty_item_get_username (item), self->search_str) == 0) + gtk_widget_show (self->new_contact_row); + } else { + guint position; + + /* Emit items-changed so that it will be re-filtered and thus shown as it's no longer selected */ + if (chatty_utils_get_item_position (chatty_manager_get_contact_list (self->manager), item, &position)) + g_list_model_items_changed (chatty_manager_get_contact_list (self->manager), position, 1, 1); + } + + chatty_utils_remove_list_item (self->selection_store, item); + g_signal_emit (self, signals[SELECTION_CHANGED], 0); +} + +static void +contact_list_row_activated_cb (ChattyContactList *self, + ChattyListRow *row, + GtkListBox *list) +{ + ChattyItem *item; + + g_assert (CHATTY_IS_CONTACT_LIST (self)); + g_assert (CHATTY_IS_LIST_ROW (row)); + g_assert (GTK_IS_LIST_BOX (list)); + g_assert (self->selection_store); + + item = chatty_list_row_get_item (row); + if (CHATTY_IS_CONTACT (item) && chatty_contact_is_dummy (CHATTY_CONTACT (item))) { + g_autoptr(ChattyContact) contact = NULL; + + contact = chatty_contact_dummy_new (_("Unknown Contact"), + chatty_item_get_username (item)); + g_list_store_append (self->selection_store, contact); + } else { + g_object_set_data (G_OBJECT (item), "selected", GINT_TO_POINTER (TRUE)); + g_list_store_append (self->selection_store, item); + } + + if (self->can_multi_select) + gtk_widget_hide (GTK_WIDGET (row)); + + g_signal_emit (self, signals[SELECTION_CHANGED], 0); +} + +static void +contact_list_changed_cb (ChattyContactList *self) +{ + HdyStatusPage *page; + gboolean empty; + + g_assert (CHATTY_IS_CONTACT_LIST (self)); + + empty = !gtk_widget_get_visible (self->new_contact_row); + empty = empty && g_list_model_get_n_items (G_LIST_MODEL (self->slice_model)) == 0; + if (self->selection_store) + empty = empty && g_list_model_get_n_items (G_LIST_MODEL (self->selection_store)) == 0; + + if (empty) + gtk_stack_set_visible_child (GTK_STACK (self->main_stack), self->empty_view); + else + gtk_stack_set_visible_child (GTK_STACK (self->main_stack), self->contact_list_view); + + page = HDY_STATUS_PAGE (self->empty_view); + if (self->search_str && *self->search_str) { + hdy_status_page_set_icon_name (page, "system-search-symbolic"); + hdy_status_page_set_title (page, _("No Search Results")); + hdy_status_page_set_description (page, _("Try different search, or type a valid " + "number to create new chat")); + } else { + hdy_status_page_set_icon_name (page, "sm.puri.Chatty-symbolic"); + hdy_status_page_set_title (page, _("No Contacts")); + hdy_status_page_set_description (page, NULL); + } +} + +static void +contact_list_active_protocols_changed_cb (ChattyContactList *self) +{ + ChattyAccount *mm_account; + ChattyProtocol protocol; + gboolean valid; + + g_assert (CHATTY_IS_CONTACT_LIST (self)); + + self->active_protocols = chatty_manager_get_active_protocols (self->manager); + gtk_filter_changed (self->filter, GTK_FILTER_CHANGE_DIFFERENT); + + protocol = CHATTY_PROTOCOL_MMS_SMS; + valid = protocol == chatty_utils_username_is_valid (self->search_str, protocol); + mm_account = chatty_manager_get_mm_account (self->manager); + valid = valid && chatty_account_get_status (mm_account) == CHATTY_CONNECTED; + gtk_widget_set_visible (self->new_contact_row, valid); + contact_list_changed_cb (self); +} + +static void +contact_list_delete_item (ChattyContactList *self, + ChattyListRow *row) +{ + g_assert (CHATTY_IS_CONTACT_LIST (self)); + g_assert (CHATTY_IS_LIST_ROW (row)); + + selected_contact_row_activated_cb (self, row, GTK_LIST_BOX (self->selected_contact_list)); +} + +static void +chatty_contact_list_finalize (GObject *object) +{ + ChattyContactList *self = (ChattyContactList *)object; + + g_clear_object (&self->dummy_contact); + g_clear_object (&self->slice_model); + g_clear_object (&self->selection_store); + g_clear_object (&self->filter); + g_clear_object (&self->manager); + g_free (self->search_str); + + G_OBJECT_CLASS (chatty_contact_list_parent_class)->finalize (object); +} + +static void +chatty_contact_list_class_init (ChattyContactListClass *klass) +{ + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = chatty_contact_list_finalize; + + signals [DELETE_ROW] = + g_signal_new ("delete-row", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, 1, CHATTY_TYPE_LIST_ROW); + + signals [SELECTION_CHANGED] = + g_signal_new ("selection-changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, 0); + + gtk_widget_class_set_template_from_resource (widget_class, + "/sm/puri/Chatty/" + "ui/chatty-contact-list.ui"); + + gtk_widget_class_bind_template_child (widget_class, ChattyContactList, scrolled_window); + gtk_widget_class_bind_template_child (widget_class, ChattyContactList, main_stack); + gtk_widget_class_bind_template_child (widget_class, ChattyContactList, empty_view); + gtk_widget_class_bind_template_child (widget_class, ChattyContactList, contact_list_view); + + gtk_widget_class_bind_template_child (widget_class, ChattyContactList, selected_contact_list); + gtk_widget_class_bind_template_child (widget_class, ChattyContactList, new_contact_list); + gtk_widget_class_bind_template_child (widget_class, ChattyContactList, new_contact_row); + gtk_widget_class_bind_template_child (widget_class, ChattyContactList, contact_list); + + gtk_widget_class_bind_template_callback (widget_class, contact_list_edge_reached_cb); + gtk_widget_class_bind_template_callback (widget_class, selected_contact_row_activated_cb); + gtk_widget_class_bind_template_callback (widget_class, contact_list_row_activated_cb); + gtk_widget_class_bind_template_callback (widget_class, contact_list_changed_cb); +} + +static void +chatty_contact_list_init (ChattyContactList *self) +{ + g_autoptr(GtkFilterListModel) filter_model = NULL; + g_autoptr(GtkSortListModel) sort_model = NULL; + g_autoptr(GtkSorter) sorter = NULL; + + gtk_widget_init_template (GTK_WIDGET (self)); + + self->manager = g_object_ref (chatty_manager_get_default ()); + self->filter_protocols = CHATTY_PROTOCOL_ANY; + + self->dummy_contact = CHATTY_ITEM (chatty_contact_dummy_new (_("Send To"), NULL)); + chatty_list_row_set_item (CHATTY_LIST_ROW (self->new_contact_row), self->dummy_contact); + + sorter = gtk_custom_sorter_new ((GCompareDataFunc)chatty_item_compare, NULL, NULL); + sort_model = gtk_sort_list_model_new (chatty_manager_get_contact_list (self->manager), sorter); + + self->filter = gtk_custom_filter_new ((GtkCustomFilterFunc)contact_list_filter_item_cb, self, NULL); + filter_model = gtk_filter_list_model_new (G_LIST_MODEL (sort_model), self->filter); + + self->slice_model = gtk_slice_list_model_new (G_LIST_MODEL (filter_model), 0, ITEMS_COUNT); + g_signal_connect_object (self->slice_model, "items-changed", + G_CALLBACK (contact_list_changed_cb), self, + G_CONNECT_SWAPPED); + gtk_list_box_bind_model (GTK_LIST_BOX (self->contact_list), + G_LIST_MODEL (self->slice_model), + (GtkListBoxCreateWidgetFunc)new_chat_contact_row_new, + g_object_ref (self), g_object_unref); + g_signal_connect_object (self->manager, "notify::active-protocols", + G_CALLBACK (contact_list_active_protocols_changed_cb), self, G_CONNECT_SWAPPED); + g_signal_connect_object (self, "delete-row", + G_CALLBACK (contact_list_delete_item), + self, G_CONNECT_AFTER); + contact_list_active_protocols_changed_cb (self); + contact_list_changed_cb (self); +} + +GtkWidget * +chatty_contact_list_new (void) +{ + return g_object_new (CHATTY_TYPE_CONTACT_LIST, NULL); +} + +void +chatty_contact_list_set_selection_store (ChattyContactList *self, + GListStore *list_store) +{ + g_return_if_fail (CHATTY_IS_CONTACT_LIST (self)); + g_return_if_fail (G_IS_LIST_STORE (list_store)); + g_return_if_fail (g_list_model_get_item_type (G_LIST_MODEL (list_store)) == CHATTY_TYPE_ITEM); + + g_set_object (&self->selection_store, list_store); + + gtk_list_box_bind_model (GTK_LIST_BOX (self->selected_contact_list), + (gpointer) list_store, + (GtkListBoxCreateWidgetFunc)new_selected_contact_row_new, + g_object_ref (self), g_object_unref); + g_signal_connect_object (list_store, "items-changed", + G_CALLBACK (contact_list_changed_cb), self, + G_CONNECT_SWAPPED); +} + +void +chatty_contact_list_show_selected_only (ChattyContactList *self) +{ + g_return_if_fail (CHATTY_IS_CONTACT_LIST (self)); + + gtk_stack_set_visible_child (GTK_STACK (self->main_stack), self->contact_list_view); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (self->scrolled_window), + GTK_POLICY_NEVER, GTK_POLICY_NEVER); + gtk_widget_hide (self->new_contact_row); + gtk_widget_hide (self->contact_list); +} + +static void +contact_list_update_selectable (GtkWidget *widget, + gpointer callback_data) +{ + ChattyContactList *self = callback_data; + + g_assert (CHATTY_IS_CONTACT_LIST (self)); + + chatty_list_row_set_selectable ((ChattyListRow *)widget, self->can_multi_select); +} + +void +chatty_contact_list_can_multi_select (ChattyContactList *self, + gboolean can_multi_select) +{ + GListModel *model; + guint n_items; + + g_return_if_fail (CHATTY_IS_CONTACT_LIST (self)); + g_return_if_fail (self->selection_store); + + self->can_multi_select = !!can_multi_select; + + gtk_widget_set_visible (self->selected_contact_list, can_multi_select); + chatty_list_row_set_selectable (CHATTY_LIST_ROW (self->new_contact_row), can_multi_select); + gtk_container_foreach (GTK_CONTAINER (self->contact_list), + (GtkCallback)contact_list_update_selectable, self); + + model = G_LIST_MODEL (self->selection_store); + n_items = g_list_model_get_n_items (model); + + for (guint i = 0; i < n_items; i++) { + g_autoptr(GObject) item = NULL; + + item = g_list_model_get_item (model, i); + g_object_set_data (item, "selected", GINT_TO_POINTER (FALSE)); + } + + g_list_store_remove_all (self->selection_store); +} + +void +chatty_contact_list_set_filter (ChattyContactList *self, + ChattyProtocol protocol, + const char *needle) +{ + g_return_if_fail (CHATTY_IS_CONTACT_LIST (self)); + + self->filter_protocols = protocol; + g_free (self->search_str); + self->search_str = g_utf8_casefold (needle, -1); + + update_new_contact_row (self); + gtk_slice_list_model_set_size (self->slice_model, ITEMS_COUNT); + gtk_filter_changed (self->filter, GTK_FILTER_CHANGE_DIFFERENT); +} diff --git a/src/chatty-contact-list.h b/src/chatty-contact-list.h new file mode 100644 index 00000000..7d329c05 --- /dev/null +++ b/src/chatty-contact-list.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2022 Purism SPC + * + * Authors: + * Mohammed Sadiq + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#pragma once + +#include + +#include "chatty-enums.h" + +G_BEGIN_DECLS + +#define CHATTY_TYPE_CONTACT_LIST (chatty_contact_list_get_type ()) + +G_DECLARE_FINAL_TYPE (ChattyContactList, chatty_contact_list, CHATTY, CONTACT_LIST, GtkBox) + +GtkWidget *chatty_contact_list_new (void); +void chatty_contact_list_set_selection_store (ChattyContactList *self, + GListStore *list_store); +void chatty_contct_list_show_selected_only (ChattyContactList *self, + gboolean show_selected_only); +void chatty_contact_list_can_multi_select (ChattyContactList *self, + gboolean can_multi_select); +void chatty_contact_list_set_filter (ChattyContactList *self, + ChattyProtocol protocol, + const char *needle); + +G_END_DECLS diff --git a/src/chatty.gresource.xml b/src/chatty.gresource.xml index 1bf8b36b..b9f8a8db 100644 --- a/src/chatty.gresource.xml +++ b/src/chatty.gresource.xml @@ -8,6 +8,7 @@ ui/chatty-list-row.ui ui/chatty-chat-list.ui ui/chatty-chat-view.ui + ui/chatty-contact-list.ui ui/chatty-contact-row.ui ui/chatty-file-item.ui ui/chatty-image-item.ui diff --git a/src/meson.build b/src/meson.build index 4a91ccea..51a19e01 100644 --- a/src/meson.build +++ b/src/meson.build @@ -88,6 +88,7 @@ chatty_sources += [ 'chatty-manager.c', 'chatty-application.c', 'chatty-chat-list.c', + 'chatty-contact-list.c', 'chatty-window.c', 'dialogs/chatty-info-dialog.c', 'dialogs/chatty-settings-dialog.c', diff --git a/src/ui/chatty-contact-list.ui b/src/ui/chatty-contact-list.ui new file mode 100644 index 00000000..dcb0d727 --- /dev/null +++ b/src/ui/chatty-contact-list.ui @@ -0,0 +1,80 @@ + + + + -- GitLab From 1daa6f3511b1fea67e151c09023015c88c355fc6 Mon Sep 17 00:00:00 2001 From: Mohammed Sadiq Date: Fri, 7 Jan 2022 17:53:37 +0530 Subject: [PATCH 4/8] new-chat-dialog: Use the new contact-list to list contacts --- src/dialogs/chatty-new-chat-dialog.c | 473 +++------------------------ src/ui/chatty-dialog-new-chat.ui | 74 +---- 2 files changed, 47 insertions(+), 500 deletions(-) diff --git a/src/dialogs/chatty-new-chat-dialog.c b/src/dialogs/chatty-new-chat-dialog.c index ca8cfb18..3cdd7068 100644 --- a/src/dialogs/chatty-new-chat-dialog.c +++ b/src/dialogs/chatty-new-chat-dialog.c @@ -20,10 +20,9 @@ #include "chatty-manager.h" #include "chatty-chat.h" #include "chatty-purple.h" -#include "chatty-contact.h" +#include "chatty-contact-list.h" #include "chatty-mm-account.h" #include "chatty-ma-account.h" -#include "chatty-list-row.h" #include "chatty-log.h" #include "chatty-utils.h" #include "chatty-new-chat-dialog.h" @@ -36,15 +35,11 @@ static void chatty_new_chat_name_check (ChattyNewChatDialog *self, GtkWidget *button); -#define ITEMS_COUNT 50 - struct _ChattyNewChatDialog { GtkDialog parent_instance; - GtkWidget *chats_listbox; - GtkWidget *contacts_listbox; - GtkWidget *new_contact_row; + GtkWidget *contact_list; GtkWidget *contacts_search_entry; GtkWidget *contact_edit_grid; GtkWidget *new_chat_stack; @@ -60,22 +55,14 @@ struct _ChattyNewChatDialog GtkWidget *dummy_prefix_radio; GtkWidget *header_view_new_chat; - GtkWidget *contact_list_stack; - GtkWidget *contact_list_view; - GtkWidget *empty_search_view; - - GtkSliceListModel *slice_model; - GtkFilter *filter; - char *search_str; ChattyAccount *selected_account; ChattyManager *manager; - ChattyProtocol active_protocols; + GListStore *selection_list; GPtrArray *selected_items; ChattyItem *selected_item; - ChattyContact *dummy_contact; GCancellable *cancellable; gboolean multi_selection; @@ -84,102 +71,24 @@ struct _ChattyNewChatDialog G_DEFINE_TYPE (ChattyNewChatDialog, chatty_new_chat_dialog, GTK_TYPE_DIALOG) - -static GtkWidget * -new_chat_contact_row_new (ChattyItem *item, - ChattyNewChatDialog *self) -{ - GtkWidget *row; - - row = chatty_list_contact_row_new (item); - chatty_list_row_set_selectable (CHATTY_LIST_ROW (row), self->multi_selection); - - return row; -} - static void -dialog_active_protocols_changed_cb (ChattyNewChatDialog *self) +start_button_clicked_cb (ChattyNewChatDialog *self) { - ChattyAccount *mm_account; - ChattyProtocol protocol; - gboolean valid; + GListModel *model; + guint n_items; g_assert (CHATTY_IS_NEW_CHAT_DIALOG (self)); - self->active_protocols = chatty_manager_get_active_protocols (self->manager); - gtk_filter_changed (self->filter, GTK_FILTER_CHANGE_DIFFERENT); - - protocol = CHATTY_PROTOCOL_MMS_SMS; - valid = protocol == chatty_utils_username_is_valid (self->search_str, protocol); - mm_account = chatty_manager_get_mm_account (self->manager); - valid = valid && chatty_account_get_status (mm_account) == CHATTY_CONNECTED; - gtk_widget_set_visible (self->new_contact_row, valid); - - if (valid || g_list_model_get_n_items (G_LIST_MODEL (self->slice_model)) > 0) - gtk_stack_set_visible_child (GTK_STACK (self->contact_list_stack), self->contact_list_view); - else - gtk_stack_set_visible_child (GTK_STACK (self->contact_list_stack), self->empty_search_view); -} - -static gboolean -new_chat_dialog_contact_is_selected (ChattyContact *contact) -{ - g_return_val_if_fail (CHATTY_IS_CONTACT (contact), FALSE); - - return !!g_object_get_data (G_OBJECT (contact), "selected"); -} - -static gboolean -dialog_filter_item_cb (ChattyItem *item, - ChattyNewChatDialog *self) -{ - ChattyAccount *account; - - g_return_val_if_fail (CHATTY_IS_NEW_CHAT_DIALOG (self), FALSE); - - if (self->multi_selection) { - - account = chatty_manager_get_mm_account (self->manager); - if (chatty_account_get_status (account) == CHATTY_CONNECTED) { - if (chatty_item_matches (item, self->search_str, CHATTY_PROTOCOL_MMS_SMS, TRUE) && - !new_chat_dialog_contact_is_selected (CHATTY_CONTACT (item))) - return TRUE; - else - return FALSE; - } else - return FALSE; - } - -#ifdef PURPLE_ENABLED - if (CHATTY_IS_PP_BUDDY (item)) { - account = chatty_pp_buddy_get_account (CHATTY_PP_BUDDY (item)); - - if (chatty_account_get_status (account) != CHATTY_CONNECTED) - return FALSE; - } -#endif - - if (CHATTY_IS_CHAT (item)) { -#ifdef PURPLE_ENABLED - /* Hide chat if it's buddy chat as the buddy is shown separately */ - if (CHATTY_IS_PP_CHAT (item) && - chatty_pp_chat_get_purple_buddy (CHATTY_PP_CHAT (item))) - return FALSE; -#endif - - account = chatty_chat_get_account (CHATTY_CHAT (item)); + model = G_LIST_MODEL (self->selection_list); + n_items = g_list_model_get_n_items (model); - if (!account || chatty_account_get_status (account) != CHATTY_CONNECTED) - return FALSE; - } + if (n_items < 1) + return; - return chatty_item_matches (item, self->search_str, self->active_protocols, TRUE); -} + g_ptr_array_set_size (self->selected_items, 0); -static void -start_button_clicked_cb (ChattyNewChatDialog *self) -{ - g_assert (CHATTY_IS_NEW_CHAT_DIALOG (self)); + for (guint i = 0; i < n_items; i++) + g_ptr_array_add (self->selected_items, g_list_model_get_item (model, i)); gtk_dialog_response (GTK_DIALOG (self), GTK_RESPONSE_OK); } @@ -192,17 +101,6 @@ cancel_button_clicked_cb (ChattyNewChatDialog *self) gtk_dialog_response (GTK_DIALOG (self), GTK_RESPONSE_CANCEL); } -static void -chatty_new_chat_dialog_update_selectable (GtkWidget *widget, - gpointer callback_data) -{ - ChattyNewChatDialog *self = callback_data; - - g_assert (CHATTY_IS_NEW_CHAT_DIALOG (self)); - - chatty_list_row_set_selectable ((ChattyListRow *)widget, self->multi_selection); -} - void chatty_new_chat_dialog_set_multi_selection (ChattyNewChatDialog *self, gboolean enable) @@ -211,50 +109,20 @@ chatty_new_chat_dialog_set_multi_selection (ChattyNewChatDialog *self, self->multi_selection = enable; gtk_header_bar_set_show_close_button (GTK_HEADER_BAR (self->header_view_new_chat), !enable); - - chatty_list_row_set_selectable (CHATTY_LIST_ROW (self->new_contact_row), enable); - gtk_container_foreach (GTK_CONTAINER (self->chats_listbox), - (GtkCallback)chatty_new_chat_dialog_update_selectable, self); + chatty_contact_list_can_multi_select (CHATTY_CONTACT_LIST (self->contact_list), enable); if (enable) { gtk_widget_show (self->start_button); - gtk_widget_show (self->contacts_listbox); gtk_widget_show (self->cancel_button); gtk_widget_hide (self->edit_contact_button); gtk_widget_set_sensitive (self->start_button, FALSE); } else { gtk_widget_show (self->edit_contact_button); - gtk_widget_hide (self->contacts_listbox); gtk_widget_hide (self->start_button); gtk_widget_hide (self->cancel_button); } } -static void -new_chat_list_changed_cb (ChattyNewChatDialog *self) -{ - guint n_items; - - g_assert (CHATTY_IS_NEW_CHAT_DIALOG (self)); - - n_items = g_list_model_get_n_items (G_LIST_MODEL (self->slice_model)); - - if (n_items > 0 || gtk_widget_get_visible (self->new_contact_row)) - gtk_stack_set_visible_child (GTK_STACK (self->contact_list_stack), self->contact_list_view); - else - gtk_stack_set_visible_child (GTK_STACK (self->contact_list_stack), self->empty_search_view); -} - -static void -chatty_new_chat_dialog_update_new_contact_row (ChattyNewChatDialog *self) -{ - g_assert (CHATTY_IS_NEW_CHAT_DIALOG (self)); - - self->dummy_contact = g_object_new (CHATTY_TYPE_CONTACT, NULL); - chatty_contact_set_name (self->dummy_contact, _("Send To")); - g_object_set_data (G_OBJECT (self->dummy_contact), "dummy", GINT_TO_POINTER (TRUE)); -} - static void back_button_clicked_cb (ChattyNewChatDialog *self) { @@ -318,266 +186,52 @@ add_in_contacts_button_clicked_cb (ChattyNewChatDialog *self) open_contacts_finish_cb, self); } - - static void -contact_stroll_edge_reached_cb (ChattyNewChatDialog *self, - GtkPositionType position) +contact_list_selection_changed_cb (ChattyNewChatDialog *self) { - const char *name; + GListModel *model; + guint n_items; g_assert (CHATTY_IS_NEW_CHAT_DIALOG (self)); - if (position != GTK_POS_BOTTOM) - return; - - name = gtk_stack_get_visible_child_name (GTK_STACK (self->new_chat_stack)); + g_clear_object (&self->selected_item); + model = G_LIST_MODEL (self->selection_list); + n_items = g_list_model_get_n_items (model); - if (!g_str_equal (name, "view-new-chat")) - return; + if (self->multi_selection) { + gtk_widget_set_sensitive (self->start_button, n_items > 0); + } else if (n_items > 0) { + self->selected_item = g_list_model_get_item (model, 0); + g_list_store_remove_all (self->selection_list); - gtk_slice_list_model_set_size (self->slice_model, - gtk_slice_list_model_get_size (self->slice_model) + ITEMS_COUNT); + gtk_dialog_response (GTK_DIALOG (self), GTK_RESPONSE_OK); + } } static void contact_search_entry_activated_cb (ChattyNewChatDialog *self) { - GtkListBox *box; - GtkWidget *row; - g_assert (CHATTY_IS_NEW_CHAT_DIALOG (self)); - box = GTK_LIST_BOX (self->chats_listbox); - - if (gtk_widget_is_visible (self->new_contact_row)) - row = self->new_contact_row; + if (self->multi_selection) + start_button_clicked_cb (self); else - row = (GtkWidget *)gtk_list_box_get_row_at_index (box, 0); - - if (row) { - self->selected_item = chatty_list_row_get_item (CHATTY_LIST_ROW (row)); - - gtk_dialog_response (GTK_DIALOG (self), GTK_RESPONSE_OK); - } + contact_list_selection_changed_cb (self); } static void contact_search_entry_changed_cb (ChattyNewChatDialog *self, GtkEntry *entry) { - ChattyAccount *account; - g_autofree char *old_needle = NULL; const char *str; - GtkFilterChange change; - ChattyProtocol protocol; - gboolean valid; - guint len; g_assert (CHATTY_IS_NEW_CHAT_DIALOG (self)); g_assert (GTK_IS_ENTRY (entry)); str = gtk_entry_get_text (entry); - if (!str) - str = ""; - - old_needle = self->search_str; - self->search_str = g_utf8_casefold (str, -1); - len = strlen (self->search_str); - - if (!old_needle) - old_needle = g_strdup (""); - - if (g_str_has_prefix (self->search_str, old_needle)) - change = GTK_FILTER_CHANGE_MORE_STRICT; - else if (g_str_has_prefix (old_needle, self->search_str)) - change = GTK_FILTER_CHANGE_LESS_STRICT; - else - change = GTK_FILTER_CHANGE_DIFFERENT; - - gtk_slice_list_model_set_size (self->slice_model, ITEMS_COUNT); - gtk_filter_changed (self->filter, change); - - chatty_contact_set_value (self->dummy_contact, self->search_str); - chatty_list_row_set_item (CHATTY_LIST_ROW (self->new_contact_row), - CHATTY_ITEM (self->dummy_contact)); - - protocol = CHATTY_PROTOCOL_MMS_SMS; - valid = protocol == chatty_utils_username_is_valid (self->search_str, protocol); - /* It is confusing for the dummy contact to disappear if the length is less than 3 */ - if (!valid && len < 3 && len > 0) { - guint end_len; - end_len = strspn (self->search_str, "0123456789"); - - if (end_len == len) - valid = TRUE; - } - account = chatty_manager_get_mm_account (self->manager); - valid = valid && chatty_account_get_status (account) == CHATTY_CONNECTED; - gtk_widget_set_visible (self->new_contact_row, valid); - - if (valid || g_list_model_get_n_items (G_LIST_MODEL (self->slice_model)) > 0) { - gtk_stack_set_visible_child (GTK_STACK (self->contact_list_stack), self->contact_list_view); - if (self->multi_selection) { - ChattyItem *selected_item; - const char *phone_number; - gboolean has_match = FALSE; - - selected_item = chatty_list_row_get_item (CHATTY_LIST_ROW (self->new_contact_row)); - phone_number = chatty_item_get_username (selected_item); - - /* Check if search string matches an item in the selected list */ - for (guint i = 0; i < self->selected_items->len; i++) { - const char *item_number = NULL; - ChattyItem *item; - - item = self->selected_items->pdata[i]; - if (item) - item_number = chatty_item_get_username (item); - - if (g_strcmp0 (item_number, phone_number) == 0) { - has_match = TRUE; - break; - } - } - - chatty_list_row_select (CHATTY_LIST_ROW (self->new_contact_row), has_match); - - gtk_container_foreach (GTK_CONTAINER (self->chats_listbox), - (GtkCallback)chatty_new_chat_dialog_update_selectable, - self); - } - } else - gtk_stack_set_visible_child (GTK_STACK (self->contact_list_stack), self->empty_search_view); -} - -static void -selected_contact_row_activated_cb (ChattyNewChatDialog *self, - ChattyListRow *row) -{ - const char *phone_number = NULL; - ChattyItem *selected_item; - - g_assert (CHATTY_IS_NEW_CHAT_DIALOG (self)); - g_assert (CHATTY_IS_LIST_ROW (row)); - - selected_item = chatty_list_row_get_item (row); - phone_number = chatty_item_get_username (selected_item); - - for (guint i = 0; i < self->selected_items->len; i++) { - const char *item_number = NULL; - ChattyItem *item; - - item = self->selected_items->pdata[i]; - if (item) - item_number = chatty_item_get_username (item); - - if (g_strcmp0 (item_number, phone_number) == 0) { - CHATTY_DEBUG (phone_number, "Removing item from list:"); - g_ptr_array_remove_index (self->selected_items, i); - - if (!self->selected_items->len) - gtk_widget_set_sensitive (self->start_button, FALSE); - - break; - } - } - if (chatty_contact_is_dummy (CHATTY_CONTACT (selected_item))) { - ChattyItem *dummy_item; - const char *dummy_number; - - dummy_item = chatty_list_row_get_item (CHATTY_LIST_ROW (self->new_contact_row)); - dummy_number = chatty_item_get_username (dummy_item); - if (g_strcmp0 (dummy_number, phone_number) == 0) - chatty_list_row_select (CHATTY_LIST_ROW (self->new_contact_row), FALSE); - - } else { - g_autofree char *contacts_search_entry = NULL; - - contacts_search_entry = g_strdup(gtk_entry_get_text (GTK_ENTRY (self->contacts_search_entry))); - g_object_set_data (G_OBJECT (selected_item), "selected", GINT_TO_POINTER (FALSE)); - if (!*contacts_search_entry) - gtk_entry_set_text (GTK_ENTRY (self->contacts_search_entry), "reset"); - else - gtk_entry_set_text (GTK_ENTRY (self->contacts_search_entry), ""); - - contact_search_entry_changed_cb (self, GTK_ENTRY (self->contacts_search_entry)); - gtk_entry_set_text (GTK_ENTRY (self->contacts_search_entry), contacts_search_entry); - } - gtk_widget_destroy (GTK_WIDGET (row)); -} - -static void -contact_row_activated_cb (ChattyNewChatDialog *self, - ChattyListRow *row) -{ - g_assert (CHATTY_IS_NEW_CHAT_DIALOG (self)); - g_assert (CHATTY_IS_LIST_ROW (row)); - - if (self->multi_selection) { - GtkListBoxRow *chats_listbox_row; - GtkWidget *new_row = NULL; - ChattyItem *selected_item; - const char *phone_number; - - selected_item = chatty_list_row_get_item (row); - phone_number = chatty_item_get_username (selected_item); - /* If there is a dummy contact, make sure it is not already selected */ - if (chatty_contact_is_dummy (CHATTY_CONTACT (selected_item))) { - guint i = 0; - - chatty_list_row_select (CHATTY_LIST_ROW (self->new_contact_row), TRUE); - chats_listbox_row = gtk_list_box_get_row_at_index (GTK_LIST_BOX (self->contacts_listbox), 0); - while (chats_listbox_row != NULL) { - ChattyItem *item = chatty_list_row_get_item (CHATTY_LIST_ROW (chats_listbox_row)); - const char *item_number = chatty_item_get_username (item); - if (g_strcmp0 (item_number, phone_number) == 0) { - selected_contact_row_activated_cb (self, (CHATTY_LIST_ROW (chats_listbox_row))); - return; - } - i++; - chats_listbox_row = gtk_list_box_get_row_at_index (GTK_LIST_BOX (self->contacts_listbox), i); - } - } - - CHATTY_DEBUG_MSG ("Adding %s to list", phone_number); - if (chatty_contact_is_dummy (CHATTY_CONTACT (selected_item))) { - ChattyContact *dummy_contact = NULL; - - dummy_contact = g_object_new (CHATTY_TYPE_CONTACT, NULL); - chatty_contact_set_name (dummy_contact, _("Unknown Contact")); - chatty_contact_set_value (dummy_contact, - gtk_entry_get_text (GTK_ENTRY (self->contacts_search_entry))); - g_object_set_data (G_OBJECT (dummy_contact), "dummy", GINT_TO_POINTER (TRUE)); - new_row = chatty_list_row_new (CHATTY_ITEM (dummy_contact)); - g_ptr_array_add (self->selected_items, dummy_contact); - } else { - ChattyItem *dummy_item; - const char *dummy_number; - - dummy_item = chatty_list_row_get_item (CHATTY_LIST_ROW (self->new_contact_row)); - dummy_number = chatty_item_get_username (dummy_item); - new_row = chatty_list_row_new (chatty_list_row_get_item (row)); - g_ptr_array_add (self->selected_items, g_object_ref (selected_item)); - - g_object_set_data (G_OBJECT (selected_item), "selected", GINT_TO_POINTER (TRUE)); - gtk_widget_hide (GTK_WIDGET (row)); - if (g_strcmp0 (dummy_number, phone_number) == 0) { - chatty_list_row_select (CHATTY_LIST_ROW (self->new_contact_row), TRUE); - } - } - - chatty_list_row_set_selectable (CHATTY_LIST_ROW (new_row), TRUE); - chatty_list_row_select (CHATTY_LIST_ROW (new_row), TRUE); - gtk_list_box_prepend (GTK_LIST_BOX (self->contacts_listbox), - GTK_WIDGET (new_row)); - gtk_widget_set_sensitive (self->start_button, TRUE); - } else { - self->selected_item = chatty_list_row_get_item (row); - - gtk_dialog_response (GTK_DIALOG (self), GTK_RESPONSE_OK); - } + chatty_contact_list_set_filter (CHATTY_CONTACT_LIST (self->contact_list), + CHATTY_PROTOCOL_ANY, str ?: ""); } static void @@ -813,32 +467,18 @@ static void chatty_new_chat_dialog_show (GtkWidget *widget) { ChattyNewChatDialog *self = (ChattyNewChatDialog *)widget; - const char *contacts_search_entry; g_return_if_fail (CHATTY_IS_NEW_CHAT_DIALOG (self)); + /* Reset selection list */ + g_clear_object (&self->selected_item); + g_list_store_remove_all (self->selection_list); g_ptr_array_foreach (self->selected_items, chatty_new_chat_unset_items, NULL); g_ptr_array_set_size (self->selected_items, 0); self->selected_items->pdata[0] = NULL; - /* Re-filter so that selection changes are reverted */ - gtk_filter_changed (self->filter, GTK_FILTER_CHANGE_DIFFERENT); - chatty_list_row_select (CHATTY_LIST_ROW (self->new_contact_row), FALSE); - gtk_widget_set_sensitive (self->start_button, FALSE); - - gtk_container_foreach (GTK_CONTAINER (self->contacts_listbox), - (GtkCallback)gtk_widget_destroy, NULL); - - /* Reset selection list */ - self->selected_item = NULL; - - contacts_search_entry = gtk_entry_get_text (GTK_ENTRY (self->contacts_search_entry)); - if (!*contacts_search_entry) { - gtk_entry_set_text (GTK_ENTRY (self->contacts_search_entry), "reset"); - contact_search_entry_changed_cb (self, GTK_ENTRY (self->contacts_search_entry)); - } gtk_entry_set_text (GTK_ENTRY (self->contacts_search_entry), ""); GTK_WIDGET_CLASS (chatty_new_chat_dialog_parent_class)->show (widget); @@ -859,8 +499,6 @@ chatty_new_chat_dialog_dispose (GObject *object) g_clear_pointer (&self->selected_items, g_ptr_array_unref); g_clear_object (&self->cancellable); g_clear_object (&self->manager); - g_clear_object (&self->slice_model); - g_clear_object (&self->filter); G_OBJECT_CLASS (chatty_new_chat_dialog_parent_class)->dispose (object); } @@ -882,9 +520,7 @@ chatty_new_chat_dialog_class_init (ChattyNewChatDialogClass *klass) gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, new_chat_stack); gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, header_view_new_chat); gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, contacts_search_entry); - gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, new_contact_row); - gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, contacts_listbox); - gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, chats_listbox); + gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, contact_list); gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, contact_edit_grid); gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, contact_name_entry); gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, contact_alias_entry); @@ -896,17 +532,11 @@ chatty_new_chat_dialog_class_init (ChattyNewChatDialogClass *klass) gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, start_button); gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, cancel_button); - gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, contact_list_stack); - gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, contact_list_view); - gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, empty_search_view); - gtk_widget_class_bind_template_callback (widget_class, back_button_clicked_cb); gtk_widget_class_bind_template_callback (widget_class, edit_contact_button_clicked_cb); - gtk_widget_class_bind_template_callback (widget_class, contact_stroll_edge_reached_cb); gtk_widget_class_bind_template_callback (widget_class, contact_search_entry_activated_cb); gtk_widget_class_bind_template_callback (widget_class, contact_search_entry_changed_cb); - gtk_widget_class_bind_template_callback (widget_class, selected_contact_row_activated_cb); - gtk_widget_class_bind_template_callback (widget_class, contact_row_activated_cb); + gtk_widget_class_bind_template_callback (widget_class, contact_list_selection_changed_cb); gtk_widget_class_bind_template_callback (widget_class, add_contact_button_clicked_cb); gtk_widget_class_bind_template_callback (widget_class, add_in_contacts_button_clicked_cb); gtk_widget_class_bind_template_callback (widget_class, contact_name_text_changed_cb); @@ -919,39 +549,18 @@ chatty_new_chat_dialog_class_init (ChattyNewChatDialogClass *klass) static void chatty_new_chat_dialog_init (ChattyNewChatDialog *self) { - g_autoptr(GtkFilterListModel) filter_model = NULL; - g_autoptr(GtkSortListModel) sort_model = NULL; - g_autoptr(GtkSorter) sorter = NULL; - gtk_widget_init_template (GTK_WIDGET (self)); self->cancellable = g_cancellable_new (); + self->selection_list = g_list_store_new (CHATTY_TYPE_ITEM); + chatty_contact_list_set_selection_store (CHATTY_CONTACT_LIST (self->contact_list), + self->selection_list); + self->multi_selection = FALSE; self->selected_items = g_ptr_array_new_full (1, g_object_unref); self->dummy_prefix_radio = gtk_radio_button_new_from_widget (GTK_RADIO_BUTTON (NULL)); self->manager = g_object_ref (chatty_manager_get_default ()); - - sorter = gtk_custom_sorter_new ((GCompareDataFunc)chatty_item_compare, NULL, NULL); - sort_model = gtk_sort_list_model_new (chatty_manager_get_contact_list (self->manager), sorter); - - self->filter = gtk_custom_filter_new ((GtkCustomFilterFunc)dialog_filter_item_cb, self, NULL); - filter_model = gtk_filter_list_model_new (G_LIST_MODEL (sort_model), self->filter); - - self->slice_model = gtk_slice_list_model_new (G_LIST_MODEL (filter_model), 0, ITEMS_COUNT); - g_signal_connect_object (self->slice_model, "items-changed", - G_CALLBACK (new_chat_list_changed_cb), self, - G_CONNECT_SWAPPED); - gtk_list_box_bind_model (GTK_LIST_BOX (self->chats_listbox), - G_LIST_MODEL (self->slice_model), - (GtkListBoxCreateWidgetFunc)new_chat_contact_row_new, - g_object_ref (self), g_object_unref); - - g_signal_connect_object (self->manager, "notify::active-protocols", - G_CALLBACK (dialog_active_protocols_changed_cb), self, G_CONNECT_SWAPPED); - dialog_active_protocols_changed_cb (self); - - chatty_new_chat_dialog_update_new_contact_row (self); } diff --git a/src/ui/chatty-dialog-new-chat.ui b/src/ui/chatty-dialog-new-chat.ui index e59970a5..ff18d9c3 100644 --- a/src/ui/chatty-dialog-new-chat.ui +++ b/src/ui/chatty-dialog-new-chat.ui @@ -145,9 +145,10 @@ True never + never True True - + True @@ -194,75 +195,11 @@ - - True - False - False - none - - + + 1 + - - - - True - - - - - True - False - True - vertical - start - - - - - none - - - - - - - - - - - True - False - True - none - - - - - - - - - - - - True - True - system-search-symbolic - No Search Results - Try different search, or type a valid number to create new chat - - - - - - view-new-chat @@ -419,6 +356,7 @@ + True -- GitLab From c13940ca864b17f1ad47395e12fa95f8498653e3 Mon Sep 17 00:00:00 2001 From: Mohammed Sadiq Date: Fri, 7 Jan 2022 19:38:21 +0530 Subject: [PATCH 5/8] new-chat-dialog: Return a GListModel of selected chat list And adapt to changes This will help keep a single API for both single and multi contact selection list --- src/chatty-window.c | 72 +++++++++++++--------------- src/dialogs/chatty-new-chat-dialog.c | 49 ++----------------- src/dialogs/chatty-new-chat-dialog.h | 3 +- 3 files changed, 37 insertions(+), 87 deletions(-) diff --git a/src/chatty-window.c b/src/chatty-window.c index 7a72eea7..14ffd447 100644 --- a/src/chatty-window.c +++ b/src/chatty-window.c @@ -268,50 +268,19 @@ notify_fold_cb (ChattyWindow *self) } static void -window_new_message_clicked_cb (ChattyWindow *self) -{ - ChattyNewChatDialog *dialog; - ChattyItem *item; - const char *phone_number = NULL; - gint response; - - g_assert (CHATTY_IS_WINDOW (self)); - - dialog = CHATTY_NEW_CHAT_DIALOG (self->new_chat_dialog); - chatty_new_chat_dialog_set_multi_selection (dialog, FALSE); - - response = gtk_dialog_run (GTK_DIALOG (self->new_chat_dialog)); - gtk_widget_hide (self->new_chat_dialog); - - if (response != GTK_RESPONSE_OK) - return; - - item = chatty_new_chat_dialog_get_selected_item (dialog); - - if (CHATTY_IS_CONTACT (item) && - chatty_contact_is_dummy (CHATTY_CONTACT (item))) - phone_number = chatty_item_get_username (item); - - if (phone_number) - chatty_window_set_uri (self, phone_number); - else if (item) - chatty_window_open_item (self, item); - else - g_return_if_reached (); -} - -static void -window_new_sms_mms_message_clicked_cb (ChattyWindow *self) +window_show_new_chat_dialog (ChattyWindow *self, + gboolean can_multi_select) { g_autoptr(GString) sendlist = g_string_new (NULL); ChattyNewChatDialog *dialog; - GPtrArray *items; + GListModel *model; + guint n_items; gint response; g_assert (CHATTY_IS_WINDOW (self)); dialog = CHATTY_NEW_CHAT_DIALOG (self->new_chat_dialog); - chatty_new_chat_dialog_set_multi_selection (dialog, TRUE); + chatty_new_chat_dialog_set_multi_selection (dialog, can_multi_select); response = gtk_dialog_run (GTK_DIALOG (self->new_chat_dialog)); gtk_widget_hide (self->new_chat_dialog); @@ -319,13 +288,14 @@ window_new_sms_mms_message_clicked_cb (ChattyWindow *self) if (response != GTK_RESPONSE_OK) return; - items = chatty_new_chat_dialog_get_selected_items (dialog); + model = chatty_new_chat_dialog_get_selected_items (dialog); + n_items = g_list_model_get_n_items (model); - for (guint i = 0; i < items->len; i++) { + for (guint i = 0; i < n_items; i++) { + g_autoptr(ChattyItem) item = NULL; const char *phone_number; - ChattyItem *item; - item = items->pdata[i]; + item = g_list_model_get_item (model, i); if (CHATTY_IS_CONTACT (item)) { phone_number = chatty_item_get_username (item); @@ -338,9 +308,31 @@ window_new_sms_mms_message_clicked_cb (ChattyWindow *self) if (sendlist->len >= 1) g_string_truncate (sendlist, sendlist->len - 1); + if (n_items == 1) { + g_autoptr(ChattyItem) item = NULL; + + item = g_list_model_get_item (model, 0); + + if (!CHATTY_IS_CONTACT (item) || + !chatty_contact_is_dummy (CHATTY_CONTACT (item))) + chatty_window_open_item (self, item); + } + chatty_window_set_uri (self, sendlist->str); } +static void +window_new_message_clicked_cb (ChattyWindow *self) +{ + window_show_new_chat_dialog (self, FALSE); +} + +static void +window_new_sms_mms_message_clicked_cb (ChattyWindow *self) +{ + window_show_new_chat_dialog (self, TRUE); +} + static void window_new_muc_clicked_cb (ChattyWindow *self) { diff --git a/src/dialogs/chatty-new-chat-dialog.c b/src/dialogs/chatty-new-chat-dialog.c index 3cdd7068..4f07d9da 100644 --- a/src/dialogs/chatty-new-chat-dialog.c +++ b/src/dialogs/chatty-new-chat-dialog.c @@ -58,10 +58,7 @@ struct _ChattyNewChatDialog ChattyAccount *selected_account; ChattyManager *manager; - - GListStore *selection_list; - GPtrArray *selected_items; - ChattyItem *selected_item; + GListStore *selection_list; GCancellable *cancellable; @@ -75,21 +72,14 @@ static void start_button_clicked_cb (ChattyNewChatDialog *self) { GListModel *model; - guint n_items; g_assert (CHATTY_IS_NEW_CHAT_DIALOG (self)); model = G_LIST_MODEL (self->selection_list); - n_items = g_list_model_get_n_items (model); - if (n_items < 1) + if (g_list_model_get_n_items (model) < 1) return; - g_ptr_array_set_size (self->selected_items, 0); - - for (guint i = 0; i < n_items; i++) - g_ptr_array_add (self->selected_items, g_list_model_get_item (model, i)); - gtk_dialog_response (GTK_DIALOG (self), GTK_RESPONSE_OK); } @@ -194,16 +184,12 @@ contact_list_selection_changed_cb (ChattyNewChatDialog *self) g_assert (CHATTY_IS_NEW_CHAT_DIALOG (self)); - g_clear_object (&self->selected_item); model = G_LIST_MODEL (self->selection_list); n_items = g_list_model_get_n_items (model); if (self->multi_selection) { gtk_widget_set_sensitive (self->start_button, n_items > 0); } else if (n_items > 0) { - self->selected_item = g_list_model_get_item (model, 0); - g_list_store_remove_all (self->selection_list); - gtk_dialog_response (GTK_DIALOG (self), GTK_RESPONSE_OK); } } @@ -456,13 +442,6 @@ chatty_new_chat_dialog_update (ChattyNewChatDialog *self) chatty_new_chat_populate_account_list (self); } -static void -chatty_new_chat_unset_items (gpointer data, - gpointer user_data) -{ - g_object_set_data (data, "selected", GINT_TO_POINTER (FALSE)); -} - static void chatty_new_chat_dialog_show (GtkWidget *widget) { @@ -471,12 +450,7 @@ chatty_new_chat_dialog_show (GtkWidget *widget) g_return_if_fail (CHATTY_IS_NEW_CHAT_DIALOG (self)); /* Reset selection list */ - g_clear_object (&self->selected_item); g_list_store_remove_all (self->selection_list); - g_ptr_array_foreach (self->selected_items, - chatty_new_chat_unset_items, NULL); - g_ptr_array_set_size (self->selected_items, 0); - self->selected_items->pdata[0] = NULL; gtk_widget_set_sensitive (self->start_button, FALSE); gtk_entry_set_text (GTK_ENTRY (self->contacts_search_entry), ""); @@ -492,11 +466,6 @@ chatty_new_chat_dialog_dispose (GObject *object) if (self->cancellable) g_cancellable_cancel (self->cancellable); - if (self->selected_items) - g_ptr_array_foreach (self->selected_items, - chatty_new_chat_unset_items, NULL); - - g_clear_pointer (&self->selected_items, g_ptr_array_unref); g_clear_object (&self->cancellable); g_clear_object (&self->manager); @@ -557,7 +526,6 @@ chatty_new_chat_dialog_init (ChattyNewChatDialog *self) self->selection_list); self->multi_selection = FALSE; - self->selected_items = g_ptr_array_new_full (1, g_object_unref); self->dummy_prefix_radio = gtk_radio_button_new_from_widget (GTK_RADIO_BUTTON (NULL)); self->manager = g_object_ref (chatty_manager_get_default ()); @@ -575,19 +543,10 @@ chatty_new_chat_dialog_new (GtkWindow *parent_window) NULL); } - -ChattyItem * -chatty_new_chat_dialog_get_selected_item (ChattyNewChatDialog *self) -{ - g_return_val_if_fail (CHATTY_IS_NEW_CHAT_DIALOG (self), NULL); - - return self->selected_item; -} - -GPtrArray * +GListModel * chatty_new_chat_dialog_get_selected_items (ChattyNewChatDialog *self) { g_return_val_if_fail (CHATTY_IS_NEW_CHAT_DIALOG (self), NULL); - return self->selected_items; + return G_LIST_MODEL (self->selection_list); } diff --git a/src/dialogs/chatty-new-chat-dialog.h b/src/dialogs/chatty-new-chat-dialog.h index 3499a55e..ea1bdab3 100644 --- a/src/dialogs/chatty-new-chat-dialog.h +++ b/src/dialogs/chatty-new-chat-dialog.h @@ -19,9 +19,8 @@ G_DECLARE_FINAL_TYPE (ChattyNewChatDialog, chatty_new_chat_dialog, CHATTY, NEW_C GtkWidget *chatty_new_chat_dialog_new (GtkWindow *parent_window); void chatty_new_chat_set_edit_mode (ChattyNewChatDialog *self, gboolean edit); -ChattyItem *chatty_new_chat_dialog_get_selected_item (ChattyNewChatDialog *self); +GListModel *chatty_new_chat_dialog_get_selected_items (ChattyNewChatDialog *self); void chatty_new_chat_dialog_set_multi_selection (ChattyNewChatDialog *self, gboolean enable); -GPtrArray *chatty_new_chat_dialog_get_selected_items (ChattyNewChatDialog *self); G_END_DECLS -- GitLab From 06460a966ba14625dd315fe7c3bd08bdbf78a378 Mon Sep 17 00:00:00 2001 From: Mohammed Sadiq Date: Fri, 7 Jan 2022 20:47:51 +0530 Subject: [PATCH 6/8] new-chat-dialog: Port to use HdyPreferencesPage And adapt to changes. This looks easier as more pages and items are added to the dialog --- src/chatty-window.c | 93 +++--- src/css/style.css | 5 + src/dialogs/chatty-new-chat-dialog.c | 192 ++++++++---- src/meson.build | 2 +- src/ui/chatty-dialog-new-chat.ui | 452 +++++++++++---------------- 5 files changed, 372 insertions(+), 372 deletions(-) diff --git a/src/chatty-window.c b/src/chatty-window.c index 14ffd447..efea9179 100644 --- a/src/chatty-window.c +++ b/src/chatty-window.c @@ -271,54 +271,13 @@ static void window_show_new_chat_dialog (ChattyWindow *self, gboolean can_multi_select) { - g_autoptr(GString) sendlist = g_string_new (NULL); ChattyNewChatDialog *dialog; - GListModel *model; - guint n_items; - gint response; g_assert (CHATTY_IS_WINDOW (self)); dialog = CHATTY_NEW_CHAT_DIALOG (self->new_chat_dialog); chatty_new_chat_dialog_set_multi_selection (dialog, can_multi_select); - - response = gtk_dialog_run (GTK_DIALOG (self->new_chat_dialog)); - gtk_widget_hide (self->new_chat_dialog); - - if (response != GTK_RESPONSE_OK) - return; - - model = chatty_new_chat_dialog_get_selected_items (dialog); - n_items = g_list_model_get_n_items (model); - - for (guint i = 0; i < n_items; i++) { - g_autoptr(ChattyItem) item = NULL; - const char *phone_number; - - item = g_list_model_get_item (model, i); - - if (CHATTY_IS_CONTACT (item)) { - phone_number = chatty_item_get_username (item); - sendlist = g_string_append (sendlist, phone_number); - g_string_append (sendlist, ","); - } - } - - /* Remove the trailing "," */ - if (sendlist->len >= 1) - g_string_truncate (sendlist, sendlist->len - 1); - - if (n_items == 1) { - g_autoptr(ChattyItem) item = NULL; - - item = g_list_model_get_item (model, 0); - - if (!CHATTY_IS_CONTACT (item) || - !chatty_contact_is_dummy (CHATTY_CONTACT (item))) - chatty_window_open_item (self, item); - } - - chatty_window_set_uri (self, sendlist->str); + gtk_window_present (GTK_WINDOW (self->new_chat_dialog)); } static void @@ -607,6 +566,52 @@ protocol_list_header_func (GtkListBoxRow *row, } } +static void +new_chat_selection_changed_cb (ChattyWindow *self, + ChattyNewChatDialog *dialog) +{ + g_autoptr(GString) users = g_string_new (NULL); + GListModel *model; + guint n_items; + + g_assert (CHATTY_IS_WINDOW (self)); + g_assert (CHATTY_IS_NEW_CHAT_DIALOG (dialog)); + + model = chatty_new_chat_dialog_get_selected_items (dialog); + n_items = g_list_model_get_n_items (model); + + if (n_items == 0) + return; + + for (guint i = 0; i < n_items; i++) { + g_autoptr(ChattyItem) item = NULL; + const char *phone_number; + + item = g_list_model_get_item (model, i); + + if (CHATTY_IS_CONTACT (item)) { + phone_number = chatty_item_get_username (item); + g_string_append (users, phone_number); + g_string_append (users, ","); + } + } + + /* Remove the trailing "," */ + if (users->len >= 1) + g_string_truncate (users, users->len - 1); + + if (n_items == 1) { + g_autoptr(ChattyItem) item = NULL; + + item = g_list_model_get_item (model, 0); + + if (!CHATTY_IS_CONTACT (item) || + !chatty_contact_is_dummy (CHATTY_CONTACT (item))) + chatty_window_open_item (self, item); + } + + chatty_window_set_uri (self, users->str); +} static void chatty_window_unmap (GtkWidget *widget) @@ -663,6 +668,10 @@ chatty_window_constructed (GObject *object) gtk_window_maximize (window); self->new_chat_dialog = chatty_new_chat_dialog_new (GTK_WINDOW (self)); + g_signal_connect_object (self->new_chat_dialog, "selection-changed", + G_CALLBACK (new_chat_selection_changed_cb), + self, + G_CONNECT_SWAPPED); self->chat_info_dialog = chatty_info_dialog_new (GTK_WINDOW (self)); G_OBJECT_CLASS (chatty_window_parent_class)->constructed (object); diff --git a/src/css/style.css b/src/css/style.css index 7668747f..e7e5a537 100644 --- a/src/css/style.css +++ b/src/css/style.css @@ -147,3 +147,8 @@ button.delete-button { min-height: 27px; min-width: 27px; } + +.no-margin, +.no-margin > scrolledwindow > viewport > clamp { + margin: 0; +} diff --git a/src/dialogs/chatty-new-chat-dialog.c b/src/dialogs/chatty-new-chat-dialog.c index 4f07d9da..39ddce01 100644 --- a/src/dialogs/chatty-new-chat-dialog.c +++ b/src/dialogs/chatty-new-chat-dialog.c @@ -37,7 +37,14 @@ static void chatty_new_chat_name_check (ChattyNewChatDialog *self, struct _ChattyNewChatDialog { - GtkDialog parent_instance; + HdyWindow parent_instance; + + GtkWidget *header_bar; + GtkWidget *edit_contact_button; + GtkWidget *back_button; + GtkWidget *cancel_button; + GtkWidget *apply_button; + GtkWidget *progress_spinner; GtkWidget *contact_list; GtkWidget *contacts_search_entry; @@ -46,15 +53,13 @@ struct _ChattyNewChatDialog GtkWidget *accounts_list; GtkWidget *contact_name_entry; GtkWidget *contact_alias_entry; - GtkWidget *back_button; - GtkWidget *add_contact_button; - GtkWidget *edit_contact_button; - GtkWidget *start_button; - GtkWidget *cancel_button; GtkWidget *add_in_contacts_button; - GtkWidget *dummy_prefix_radio; - GtkWidget *header_view_new_chat; + GtkWidget *main_stack; + GtkWidget *contact_list_view; + GtkWidget *add_contact_view; + + GtkWidget *dummy_prefix_radio; ChattyAccount *selected_account; ChattyManager *manager; @@ -66,7 +71,14 @@ struct _ChattyNewChatDialog }; -G_DEFINE_TYPE (ChattyNewChatDialog, chatty_new_chat_dialog, GTK_TYPE_DIALOG) +G_DEFINE_TYPE (ChattyNewChatDialog, chatty_new_chat_dialog, HDY_TYPE_WINDOW) + +enum { + SELECTION_CHANGED, + N_SIGNALS +}; + +static guint signals[N_SIGNALS]; static void start_button_clicked_cb (ChattyNewChatDialog *self) @@ -80,7 +92,7 @@ start_button_clicked_cb (ChattyNewChatDialog *self) if (g_list_model_get_n_items (model) < 1) return; - gtk_dialog_response (GTK_DIALOG (self), GTK_RESPONSE_OK); + g_signal_emit (self, signals[SELECTION_CHANGED], 0); } static void @@ -88,7 +100,7 @@ cancel_button_clicked_cb (ChattyNewChatDialog *self) { g_assert (CHATTY_IS_NEW_CHAT_DIALOG (self)); - gtk_dialog_response (GTK_DIALOG (self), GTK_RESPONSE_CANCEL); + gtk_widget_hide (GTK_WIDGET (self)); } void @@ -98,17 +110,18 @@ chatty_new_chat_dialog_set_multi_selection (ChattyNewChatDialog *self, g_assert (CHATTY_IS_NEW_CHAT_DIALOG (self)); self->multi_selection = enable; - gtk_header_bar_set_show_close_button (GTK_HEADER_BAR (self->header_view_new_chat), !enable); + hdy_header_bar_set_show_close_button (HDY_HEADER_BAR (self->header_bar), !enable); chatty_contact_list_can_multi_select (CHATTY_CONTACT_LIST (self->contact_list), enable); if (enable) { - gtk_widget_show (self->start_button); + gtk_button_set_label (GTK_BUTTON (self->apply_button), _("Create")); + gtk_widget_show (self->apply_button); + gtk_widget_set_sensitive (self->apply_button, FALSE); gtk_widget_show (self->cancel_button); gtk_widget_hide (self->edit_contact_button); - gtk_widget_set_sensitive (self->start_button, FALSE); } else { gtk_widget_show (self->edit_contact_button); - gtk_widget_hide (self->start_button); + gtk_widget_hide (self->apply_button); gtk_widget_hide (self->cancel_button); } } @@ -118,7 +131,7 @@ back_button_clicked_cb (ChattyNewChatDialog *self) { g_assert (CHATTY_IS_NEW_CHAT_DIALOG (self)); - gtk_stack_set_visible_child_name (GTK_STACK (self->new_chat_stack), "view-new-chat"); + gtk_stack_set_visible_child (GTK_STACK (self->main_stack), self->contact_list_view); } @@ -129,7 +142,30 @@ edit_contact_button_clicked_cb (ChattyNewChatDialog *self) chatty_new_chat_dialog_update (self); - gtk_stack_set_visible_child_name (GTK_STACK (self->new_chat_stack), "view-new-contact"); + gtk_stack_set_visible_child (GTK_STACK (self->main_stack), self->add_contact_view); +} + +static void +new_chat_dialog_page_changed_cb (ChattyNewChatDialog *self) +{ + GtkWidget *visible_child; + + g_assert (CHATTY_IS_NEW_CHAT_DIALOG (self)); + + gtk_widget_hide (self->back_button); + gtk_widget_hide (self->cancel_button); + gtk_widget_hide (self->apply_button); + gtk_widget_hide (self->edit_contact_button); + + visible_child = gtk_stack_get_visible_child (GTK_STACK (self->main_stack)); + + if (visible_child == self->contact_list_view) { + gtk_widget_show (self->edit_contact_button); + } else { + gtk_button_set_label (GTK_BUTTON (self->apply_button), _("Add Contact")); + gtk_widget_show (self->apply_button); + gtk_widget_show (self->back_button); + } } static void @@ -147,7 +183,7 @@ open_contacts_finish_cb (GObject *object, chatty_eds_open_contacts_app_finish (chatty_eds, result, &error); gtk_widget_set_sensitive (self->add_in_contacts_button, TRUE); - gtk_stack_set_visible_child_name (GTK_STACK (self->new_chat_stack), "view-new-chat"); + gtk_stack_set_visible_child (GTK_STACK (self->main_stack), self->contact_list_view); if (!error) return; @@ -188,9 +224,9 @@ contact_list_selection_changed_cb (ChattyNewChatDialog *self) n_items = g_list_model_get_n_items (model); if (self->multi_selection) { - gtk_widget_set_sensitive (self->start_button, n_items > 0); + gtk_widget_set_sensitive (self->apply_button, n_items > 0); } else if (n_items > 0) { - gtk_dialog_response (GTK_DIALOG (self), GTK_RESPONSE_OK); + g_signal_emit (self, signals[SELECTION_CHANGED], 0); } } @@ -220,37 +256,6 @@ contact_search_entry_changed_cb (ChattyNewChatDialog *self, CHATTY_PROTOCOL_ANY, str ?: ""); } -static void -add_contact_button_clicked_cb (ChattyNewChatDialog *self) -{ -#ifdef PURPLE_ENABLED - GPtrArray *buddies; - const char *who, *alias; - - g_assert (CHATTY_IS_NEW_CHAT_DIALOG (self)); - - if (!gtk_widget_get_sensitive (self->add_contact_button)) - return; - - buddies = g_ptr_array_new_full (1, g_free); - - who = gtk_entry_get_text (GTK_ENTRY (self->contact_name_entry)); - alias = gtk_entry_get_text (GTK_ENTRY (self->contact_alias_entry)); - chatty_pp_account_add_buddy (CHATTY_PP_ACCOUNT (self->selected_account), who, alias); - - g_ptr_array_add (buddies, g_strdup (who)); - chatty_account_start_direct_chat_async (self->selected_account, buddies, NULL, NULL); -#endif - - gtk_widget_hide (GTK_WIDGET (self)); - - gtk_entry_set_text (GTK_ENTRY (self->contact_name_entry), ""); - gtk_entry_set_text (GTK_ENTRY (self->contact_alias_entry), ""); - - gtk_stack_set_visible_child_name (GTK_STACK (self->new_chat_stack), "view-new-chat"); -} - - static void contact_name_text_changed_cb (ChattyNewChatDialog *self) { @@ -258,7 +263,7 @@ contact_name_text_changed_cb (ChattyNewChatDialog *self) chatty_new_chat_name_check (self, GTK_ENTRY (self->contact_name_entry), - self->add_contact_button); + self->apply_button); } @@ -284,6 +289,45 @@ account_list_row_activated_cb (ChattyNewChatDialog *self, chatty_new_chat_set_edit_mode (self, TRUE); } +static void +new_chat_dialog_apply_button_clicked_cb (ChattyNewChatDialog *self) +{ + g_assert (CHATTY_IS_NEW_CHAT_DIALOG (self)); + + if (gtk_stack_get_visible_child (GTK_STACK (self->main_stack)) == self->add_contact_view) { +#ifdef PURPLE_ENABLED + GPtrArray *buddies; + const char *who, *alias; + + g_assert (CHATTY_IS_NEW_CHAT_DIALOG (self)); + + if (!gtk_widget_get_sensitive (self->apply_button)) + return; + + buddies = g_ptr_array_new_full (1, g_free); + + who = gtk_entry_get_text (GTK_ENTRY (self->contact_name_entry)); + alias = gtk_entry_get_text (GTK_ENTRY (self->contact_alias_entry)); + chatty_pp_account_add_buddy (CHATTY_PP_ACCOUNT (self->selected_account), who, alias); + + g_ptr_array_add (buddies, g_strdup (who)); + chatty_account_start_direct_chat_async (self->selected_account, buddies, NULL, NULL); +#endif + + gtk_widget_hide (GTK_WIDGET (self)); + } else if (gtk_stack_get_visible_child (GTK_STACK (self->main_stack)) == self->contact_list_view) { + GListModel *model; + + g_assert (CHATTY_IS_NEW_CHAT_DIALOG (self)); + + model = G_LIST_MODEL (self->selection_list); + + if (g_list_model_get_n_items (model) == 0) + return; + + g_signal_emit (self, signals[SELECTION_CHANGED], 0); + } +} static void chatty_new_chat_name_check (ChattyNewChatDialog *self, @@ -317,11 +361,11 @@ chatty_new_chat_set_edit_mode (ChattyNewChatDialog *self, if (edit) { gtk_widget_show (GTK_WIDGET (self->contact_edit_grid)); - gtk_widget_show (GTK_WIDGET (self->add_contact_button)); + gtk_widget_show (GTK_WIDGET (self->apply_button)); gtk_widget_hide (GTK_WIDGET (self->add_in_contacts_button)); } else { gtk_widget_hide (GTK_WIDGET (self->contact_edit_grid)); - gtk_widget_hide (GTK_WIDGET (self->add_contact_button)); + gtk_widget_hide (GTK_WIDGET (self->apply_button)); gtk_widget_show (GTK_WIDGET (self->add_in_contacts_button)); } } @@ -452,8 +496,11 @@ chatty_new_chat_dialog_show (GtkWidget *widget) /* Reset selection list */ g_list_store_remove_all (self->selection_list); - gtk_widget_set_sensitive (self->start_button, FALSE); + gtk_widget_set_sensitive (self->apply_button, FALSE); gtk_entry_set_text (GTK_ENTRY (self->contacts_search_entry), ""); + gtk_stack_set_visible_child (GTK_STACK (self->main_stack), self->contact_list_view); + new_chat_dialog_page_changed_cb (self); + chatty_new_chat_dialog_set_multi_selection (self, self->multi_selection); GTK_WIDGET_CLASS (chatty_new_chat_dialog_parent_class)->show (widget); } @@ -482,36 +529,48 @@ chatty_new_chat_dialog_class_init (ChattyNewChatDialogClass *klass) widget_class->show = chatty_new_chat_dialog_show; + signals [SELECTION_CHANGED] = + g_signal_new ("selection-changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, 0); + gtk_widget_class_set_template_from_resource (widget_class, "/sm/puri/Chatty/" "ui/chatty-dialog-new-chat.ui"); - gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, new_chat_stack); - gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, header_view_new_chat); + gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, header_bar); + gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, edit_contact_button); + gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, back_button); + gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, cancel_button); + gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, apply_button); + gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, progress_spinner); + gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, contacts_search_entry); gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, contact_list); gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, contact_edit_grid); gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, contact_name_entry); gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, contact_alias_entry); gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, accounts_list); - gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, back_button); - gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, edit_contact_button); - gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, add_contact_button); gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, add_in_contacts_button); - gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, start_button); - gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, cancel_button); - gtk_widget_class_bind_template_callback (widget_class, back_button_clicked_cb); + gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, main_stack); + gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, contact_list_view); + gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, add_contact_view); + gtk_widget_class_bind_template_callback (widget_class, edit_contact_button_clicked_cb); + gtk_widget_class_bind_template_callback (widget_class, back_button_clicked_cb); + gtk_widget_class_bind_template_callback (widget_class, cancel_button_clicked_cb); + gtk_widget_class_bind_template_callback (widget_class, new_chat_dialog_apply_button_clicked_cb); + + gtk_widget_class_bind_template_callback (widget_class, new_chat_dialog_page_changed_cb); gtk_widget_class_bind_template_callback (widget_class, contact_search_entry_activated_cb); gtk_widget_class_bind_template_callback (widget_class, contact_search_entry_changed_cb); gtk_widget_class_bind_template_callback (widget_class, contact_list_selection_changed_cb); - gtk_widget_class_bind_template_callback (widget_class, add_contact_button_clicked_cb); gtk_widget_class_bind_template_callback (widget_class, add_in_contacts_button_clicked_cb); gtk_widget_class_bind_template_callback (widget_class, contact_name_text_changed_cb); gtk_widget_class_bind_template_callback (widget_class, account_list_row_activated_cb); - gtk_widget_class_bind_template_callback (widget_class, start_button_clicked_cb); - gtk_widget_class_bind_template_callback (widget_class, cancel_button_clicked_cb); } @@ -539,7 +598,6 @@ chatty_new_chat_dialog_new (GtkWindow *parent_window) return g_object_new (CHATTY_TYPE_NEW_CHAT_DIALOG, "transient-for", parent_window, - "use-header-bar", 1, NULL); } diff --git a/src/meson.build b/src/meson.build index 51a19e01..05e8c9f9 100644 --- a/src/meson.build +++ b/src/meson.build @@ -69,7 +69,7 @@ ui_files = files ( # but works fine locally # 'ui/chatty-info-dialog.ui', # 'ui/chatty-dialog-join-muc.ui', - 'ui/chatty-dialog-new-chat.ui', + # 'ui/chatty-dialog-new-chat.ui', 'ui/chatty-fp-row.ui', 'ui/chatty-list-row.ui', 'ui/chatty-message-row.ui', diff --git a/src/ui/chatty-dialog-new-chat.ui b/src/ui/chatty-dialog-new-chat.ui index ff18d9c3..353232af 100644 --- a/src/ui/chatty-dialog-new-chat.ui +++ b/src/ui/chatty-dialog-new-chat.ui @@ -1,167 +1,135 @@ - + + + vertical + + + + + + -- GitLab From 7ada115029497374a8712da655a4c9d742489aa9 Mon Sep 17 00:00:00 2001 From: Mohammed Sadiq Date: Mon, 10 Jan 2022 22:30:52 +0530 Subject: [PATCH 8/8] list-row: Add close button And an API to show it when required --- src/chatty-list-row.c | 31 +++++++++++++++++++++++++++++++ src/chatty-list-row.h | 1 + src/ui/chatty-list-row.ui | 23 +++++++++++++++++++++++ 3 files changed, 55 insertions(+) diff --git a/src/chatty-list-row.c b/src/chatty-list-row.c index e610e1e6..2a7fb0e4 100644 --- a/src/chatty-list-row.c +++ b/src/chatty-list-row.c @@ -18,6 +18,7 @@ #include "chatty-purple.h" #include "chatty-contact.h" +#include "chatty-contact-list.h" #include "chatty-chat.h" #include "chatty-avatar.h" #include "chatty-list-row.h" @@ -39,6 +40,7 @@ struct _ChattyListRow GtkWidget *last_modified; GtkWidget *unread_message_count; GtkWidget *checkbox; + GtkWidget *close_button; GtkWidget *add_contact_button; GtkWidget *call_button; @@ -382,6 +384,24 @@ write_eds_contact_cb (GObject *object, } } +static void +chatty_list_row_delete_clicked_cb (ChattyListRow *self) +{ + GtkWidget *scrolled, *list; + + g_assert (CHATTY_IS_LIST_ROW (self)); + + /* We can't directly use CHATTY_TYPE_CONTACT_LIST as it's not linked with the shared library */ + scrolled = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_SCROLLED_WINDOW); + + if (!scrolled) + return; + + list = gtk_widget_get_parent (scrolled); + if (list) + g_signal_emit_by_name (list, "delete-row", self); +} + static void chatty_list_row_add_contact_clicked_cb (ChattyListRow *self) { @@ -434,6 +454,7 @@ chatty_list_row_class_init (ChattyListRowClass *klass) "ui/chatty-list-row.ui"); gtk_widget_class_bind_template_child (widget_class, ChattyListRow, avatar); gtk_widget_class_bind_template_child (widget_class, ChattyListRow, checkbox); + gtk_widget_class_bind_template_child (widget_class, ChattyListRow, close_button); gtk_widget_class_bind_template_child (widget_class, ChattyListRow, title); gtk_widget_class_bind_template_child (widget_class, ChattyListRow, subtitle); gtk_widget_class_bind_template_child (widget_class, ChattyListRow, last_modified); @@ -441,6 +462,7 @@ chatty_list_row_class_init (ChattyListRowClass *klass) gtk_widget_class_bind_template_child (widget_class, ChattyListRow, add_contact_button); gtk_widget_class_bind_template_child (widget_class, ChattyListRow, call_button); + gtk_widget_class_bind_template_callback (widget_class, chatty_list_row_delete_clicked_cb); gtk_widget_class_bind_template_callback (widget_class, chatty_list_row_add_contact_clicked_cb); gtk_widget_class_bind_template_callback (widget_class, chatty_list_row_call_button_clicked_cb); } @@ -560,3 +582,12 @@ chatty_list_row_set_call (ChattyListRow *self, gboolean enable) } else gtk_widget_hide (self->call_button); } + +void +chatty_list_row_show_delete_button (ChattyListRow *self) +{ + g_return_if_fail (CHATTY_IS_LIST_ROW (self)); + + gtk_widget_show (self->close_button); + gtk_widget_hide (self->checkbox); +} diff --git a/src/chatty-list-row.h b/src/chatty-list-row.h index b4f40d2c..b826549e 100644 --- a/src/chatty-list-row.h +++ b/src/chatty-list-row.h @@ -32,5 +32,6 @@ void chatty_list_row_set_contact (ChattyListRow *self, gboolean enable); void chatty_list_row_set_call (ChattyListRow *self, gboolean enable); +void chatty_list_row_show_delete_button (ChattyListRow *self); G_END_DECLS diff --git a/src/ui/chatty-list-row.ui b/src/ui/chatty-list-row.ui index f9299d8c..ea5901b1 100644 --- a/src/ui/chatty-list-row.ui +++ b/src/ui/chatty-list-row.ui @@ -98,6 +98,29 @@ + + + + 0 + + + + + True + 32 + 32 + edit-delete-symbolic + + + + + 2 + + + -- GitLab