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-worlds-list-dialog.c

467 lines
14 KiB
C

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>
#include <libgnomeui/libgnomeui.h>
#include "../gm-support.h"
#include "../gm-debug.h"
#include "../gm-app.h"
#include "gm-worlds-list-dialog.h"
#include "gm-world-properties-dialog.h"
#include "../gm-pixbuf.h"
typedef struct _GmWorldsListDialog {
GladeXML *xml;
GtkWidget *dialog;
GtkTreeView *tree_view_worlds;
GtkTreeModel *model_worlds;
} GmWorldsListDialog;
void on_gm_worlds_list_dialog_button_delete_clicked(GtkButton * utton,
gpointer user_data);
void on_gm_worlds_list_dialog_button_new_clicked(GtkButton *button,
gpointer user_data);
void on_gm_worlds_list_dialog_button_modify_clicked(GtkButton *button,
gpointer user_data);
void on_gm_worlds_list_dialog_button_duplicate_clicked(GtkButton *button,
gpointer user_data);
void on_gm_worlds_list_dialog_button_connect_clicked(GtkButton *button,
gpointer user_data);
void on_gm_worlds_list_dialog_tree_view_worlds_key_press(GtkWidget *widget,
GdkEventKey *event, gpointer user_data);
void on_gm_worlds_list_dialog_app_world_added(GmApp *app, GmWorld *world,
gpointer user_data);
void on_gm_worlds_list_dialog_app_world_removed(GmApp *app, GmWorld *world,
gpointer user_data);
void on_gm_worlds_list_dialog_world_option_changed(GmOptions *options,
const gchar *key, GmWorld *world);
void on_gm_worlds_list_dialog_response(GtkDialog *dialog, gint response,
gpointer user_data);
static GmWorldsListDialog *gm_worlds_list_dialog_instance;
enum {
LOGO_COLUMN,
NAME_COLUMN,
WORLD_COLUMN,
N_COLUMNS
};
GtkWidget *
gm_worlds_list_dialog_widget(gchar *name) {
return glade_xml_get_widget(gm_worlds_list_dialog_instance->xml, name);
}
gchar *
gm_worlds_list_dialog_world_text(GmWorld *world) {
gchar *text;
const gchar *player, *server;
GmOptions *options = gm_world_options(world);
player = gm_options_get(options, "player_name");
server = gm_options_get(options, "host");
text = g_strconcat("<b>", gm_options_get(options, "name"),
_("</b>\nServer: "),
((server && server[0] != '\0') ? server : _("<i>unspecified</i>")),
_("\nPlayer: "),
((player && player[0] != '\0') ? player : _("<i>unspecified</i>")),
NULL);
return text;
}
static void
gm_worlds_list_dialog_add_world(GmWorld *world) {
GtkTreeIter iter;
GdkPixbuf *pix_logo = NULL;
gchar *name = gm_worlds_list_dialog_world_text(world);
const gchar *logo = gm_options_get(gm_world_options(world), "logo");
GtkListStore *store = GTK_LIST_STORE(
gm_worlds_list_dialog_instance->model_worlds);
if (logo) {
pix_logo = gm_pixbuf_get_at_size(logo, 32, 32);
} else {
pix_logo = gm_pixbuf_get_at_size("world.svg", 32, 32);
}
gtk_list_store_append(store, &iter);
gtk_list_store_set(store, &iter, LOGO_COLUMN, pix_logo, NAME_COLUMN,
name, WORLD_COLUMN, world, -1);
g_signal_connect(gm_world_options(world), "option_changed",
G_CALLBACK(on_gm_worlds_list_dialog_world_option_changed), world);
g_free(name);
}
#define G_WORLDS_LISTS_DIALOG_XML PACKAGE_DATA_DIR "/" PACKAGE \
"/ui/gm-worlds-list.glade"
static void
gm_worlds_list_dialog_populate_worlds() {
GmApp *app = gm_app_instance();
GList *worlds = gm_app_worlds(app);
GList *item;
GmWorld *world;
for (item = worlds; item; item = item->next) {
world = (GmWorld *)(item->data);
gm_worlds_list_dialog_add_world(world);
}
g_list_free(worlds);
}
static void
gm_worlds_list_dialog_create_tree_view_worlds() {
GtkCellRenderer *renderer;
GtkTreeViewColumn *column;
GtkTreeView *tree_view;
GtkTreeModel *model;
model = GTK_TREE_MODEL(gtk_list_store_new(N_COLUMNS, GDK_TYPE_PIXBUF,
G_TYPE_STRING, G_TYPE_POINTER));
tree_view = GTK_TREE_VIEW(gm_worlds_list_dialog_widget("tree_view_worlds"));
gtk_tree_view_set_model(tree_view, model);
gtk_tree_selection_set_mode(gtk_tree_view_get_selection(tree_view),
GTK_SELECTION_MULTIPLE);
renderer = gtk_cell_renderer_pixbuf_new();
column = gtk_tree_view_column_new_with_attributes(_("Logo"), renderer,
"pixbuf", LOGO_COLUMN, NULL);
gtk_tree_view_column_set_min_width(column, 40);
gtk_tree_view_append_column(tree_view, column);
renderer = gtk_cell_renderer_text_new();
column = gtk_tree_view_column_new_with_attributes(_("Name"), renderer,
"markup", NAME_COLUMN, NULL);
gtk_tree_view_append_column(tree_view, column);
gm_worlds_list_dialog_instance->tree_view_worlds = tree_view;
gm_worlds_list_dialog_instance->model_worlds = model;
gm_worlds_list_dialog_populate_worlds();
}
void
gm_worlds_list_dialog_run() {
GladeXML *xml;
if (gm_worlds_list_dialog_instance) {
gtk_widget_show(gm_worlds_list_dialog_instance->dialog);
gtk_window_present(GTK_WINDOW(gm_worlds_list_dialog_instance->dialog));
return;
}
gm_worlds_list_dialog_instance = g_new0(GmWorldsListDialog, 1);
xml = glade_xml_new(G_WORLDS_LISTS_DIALOG_XML, "gm_worlds_list_dialog",
NULL);
gm_worlds_list_dialog_instance->xml = xml;
gm_worlds_list_dialog_create_tree_view_worlds();
glade_xml_signal_connect(xml, "on_button_delete_clicked",
G_CALLBACK(on_gm_worlds_list_dialog_button_delete_clicked));
glade_xml_signal_connect(xml, "on_button_new_clicked",
G_CALLBACK(on_gm_worlds_list_dialog_button_new_clicked));
glade_xml_signal_connect(xml, "on_button_modify_clicked",
G_CALLBACK(on_gm_worlds_list_dialog_button_modify_clicked));
glade_xml_signal_connect(xml, "on_button_duplicate_clicked",
G_CALLBACK(on_gm_worlds_list_dialog_button_connect_clicked));
glade_xml_signal_connect(xml, "on_button_connect_clicked",
G_CALLBACK(on_gm_worlds_list_dialog_button_connect_clicked));
glade_xml_signal_connect(xml, "on_tree_view_worlds_key_press",
G_CALLBACK(on_gm_worlds_list_dialog_tree_view_worlds_key_press));
gm_worlds_list_dialog_instance->dialog =
gm_worlds_list_dialog_widget("gm_worlds_list_dialog");
g_signal_connect(gm_app_instance(), "world_added",
G_CALLBACK(on_gm_worlds_list_dialog_app_world_added), NULL);
g_signal_connect(gm_app_instance(), "world_removed",
G_CALLBACK(on_gm_worlds_list_dialog_app_world_removed), NULL);
gtk_window_set_icon(GTK_WINDOW(gm_worlds_list_dialog_instance->dialog),
gm_pixbuf_get("world.svg"));
gtk_widget_show(gm_worlds_list_dialog_instance->dialog);
g_signal_connect(gm_worlds_list_dialog_instance->dialog, "response",
G_CALLBACK(on_gm_worlds_list_dialog_response), NULL);
}
static void
gm_worlds_list_dialog_delete_selected_worlds() {
GtkTreeView *tree_view = gm_worlds_list_dialog_instance->tree_view_worlds;
GtkTreeModel *model = gm_worlds_list_dialog_instance->model_worlds;
GtkTreeSelection *selection = gtk_tree_view_get_selection(tree_view);
GtkTreeIter iter;
GList *paths = gtk_tree_selection_get_selected_rows(selection, &model);
GList *refs = NULL;
GList *node = NULL;
gchar *message;
gpointer proxy = g_object_newv(G_TYPE_OBJECT, 0, NULL);
GmWorld *world;
for (node = paths; node; node = node->next) {
refs = g_list_append(refs,
gtk_tree_row_reference_new_proxy(proxy, model, node->data));
gtk_tree_path_free(node->data);
}
g_list_free(paths);
if (refs) {
for (node = refs; node; node = node->next) {
GtkTreePath *path = gtk_tree_row_reference_get_path(node->data);
gtk_tree_model_get_iter(model, &iter, path);
gtk_tree_model_get(model, &iter, WORLD_COLUMN, &world, -1);
if (!(world && gm_world_loaded(world))) {
gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
gm_app_remove_world(gm_app_instance(), world);
} else {
message = g_strdup_printf(_
("Can't remove the world %s because it is loaded. "
"First close the world and then try again."),
gm_world_name(world));
gm_error_dialog(message,
GTK_WINDOW(gm_worlds_list_dialog_instance->dialog));
g_free(message);
}
gtk_tree_row_reference_deleted(proxy, path);
gtk_tree_path_free(path);
gtk_tree_row_reference_free(node->data);
}
} else {
gm_error_dialog(_("You first need to select a world to delete."),
GTK_WINDOW(gm_worlds_list_dialog_instance->dialog));
}
g_list_free(refs);
g_object_unref(proxy);
}
void
gm_worlds_list_dialog_modify_world() {
GtkTreeView *tree_view = gm_worlds_list_dialog_instance->tree_view_worlds;
GtkTreeModel *model = gm_worlds_list_dialog_instance->model_worlds;
GtkTreeSelection *selection = gtk_tree_view_get_selection(tree_view);
GtkTreeIter iter;
GList *first_path = gtk_tree_selection_get_selected_rows(selection, &model);
GmWorld *world;
if (first_path) {
gtk_tree_model_get_iter(model, &iter, first_path->data);
gtk_tree_model_get(model, &iter, WORLD_COLUMN, &world, -1);
gm_world_properties_dialog_run(world);
} else {
gm_error_dialog(_("You first need to select a world to modify."),
GTK_WINDOW(gm_worlds_list_dialog_instance->dialog));
}
g_list_free(first_path);
}
GList *
gm_worlds_list_dialog_selected_path() {
GtkTreeView *tree_view = gm_worlds_list_dialog_instance->tree_view_worlds;
GtkTreeModel *model = gm_worlds_list_dialog_instance->model_worlds;
GtkTreeSelection *selection = gtk_tree_view_get_selection(tree_view);
return gtk_tree_selection_get_selected_rows(selection, &model);
}
GmWorld *
gm_worlds_list_dialog_selected_world() {
GtkTreeIter iter;
GList *first_path = gm_worlds_list_dialog_selected_path();
GmWorld *world = NULL;
if (first_path) {
gtk_tree_model_get_iter(gm_worlds_list_dialog_instance->model_worlds,
&iter, first_path->data);
gtk_tree_model_get(gm_worlds_list_dialog_instance->model_worlds, &iter,
WORLD_COLUMN, &world, -1);
}
g_list_free(first_path);
return world;
}
gboolean
gm_worlds_list_dialog_find(GmWorld *world, GtkTreeIter *iter) {
GtkTreeModel *model = gm_worlds_list_dialog_instance->model_worlds;
GmWorld *list_world;
if (gtk_tree_model_get_iter_first(model, iter)) {
do {
gtk_tree_model_get(model, iter, WORLD_COLUMN, &list_world, -1);
if (world == list_world) {
return TRUE;
}
} while (gtk_tree_model_iter_next(model, iter));
}
return FALSE;
}
// Callbacks
void
on_gm_worlds_list_dialog_response(GtkDialog *dialog, gint response,
gpointer user_data) {
g_object_unref(gm_worlds_list_dialog_instance->xml);
gtk_widget_destroy(gm_worlds_list_dialog_instance->dialog);
g_free(gm_worlds_list_dialog_instance);
gm_worlds_list_dialog_instance = NULL;
}
void
on_gm_worlds_list_dialog_button_delete_clicked(GtkButton *button,
gpointer user_data) {
gm_worlds_list_dialog_delete_selected_worlds();
}
void
on_gm_worlds_list_dialog_tree_view_worlds_key_press(GtkWidget *widget,
GdkEventKey *event, gpointer user_data) {
switch (event->keyval) {
case GDK_D: case GDK_d:
gm_worlds_list_dialog_delete_selected_worlds();
break;
case GDK_O: case GDK_o:
break;
case GDK_N: case GDK_n:
gm_world_properties_dialog_run_new(NULL);
break;
case GDK_M: case GDK_m:
gm_worlds_list_dialog_modify_world();
break;
}
}
void
on_gm_worlds_list_dialog_button_new_clicked(GtkButton *button,
gpointer user_data) {
gm_world_properties_dialog_run_new(NULL);
}
void
on_gm_worlds_list_dialog_button_modify_clicked(GtkButton *button,
gpointer user_data) {
gm_worlds_list_dialog_modify_world();
}
void
on_gm_worlds_list_dialog_button_duplicate_clicked(GtkButton *button,
gpointer user_data) {
GmWorld *world = gm_worlds_list_dialog_selected_world();
GmWorld *new_world;
if (world) {
// now duplicate the world
new_world = gm_world_dup(world);
// Yeah we got some world, now show the props!
gm_world_properties_dialog_run_new(new_world);
} else {
gm_error_dialog(
_("You first need to select a world to duplicate."),
GTK_WINDOW(gm_worlds_list_dialog_instance->dialog));
}
}
void
on_gm_worlds_list_dialog_button_connect_clicked(GtkButton *button,
gpointer user_data) {
GList *first_path = gm_worlds_list_dialog_selected_path();
GList *path;
GmWorld *world;
GtkTreeIter iter;
if (first_path) {
for (path = first_path; path; path = path->next) {
gtk_tree_model_get_iter(
gm_worlds_list_dialog_instance->model_worlds, &iter,
first_path->data);
gtk_tree_model_get(gm_worlds_list_dialog_instance->model_worlds,
&iter, WORLD_COLUMN, &world, -1);
gm_world_load(world);
}
} else {
gm_error_dialog(
_("You first need to select a world to connect to."),
GTK_WINDOW(gm_worlds_list_dialog_instance->dialog));
}
g_list_free(first_path);
}
void
on_gm_worlds_list_dialog_app_world_added(GmApp *app, GmWorld *world,
gpointer user_data) {
gm_worlds_list_dialog_add_world(world);
}
void
on_gm_worlds_list_dialog_app_world_removed(GmApp *app, GmWorld *world,
gpointer user_data) {
GtkTreeIter iter;
if (gm_worlds_list_dialog_find(world, &iter)) {
gtk_list_store_remove(GTK_LIST_STORE(
gm_worlds_list_dialog_instance->model_worlds), &iter);
}
}
void
on_gm_worlds_list_dialog_world_option_changed(GmOptions *options,
const gchar *key, GmWorld *world) {
GtkTreeIter iter;
GtkListStore *store =
GTK_LIST_STORE(gm_worlds_list_dialog_instance->model_worlds);
gchar *text;
const gchar *logo;
GdkPixbuf *pix_logo;
if (!gm_worlds_list_dialog_find(world, &iter)) {
return;
}
if (strcmp(key, "name") == 0 ||
strcmp(key, "player_name") == 0 ||
strcmp(key, "host") == 0) {
text = gm_worlds_list_dialog_world_text(world);
gtk_list_store_set(store, &iter, NAME_COLUMN, text, -1);
g_free(text);
} else if (strcmp(key, "logo")) {
logo = gm_options_get(options, "logo");
if (logo) {
pix_logo = gm_pixbuf_get_at_size(logo, 32, 32);
} else {
pix_logo = gm_pixbuf_get_at_size("world.svg", 32, 32);
}
gtk_list_store_set(store, &iter, LOGO_COLUMN, pix_logo, -1);
}
}