2005-11-15 12:48:19 +01:00
|
|
|
#include <gtk/gtk.h>
|
2006-04-07 18:32:44 +02:00
|
|
|
#include <string.h>
|
2005-11-15 12:48:19 +01:00
|
|
|
|
|
|
|
#include "gm-mcp-package.h"
|
|
|
|
#include "gm-mcp-userlist-view.h"
|
2006-04-23 16:51:04 +02:00
|
|
|
#include "gm-cell-renderer-text.h"
|
2006-01-08 17:32:51 +01:00
|
|
|
#include "gm-iuserlist.h"
|
2006-01-10 01:41:39 +01:00
|
|
|
#include "widgets/gm-world-view.h"
|
|
|
|
#include "gm-pixbuf.h"
|
2006-04-07 18:32:44 +02:00
|
|
|
#include "gm-app.h"
|
2006-01-10 01:41:39 +01:00
|
|
|
#include "gm-debug.h"
|
2005-11-15 12:48:19 +01:00
|
|
|
|
|
|
|
#define GM_USERLIST_ICON_SIZE 22
|
|
|
|
|
|
|
|
typedef struct _GmMcpUserlistView {
|
|
|
|
GmWorldView *view;
|
|
|
|
GmMcpPackage *package;
|
|
|
|
GtkTreeModel *model;
|
|
|
|
GtkListStore *store;
|
|
|
|
GtkTreeView *tree_view;
|
2006-04-07 18:32:44 +02:00
|
|
|
GtkWidget *label;
|
2005-11-15 12:48:19 +01:00
|
|
|
GtkScrolledWindow *scrolled_window;
|
2006-01-08 17:32:51 +01:00
|
|
|
GtkWidget *popup_menu;
|
2006-09-29 18:16:16 +02:00
|
|
|
GtkWidget *vbox;
|
2006-01-02 18:49:01 +01:00
|
|
|
gboolean initializing;
|
2006-04-07 18:32:44 +02:00
|
|
|
GmUserlistSortType sort_type;
|
|
|
|
gboolean show_object;
|
|
|
|
gboolean show_status;
|
|
|
|
gboolean use_state_icon;
|
|
|
|
|
|
|
|
gint num_players;
|
|
|
|
gint num_active;
|
2006-04-23 16:51:04 +02:00
|
|
|
|
|
|
|
GdkColor status_color;
|
2006-09-30 16:20:20 +02:00
|
|
|
|
|
|
|
gdouble scroll_position;
|
|
|
|
gulong idle_scroll;
|
2005-11-15 12:48:19 +01:00
|
|
|
} GmMcpUserlistView;
|
|
|
|
|
2006-01-08 17:32:51 +01:00
|
|
|
static void on_gm_mcp_userlist_view_weak_notify(gpointer data, GObject *obj);
|
2005-11-15 12:48:19 +01:00
|
|
|
|
2006-01-08 17:32:51 +01:00
|
|
|
static void on_gm_mcp_userlist_view_player_added(GmMcpPackage *package, gint id,
|
2005-11-15 12:48:19 +01:00
|
|
|
GmMcpUserlistView *view);
|
2006-01-08 17:32:51 +01:00
|
|
|
static void on_gm_mcp_userlist_view_player_removed(GmMcpPackage *package, gint id,
|
2005-11-15 12:48:19 +01:00
|
|
|
GmMcpUserlistView *view);
|
2006-01-08 17:32:51 +01:00
|
|
|
static void on_gm_mcp_userlist_view_name_changed(GmMcpPackage *package, gint id,
|
2006-04-07 18:32:44 +02:00
|
|
|
GmMcpUserlistView *view);
|
2006-01-08 17:32:51 +01:00
|
|
|
static void on_gm_mcp_userlist_view_rank_changed(GmMcpPackage *package, gint id,
|
2006-04-07 18:32:44 +02:00
|
|
|
GmMcpUserlistView *view);
|
2006-01-08 17:32:51 +01:00
|
|
|
static void on_gm_mcp_userlist_view_state_changed(GmMcpPackage *package, gint id,
|
2006-04-07 18:32:44 +02:00
|
|
|
GmMcpUserlistView *view);
|
|
|
|
|
2006-01-08 17:32:51 +01:00
|
|
|
static gboolean on_gm_mcp_userlist_view_popup_menu(GtkWidget *widget,
|
|
|
|
GmMcpUserlistView *view);
|
|
|
|
static gboolean on_gm_mcp_userlist_view_button_press(GtkWidget *widget,
|
|
|
|
GdkEventButton *event, GmMcpUserlistView *view);
|
2005-11-15 12:48:19 +01:00
|
|
|
|
2006-04-07 18:32:44 +02:00
|
|
|
static void on_gm_mcp_userlist_view_option_changed(GmOptions *options,
|
|
|
|
gchar const *key, GmMcpUserlistView *view);
|
|
|
|
|
|
|
|
typedef struct _SortInfo {
|
|
|
|
gchar *name;
|
|
|
|
gint rank_priority;
|
|
|
|
gint state_priority;
|
|
|
|
} SortInfo;
|
|
|
|
|
|
|
|
static gint gm_mcp_userlist_view_sort_state_rank_name(SortInfo *info1,
|
|
|
|
SortInfo *info2);
|
|
|
|
static gint gm_mcp_userlist_view_sort_rank_name(SortInfo *info1,
|
|
|
|
SortInfo *info2);
|
|
|
|
static gint gm_mcp_userlist_view_sort_state_name(SortInfo *info1,
|
|
|
|
SortInfo *info2);
|
|
|
|
static gint gm_mcp_userlist_view_sort_name(SortInfo *info1,
|
|
|
|
SortInfo *info2);
|
|
|
|
|
|
|
|
typedef gint (*GmUserlistCompareFunc) (SortInfo *info1, SortInfo *info2);
|
|
|
|
|
|
|
|
static GmUserlistCompareFunc compare_functions[] = {
|
|
|
|
gm_mcp_userlist_view_sort_state_rank_name,
|
|
|
|
gm_mcp_userlist_view_sort_rank_name,
|
|
|
|
gm_mcp_userlist_view_sort_state_name,
|
|
|
|
gm_mcp_userlist_view_sort_name
|
|
|
|
};
|
|
|
|
|
2006-09-30 16:20:20 +02:00
|
|
|
static gboolean
|
|
|
|
gm_mcp_userlist_view_idle_scroll(GmMcpUserlistView *view) {
|
|
|
|
GtkAdjustment *adj;
|
|
|
|
|
|
|
|
view->idle_scroll = 0;
|
|
|
|
adj = gtk_scrolled_window_get_vadjustment(view->scrolled_window);
|
|
|
|
gtk_adjustment_set_value(adj, view->scroll_position);
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gm_mcp_userlist_view_prepare_scroll(GmMcpUserlistView *view) {
|
|
|
|
GtkAdjustment *adj;
|
|
|
|
|
|
|
|
if (view->idle_scroll != 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
adj = gtk_scrolled_window_get_vadjustment(view->scrolled_window);
|
|
|
|
|
|
|
|
view->scroll_position = gtk_adjustment_get_value(adj);
|
|
|
|
view->idle_scroll = g_idle_add((GSourceFunc)(gm_mcp_userlist_view_idle_scroll), view);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
on_rows_reordered(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter,
|
|
|
|
gpointer arg3, GmMcpUserlistView *view) {
|
|
|
|
gm_mcp_userlist_view_prepare_scroll(view);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
on_row_inserted(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter,
|
|
|
|
GmMcpUserlistView *view) {
|
|
|
|
gm_mcp_userlist_view_prepare_scroll(view);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
on_row_deleted(GtkTreeModel *model, GtkTreePath *path,
|
|
|
|
GmMcpUserlistView *view) {
|
|
|
|
gm_mcp_userlist_view_prepare_scroll(view);
|
|
|
|
}
|
|
|
|
|
2005-11-15 12:48:19 +01:00
|
|
|
GtkTreeModel *
|
|
|
|
gm_mcp_userlist_view_model_create(GmMcpUserlistView *view) {
|
|
|
|
GtkListStore *store = gtk_list_store_new(GM_USERLIST_N_COLUMNS,
|
2006-04-23 16:51:04 +02:00
|
|
|
GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING,
|
|
|
|
G_TYPE_INT, G_TYPE_INT, G_TYPE_INT);
|
2005-11-15 12:48:19 +01:00
|
|
|
GtkTreeModel *model = gtk_tree_model_sort_new_with_model(GTK_TREE_MODEL(
|
|
|
|
store));
|
|
|
|
|
|
|
|
view->store = store;
|
|
|
|
view->model = model;
|
2006-09-30 16:20:20 +02:00
|
|
|
|
|
|
|
g_signal_connect(model, "row-inserted",
|
|
|
|
G_CALLBACK(on_row_inserted),
|
|
|
|
view);
|
|
|
|
g_signal_connect(model, "row-deleted",
|
|
|
|
G_CALLBACK(on_row_deleted),
|
|
|
|
view);
|
|
|
|
g_signal_connect(model, "rows-reordered",
|
|
|
|
G_CALLBACK(on_rows_reordered),
|
|
|
|
view);
|
2005-11-15 12:48:19 +01:00
|
|
|
|
|
|
|
return model;
|
|
|
|
}
|
|
|
|
|
2006-04-07 18:32:44 +02:00
|
|
|
gint
|
|
|
|
gm_userlist_view_strcmp_safe(gchar const *str1, gchar const *str2) {
|
|
|
|
gchar *u1, *u2;
|
|
|
|
gint result;
|
|
|
|
|
|
|
|
if (str1 == NULL || str2 == NULL) {
|
|
|
|
if (str1 == NULL && str2 == NULL) {
|
|
|
|
result = 0;
|
|
|
|
} else if (str1 == NULL) {
|
|
|
|
result = -1;
|
|
|
|
} else {
|
|
|
|
result = 1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
u1 = g_utf8_casefold(str1, -1);
|
|
|
|
u2 = g_utf8_casefold(str2, -1);
|
|
|
|
|
|
|
|
result = g_utf8_collate(u1, u2);
|
|
|
|
|
|
|
|
g_free(u1);
|
|
|
|
g_free(u2);
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
|
|
|
gm_mcp_userlist_view_sort_state_rank_name(SortInfo *info1, SortInfo *info2) {
|
|
|
|
// Sort by 'icon' (so first by state, then if state is avail sort by rank
|
|
|
|
// and then by name, otherwise sort by name)
|
|
|
|
if (info1->state_priority == info2->state_priority) {
|
|
|
|
// The same state, if state is 0 then go by rank and then name,
|
|
|
|
// otherwise go by name
|
|
|
|
if (info1->state_priority == 0) {
|
|
|
|
if (info1->rank_priority == info2->rank_priority) {
|
|
|
|
return gm_userlist_view_strcmp_safe(info1->name, info2->name);
|
|
|
|
} else {
|
|
|
|
return info1->rank_priority - info2->rank_priority;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return gm_userlist_view_strcmp_safe(info1->name, info2->name);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return info1->state_priority - info2->state_priority;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
|
|
|
gm_mcp_userlist_view_sort_rank_name(SortInfo *info1, SortInfo *info2) {
|
|
|
|
// First sort by rank, then sort by name
|
|
|
|
if (info1->rank_priority == info2->rank_priority) {
|
|
|
|
return gm_userlist_view_strcmp_safe(info1->name, info2->name);
|
|
|
|
} else {
|
|
|
|
return info1->rank_priority - info2->rank_priority;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
|
|
|
gm_mcp_userlist_view_sort_state_name(SortInfo *info1, SortInfo *info2) {
|
|
|
|
// First sort by state, then sort by name
|
|
|
|
if (info1->state_priority == info2->state_priority) {
|
|
|
|
return gm_userlist_view_strcmp_safe(info1->name, info2->name);
|
|
|
|
} else {
|
|
|
|
return info1->state_priority - info2->state_priority;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
|
|
|
gm_mcp_userlist_view_sort_name(SortInfo *info1, SortInfo *info2) {
|
|
|
|
// Sort by name
|
|
|
|
return gm_userlist_view_strcmp_safe(info1->name, info2->name);
|
|
|
|
}
|
|
|
|
|
|
|
|
gint
|
|
|
|
gm_mcp_userlist_view_sort_func(GtkTreeModel *model, GtkTreeIter *a,
|
|
|
|
GtkTreeIter *b, GmMcpUserlistView *view) {
|
|
|
|
/* a < b => -1
|
|
|
|
a == b => 0
|
|
|
|
a > b => 1 */
|
|
|
|
SortInfo info1, info2;
|
|
|
|
gint result;
|
|
|
|
|
|
|
|
gtk_tree_model_get(model, a,
|
|
|
|
GM_USERLIST_RANK_PRIORITY, &(info1.rank_priority),
|
|
|
|
GM_USERLIST_STATE_PRIORITY, &(info1.state_priority),
|
2006-04-23 16:51:04 +02:00
|
|
|
GM_USERLIST_NAME, &(info1.name), -1);
|
2006-04-07 18:32:44 +02:00
|
|
|
gtk_tree_model_get(model, b,
|
|
|
|
GM_USERLIST_RANK_PRIORITY, &(info2.rank_priority),
|
|
|
|
GM_USERLIST_STATE_PRIORITY, &(info2.state_priority),
|
2006-04-23 16:51:04 +02:00
|
|
|
GM_USERLIST_NAME, &(info2.name), -1);
|
2006-04-07 18:32:44 +02:00
|
|
|
|
|
|
|
result = (* compare_functions[view->sort_type]) (&info1, &info2);
|
|
|
|
|
|
|
|
g_free(info1.name);
|
|
|
|
g_free(info2.name);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gm_mcp_userlist_view_update_label(GmMcpUserlistView *view) {
|
|
|
|
gchar *label;
|
|
|
|
|
|
|
|
label = g_strdup_printf(_("Players: %d, active: %d"), view->num_players,
|
|
|
|
view->num_active);
|
|
|
|
|
|
|
|
gtk_label_set_label(GTK_LABEL(view->label), label);
|
|
|
|
g_free(label);
|
|
|
|
}
|
|
|
|
|
|
|
|
GtkWidget *
|
|
|
|
gm_mcp_userlist_view_create_label(GmMcpUserlistView *view) {
|
|
|
|
view->label = gtk_label_new(NULL);
|
|
|
|
gm_mcp_userlist_view_update_label(view);
|
|
|
|
|
|
|
|
return view->label;
|
2006-04-01 16:30:50 +02:00
|
|
|
}
|
|
|
|
|
2006-09-30 16:20:20 +02:00
|
|
|
static void
|
|
|
|
on_adj_changed(GtkAdjustment *adj, GmMcpUserlistView *view) {
|
|
|
|
if (view->idle_scroll != 0 && gtk_adjustment_get_value(adj) != view->scroll_position) {
|
|
|
|
gtk_adjustment_set_value(adj, view->scroll_position);
|
|
|
|
g_source_remove(view->idle_scroll);
|
|
|
|
view->idle_scroll = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-11-15 12:48:19 +01:00
|
|
|
GtkWidget *
|
|
|
|
gm_mcp_userlist_view_create_userlist(GmMcpUserlistView *view) {
|
|
|
|
GtkWidget *scrolled_window = gtk_scrolled_window_new(NULL, NULL);
|
|
|
|
GtkTreeModel *model = gm_mcp_userlist_view_model_create(view);
|
|
|
|
GtkWidget *tree_view = gtk_tree_view_new_with_model(model);
|
|
|
|
GtkCellRenderer *renderer;
|
|
|
|
GtkTreeViewColumn *column;
|
|
|
|
|
|
|
|
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
|
2006-04-01 16:30:50 +02:00
|
|
|
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
|
2005-11-15 12:48:19 +01:00
|
|
|
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window),
|
|
|
|
GTK_SHADOW_IN);
|
|
|
|
|
2006-09-30 16:20:20 +02:00
|
|
|
GtkAdjustment *adj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(scrolled_window));
|
|
|
|
g_signal_connect(adj, "changed", G_CALLBACK(on_adj_changed), view);
|
|
|
|
|
2005-11-15 12:48:19 +01:00
|
|
|
gtk_widget_set_size_request(scrolled_window, 150, -1);
|
|
|
|
gtk_widget_set_size_request(tree_view, 150, -1);
|
|
|
|
|
|
|
|
gtk_container_add(GTK_CONTAINER(scrolled_window), tree_view);
|
|
|
|
|
|
|
|
renderer = gtk_cell_renderer_pixbuf_new();
|
|
|
|
column = gtk_tree_view_column_new_with_attributes(_("I"), renderer,
|
|
|
|
"pixbuf", GM_USERLIST_ICON, NULL);
|
|
|
|
gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column);
|
|
|
|
gtk_tree_view_column_set_min_width(column, 30);
|
|
|
|
|
2006-04-23 16:51:04 +02:00
|
|
|
renderer = gm_cell_renderer_text_new();
|
2005-11-15 12:48:19 +01:00
|
|
|
column = gtk_tree_view_column_new_with_attributes(_("Name"), renderer,
|
2006-04-23 16:51:04 +02:00
|
|
|
"name", GM_USERLIST_NAME, "status", GM_USERLIST_STATUS, NULL);
|
2005-11-15 12:48:19 +01:00
|
|
|
gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column);
|
|
|
|
|
|
|
|
gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(model),
|
2006-04-07 18:32:44 +02:00
|
|
|
GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, GTK_SORT_ASCENDING);
|
|
|
|
gtk_tree_sortable_set_default_sort_func(GTK_TREE_SORTABLE(model),
|
|
|
|
(GtkTreeIterCompareFunc)gm_mcp_userlist_view_sort_func, view, NULL);
|
2005-11-15 12:48:19 +01:00
|
|
|
|
2006-01-08 17:32:51 +01:00
|
|
|
GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(tree_view), GTK_CAN_FOCUS);
|
|
|
|
|
|
|
|
gtk_widget_modify_base(GTK_WIDGET(tree_view), GTK_STATE_ACTIVE,
|
|
|
|
&(GTK_WIDGET(tree_view)->style->base[GTK_STATE_SELECTED]));
|
|
|
|
gtk_widget_modify_text(GTK_WIDGET(tree_view), GTK_STATE_ACTIVE,
|
|
|
|
&(GTK_WIDGET(tree_view)->style->text[GTK_STATE_SELECTED]));
|
|
|
|
|
2005-11-15 12:48:19 +01:00
|
|
|
gtk_tree_view_columns_autosize(GTK_TREE_VIEW(tree_view));
|
|
|
|
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree_view), FALSE);
|
|
|
|
|
|
|
|
view->tree_view = GTK_TREE_VIEW(tree_view);
|
|
|
|
view->scrolled_window = GTK_SCROLLED_WINDOW(scrolled_window);
|
|
|
|
|
|
|
|
return scrolled_window;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gm_mcp_userlist_view_new(GmMcpPackage *package, GObject *parent) {
|
|
|
|
GmMcpUserlistView *view;
|
|
|
|
GtkPaned *paned;
|
|
|
|
GtkWidget *vbox, *child;
|
2006-04-07 18:32:44 +02:00
|
|
|
GmOptions *options;
|
2005-11-15 12:48:19 +01:00
|
|
|
|
|
|
|
if (!GM_IS_WORLD_VIEW(parent)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-01-08 17:32:51 +01:00
|
|
|
view = g_new0(GmMcpUserlistView, 1);
|
2005-11-15 12:48:19 +01:00
|
|
|
view->view = GM_WORLD_VIEW(parent);
|
|
|
|
view->package = package;
|
2006-04-07 18:32:44 +02:00
|
|
|
|
2005-11-15 12:48:19 +01:00
|
|
|
paned = GTK_PANED(gm_world_view_hpaned(view->view));
|
|
|
|
vbox = gtk_paned_get_child2(paned);
|
|
|
|
|
|
|
|
if (vbox == NULL) {
|
2006-04-07 18:32:44 +02:00
|
|
|
vbox = gtk_vbox_new(FALSE, 3);
|
2006-09-29 18:16:16 +02:00
|
|
|
view->vbox = vbox;
|
|
|
|
gtk_paned_pack2(paned, view->vbox, FALSE, FALSE);
|
|
|
|
} else {
|
|
|
|
vbox = view->vbox;
|
2005-11-15 12:48:19 +01:00
|
|
|
}
|
2006-04-07 18:32:44 +02:00
|
|
|
|
2005-11-15 12:48:19 +01:00
|
|
|
child = gm_mcp_userlist_view_create_userlist(view);
|
|
|
|
|
|
|
|
gtk_box_pack_end(GTK_BOX(vbox), child, TRUE, TRUE, 0);
|
2006-04-07 18:32:44 +02:00
|
|
|
|
|
|
|
gtk_box_pack_end(GTK_BOX(vbox), gm_mcp_userlist_view_create_label(view),
|
|
|
|
FALSE, FALSE, 0);
|
|
|
|
|
2005-11-15 12:48:19 +01:00
|
|
|
gtk_widget_show_all(vbox);
|
|
|
|
|
2006-01-08 17:32:51 +01:00
|
|
|
g_signal_connect(view->tree_view, "popup-menu",
|
|
|
|
G_CALLBACK(on_gm_mcp_userlist_view_popup_menu), view);
|
|
|
|
g_signal_connect(view->tree_view, "button-press-event",
|
|
|
|
G_CALLBACK(on_gm_mcp_userlist_view_button_press), view);
|
|
|
|
|
2005-11-15 12:48:19 +01:00
|
|
|
g_signal_connect(package, "player_added",
|
|
|
|
G_CALLBACK(on_gm_mcp_userlist_view_player_added), view);
|
|
|
|
g_signal_connect(package, "player_removed",
|
|
|
|
G_CALLBACK(on_gm_mcp_userlist_view_player_removed), view);
|
|
|
|
g_signal_connect(package, "name_changed",
|
|
|
|
G_CALLBACK(on_gm_mcp_userlist_view_name_changed), view);
|
|
|
|
g_signal_connect(package, "state_changed",
|
|
|
|
G_CALLBACK(on_gm_mcp_userlist_view_state_changed), view);
|
|
|
|
g_signal_connect(package, "rank_changed",
|
|
|
|
G_CALLBACK(on_gm_mcp_userlist_view_rank_changed), view);
|
|
|
|
|
2006-04-07 18:32:44 +02:00
|
|
|
// Userlist options
|
|
|
|
options = gm_app_options(gm_app_instance());
|
|
|
|
view->show_object = gm_options_get_int(options,
|
|
|
|
"userlist_show_object_number");
|
|
|
|
view->sort_type = gm_options_get_int(options, "userlist_sort_type");
|
|
|
|
view->show_status = gm_options_get_int(options, "userlist_show_status");
|
|
|
|
view->use_state_icon = gm_options_get_int(options,
|
|
|
|
"userlist_use_state_icon");
|
|
|
|
|
2006-09-29 18:16:16 +02:00
|
|
|
if (!gm_options_get_int(options, "show_userlist"))
|
|
|
|
gtk_widget_hide(vbox);
|
|
|
|
|
2006-04-07 18:32:44 +02:00
|
|
|
g_signal_connect(options, "option-changed",
|
|
|
|
G_CALLBACK(on_gm_mcp_userlist_view_option_changed), view);
|
|
|
|
|
2005-11-15 12:48:19 +01:00
|
|
|
g_object_weak_ref(G_OBJECT(package), on_gm_mcp_userlist_view_weak_notify,
|
|
|
|
view);
|
|
|
|
}
|
|
|
|
|
2006-04-23 16:51:04 +02:00
|
|
|
static gchar *
|
|
|
|
gm_mcp_userlist_view_get_status(GmMcpUserlistView *view, gint id) {
|
|
|
|
if (!view->show_status ||
|
|
|
|
!gm_iuserlist_supports_status(GM_IUSERLIST(view->package))) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return gm_iuserlist_get_status(GM_IUSERLIST(view->package), id);
|
|
|
|
}
|
|
|
|
|
2006-04-07 18:32:44 +02:00
|
|
|
static gchar *
|
|
|
|
gm_mcp_userlist_view_get_name(GmMcpUserlistView *view, gint id) {
|
|
|
|
gchar const *name;
|
|
|
|
|
|
|
|
name = gm_iuserlist_get_name(GM_IUSERLIST(view->package), id);
|
|
|
|
|
|
|
|
if (view->show_object) {
|
2006-04-23 16:51:04 +02:00
|
|
|
return g_strdup_printf("%s (#%d)", name, id);
|
2006-04-07 18:32:44 +02:00
|
|
|
} else {
|
2006-04-23 16:51:04 +02:00
|
|
|
return g_strdup(name);
|
2006-04-07 18:32:44 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gm_mcp_userlist_view_update_sort_type(GmMcpUserlistView *view,
|
|
|
|
GmUserlistSortType sort_type) {
|
|
|
|
if (sort_type == view->sort_type) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sort_type < 0 || sort_type >= GM_USERLIST_SORT_TYPE_NUM) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
view->sort_type = sort_type;
|
|
|
|
|
|
|
|
gtk_tree_model_sort_reset_default_sort_func(GTK_TREE_MODEL_SORT(
|
|
|
|
view->model));
|
|
|
|
gtk_tree_sortable_set_default_sort_func(GTK_TREE_SORTABLE(view->model),
|
|
|
|
(GtkTreeIterCompareFunc)gm_mcp_userlist_view_sort_func, view, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gm_mcp_userlist_view_update_names(GmMcpUserlistView *view) {
|
|
|
|
GtkTreeModel *model = GTK_TREE_MODEL(view->store);
|
|
|
|
gint iterid;
|
|
|
|
GtkTreeIter iter;
|
|
|
|
gchar *name;
|
2006-04-23 16:51:04 +02:00
|
|
|
gchar *status;
|
2006-04-07 18:32:44 +02:00
|
|
|
|
|
|
|
if (gtk_tree_model_get_iter_first(model, &iter)) {
|
|
|
|
do {
|
|
|
|
gtk_tree_model_get(model, &iter, GM_USERLIST_ID, &iterid, -1);
|
|
|
|
name = gm_mcp_userlist_view_get_name(view, iterid);
|
2006-04-23 16:51:04 +02:00
|
|
|
status = gm_mcp_userlist_view_get_status(view, iterid);
|
|
|
|
|
|
|
|
gtk_list_store_set(view->store, &iter, GM_USERLIST_NAME, name,
|
|
|
|
GM_USERLIST_STATUS, status, -1);
|
|
|
|
|
2006-04-07 18:32:44 +02:00
|
|
|
g_free(name);
|
2006-04-23 16:51:04 +02:00
|
|
|
g_free(status);
|
2006-04-07 18:32:44 +02:00
|
|
|
} while (gtk_tree_model_iter_next(model, &iter));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gm_mcp_userlist_view_update_show_object_number(GmMcpUserlistView *view,
|
|
|
|
gboolean show_object) {
|
|
|
|
if (view->show_object == show_object) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
view->show_object = show_object;
|
|
|
|
|
|
|
|
gm_mcp_userlist_view_update_names(view);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gm_mcp_userlist_view_update_show_status(GmMcpUserlistView *view,
|
|
|
|
gboolean show_status) {
|
|
|
|
if (view->show_status == show_status) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
view->show_status = show_status;
|
|
|
|
gm_mcp_userlist_view_update_names(view);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gm_mcp_userlist_view_update_use_state_icon(GmMcpUserlistView *view,
|
|
|
|
gboolean use_state_icon) {
|
|
|
|
gchar const *icon;
|
|
|
|
GtkTreeModel *model = GTK_TREE_MODEL(view->store);
|
|
|
|
GtkTreeIter iter;
|
|
|
|
gint iterid;
|
|
|
|
|
|
|
|
if (view->use_state_icon == use_state_icon) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
view->use_state_icon = use_state_icon;
|
|
|
|
|
|
|
|
// Update icons for all players
|
|
|
|
if (gtk_tree_model_get_iter_first(model, &iter)) {
|
|
|
|
do {
|
|
|
|
gtk_tree_model_get(model, &iter, GM_USERLIST_ID, &iterid, -1);
|
|
|
|
icon = gm_iuserlist_get_icon(GM_IUSERLIST(view->package), iterid,
|
|
|
|
use_state_icon);
|
|
|
|
|
|
|
|
gtk_list_store_set(view->store, &iter, GM_USERLIST_ICON,
|
|
|
|
gm_pixbuf_get_at_size(icon, GM_USERLIST_ICON_SIZE,
|
|
|
|
GM_USERLIST_ICON_SIZE), -1);
|
|
|
|
} while (gtk_tree_model_iter_next(model, &iter));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
gm_mcp_userlist_view_player_active(GmMcpUserlistView *view, GtkTreeIter *iter) {
|
|
|
|
gint state;
|
|
|
|
|
|
|
|
gtk_tree_model_get(GTK_TREE_MODEL(view->store), iter,
|
|
|
|
GM_USERLIST_STATE_PRIORITY, &state, -1);
|
|
|
|
|
|
|
|
return (state == 0);
|
|
|
|
}
|
|
|
|
|
2005-11-15 12:48:19 +01:00
|
|
|
/* Callbacks */
|
2006-01-08 17:32:51 +01:00
|
|
|
static void
|
2005-11-15 12:48:19 +01:00
|
|
|
on_gm_mcp_userlist_view_weak_notify(gpointer data, GObject *obj) {
|
|
|
|
GmMcpUserlistView *view = (GmMcpUserlistView *)(data);
|
|
|
|
GtkWidget *vbox;
|
|
|
|
GList *children;
|
|
|
|
|
|
|
|
if (GM_IS_WORLD_VIEW(view->view)) {
|
|
|
|
gtk_widget_destroy(GTK_WIDGET(view->scrolled_window));
|
2006-04-07 18:32:44 +02:00
|
|
|
gtk_widget_destroy(view->label);
|
|
|
|
|
2005-11-15 12:48:19 +01:00
|
|
|
vbox = gtk_paned_get_child2(GTK_PANED(gm_world_view_hpaned(
|
|
|
|
view->view)));
|
|
|
|
|
|
|
|
if (vbox != NULL) {
|
|
|
|
children = gtk_container_get_children(GTK_CONTAINER(vbox));
|
|
|
|
|
|
|
|
if (children == NULL) {
|
|
|
|
gtk_widget_destroy(vbox);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_list_free(children);
|
|
|
|
}
|
|
|
|
}
|
2006-01-08 17:32:51 +01:00
|
|
|
|
2006-04-23 16:51:04 +02:00
|
|
|
g_object_unref(G_OBJECT(view->store));
|
|
|
|
g_object_unref(G_OBJECT(view->model));
|
|
|
|
|
2006-04-07 18:32:44 +02:00
|
|
|
g_signal_handlers_disconnect_by_func(gm_app_options(gm_app_instance()),
|
|
|
|
G_CALLBACK(on_gm_mcp_userlist_view_option_changed), view);
|
|
|
|
|
2005-11-15 12:48:19 +01:00
|
|
|
g_free(data);
|
|
|
|
}
|
|
|
|
|
2006-04-07 18:32:44 +02:00
|
|
|
static void
|
|
|
|
on_gm_mcp_userlist_view_option_changed(GmOptions *options, gchar const *key,
|
|
|
|
GmMcpUserlistView *view) {
|
|
|
|
if (strcmp(key, "userlist_sort_type") == 0) {
|
|
|
|
gm_mcp_userlist_view_update_sort_type(view,
|
|
|
|
gm_options_get_int(options, "userlist_sort_type"));
|
|
|
|
} else if (strcmp(key, "userlist_show_status") == 0) {
|
|
|
|
gm_mcp_userlist_view_update_show_status(view,
|
|
|
|
gm_options_get_int(options, "userlist_show_status"));
|
|
|
|
} else if (strcmp(key, "userlist_use_state_icon") == 0) {
|
|
|
|
gm_mcp_userlist_view_update_use_state_icon(view,
|
|
|
|
gm_options_get_int(options, "userlist_use_state_icon"));
|
|
|
|
} else if (strcmp(key, "userlist_show_object_number") == 0) {
|
|
|
|
gm_mcp_userlist_view_update_show_object_number(view,
|
|
|
|
gm_options_get_int(options, "userlist_show_object_number"));
|
2006-09-29 18:16:16 +02:00
|
|
|
} else if (strcmp(key, "show_userlist") == 0) {
|
|
|
|
if (gm_options_get_int(options, "show_userlist"))
|
|
|
|
gtk_widget_show(view->vbox);
|
|
|
|
else
|
|
|
|
gtk_widget_hide(view->vbox);
|
2006-04-07 18:32:44 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-01-08 17:32:51 +01:00
|
|
|
static gboolean
|
2005-11-15 12:48:19 +01:00
|
|
|
gm_mcp_userlist_view_find(GmMcpUserlistView *view, gint id, GtkTreeIter *iter) {
|
|
|
|
GtkTreeModel *model = GTK_TREE_MODEL(view->store);
|
|
|
|
gint iterid;
|
|
|
|
|
|
|
|
if (gtk_tree_model_get_iter_first(model, iter)) {
|
|
|
|
do {
|
|
|
|
gtk_tree_model_get(model, iter, GM_USERLIST_ID, &iterid, -1);
|
|
|
|
|
|
|
|
if (iterid == id) {
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
} while (gtk_tree_model_iter_next(model, iter));
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2006-01-08 17:32:51 +01:00
|
|
|
static void
|
2005-11-15 12:48:19 +01:00
|
|
|
on_gm_mcp_userlist_view_player_added(GmMcpPackage *package, gint id,
|
|
|
|
GmMcpUserlistView *view) {
|
|
|
|
GtkTreeIter iter;
|
2006-04-23 16:51:04 +02:00
|
|
|
gchar *name, *status;
|
2006-04-07 18:32:44 +02:00
|
|
|
GmIUserlist *userlist = GM_IUSERLIST(package);
|
2005-11-15 12:48:19 +01:00
|
|
|
|
|
|
|
if (gm_mcp_userlist_view_find(view, id, &iter)) {
|
|
|
|
gm_debug_msg(DEBUG_MCP, "GmMcpUserlistView.OnPlayerAdded: player %d "
|
|
|
|
"is already in the list, can't be added twice!", id);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-04-07 18:32:44 +02:00
|
|
|
name = gm_mcp_userlist_view_get_name(view, id);
|
2006-04-23 16:51:04 +02:00
|
|
|
status = gm_mcp_userlist_view_get_status(view, id);
|
2006-04-07 18:32:44 +02:00
|
|
|
gtk_list_store_insert_with_values(view->store, &iter,
|
|
|
|
gtk_tree_model_iter_n_children(GTK_TREE_MODEL(view->store), NULL),
|
|
|
|
GM_USERLIST_ID, id,
|
|
|
|
GM_USERLIST_ICON, gm_pixbuf_get_at_size(
|
|
|
|
gm_iuserlist_get_icon(userlist, id, view->use_state_icon),
|
|
|
|
GM_USERLIST_ICON_SIZE, GM_USERLIST_ICON_SIZE),
|
2006-04-23 16:51:04 +02:00
|
|
|
GM_USERLIST_NAME, name,
|
|
|
|
GM_USERLIST_STATUS, status,
|
2006-04-07 18:32:44 +02:00
|
|
|
GM_USERLIST_RANK_PRIORITY,
|
|
|
|
gm_iuserlist_get_rank_priority(userlist, id),
|
|
|
|
GM_USERLIST_STATE_PRIORITY,
|
|
|
|
gm_iuserlist_get_state_priority(userlist, id),
|
|
|
|
-1);
|
2006-04-01 16:30:50 +02:00
|
|
|
|
|
|
|
g_free(name);
|
2006-04-23 16:51:04 +02:00
|
|
|
g_free(status);
|
|
|
|
|
2006-04-07 18:32:44 +02:00
|
|
|
view->num_players = view->num_players + 1;
|
|
|
|
|
|
|
|
if (gm_mcp_userlist_view_player_active(view, &iter)) {
|
|
|
|
view->num_active = view->num_active + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
gm_mcp_userlist_view_update_label(view);
|
|
|
|
|
2005-11-15 12:48:19 +01:00
|
|
|
}
|
|
|
|
|
2006-01-08 17:32:51 +01:00
|
|
|
static void
|
2005-11-15 12:48:19 +01:00
|
|
|
on_gm_mcp_userlist_view_player_removed(GmMcpPackage *package, gint id,
|
|
|
|
GmMcpUserlistView *view) {
|
|
|
|
GtkTreeIter iter;
|
2006-04-07 18:32:44 +02:00
|
|
|
|
2005-11-15 12:48:19 +01:00
|
|
|
if (!gm_mcp_userlist_view_find(view, id, &iter)) {
|
|
|
|
gm_debug_msg(DEBUG_MCP, "GmMcpUserlistView.OnPlayerRemoved: player %d "
|
|
|
|
"is not in the list, can't be removed!", id);
|
|
|
|
return;
|
|
|
|
}
|
2006-04-07 18:32:44 +02:00
|
|
|
|
|
|
|
view->num_players = view->num_players - 1;
|
|
|
|
|
|
|
|
if (gm_mcp_userlist_view_player_active(view, &iter)) {
|
|
|
|
view->num_active = view->num_active - 1;
|
|
|
|
}
|
2005-11-15 12:48:19 +01:00
|
|
|
|
2006-04-07 18:32:44 +02:00
|
|
|
gm_mcp_userlist_view_update_label(view);
|
2005-11-15 12:48:19 +01:00
|
|
|
gtk_list_store_remove(view->store, &iter);
|
|
|
|
}
|
|
|
|
|
2006-01-08 17:32:51 +01:00
|
|
|
static void
|
|
|
|
on_gm_mcp_userlist_view_name_changed(GmMcpPackage *package, gint id,
|
2006-04-07 18:32:44 +02:00
|
|
|
GmMcpUserlistView *view) {
|
2005-11-15 12:48:19 +01:00
|
|
|
GtkTreeIter iter;
|
2006-04-01 16:30:50 +02:00
|
|
|
gchar *name;
|
2005-11-15 12:48:19 +01:00
|
|
|
|
|
|
|
if (!gm_mcp_userlist_view_find(view, id, &iter)) {
|
|
|
|
gm_debug_msg(DEBUG_MCP, "GmMcpUserlistView.OnNameChanged: player %d "
|
|
|
|
"is not in the list!", id);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-04-07 18:32:44 +02:00
|
|
|
name = gm_mcp_userlist_view_get_name(view, id);
|
2006-04-23 16:51:04 +02:00
|
|
|
|
2006-04-07 18:32:44 +02:00
|
|
|
if (name != NULL) {
|
2006-04-23 16:51:04 +02:00
|
|
|
gtk_list_store_set(view->store, &iter, GM_USERLIST_NAME, name, -1);
|
2006-04-07 18:32:44 +02:00
|
|
|
g_free(name);
|
2005-11-15 12:48:19 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-01-08 17:32:51 +01:00
|
|
|
static void
|
|
|
|
on_gm_mcp_userlist_view_rank_changed(GmMcpPackage *package, gint id,
|
2006-04-07 18:32:44 +02:00
|
|
|
GmMcpUserlistView *view) {
|
2005-11-15 12:48:19 +01:00
|
|
|
GtkTreeIter iter;
|
2006-04-07 18:32:44 +02:00
|
|
|
gchar const *icon;
|
2005-11-15 12:48:19 +01:00
|
|
|
|
|
|
|
if (!gm_mcp_userlist_view_find(view, id, &iter)) {
|
|
|
|
gm_debug_msg(DEBUG_MCP, "GmMcpUserlistView.OnRankChanged: player %d "
|
|
|
|
"is not in the list!", id);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-04-07 18:32:44 +02:00
|
|
|
icon = gm_iuserlist_get_icon(GM_IUSERLIST(package),
|
|
|
|
id, view->use_state_icon);
|
|
|
|
|
2005-11-15 12:48:19 +01:00
|
|
|
gtk_list_store_set(view->store, &iter, GM_USERLIST_ICON,
|
|
|
|
gm_pixbuf_get_at_size(icon, GM_USERLIST_ICON_SIZE,
|
2006-04-07 18:32:44 +02:00
|
|
|
GM_USERLIST_ICON_SIZE),
|
|
|
|
GM_USERLIST_RANK_PRIORITY, gm_iuserlist_get_rank_priority(
|
|
|
|
GM_IUSERLIST(package), id),
|
|
|
|
-1);
|
2005-11-15 12:48:19 +01:00
|
|
|
}
|
|
|
|
|
2006-01-08 17:32:51 +01:00
|
|
|
static void
|
|
|
|
on_gm_mcp_userlist_view_state_changed(GmMcpPackage *package, gint id,
|
2006-04-07 18:32:44 +02:00
|
|
|
GmMcpUserlistView *view) {
|
2005-11-15 12:48:19 +01:00
|
|
|
GtkTreeIter iter;
|
2006-04-23 16:51:04 +02:00
|
|
|
gchar *name, *status;
|
2006-04-07 18:32:44 +02:00
|
|
|
gchar const *icon;
|
|
|
|
gboolean active;
|
2005-11-15 12:48:19 +01:00
|
|
|
|
|
|
|
if (!gm_mcp_userlist_view_find(view, id, &iter)) {
|
|
|
|
gm_debug_msg(DEBUG_MCP, "GmMcpUserlistView.OnStateChanged: player %d "
|
|
|
|
"is not in the list!", id);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-04-07 18:32:44 +02:00
|
|
|
active = gm_mcp_userlist_view_player_active(view, &iter);
|
|
|
|
|
|
|
|
name = gm_mcp_userlist_view_get_name(view, id);
|
2006-04-23 16:51:04 +02:00
|
|
|
status = gm_mcp_userlist_view_get_status(view, id);
|
2006-04-07 18:32:44 +02:00
|
|
|
icon = gm_iuserlist_get_icon(GM_IUSERLIST(package), id,
|
|
|
|
view->use_state_icon);
|
2006-04-01 16:30:50 +02:00
|
|
|
|
2005-11-15 12:48:19 +01:00
|
|
|
gtk_list_store_set(view->store, &iter, GM_USERLIST_ICON,
|
|
|
|
gm_pixbuf_get_at_size(icon, GM_USERLIST_ICON_SIZE,
|
2006-04-07 18:32:44 +02:00
|
|
|
GM_USERLIST_ICON_SIZE),
|
2006-04-23 16:51:04 +02:00
|
|
|
GM_USERLIST_NAME, name,
|
|
|
|
GM_USERLIST_STATUS, status,
|
2006-04-07 18:32:44 +02:00
|
|
|
GM_USERLIST_STATE_PRIORITY, gm_iuserlist_get_state_priority(
|
|
|
|
GM_IUSERLIST(package), id),
|
|
|
|
-1);
|
2006-04-01 16:30:50 +02:00
|
|
|
|
|
|
|
g_free(name);
|
2006-04-23 16:51:04 +02:00
|
|
|
g_free(status);
|
2006-04-07 18:32:44 +02:00
|
|
|
|
|
|
|
if (gm_mcp_userlist_view_player_active(view, &iter) != active) {
|
|
|
|
if (active) {
|
|
|
|
// no longer active
|
|
|
|
view->num_active = view->num_active - 1;
|
|
|
|
} else {
|
|
|
|
// now active
|
|
|
|
view->num_active = view->num_active + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
gm_mcp_userlist_view_update_label(view);
|
2005-11-15 12:48:19 +01:00
|
|
|
}
|
2006-01-08 17:32:51 +01:00
|
|
|
|
|
|
|
static void
|
|
|
|
popup_menu_detach(GtkWidget *attach_widget, GtkMenu *menu) {
|
|
|
|
GmMcpUserlistView *view = (GmMcpUserlistView *)g_object_get_data(
|
|
|
|
G_OBJECT(menu), "McpUserlistView");
|
|
|
|
|
|
|
|
view->popup_menu = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
on_gm_mcp_userlist_view_menuitem_activate(GtkMenuItem *item,
|
|
|
|
GmMcpUserlistView *view) {
|
|
|
|
gchar *action = (gchar *)g_object_get_data(G_OBJECT(item),
|
|
|
|
"UserlistAction");
|
|
|
|
|
|
|
|
if (action) {
|
|
|
|
gm_world_sendln(GM_MCP_SESSION_WORLD(GM_MCP_PACKAGE_SESSION(
|
|
|
|
view->package)), action);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
gm_mcp_userlist_view_do_popup(GmMcpUserlistView *view, GdkEventButton *event) {
|
|
|
|
GList *menu;
|
|
|
|
GList *item;
|
|
|
|
GmKeyValuePair *pair;
|
|
|
|
GtkWidget *menuitem;
|
|
|
|
GtkTreeSelection *selection = gtk_tree_view_get_selection(view->tree_view);
|
|
|
|
gint id;
|
|
|
|
GtkTreeModel *model;
|
|
|
|
GtkTreeIter iter;
|
|
|
|
GtkTreePath *path;
|
|
|
|
|
|
|
|
if (!event) {
|
|
|
|
if (!gtk_tree_selection_get_selected(selection, &model, &iter)) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
gtk_tree_model_get(model, &iter, GM_USERLIST_ID, &id, -1);
|
|
|
|
} else {
|
|
|
|
if (!gtk_tree_view_get_path_at_pos(view->tree_view, event->x, event->y,
|
|
|
|
&path, NULL, NULL, NULL)) {
|
|
|
|
return FALSE;
|
|
|
|
} else {
|
|
|
|
gtk_tree_model_get_iter(view->model, &iter, path);
|
|
|
|
gtk_tree_path_free(path);
|
|
|
|
|
|
|
|
gtk_tree_model_get(view->model, &iter, GM_USERLIST_ID, &id, -1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
menu = gm_iuserlist_get_menu(GM_IUSERLIST(view->package), id);
|
|
|
|
|
|
|
|
if (view->popup_menu) {
|
|
|
|
gtk_widget_destroy(view->popup_menu);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!menu) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
view->popup_menu = gtk_menu_new();
|
|
|
|
g_object_set_data(G_OBJECT(view->popup_menu), "McpUserlistView", view);
|
|
|
|
|
|
|
|
gtk_menu_attach_to_widget(GTK_MENU(view->popup_menu),
|
|
|
|
GTK_WIDGET(view->tree_view), popup_menu_detach);
|
|
|
|
|
|
|
|
for (item = menu; item; item = item->next) {
|
|
|
|
pair = (GmKeyValuePair *)(item->data);
|
|
|
|
|
|
|
|
if (pair->key == NULL) {
|
|
|
|
menuitem = gtk_separator_menu_item_new();
|
|
|
|
g_free(pair->value);
|
|
|
|
} else {
|
|
|
|
menuitem = gtk_menu_item_new_with_mnemonic(pair->key);
|
|
|
|
g_object_set_data_full(G_OBJECT(menuitem), "UserlistAction",
|
|
|
|
pair->value, g_free);
|
|
|
|
|
|
|
|
g_signal_connect(menuitem, "activate",
|
|
|
|
G_CALLBACK(on_gm_mcp_userlist_view_menuitem_activate),
|
|
|
|
view);
|
|
|
|
}
|
|
|
|
|
|
|
|
gtk_widget_show(menuitem);
|
|
|
|
gtk_menu_shell_append(GTK_MENU_SHELL(view->popup_menu), menuitem);
|
|
|
|
|
|
|
|
g_free(pair->key);
|
|
|
|
g_free(pair);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_list_free(menu);
|
|
|
|
|
|
|
|
if (!event) {
|
|
|
|
gtk_menu_popup(GTK_MENU(view->popup_menu), NULL, NULL, NULL, NULL, 0,
|
|
|
|
gtk_get_current_event_time());
|
|
|
|
} else {
|
|
|
|
gtk_menu_popup(GTK_MENU(view->popup_menu), NULL, NULL, NULL, NULL,
|
|
|
|
event->button, event->time);
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
on_gm_mcp_userlist_view_popup_menu(GtkWidget *widget,
|
|
|
|
GmMcpUserlistView *view) {
|
|
|
|
return gm_mcp_userlist_view_do_popup(view, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
on_gm_mcp_userlist_view_button_press(GtkWidget *widget, GdkEventButton *event,
|
|
|
|
GmMcpUserlistView *view) {
|
|
|
|
if (event->button == 3 && event->type == GDK_BUTTON_PRESS) {
|
|
|
|
gm_mcp_userlist_view_do_popup(view, event);
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|