#ifdef HAVE_CONFIG_H # include #endif #include #include #include #include "gm-support.h" #include "gm-debug.h" #include "gm-app.h" #include "gm-world-paste-dialog.h" #include "widgets/gm-world-view.h" #include "mcp/gm-mcp-userlist-view.h" typedef struct _GmWorldPasteDialog { GladeXML *xml; GtkWidget *dialog; GmAppView *view; GtkTreeModel *model; } GmWorldPasteDialog; static void on_gm_world_paste_dialog_response(GtkDialog *dialog, gint response, gpointer user_data); static void on_gm_world_paste_dialog_active_world_changed(GmAppView *view, GmWorldView *world_view); static GmWorldPasteDialog *gm_world_paste_dialog_instance; static GtkWidget * gm_world_paste_dialog_widget(gchar *name) { return glade_xml_get_widget(gm_world_paste_dialog_instance->xml, name); } #define GM_WORLD_PASTE_DIALOG_XML PACKAGE_DATA_DIR "/" PACKAGE \ "/ui/gm-world-paste.glade" static gchar const *commands[] = { "@paste", "@chanpaste", NULL }; static void gm_world_paste_dialog_init_command() { GtkComboBox *combo_box = GTK_COMBO_BOX( gm_world_paste_dialog_widget("combo_box_command")); gchar const **command; for (command = commands; *command; ++command) { gtk_combo_box_append_text(combo_box, *command); } gtk_combo_box_set_active(combo_box, 0); } static void gm_world_paste_dialog_remove_model(gpointer data, GObject *model, gboolean is_last_ref) { GtkWidget *widget; if (is_last_ref) { widget = gm_world_paste_dialog_widget("combo_box_to"); gtk_combo_box_set_model(GTK_COMBO_BOX(widget), NULL); gm_world_paste_dialog_instance->model = NULL; } } static void gm_world_paste_dialog_fill_to() { GtkWidget *widget = gm_world_paste_dialog_widget("combo_box_to"); GmWorldView *view = gm_app_view_active_world_view( gm_world_paste_dialog_instance->view); GtkWidget *paned = GTK_WIDGET(gm_world_view_hpaned(view)); GtkWidget *tree_view = gm_find_child(paned, GTK_TYPE_TREE_VIEW); GtkTreeModel *model; GtkTreeModel *sorted; if (gm_world_paste_dialog_instance->model != NULL) { g_object_ref(gm_world_paste_dialog_instance->model); g_object_remove_toggle_ref( G_OBJECT(gm_world_paste_dialog_instance->model), gm_world_paste_dialog_remove_model, NULL); } gtk_combo_box_set_model(GTK_COMBO_BOX(widget), NULL); if (tree_view == NULL) { gm_world_paste_dialog_instance->model = NULL; return; } model = gtk_tree_view_get_model(GTK_TREE_VIEW(tree_view)); if (GTK_IS_TREE_MODEL_SORT(model)) { model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(model)); } g_object_add_toggle_ref(G_OBJECT(model), gm_world_paste_dialog_remove_model, NULL); g_object_unref(G_OBJECT(model)); gm_world_paste_dialog_instance->model = model; sorted = gtk_tree_model_sort_new_with_model(model); gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(sorted), GM_USERLIST_NAME, GTK_SORT_ASCENDING); gtk_combo_box_set_model(GTK_COMBO_BOX(widget), sorted); if (gtk_combo_box_entry_get_text_column( GTK_COMBO_BOX_ENTRY(widget)) == -1) { gtk_combo_box_entry_set_text_column(GTK_COMBO_BOX_ENTRY(widget), GM_USERLIST_NAME); } } static void gm_world_paste_dialog_init_to() { GtkWidget *widget = gm_world_paste_dialog_widget("combo_box_to"); GtkCellRenderer *cell; cell = gtk_cell_renderer_pixbuf_new(); gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(widget), cell, FALSE); gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(widget), cell, "pixbuf", GM_USERLIST_ICON); gtk_cell_layout_reorder(GTK_CELL_LAYOUT(widget), cell, 0); gm_world_paste_dialog_fill_to(); } static void gm_world_paste_dialog_init_text() { GtkWidget *widget = gm_world_paste_dialog_widget("text_view_text"); GtkClipboard *clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY); gchar *text = gtk_clipboard_wait_for_text(clipboard); if (text != NULL) { gtk_text_buffer_set_text(gtk_text_view_get_buffer( GTK_TEXT_VIEW(widget)), text, -1); } g_free(text); } static void gm_world_paste_dialog_init_end_with() { gtk_entry_set_text(GTK_ENTRY(gm_world_paste_dialog_widget( "entry_end_with")), "."); } void gm_world_paste_dialog_run(GmAppView *view) { GladeXML *xml; if (gm_world_paste_dialog_instance) { if (view != gm_world_paste_dialog_instance->view) { g_signal_handlers_disconnect_by_func(view, G_CALLBACK(on_gm_world_paste_dialog_active_world_changed), NULL); g_signal_connect(view, "active_world_changed", G_CALLBACK(on_gm_world_paste_dialog_active_world_changed), NULL); } gm_world_paste_dialog_fill_to(); gtk_widget_show(gm_world_paste_dialog_instance->dialog); gtk_window_present(GTK_WINDOW(gm_world_paste_dialog_instance->dialog)); return; } xml = glade_xml_new(GM_WORLD_PASTE_DIALOG_XML, "gm_world_paste_dialog", NULL); if (xml == NULL) { gm_debug_msg(DEBUG_ALWAYS, "Couldn't find glade file %s!", GM_WORLD_PASTE_DIALOG_XML); return; } gm_world_paste_dialog_instance = g_new0(GmWorldPasteDialog, 1); gm_world_paste_dialog_instance->xml = xml; gm_world_paste_dialog_instance->view = view; gm_world_paste_dialog_instance->dialog = gm_world_paste_dialog_widget("gm_world_paste_dialog"); gtk_window_set_transient_for(GTK_WINDOW( gm_world_paste_dialog_instance->dialog), GTK_WINDOW(view)); g_signal_connect(gm_world_paste_dialog_instance->dialog, "response", G_CALLBACK(on_gm_world_paste_dialog_response), NULL); g_signal_connect(view, "active_world_changed", G_CALLBACK(on_gm_world_paste_dialog_active_world_changed), NULL); gtk_widget_show(gm_world_paste_dialog_instance->dialog); gm_world_paste_dialog_init_command(); gm_world_paste_dialog_init_to(); gm_world_paste_dialog_init_text(); gm_world_paste_dialog_init_end_with(); } static void gm_world_paste_dialog_send_text(GmWorld *world, gchar const *end_with) { GtkTextView *text_view = GTK_TEXT_VIEW( gm_world_paste_dialog_widget("text_view_text")); GtkTextBuffer *buffer = gtk_text_view_get_buffer(text_view); GtkTextIter start, end; gchar *text; gchar **lines, **ptr; gchar *escape = NULL; gtk_text_buffer_get_bounds(buffer, &start, &end); text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE); lines = g_strsplit(text, "\n", -1); if (end_with) { escape = g_strconcat(end_with, end_with, NULL); } for (ptr = lines; *ptr; ++ptr) { if (escape != NULL && strcmp(end_with, *ptr) == 0) { gm_world_sendln(world, escape); } else { gm_world_sendln(world, *ptr); } } g_strfreev(lines); g_free(text); g_free(escape); } static gchar * gm_world_paste_get_to() { GtkComboBox *combo = GTK_COMBO_BOX( gm_world_paste_dialog_widget("combo_box_to")); gint active = gtk_combo_box_get_active(combo); gchar *text; gint id; GtkTreeModel *model = gtk_combo_box_get_model(combo); GtkTreeIter iter; if (!gtk_combo_box_get_active_iter(combo, &iter) || active == -1) { text = gtk_combo_box_get_active_text(combo); } else { gtk_tree_model_get(model, &iter, GM_USERLIST_ID, &id, -1); text = g_strdup_printf("#%d", id); } return text; } static void gm_world_paste_dialog_do_paste() { GmWorld *world = gm_app_view_active_world( gm_world_paste_dialog_instance->view); gchar *command = gtk_combo_box_get_active_text(GTK_COMBO_BOX( gm_world_paste_dialog_widget("combo_box_command"))); gchar *to = gm_world_paste_get_to(); gchar *cmd; gchar const *end_with; if (!gm_world_connected(world)) { gm_error_dialog(_("The current world is not connected"), GTK_WINDOW(gm_world_paste_dialog_instance->dialog)); } else if (command == NULL) { gm_error_dialog(_("Please specify a command to be send"), GTK_WINDOW(gm_world_paste_dialog_instance->dialog)); } else { if (to && *to != '\0') { cmd = g_strconcat(command, " ", to, NULL); } else { cmd = g_strdup(command); } gm_world_sendln(world, cmd); g_free(cmd); end_with = gtk_entry_get_text(GTK_ENTRY( gm_world_paste_dialog_widget("entry_end_with"))); gm_world_paste_dialog_send_text(world, end_with); if (end_with) { gm_world_sendln(world, end_with); } } g_free(command); g_free(to); } // Callbacks static void on_gm_world_paste_dialog_response(GtkDialog *dialog, gint response, gpointer user_data) { if (response == GTK_RESPONSE_APPLY) { gm_world_paste_dialog_do_paste(); } else { if (gm_world_paste_dialog_instance->model != NULL) { g_object_ref(gm_world_paste_dialog_instance->model); g_object_remove_toggle_ref( G_OBJECT(gm_world_paste_dialog_instance->model), gm_world_paste_dialog_remove_model, NULL); } g_signal_handlers_disconnect_by_func( gm_world_paste_dialog_instance->view, G_CALLBACK(on_gm_world_paste_dialog_active_world_changed), NULL); g_object_unref(gm_world_paste_dialog_instance->xml); gtk_widget_destroy(gm_world_paste_dialog_instance->dialog); g_free(gm_world_paste_dialog_instance); gm_world_paste_dialog_instance = NULL; } } static void on_gm_world_paste_dialog_active_world_changed(GmAppView *view, GmWorldView *world_view) { gm_world_paste_dialog_fill_to(); }