This repository has been archived on 2020-04-11. You can view files and clone it, but cannot push or open issues or pull requests.
gnoemoe/gnoemoe/dialogs/gm-world-paste-dialog.c

328 lines
8.9 KiB
C

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include <gtk/gtk.h>
#include <glade/glade.h>
#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();
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();
}