/soc/2015/igor.gajowiak/chatlog: 4e79be028d92: Implemented log i...
Igor Gajowiak <[email protected]>
| Newsgroups | gmane.comp.gnome.gaim.cvs |
|---|---|
| Message-ID | <[email protected]> |
Changeset: 4e79be028d92a4565da3a29de9a8d235f1d65c2e Author: Igor Gajowiak <[email protected]> Date: 2015-08-08 20:47 +0200 Branch: default URL: https://hg.pidgin.im/soc/2015/igor.gajowiak/chatlog/rev/4e79be028d92 Description: Implemented log import UI. diffstat: libpurple/genericlog.c | 18 ++- libpurple/genericlog.h | 15 ++- pidgin/gtkgenericlog.c | 268 ++++++++++++++++++++++++++++++++++++++++++++++-- pidgin/gtkgenericlog.h | 17 +++ 4 files changed, 297 insertions(+), 21 deletions(-) diffs (truncated from 420 to 300 lines): diff --git a/libpurple/genericlog.c b/libpurple/genericlog.c --- a/libpurple/genericlog.c +++ b/libpurple/genericlog.c @@ -26,7 +26,11 @@ #define PURPLE_GENERICLOG_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_GENERICLOG, PurpleGenericLogPrivate)) -#define PURPLE_GENERICLOG_IMPORT_CHUNK_SIZE 500 +/* Defines how many messages should be imported in a single chunk */ +#define PURPLE_GENERICLOG_IMPORT_CHUNK_SIZE 200 + +/* Defines how much time to wait between importing next chunk */ +#define PURPLE_GENERICLOG_IMPORT_TIMESLICE 20 typedef struct { @@ -53,6 +57,7 @@ typedef struct { PurpleGenericLog *src_log; PurpleGenericLog_OnImportFinished on_finished; + gpointer user_data; void *export_state; guint timer; guint imported_messages_count; @@ -353,7 +358,8 @@ run_import_iteration(gpointer unused) uninit_import_state(import_state); import_state->on_finished(status, - import_state->imported_messages_count); + import_state->imported_messages_count, + import_state->user_data); g_free(import_state); import_state = NULL; @@ -380,7 +386,8 @@ run_import_iteration(gpointer unused) gboolean purple_genericlog_import_msgs(PurpleGenericLog *src_log, - PurpleGenericLog_OnImportFinished on_finished, GError **error) + PurpleGenericLog_OnImportFinished on_finished, gpointer user_data, + GError **error) { if (!purple_genericlog_inuse) { if (!error) return FALSE; @@ -431,10 +438,11 @@ purple_genericlog_import_msgs(PurpleGene import_state = g_new0(PurpleGenericLogImportState, 1); import_state->src_log = src_log; import_state->on_finished = on_finished; + import_state->user_data = user_data; import_state->export_state = export_state; - import_state->timer = purple_timeout_add(1, run_import_iteration, - import_state); + import_state->timer = purple_timeout_add(PURPLE_GENERICLOG_IMPORT_TIMESLICE, + run_import_iteration, import_state); return TRUE; } diff --git a/libpurple/genericlog.h b/libpurple/genericlog.h --- a/libpurple/genericlog.h +++ b/libpurple/genericlog.h @@ -140,7 +140,15 @@ struct _PurpleGenericLogClass void (*reserved4)(void); }; -typedef void (*PurpleGenericLog_OnImportFinished)(gboolean, guint); +/** + * PurpleGenericLog_OnImportFinished: + * @1: The status. + * @2: The number of imported messages. + * @3: The user data. + * + * Called after import had finished. + */ +typedef void (*PurpleGenericLog_OnImportFinished)(gboolean, guint, gpointer); #define PURPLE_GENERICLOG_DEFAULT "genericlog-sqlitelog" @@ -185,7 +193,7 @@ purple_genericlog_get_name(const PurpleG * Returns: A #GList of elements of type #PurpleGenericLog. */ GList* -purple_genericlog_get_registered_logs(); +purple_genericlog_get_registered_logs(void); /** * purple_genericlog_find_by_id: @@ -404,7 +412,8 @@ purple_genericlog_wipe_log_for_buddy(Pur */ gboolean purple_genericlog_import_msgs(PurpleGenericLog *src_log, - PurpleGenericLog_OnImportFinished on_finished, GError **error); + PurpleGenericLog_OnImportFinished on_finished, gpointer user_data, + GError **error); /**************************************************************************/ /* Error Codes */ diff --git a/pidgin/gtkgenericlog.c b/pidgin/gtkgenericlog.c --- a/pidgin/gtkgenericlog.c +++ b/pidgin/gtkgenericlog.c @@ -34,6 +34,254 @@ static PidginGenericLogViewer *generic_log_viewer = NULL; /******************************************************************************/ +/* Import window */ +/******************************************************************************/ + +static const gchar * const labels[] = +{ + "Importing ", + "Importing. ", + "Importing.. ", + "Importing..." +}; + +typedef enum +{ + LOGS_LIST_STORE_LOGID = 0, + LOGS_LIST_STORE_COLS = 1, +} LogsListStore; + +static GtkListStore * +create_logs_store() +{ + /* Stores generic log ids */ + return gtk_list_store_new(LOGS_LIST_STORE_COLS, + G_TYPE_STRING); +} + +static void +populate_logs_store(GtkListStore *store) +{ + g_assert(store); + + gtk_list_store_clear(store); + + PurpleGenericLog *inuse = purple_genericlog_get_inuse(); + + GList *logs = purple_genericlog_get_registered_logs(); + for (; logs != NULL; logs = logs->next) { + PurpleGenericLog *log = PURPLE_GENERICLOG(logs->data); + + if (log == inuse) + continue; + + GtkTreeIter iter; + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, + LOGS_LIST_STORE_LOGID, purple_genericlog_get_id(log), -1); + } +} + +static GtkWidget * +create_logs_combobox(GtkListStore *store) +{ + g_assert(store); + + GtkWidget *combobox = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store)); + + GtkCellRenderer *renderer = gtk_cell_renderer_text_new(); + gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combobox), renderer, TRUE); + gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combobox), renderer, + "text", 0, NULL); + + return combobox; +} + +static gboolean +start_import(PidginGenericLogViewer *viewer); + +static void +update_sensitivity(PidginGenericLogViewer *viewer, gboolean sensitive) +{ + g_assert(viewer); + + gtk_widget_set_sensitive(viewer->window, sensitive); + gtk_widget_set_sensitive(viewer->importer->import_button, sensitive); + gtk_widget_set_sensitive(viewer->importer->close_button, sensitive); +} + +static void +on_import_window_response(GtkWidget *widget, gint resp, gpointer data) +{ + g_assert(data); + + PidginGenericLogViewer *viewer = (PidginGenericLogViewer*) data; + + switch (resp) { + case GTK_RESPONSE_ACCEPT: + { + if (start_import(viewer)) { + /* Block log window until import is done */ + update_sensitivity(viewer, FALSE); + } + return; + } + case GTK_RESPONSE_CLOSE: + { + gtk_widget_hide(viewer->importer->window); + return; + } + } + + /* Not reachable */ + g_assert(FALSE); +} + +static GtkWidget * +create_import_window(PidginGenericLogViewer *viewer, + GtkWindow *parent_window, GtkWidget **logs_combobox_res, + GtkListStore **logs_store_res, GtkWidget **status_label_res, + GtkWidget **import_button_res, GtkWidget **close_button_res) +{ + g_assert(viewer); + g_assert(parent_window); + g_assert(logs_combobox_res); + g_assert(logs_store_res); + g_assert(status_label_res); + g_assert(import_button_res); + g_assert(close_button_res); + + GtkWidget *window = gtk_dialog_new(); + gtk_window_set_title(GTK_WINDOW(window), "Import messages"); + gtk_window_set_transient_for(GTK_WINDOW(window), parent_window); + + GtkWidget *import_button = gtk_dialog_add_button(GTK_DIALOG(window), + "_Import", GTK_RESPONSE_ACCEPT); + GtkWidget *close_button = gtk_dialog_add_button(GTK_DIALOG(window), + "_Close", GTK_RESPONSE_CLOSE); + + g_signal_connect(G_OBJECT(window), "response", + G_CALLBACK(on_import_window_response), viewer); + + GtkListStore *logs_store = create_logs_store(); + populate_logs_store(logs_store); + GtkWidget *logs_combobox = create_logs_combobox(logs_store); + gtk_combo_box_set_active(GTK_COMBO_BOX(logs_combobox), 0); + gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(window))), + logs_combobox, FALSE, FALSE, 0); + + GtkWidget *status_label = gtk_label_new(""); + gtk_box_pack_end(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(window))), + status_label, FALSE, FALSE, 0); + + *logs_combobox_res = logs_combobox; + *logs_store_res = logs_store; + *status_label_res = status_label; + *import_button_res = import_button; + *close_button_res = close_button; + + return window; +} + +static PidginGenericLogImporter * +create_log_importer(PidginGenericLogViewer *viewer) +{ + PidginGenericLogImporter *importer = g_new0(PidginGenericLogImporter, 1); + + importer->iterator = 0; + importer->window = create_import_window(viewer, GTK_WINDOW(viewer->window), + &importer->logs_combobox, &importer->logs_store, + &importer->status_label, &importer->import_button, + &importer->close_button); + + return importer; +} + +static gboolean +update_importer_label(gpointer data) +{ + g_assert(data); + + PidginGenericLogImporter *importer = (PidginGenericLogImporter*) data; + + importer->iterator = (importer->iterator + 1) % + (sizeof(labels) / sizeof(labels[0])); + gtk_label_set_markup(GTK_LABEL(importer->status_label), + labels[importer->iterator]); + + return TRUE; +} + +static void +on_import_finished(gboolean status, guint msg_count, gpointer data) +{ + g_assert(data); + + PidginGenericLogViewer *viewer = (PidginGenericLogViewer*) data; + PidginGenericLogImporter *importer = viewer->importer; + + g_assert(importer); + + purple_timeout_remove(importer->timer); + importer->iterator = 0; + + const gchar *format = status ? "Import succeeded, imported %u messages\n" + : "Error occured during import, imported %u messages\n"; + + gchar *text = g_strdup_printf(format, msg_count); + gtk_label_set_markup(GTK_LABEL(importer->status_label), text); _______________________________________________ Commits mailing list [email protected] https://pidgin.im/cgi-bin/mailman/listinfo/commits