summaryrefslogtreecommitdiff
path: root/libpurple
diff options
context:
space:
mode:
authorGary Kramlich <grim@reaperworld.com>2023-02-17 19:32:38 -0600
committerGary Kramlich <grim@reaperworld.com>2023-02-17 19:32:38 -0600
commitf543bef1f1b1cfd8bae65ebeb1bd63a4afc2a571 (patch)
tree2c367c3f8195e6a945525e95a46eb538b2927d83 /libpurple
parentde0e4ee342fcec353b31434060feea0e01e89077 (diff)
downloadpidgin-f543bef1f1b1cfd8bae65ebeb1bd63a4afc2a571.tar.gz
Add search support to the contact list
This searches everything in `PurplePerson` and all of it's contacts, but does not yet cover tags. I am planning on covering that in another review request. Right now the matching is just using `strstr`, but will will update this as part of [PIDGIN-17737](https://issues.imfreedom.org/issue/PIDGIN-17737/). I also tried to figure out how to get focus back to the list view, but didn't come up with any viable solutions. Testing Done: Ran the unit tests and did a bunch of searches in the contact list with the demo protocol plugin. Bugs closed: PIDGIN-17717 Reviewed at https://reviews.imfreedom.org/r/2211/
Diffstat (limited to 'libpurple')
-rw-r--r--libpurple/purplecontactinfo.c40
-rw-r--r--libpurple/purplecontactinfo.h16
-rw-r--r--libpurple/purpleperson.c34
-rw-r--r--libpurple/purpleperson.h17
-rw-r--r--libpurple/tests/test_contact_info.c91
-rw-r--r--libpurple/tests/test_person.c58
6 files changed, 255 insertions, 1 deletions
diff --git a/libpurple/purplecontactinfo.c b/libpurple/purplecontactinfo.c
index 9f29f8a509..4d73ee3fd2 100644
--- a/libpurple/purplecontactinfo.c
+++ b/libpurple/purplecontactinfo.c
@@ -797,3 +797,43 @@ purple_contact_info_compare(PurpleContactInfo *a, PurpleContactInfo *b) {
return purple_utf8_strcasecmp(name_a, name_b);
}
+
+gboolean
+purple_contact_info_matches(PurpleContactInfo *info, const char *needle) {
+ PurpleContactInfoPrivate *priv = NULL;
+
+ g_return_val_if_fail(PURPLE_IS_CONTACT_INFO(info), FALSE);
+
+ if(purple_strempty(needle)) {
+ return TRUE;
+ }
+
+ priv = purple_contact_info_get_instance_private(info);
+
+ if(!purple_strempty(priv->id)) {
+ if(strstr(priv->id, needle) != NULL) {
+ return TRUE;
+ }
+ }
+
+ if(!purple_strempty(priv->username)) {
+ if(strstr(priv->username, needle) != NULL) {
+ return TRUE;
+ }
+ }
+
+ if(!purple_strempty(priv->alias)) {
+ if(strstr(priv->alias, needle) != NULL) {
+ return TRUE;
+ }
+ }
+
+ if(!purple_strempty(priv->display_name)) {
+ if(strstr(priv->display_name, needle) != NULL) {
+ return TRUE;
+ }
+ }
+
+ /* Nothing matched, so return FALSE. */
+ return FALSE;
+}
diff --git a/libpurple/purplecontactinfo.h b/libpurple/purplecontactinfo.h
index f0ef858521..e1bfc3ea7d 100644
--- a/libpurple/purplecontactinfo.h
+++ b/libpurple/purplecontactinfo.h
@@ -355,6 +355,22 @@ const char *purple_contact_info_get_name_for_display(PurpleContactInfo *info);
*/
int purple_contact_info_compare(PurpleContactInfo *a, PurpleContactInfo *b);
+/**
+ * purple_contact_info_matches:
+ * @info: The instance.
+ * @needle: (nullable): The string to match.
+ *
+ * This will determine if the alias, display name, or username matches @needle.
+ *
+ * If @needle is %NULL or empty string, %TRUE will be returned.
+ *
+ * Returns: %TRUE if @needle matches any of the above properties, otherwise
+ * %FALSE.
+ *
+ * Since: 3.0.0
+ */
+gboolean purple_contact_info_matches(PurpleContactInfo *info, const char *needle);
+
G_END_DECLS
#endif /* PURPLE_CONTACT_INFO_H */
diff --git a/libpurple/purpleperson.c b/libpurple/purpleperson.c
index 14d4cb1885..8545d653e0 100644
--- a/libpurple/purpleperson.c
+++ b/libpurple/purpleperson.c
@@ -20,6 +20,8 @@
#include "util.h"
+#include "util.h"
+
struct _PurplePerson {
GObject parent;
@@ -122,6 +124,17 @@ purple_person_sort_contacts(PurplePerson *person) {
}
}
+/* This function is used by purple_person_matches to determine if a contact info
+ * matches the needle.
+ */
+static gboolean
+purple_person_matches_find_func(gconstpointer a, gconstpointer b) {
+ PurpleContactInfo *info = (gpointer)a;
+ const char *needle = b;
+
+ return purple_contact_info_matches(info, needle);
+}
+
/******************************************************************************
* Callbacks
*****************************************************************************/
@@ -569,3 +582,24 @@ purple_person_has_contacts(PurplePerson *person) {
return person->contacts->len > 0;
}
+
+gboolean
+purple_person_matches(PurplePerson *person, const char *needle) {
+ g_return_val_if_fail(PURPLE_IS_PERSON(person), FALSE);
+
+ if(purple_strempty(needle)) {
+ return TRUE;
+ }
+
+ /* Check if the person's alias matches. */
+ if(!purple_strempty(person->alias)) {
+ if(strstr(person->alias, needle) != NULL) {
+ return TRUE;
+ }
+ }
+
+ /* See if any of the contact infos match. */
+ return g_ptr_array_find_with_equal_func(person->contacts, needle,
+ purple_person_matches_find_func,
+ NULL);
+}
diff --git a/libpurple/purpleperson.h b/libpurple/purpleperson.h
index a7a64bed73..5d7111a5e6 100644
--- a/libpurple/purpleperson.h
+++ b/libpurple/purpleperson.h
@@ -220,6 +220,23 @@ PurpleContactInfo *purple_person_get_priority_contact_info(PurplePerson *person)
*/
gboolean purple_person_has_contacts(PurplePerson *person);
+/**
+ * purple_person_matches:
+ * @person: The instance.
+ * @needle: (nullable): The string to match on.
+ *
+ * Checks if the alias matches @needle. This also checks @needle against
+ * [method@Purple.ContactInfo.matches] for each [class@Purple.ContactInfo] that
+ * @person is tracking.
+ *
+ * If @needle is %NULL or empty string, %TRUE will be returned.
+ *
+ * Returns: %TRUE if @person matches @needle in any way.
+ *
+ * Since: 3.0.0
+ */
+gboolean purple_person_matches(PurplePerson *person, const char *needle);
+
G_END_DECLS
#endif /* PURPLE_PERSON_H */
diff --git a/libpurple/tests/test_contact_info.c b/libpurple/tests/test_contact_info.c
index cea1ed90e6..5584cf1e1f 100644
--- a/libpurple/tests/test_contact_info.c
+++ b/libpurple/tests/test_contact_info.c
@@ -315,6 +315,82 @@ test_purple_contact_info_compare_name__name(void) {
}
/******************************************************************************
+ * Matches
+ *****************************************************************************/
+static void
+test_purple_contact_info_matches_accepts_null(void) {
+ PurpleContactInfo *info = purple_contact_info_new(NULL);
+
+ g_assert_true(purple_contact_info_matches(info, NULL));
+
+ g_clear_object(&info);
+}
+
+static void
+test_purple_contact_info_matches_empty_string(void) {
+ PurpleContactInfo *info = purple_contact_info_new(NULL);
+
+ g_assert_true(purple_contact_info_matches(info, ""));
+
+ g_clear_object(&info);
+}
+
+static void
+test_purple_contact_info_matches_id(void) {
+ PurpleContactInfo *info = purple_contact_info_new("this is an id");
+
+ g_assert_true(purple_contact_info_matches(info, "an"));
+
+ g_clear_object(&info);
+}
+
+static void
+test_purple_contact_info_matches_username(void) {
+ PurpleContactInfo *info = purple_contact_info_new(NULL);
+
+ purple_contact_info_set_username(info, "username");
+
+ g_assert_true(purple_contact_info_matches(info, "name"));
+
+ g_clear_object(&info);
+}
+
+static void
+test_purple_contact_info_matches_alias(void) {
+ PurpleContactInfo *info = purple_contact_info_new(NULL);
+
+ purple_contact_info_set_alias(info, "alias");
+
+ g_assert_true(purple_contact_info_matches(info, "lia"));
+
+ g_clear_object(&info);
+}
+
+static void
+test_purple_contact_info_matches_display_name(void) {
+ PurpleContactInfo *info = purple_contact_info_new(NULL);
+
+ purple_contact_info_set_display_name(info, "display name");
+
+ g_assert_true(purple_contact_info_matches(info, "play"));
+
+ g_clear_object(&info);
+}
+
+static void
+test_purple_contact_info_matches_none(void) {
+ PurpleContactInfo *info = purple_contact_info_new("id");
+
+ purple_contact_info_set_username(info, "username");
+ purple_contact_info_set_alias(info, "alias");
+ purple_contact_info_set_display_name(info, "display name");
+
+ g_assert_false(purple_contact_info_matches(info, "nothing"));
+
+ g_clear_object(&info);
+}
+
+/******************************************************************************
* Main
*****************************************************************************/
gint
@@ -352,5 +428,20 @@ main(gint argc, gchar *argv[]) {
g_test_add_func("/contact-info/compare/name__name",
test_purple_contact_info_compare_name__name);
+ g_test_add_func("/contact-info/matches/accepts_null",
+ test_purple_contact_info_matches_accepts_null);
+ g_test_add_func("/contact-info/matches/emptry_string",
+ test_purple_contact_info_matches_empty_string);
+ g_test_add_func("/contact-info/matches/id",
+ test_purple_contact_info_matches_id);
+ g_test_add_func("/contact-info/matches/username",
+ test_purple_contact_info_matches_username);
+ g_test_add_func("/contact-info/matches/alias",
+ test_purple_contact_info_matches_alias);
+ g_test_add_func("/contact-info/matches/display_name",
+ test_purple_contact_info_matches_display_name);
+ g_test_add_func("/contact-info/matches/none",
+ test_purple_contact_info_matches_none);
+
return g_test_run();
}
diff --git a/libpurple/tests/test_person.c b/libpurple/tests/test_person.c
index f5e3cb3822..a47852b692 100644
--- a/libpurple/tests/test_person.c
+++ b/libpurple/tests/test_person.c
@@ -443,6 +443,53 @@ test_purple_person_priority_multiple_with_change(void) {
}
/******************************************************************************
+ * Matches tests
+ *****************************************************************************/
+static void
+test_purple_person_matches_accepts_null(void) {
+ PurplePerson *person = purple_person_new();
+
+ g_assert_true(purple_person_matches(person, NULL));
+
+ g_clear_object(&person);
+}
+
+static void
+test_purple_person_matches_empty_string(void) {
+ PurplePerson *person = purple_person_new();
+
+ g_assert_true(purple_person_matches(person, ""));
+
+ g_clear_object(&person);
+}
+
+static void
+test_purple_person_matches_alias(void) {
+ PurplePerson *person = purple_person_new();
+
+ purple_person_set_alias(person, "this is the alias");
+
+ g_assert_true(purple_person_matches(person, "the"));
+ g_assert_false(purple_person_matches(person, "what"));
+
+ g_clear_object(&person);
+}
+
+static void
+test_purple_person_matches_contact_info(void) {
+ PurplePerson *person = purple_person_new();
+ PurpleContactInfo *info = purple_contact_info_new(NULL);
+
+ purple_contact_info_set_username(info, "user1");
+ purple_person_add_contact_info(person, info);
+ g_clear_object(&info);
+
+ g_assert_true(purple_person_matches(person, "user1"));
+
+ g_clear_object(&person);
+}
+
+/******************************************************************************
* Main
*****************************************************************************/
gint
@@ -476,5 +523,14 @@ main(gint argc, gchar *argv[]) {
g_test_add_func("/person/priority/multiple-with-change",
test_purple_person_priority_multiple_with_change);
+ g_test_add_func("/person/matches/accepts_null",
+ test_purple_person_matches_accepts_null);
+ g_test_add_func("/person/matches/empty_string",
+ test_purple_person_matches_empty_string);
+ g_test_add_func("/person/matches/alias",
+ test_purple_person_matches_alias);
+ g_test_add_func("/person/matches/contact_info",
+ test_purple_person_matches_contact_info);
+
return g_test_run();
-} \ No newline at end of file
+}