#include #include #include "gm-app.h" #include "gm-pixbuf.h" #include "gm-worlds-view.h" #include "gm-world.h" #include "gm-options.h" #include "gm-support.h" #define GM_WORLDS_VIEW_GET_PRIVATE(object)( \ G_TYPE_INSTANCE_GET_PRIVATE((object), \ GM_TYPE_WORLDS_VIEW, GmWorldsViewPrivate)) static void on_gm_worlds_view_world_option_changed(GmOptions *options, gchar const *key, GmWorldsView *view); static void on_gm_worlds_view_app_world_added(GmApp *app, GmWorld *world, GmWorldsView *view); static void on_gm_worlds_view_app_world_removed(GmApp *app, GmWorld *world, GmWorldsView *view); struct _GmWorldsViewPrivate { GtkTreeModel *model; }; /* Signals enum { PROTO NUM_SIGNALS }; static guint gm_worlds_view_signals[NUM_SIGNALS] = {0};*/ G_DEFINE_TYPE(GmWorldsView, gm_worlds_view, GTK_TYPE_TREE_VIEW) static void gm_worlds_view_finalize(GObject *object) { GmWorldsView *obj = GM_WORLDS_VIEW(object); GtkTreeModel *model = obj->priv->model; GmWorld *list_world; GtkTreeIter iter; if (gtk_tree_model_get_iter_first(model, &iter)) { do { gtk_tree_model_get(model, &iter, GM_WORLDS_VIEW_WORLD_COLUMN, &list_world, -1); g_signal_handlers_disconnect_by_func(gm_world_options(list_world), G_CALLBACK(on_gm_worlds_view_world_option_changed), obj); } while (gtk_tree_model_iter_next(model, &iter)); } g_signal_handlers_disconnect_by_func(gm_app_instance(), G_CALLBACK(on_gm_worlds_view_app_world_added), obj); g_signal_handlers_disconnect_by_func(gm_app_instance(), G_CALLBACK(on_gm_worlds_view_app_world_removed), obj); G_OBJECT_CLASS(gm_worlds_view_parent_class)->finalize(object); } static void gm_worlds_view_class_init(GmWorldsViewClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS(klass); object_class->finalize = gm_worlds_view_finalize; /*gm_worlds_view_signals[PROTO] = g_signal_new("proto", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GmWorldsViewClass, proto), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);*/ g_type_class_add_private(object_class, sizeof(GmWorldsViewPrivate)); } static void gm_worlds_view_init(GmWorldsView *obj) { obj->priv = GM_WORLDS_VIEW_GET_PRIVATE(obj); } static gchar * gm_worlds_view_world_text(GmWorldsView *view, GmWorld *world) { gchar *text; gchar const *player, *server; GmOptions *options = gm_world_options(world); player = gm_options_get(options, "player_name"); server = gm_options_get(options, "host"); text = g_strconcat("", gm_options_get(options, "name"), _("\nServer: "), ((server && *server != '\0') ? server : _("unspecified")), _("\nPlayer: "), ((player && *player != '\0') ? player : _("unspecified")), "", NULL); return text; } static void gm_worlds_view_populate_worlds(GmWorldsView *view) { 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_view_add_world(view, world); } g_list_free(worlds); } static void gm_worlds_view_build(GmWorldsView *view) { GtkCellRenderer *renderer; GtkTreeViewColumn *column; GtkTreeView *tree_view = GTK_TREE_VIEW(view); view->priv->model = GTK_TREE_MODEL(gtk_list_store_new( GM_WORLDS_VIEW_N_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_STRING)); gtk_tree_view_set_model(tree_view, view->priv->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", GM_WORLDS_VIEW_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", GM_WORLDS_VIEW_NAME_COLUMN, NULL); gtk_tree_view_append_column(tree_view, column); gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(view->priv->model), GM_WORLDS_VIEW_SORT_COLUMN, GTK_SORT_ASCENDING); gm_worlds_view_populate_worlds(view); } static gboolean gm_worlds_view_find_by_options(GmWorldsView *view, GmOptions *options, GtkTreeIter *iter, GmWorld **world) { GtkTreeModel *model = view->priv->model; GmWorld *list_world; if (gtk_tree_model_get_iter_first(model, iter)) { do { gtk_tree_model_get(model, iter, GM_WORLDS_VIEW_WORLD_COLUMN, &list_world, -1); if (options == gm_world_options(list_world)) { if (world != NULL) { *world = list_world; } return TRUE; } } while (gtk_tree_model_iter_next(model, iter)); } return FALSE; } static gboolean gm_worlds_view_find(GmWorldsView *view, GmWorld *world, GtkTreeIter *iter) { return gm_worlds_view_find_by_options(view, gm_world_options(world), iter, NULL); } /* Public */ GtkWidget * gm_worlds_view_new() { GmWorldsView *obj = GM_WORLDS_VIEW(g_object_new(GM_TYPE_WORLDS_VIEW, NULL)); gm_worlds_view_build(obj); gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(obj), FALSE); g_signal_connect(gm_app_instance(), "world_added", G_CALLBACK(on_gm_worlds_view_app_world_added), obj); g_signal_connect(gm_app_instance(), "world_removed", G_CALLBACK(on_gm_worlds_view_app_world_removed), obj); return GTK_WIDGET(obj); } void gm_worlds_view_add_world(GmWorldsView *view, GmWorld *world) { GtkTreeIter iter; GdkPixbuf *pix_logo = NULL; gchar *name = gm_worlds_view_world_text(view, world); gchar const *logo = gm_options_get(gm_world_options(world), "logo"); GtkListStore *store = GTK_LIST_STORE(view->priv->model); if (logo) { pix_logo = gm_pixbuf_get_at_size(logo, 32, 32); } if (!pix_logo) { pix_logo = gm_pixbuf_get_at_size("world.svg", 32, 32); } gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, GM_WORLDS_VIEW_LOGO_COLUMN, pix_logo, GM_WORLDS_VIEW_NAME_COLUMN, name, GM_WORLDS_VIEW_WORLD_COLUMN, world, GM_WORLDS_VIEW_SORT_COLUMN, gm_world_name(world), -1); g_signal_connect(gm_world_options(world), "option_changed", G_CALLBACK(on_gm_worlds_view_world_option_changed), view); g_free(name); } GtkTreeModel * gm_worlds_view_model(GmWorldsView *view) { return view->priv->model; } /* Callbacks */ static void on_gm_worlds_view_world_option_changed(GmOptions *options, gchar const *key, GmWorldsView *view) { GtkTreeIter iter; GtkListStore *store = GTK_LIST_STORE(view->priv->model); gchar *text; gchar const *logo; GdkPixbuf *pix_logo; GmWorld *world; if (!gm_worlds_view_find_by_options(view, options, &iter, &world)) { return; } if (strcmp(key, "name") == 0 || strcmp(key, "player_name") == 0 || strcmp(key, "host") == 0) { text = gm_worlds_view_world_text(view, world); gtk_list_store_set(store, &iter, GM_WORLDS_VIEW_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, GM_WORLDS_VIEW_LOGO_COLUMN, pix_logo, -1); } } static void on_gm_worlds_view_app_world_added(GmApp *app, GmWorld *world, GmWorldsView *view) { gm_worlds_view_add_world(view, world); } static void on_gm_worlds_view_app_world_removed(GmApp *app, GmWorld *world, GmWorldsView *view) { GtkTreeIter iter; if (gm_worlds_view_find(view, world, &iter)) { gtk_list_store_remove(GTK_LIST_STORE(view->priv->model), &iter); } }