#include "gm-log-view.h" #include "gm-searchable.h" #include "gm-app.h" #include "gm-color-table.h" #include "gm-support.h" #include "gm-options.h" #include "gm-debug.h" #define GM_LOG_VIEW_GET_PRIVATE(object)( \ G_TYPE_INSTANCE_GET_PRIVATE((object), \ GM_TYPE_LOG_VIEW, GmLogViewPrivate)) struct _GmLogViewPrivate { GtkTextView *text_view; }; /* Signals enum { PROTO NUM_SIGNALS }; static guint gm_log_view_signals[NUM_SIGNALS] = {0};*/ static void gm_log_view_searchable_iface_init( GmSearchableInterface *iface); static GtkTextView *gm_log_view_searchable_get_text_view(GmSearchable *sea); void on_gm_log_view_filter_toggled(GtkToggleButton *button, GmLogView *view); G_DEFINE_TYPE_EXTENDED(GmLogView, gm_log_view, GTK_TYPE_VBOX, 0, \ G_IMPLEMENT_INTERFACE(GM_TYPE_SEARCHABLE, \ gm_log_view_searchable_iface_init)) static void gm_log_view_searchable_iface_init(GmSearchableInterface *iface) { iface->get_text_view = gm_log_view_searchable_get_text_view; } static GtkTextView * gm_log_view_searchable_get_text_view(GmSearchable *sea) { GmLogView *view = (GmLogView *)(sea); g_return_val_if_fail(GM_IS_LOG_VIEW(sea), NULL); return view->priv->text_view; } static void gm_log_view_finalize(GObject *object) { //GmLogView *obj = GM_LOG_VIEW(object); G_OBJECT_CLASS(gm_log_view_parent_class)->finalize(object); } static void gm_log_view_class_init(GmLogViewClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS(klass); GmOptions *options; object_class->finalize = gm_log_view_finalize; /*gm_log_view_signals[PROTO] = g_signal_new("proto", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GmLogViewClass, proto), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);*/ options = gm_app_options(gm_app_instance()); g_type_class_add_private(object_class, sizeof(GmLogViewPrivate)); } static void gm_log_view_create_tags(GmLogView *obj) { GtkTextBuffer *buffer = gtk_text_view_get_buffer(obj->priv->text_view); gtk_text_buffer_create_tag(buffer, "in", NULL); gtk_text_buffer_create_tag(buffer, "out", NULL); gtk_text_buffer_create_tag(buffer, "status", NULL); gtk_text_buffer_create_tag(buffer, "mcp_in", NULL); gtk_text_buffer_create_tag(buffer, "mcp_out", NULL); gtk_text_buffer_create_tag(buffer, "mcp_status", NULL); } static void gm_log_view_create_text_view(GmLogView *obj) { GtkTextView *text_view = GTK_TEXT_VIEW(gtk_text_view_new()); gtk_text_view_set_editable(text_view, FALSE); // Margins gtk_text_view_set_left_margin(text_view, 3); gtk_text_view_set_right_margin(text_view, 3); // Set default wrapping mode gtk_text_view_set_wrap_mode(text_view, GTK_WRAP_WORD_CHAR); gtk_widget_show(GTK_WIDGET(text_view)); obj->priv->text_view = text_view; gm_log_view_create_tags(obj); } GtkWidget * gm_log_view_create_filter(GmLogView *obj) { GtkWidget *box = gtk_hbox_new(FALSE, 6); GtkWidget *label = gtk_label_new(_("Filter: ")); GtkWidget *check; GmOptions *options = gm_app_options(gm_app_instance()); gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0); check = gtk_check_button_new_with_label(_("Incoming")); g_object_set_data_full(G_OBJECT(check), "option", g_strdup("in"), g_free); g_signal_connect(check, "toggled", G_CALLBACK(on_gm_log_view_filter_toggled), obj); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), gm_options_get_int(options, "logging_filter_in")); gtk_box_pack_start(GTK_BOX(box), check, FALSE, FALSE, 0); check = gtk_check_button_new_with_label(_("Outgoing")); g_object_set_data_full(G_OBJECT(check), "option", g_strdup("out"), g_free); g_signal_connect(check, "toggled", G_CALLBACK(on_gm_log_view_filter_toggled), obj); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), gm_options_get_int(options, "logging_filter_out")); gtk_box_pack_start(GTK_BOX(box), check, FALSE, FALSE, 0); check = gtk_check_button_new_with_label(_("Status")); g_object_set_data_full(G_OBJECT(check), "option", g_strdup("status"), g_free); g_signal_connect(check, "toggled", G_CALLBACK(on_gm_log_view_filter_toggled), obj); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), gm_options_get_int(options, "logging_filter_status")); gtk_box_pack_start(GTK_BOX(box), check, FALSE, FALSE, 0); check = gtk_check_button_new_with_label(_("Mcp incoming")); g_object_set_data_full(G_OBJECT(check), "option", g_strdup("mcp_in"), g_free); g_signal_connect(check, "toggled", G_CALLBACK(on_gm_log_view_filter_toggled), obj); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), gm_options_get_int(options, "logging_filter_mcp_in")); gtk_box_pack_start(GTK_BOX(box), check, FALSE, FALSE, 0); check = gtk_check_button_new_with_label(_("Mcp outgoing")); g_object_set_data_full(G_OBJECT(check), "option", g_strdup("mcp_out"), g_free); g_signal_connect(check, "toggled", G_CALLBACK(on_gm_log_view_filter_toggled), obj); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), gm_options_get_int(options, "logging_filter_mcp_out")); gtk_box_pack_start(GTK_BOX(box), check, FALSE, FALSE, 0); check = gtk_check_button_new_with_label(_("Mcp status")); g_object_set_data_full(G_OBJECT(check), "option", g_strdup("mcp_status"), g_free); g_signal_connect(check, "toggled", G_CALLBACK(on_gm_log_view_filter_toggled), obj); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), gm_options_get_int(options, "logging_filter_mcp_status")); gtk_box_pack_start(GTK_BOX(box), check, FALSE, FALSE, 0); gtk_container_set_border_width(GTK_CONTAINER(box), 3); gtk_widget_show_all(box); return box; } static void gm_log_view_init(GmLogView *obj) { GtkWidget *srl; obj->priv = GM_LOG_VIEW_GET_PRIVATE(obj); gtk_box_set_spacing(GTK_BOX(obj), 6); gtk_box_set_homogeneous(GTK_BOX(obj), FALSE); gm_log_view_create_text_view(obj); //gtk_box_pack_start(GTK_BOX(obj), gm_log_view_create_filter(obj), FALSE, // FALSE, 0); srl = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(srl), GTK_SHADOW_IN); gtk_widget_show(srl); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(srl), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_container_add(GTK_CONTAINER(srl), GTK_WIDGET(obj->priv->text_view)); gtk_box_pack_start(GTK_BOX(obj), srl, TRUE, TRUE, 0); gm_register_schemed(GTK_WIDGET(obj->priv->text_view), gm_app_color_table( gm_app_instance()), GM_SCHEMED_COLORS | GM_SCHEMED_FONT); } GmLogView * gm_log_view_new() { GmLogView *obj = GM_LOG_VIEW(g_object_new(GM_TYPE_LOG_VIEW, NULL)); return obj; } gchar const * gm_log_view_get_tag(gchar const *last) { switch (last[11]) { case '>': return "out"; break; case '<': return "in"; break; case '#': return "status"; break; case '[': switch (last[17]) { case '>': return "mcp_out"; break; case '<': return "mcp_in"; break; case '#': return "mcp_status"; break; } break; } return NULL; } void gm_log_view_set_text(GmLogView *view, gchar const *text) { GtkTextBuffer *buffer = gtk_text_view_get_buffer(view->priv->text_view); gchar *ptr; gchar const *last = text, *tag; GtkTextIter iter; gtk_text_buffer_get_end_iter(buffer, &iter); tag = gm_log_view_get_tag(text); gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, text, -1, tag, NULL); return; // log format: [hh:mm:ss] >|<|#|[MCP] <|[MCP] > text while ((ptr = g_utf8_strchr(last, -1, '\n'))) { gtk_text_buffer_get_end_iter(buffer, &iter); tag = gm_log_view_get_tag(last); gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, last, ptr - last + 1, tag, NULL); last = ptr + 1; } if (*last != '\0') { gtk_text_buffer_get_end_iter(buffer, &iter); tag = gm_log_view_get_tag(last); gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, last, ptr - last + 1, tag, NULL); } } /* Callbacks */ void on_gm_log_view_filter_toggled(GtkToggleButton *button, GmLogView *view) { gchar *option = (gchar *)g_object_get_data(G_OBJECT(button), "option"); gchar *opt = g_strconcat("logging_filter_", option, NULL); gboolean active = gtk_toggle_button_get_active(button); GmOptions *options = gm_app_options(gm_app_instance()); GtkTextTag *tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table( gtk_text_view_get_buffer(view->priv->text_view)), option); g_object_set(G_OBJECT(tag), "invisible", !active, NULL); gm_options_set_int(options, opt, active); g_free(opt); }