/soc/2015/igor.gajowiak/chatlog: 227f25d5bef9: Implemented searc...
Igor Gajowiak <[email protected]>
| Newsgroups | gmane.comp.gnome.gaim.cvs |
|---|---|
| Message-ID | <[email protected]> |
Changeset: 227f25d5bef9715bf5d16b9950b0d2cd3344e2cc Author: Igor Gajowiak <[email protected]> Date: 2015-08-11 23:29 +0200 Branch: default URL: https://hg.pidgin.im/soc/2015/igor.gajowiak/chatlog/rev/227f25d5bef9 Description: Implemented searching for messages containing given phrase. diffstat: libpurple/genericlog.c | 11 + libpurple/genericlog.h | 28 ++++ libpurple/plugins/log/logsqlite.c | 66 ++++++++++ pidgin/gtkgenericlog.c | 246 ++++++++++++++++++++++++++++++++++--- pidgin/gtkgenericlog.h | 12 + 5 files changed, 338 insertions(+), 25 deletions(-) diffs (truncated from 636 to 300 lines): diff --git a/libpurple/genericlog.c b/libpurple/genericlog.c --- a/libpurple/genericlog.c +++ b/libpurple/genericlog.c @@ -311,6 +311,16 @@ purple_genericlog_get_older_msgs(PurpleB } gboolean +purple_genericlog_find_msgs(PurpleBlistNode *contact, const gchar* pattern, + guint limit, guint offset, GList** result, GError** error) +{ + DEFINE_GENERICLOG_FUNC_WITH_RETURN(find_msgs, + "%s does not support searching messages", + "Searching messages from %s failed", + contact, pattern, limit, offset, result); +} + +gboolean purple_genericlog_get_all_contacts(GList** result, GError** error) { DEFINE_GENERICLOG_FUNC_WITH_RETURN(get_all_contacts, @@ -566,6 +576,7 @@ purple_genericlog_class_init(PurpleGener klass->get_all_contacts = NULL; klass->get_all_days = NULL; klass->wipe_log_for_contact = NULL; + klass->find_msgs = NULL; klass->init_export = NULL; klass->read_chunk = NULL; klass->finalize_export = NULL; diff --git a/libpurple/genericlog.h b/libpurple/genericlog.h --- a/libpurple/genericlog.h +++ b/libpurple/genericlog.h @@ -74,6 +74,9 @@ struct _PurpleGenericLog * then upper bound check is skipped. Messages are sorted * by their timestamp in descending order. * Returns %TRUE if operation succeeds, %FALSE otherwise. + * @find_msgs: Gets a list of messages sent to or received from a given + * contact containing given phrase. Messages should be sorted + * by their timestamp in descending order. * @get_all_contacts: Gets a list of all #PurpleBlistNode objects with at least * one message in the log. Returns %TRUE if operation * succeeds, %FALSE otherwise. The client is responsible for @@ -127,6 +130,9 @@ struct _PurpleGenericLogClass gboolean (*get_older_msgs)(PurpleBlistNode *contact, guint64 timestamp, PurpleMessage *message, GList **result); + gboolean (*find_msgs)(PurpleBlistNode *contact, const gchar* pattern, + guint limit, guint offset, GList **result); + gboolean (*get_all_contacts)(GList **result); gboolean (*get_all_days)(PurpleBlistNode *contact, GArray **result); @@ -354,6 +360,28 @@ purple_genericlog_get_older_msgs(PurpleB PurpleMessage *message, GList **result, GError **error); /** + * purple_genericlog_find_msgs: + * @contact: The contact, must be PurpleChat or PurpleBuddy. + * @phrase: The phrase to search for. + * @limit: The limit of the size of the result. + * @offset: The number of messages to skip. + * @result[out]: The return location for the result. Contains objects of + * type #PurpleMessage. + * @error: Return location for a #GError or %NULL. If provided, this + * will be set to the reason if getting messages fails. + * + * Gets a list of messages sent to or received from a given contact containing + * given phrase from the active log. + * + * Messages are sorted by their timestamp in descending order. + * + * Returns: %TRUE if succeeds, %FALSE otherwise. + */ +gboolean +purple_genericlog_find_msgs(PurpleBlistNode *contact, const gchar* phrase, + guint limit, guint offset, GList **result, GError **error); + +/** * purple_genericlog_get_all_contacts: * @result[out]: Return location for a #GList containing a list of #PurpleBuddy * objects. This will not be set in case of any errors. diff --git a/libpurple/plugins/log/logsqlite.c b/libpurple/plugins/log/logsqlite.c --- a/libpurple/plugins/log/logsqlite.c +++ b/libpurple/plugins/log/logsqlite.c @@ -216,6 +216,22 @@ typedef enum GET_OLDER_MSGS_UPPER_QUERY_PARAM_EXCEPTID = 4, } GetOlderMsgsUpperQueryParam; +static sqlite3_stmt *find_msgs_q = NULL; + +static const char *find_msgs_q_str = + "SELECT Id, Author, AuthorAlias, Recipient, Contents, MsgTime, Flags " + "FROM Messages " + "WHERE ContactId = ?1 AND Contents LIKE '%' || ?2 || '%' " + "ORDER BY MsgTime DESC, Id DESC LIMIT ?3 OFFSET ?4;"; + +typedef enum +{ + FIND_MSGS_QUERY_PARAM_CONTACTYID = 1, + FIND_MSGS_QUERY_PARAM_PATTERN = 2, + FIND_MSGS_QUERY_PARAM_LIMIT = 3, + FIND_MSGS_QUERY_PARAM_OFFSET = 4, +} FindMsgsQueryParam; + typedef enum { GET_MSGS_QUERY_COL_ID = 0, @@ -306,6 +322,7 @@ sqlitelog_finalize_queries() sqlitelog_finalize_query(&get_all_msgs_q); sqlitelog_finalize_query(&get_older_msgs_q); sqlitelog_finalize_query(&get_older_msgs_upper_q); + sqlitelog_finalize_query(&find_msgs_q); sqlitelog_finalize_query(&mark_as_seen_q); sqlitelog_finalize_query(&get_all_contacts_q); sqlitelog_finalize_query(&get_all_days_q); @@ -354,6 +371,7 @@ sqlitelog_prepare_queries() !sqlitelog_prepare_query(get_older_msgs_q_str, &get_older_msgs_q) || !sqlitelog_prepare_query(get_older_msgs_upper_q_str, &get_older_msgs_upper_q) || + !sqlitelog_prepare_query(find_msgs_q_str, &find_msgs_q) || !sqlitelog_prepare_query(mark_as_seen_q_str, &mark_as_seen_q) || !sqlitelog_prepare_query(get_all_contacts_q_str, &get_all_contacts_q) || !sqlitelog_prepare_query(get_all_days_q_str, &get_all_days_q) || @@ -928,6 +946,37 @@ sqlitelog_get_older_msgs_upper_impl(Purp } static gboolean +sqlitelog_find_msgs_impl(PurpleBlistNode *contact, const gchar *pattern, + guint limit, guint offset, GList **result) +{ + g_assert(contact); + g_assert(pattern); + g_assert(result); + + guint contact_id; + if (!sqlitelog_get_contact_id_from_obj(contact, &contact_id)) + return FALSE; + + if (contact_id == SQLITELOG_DB_ID_NONE) { + *result = NULL; + return TRUE; + } + + if (sqlite3_bind_int64(find_msgs_q, FIND_MSGS_QUERY_PARAM_CONTACTYID, + contact_id) != SQLITE_OK || + sqlite3_bind_text(find_msgs_q, FIND_MSGS_QUERY_PARAM_PATTERN, + pattern, -1, SQLITE_STATIC) != SQLITE_OK || + sqlite3_bind_int64(find_msgs_q, FIND_MSGS_QUERY_PARAM_LIMIT, limit) + != SQLITE_OK || + sqlite3_bind_int64(find_msgs_q, FIND_MSGS_QUERY_PARAM_OFFSET, offset) + != SQLITE_OK) { + return FALSE; + } + + return sqlitelog_execute_get_msgs_query(find_msgs_q, result); +} + +static gboolean sqlitelog_mark_as_seen_impl(unsigned msg_id) { g_assert(msg_id != SQLITELOG_DB_ID_NONE); @@ -1282,6 +1331,22 @@ sqlitelog_get_older_msgs(PurpleBlistNode } static gboolean +sqlitelog_find_msgs(PurpleBlistNode *contact, const gchar *pattern, guint limit, + guint offset, GList **result) +{ + g_return_val_if_fail(contact != NULL, FALSE); + g_return_val_if_fail(pattern != NULL, FALSE); + g_return_val_if_fail(result != NULL, FALSE); + + if (!sqlitelog_db_handle) { + purple_debug_error(SQLITELOG_DEBUG_CATEGORY, "Log is not active"); + return FALSE; + } + + return sqlitelog_find_msgs_impl(contact, pattern, limit, offset, result); +} + +static gboolean sqlitelog_get_all_contacts(GList **result) { g_return_val_if_fail(result != NULL, FALSE); @@ -1370,6 +1435,7 @@ purple_sqlitelog_class_init (PurpleSqlit klass->parent_class.get_unseen_msgs = sqlitelog_get_unseen_msgs; klass->parent_class.get_all_msgs = sqlitelog_get_all_msgs; klass->parent_class.get_older_msgs = sqlitelog_get_older_msgs; + klass->parent_class.find_msgs = sqlitelog_find_msgs; klass->parent_class.get_all_contacts = sqlitelog_get_all_contacts; klass->parent_class.get_all_days = sqlitelog_get_all_days; klass->parent_class.wipe_log_for_contact = diff --git a/pidgin/gtkgenericlog.c b/pidgin/gtkgenericlog.c --- a/pidgin/gtkgenericlog.c +++ b/pidgin/gtkgenericlog.c @@ -30,6 +30,7 @@ #include "gtkwebview.h" #define GTKGENERICLOG_DEBUG_CATEGORY "gtkgenericlog" +#define GTKGENERICLOG_SEARCH_CHUNK_SIZE 50 static PidginGenericLogViewer *generic_log_viewer = NULL; @@ -307,10 +308,26 @@ on_reload_item_clicked(GtkAction *action GTK_TREE_MODEL(viewer->blist_tree_store)); } +static PidginGenericLogMsgFinder* +create_msg_finder(PidginGenericLogViewer *viewer); + +static void +reset_find_state(PidginGenericLogViewer *viewer); + static void on_search_item_clicked(GtkAction *action, gpointer data) { - printf("on_search_item_clicked\n"); + g_assert(data); + + PidginGenericLogViewer *viewer = (PidginGenericLogViewer*) data; + + if (!viewer->finder) + viewer->finder = create_msg_finder(viewer); + + reset_find_state(viewer); + + gtk_widget_show_all(viewer->finder->window); + gtk_widget_grab_focus(viewer->finder->entry); } static void @@ -348,7 +365,8 @@ on_print_item_clicked(GtkAction *action, } static GtkWidget * -create_archive_menu_item(PidginGenericLogViewer *viewer) +create_archive_menu_item(PidginGenericLogViewer *viewer, + GtkWidget **search_item_res) { g_assert(viewer); @@ -384,6 +402,8 @@ create_archive_menu_item(PidginGenericLo g_signal_connect(G_OBJECT(close_item), "activate", G_CALLBACK(on_close_item_clicked), viewer); + *search_item_res = search_item; + return archive_item; } @@ -545,13 +565,15 @@ create_contact_menu_item(PidginGenericLo static GtkWidget * create_menu_bar(PidginGenericLogViewer *viewer, GtkWidget **start_conversation_item_res, - GtkWidget **wipe_log_for_contact_item_res) + GtkWidget **wipe_log_for_contact_item_res, + GtkWidget **search_item_res) { g_assert(viewer); GtkWidget *menu_bar = gtk_menu_bar_new(); - GtkWidget *archive_item = create_archive_menu_item(viewer); + GtkWidget *archive_item = create_archive_menu_item(viewer, + search_item_res); gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), archive_item); GtkWidget *options_item = create_options_menu_item(viewer); @@ -569,12 +591,12 @@ update_menu_buttons(PidginGenericLogView { g_assert(viewer); - gboolean start_conv_enabled = TRUE; - gboolean wipe_log_enabled = TRUE; + gboolean contact_selected = TRUE; + gboolean account_enabled = TRUE; if (!viewer->current_contact) { - start_conv_enabled = FALSE; - wipe_log_enabled = FALSE; + contact_selected = FALSE; + account_enabled = FALSE; } else { PurpleAccount *account = get_account_from_contact( @@ -582,13 +604,14 @@ update_menu_buttons(PidginGenericLogView /* Disable start conversation button if account is disabled */ if (!account || !purple_account_get_connection(account)) - start_conv_enabled = FALSE; + account_enabled = FALSE; } gtk_widget_set_sensitive(viewer->start_conversation_item, - start_conv_enabled); + contact_selected && account_enabled); gtk_widget_set_sensitive(viewer->wipe_log_for_contact_item, - wipe_log_enabled); + contact_selected); + gtk_widget_set_sensitive(viewer->search_item, contact_selected); } _______________________________________________ Commits mailing list [email protected] https://pidgin.im/cgi-bin/mailman/listinfo/commits