328 lines
8.9 KiB
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();
|
|
}
|