/soc/2015/igor.gajowiak/chatlog: 4e79be028d92: Implemented log i...
Igor Gajowiak
igor.gajowiak at gmail.com
Sat Aug 8 14:47:44 EDT 2015
Changeset: 4e79be028d92a4565da3a29de9a8d235f1d65c2e
Author: Igor Gajowiak <igor.gajowiak at gmail.com>
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);
More information about the Commits
mailing list