Added context menu
This commit is contained in:
parent
9a843265cf
commit
de90a39120
|
@ -5,6 +5,7 @@
|
|||
#include <errno.h>
|
||||
|
||||
#include "gm-mcp-icecrew-userlist.h"
|
||||
#include "gm-iuserlist.h"
|
||||
#include "gm-mcp-userlist-view.h"
|
||||
#include "gm-mcp-icecrew-playerdb.h"
|
||||
#include "gm-mcp-session.h"
|
||||
|
@ -50,6 +51,8 @@ struct _GmMcpIcecrewUserlistPrivate {
|
|||
gchar *rank_dir;
|
||||
gchar *state_dir;
|
||||
|
||||
GList *menu;
|
||||
|
||||
gboolean initializing;
|
||||
};
|
||||
|
||||
|
@ -73,9 +76,12 @@ enum {
|
|||
NUM_SIGNALS
|
||||
};
|
||||
|
||||
static void gm_mcp_icecrew_userlist_iface_init(GmIUserlistInterface *iface);
|
||||
static guint gm_mcp_icecrew_userlist_signals[NUM_SIGNALS] = {0};
|
||||
|
||||
G_DEFINE_TYPE(GmMcpIcecrewUserlist, gm_mcp_icecrew_userlist, GM_TYPE_MCP_PACKAGE)
|
||||
G_DEFINE_TYPE_EXTENDED(GmMcpIcecrewUserlist, gm_mcp_icecrew_userlist, \
|
||||
GM_TYPE_MCP_PACKAGE, 0, G_IMPLEMENT_INTERFACE(GM_TYPE_IUSERLIST, \
|
||||
gm_mcp_icecrew_userlist_iface_init))
|
||||
|
||||
void on_gm_mcp_icecrew_userlist_add(GmMcpIcecrewPlayerdb *playerdb,
|
||||
GmPlayerdbPlayerInfo *ppi, GmMcpIcecrewUserlist *userlist);
|
||||
|
@ -100,6 +106,14 @@ void gm_mcp_icecrew_userlist_create_view(GmMcpPackage *package,
|
|||
void gm_mcp_icecrew_userlist_fetch_progress(GmFetchHandle *g,
|
||||
GmMcpIcecrewUserlist *package);
|
||||
|
||||
GList *gm_mcp_icecrew_userlist_get_menu(GmIUserlist *userlist, gint id);
|
||||
|
||||
static void
|
||||
gm_mcp_icecrew_userlist_iface_init(
|
||||
GmIUserlistInterface *iface) {
|
||||
iface->get_menu = gm_mcp_icecrew_userlist_get_menu;
|
||||
}
|
||||
|
||||
void
|
||||
gm_mcp_icecrew_userlist_pair_free(GmKeyValuePair *pair) {
|
||||
g_free(pair->key);
|
||||
|
@ -118,6 +132,12 @@ gm_mcp_icecrew_userlist_free_list(GList *rs) {
|
|||
g_list_free(rs);
|
||||
}
|
||||
|
||||
static void
|
||||
gm_mcp_icecrew_userlist_free_menu(GmMcpIcecrewUserlist *obj) {
|
||||
gm_mcp_icecrew_userlist_free_list(obj->priv->menu);
|
||||
obj->priv->menu = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gm_mcp_icecrew_userlist_finalize(GObject *object) {
|
||||
GmMcpIcecrewUserlist *obj = GM_MCP_ICECREW_USERLIST(object);
|
||||
|
@ -132,14 +152,7 @@ gm_mcp_icecrew_userlist_finalize(GObject *object) {
|
|||
g_signal_handlers_disconnect_by_func(playerdb,
|
||||
on_gm_mcp_icecrew_userlist_delete, obj);
|
||||
}
|
||||
|
||||
gm_mcp_icecrew_userlist_free_list(obj->priv->state_icons);
|
||||
gm_mcp_icecrew_userlist_free_list(obj->priv->rank_icons);
|
||||
gm_mcp_icecrew_userlist_free_list(obj->priv->key_datatags);
|
||||
|
||||
g_free(obj->priv->rank_dir);
|
||||
g_free(obj->priv->state_dir);
|
||||
|
||||
|
||||
if (obj->priv->rank_fetch) {
|
||||
obj->priv->rank_fetch->aborted = TRUE;
|
||||
}
|
||||
|
@ -147,6 +160,16 @@ gm_mcp_icecrew_userlist_finalize(GObject *object) {
|
|||
if (obj->priv->state_fetch) {
|
||||
obj->priv->state_fetch->aborted = TRUE;
|
||||
}
|
||||
|
||||
gm_mcp_icecrew_userlist_free_list(obj->priv->state_icons);
|
||||
gm_mcp_icecrew_userlist_free_list(obj->priv->rank_icons);
|
||||
gm_mcp_icecrew_userlist_free_list(obj->priv->key_datatags);
|
||||
gm_mcp_icecrew_userlist_free_menu(obj);
|
||||
gm_mcp_icecrew_userlist_free_list(obj->priv->rank_alternatives);
|
||||
gm_mcp_icecrew_userlist_free_list(obj->priv->state_alternatives);
|
||||
|
||||
g_free(obj->priv->rank_dir);
|
||||
g_free(obj->priv->state_dir);
|
||||
|
||||
G_OBJECT_CLASS(gm_mcp_icecrew_userlist_parent_class)->finalize(object);
|
||||
}
|
||||
|
@ -682,28 +705,18 @@ void
|
|||
gm_mcp_icecrew_userlist_fetch_progress(GmFetchHandle *g,
|
||||
GmMcpIcecrewUserlist *package) {
|
||||
gchar *path;
|
||||
gboolean rank = (package->priv->rank_fetch == g);
|
||||
gboolean rank;
|
||||
GdkPixbuf *pixtest;
|
||||
GError *err = NULL;
|
||||
|
||||
if (g->aborted) {
|
||||
if (rank) {
|
||||
package->priv->rank_fetch = NULL;
|
||||
gm_mcp_icecrew_userlist_free_list(
|
||||
package->priv->rank_alternatives);
|
||||
package->priv->rank_alternatives = NULL;
|
||||
} else {
|
||||
package->priv->state_fetch = NULL;
|
||||
gm_mcp_icecrew_userlist_free_list(
|
||||
package->priv->state_alternatives);
|
||||
package->priv->state_alternatives = NULL;
|
||||
}
|
||||
|
||||
if (g->aborted) {
|
||||
gm_debug_msg(DEBUG_MCP, "GmMcpIcecrewUserlist.FetchProgress: "
|
||||
"fetch aborted!");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
rank = (package->priv->rank_fetch == g);
|
||||
|
||||
if (g->done) {
|
||||
gm_debug_msg(DEBUG_MCP, "GmMcpIcecrewUserlist.FetchProgress: "
|
||||
"fetch done!");
|
||||
|
@ -791,13 +804,156 @@ gm_mcp_icecrew_userlist_process_triggers(GmMcpIcecrewUserlist *package,
|
|||
|
||||
}
|
||||
|
||||
gchar *
|
||||
gm_mcp_icecrew_userlist_menu_item_subst(GmMcpIcecrewUserlist *package,
|
||||
gchar *str, GmPlayerdbPlayerInfo *info) {
|
||||
GString *result;
|
||||
gchar *ptr = str, *subst, *tmp, *prop;
|
||||
gchar const *value;
|
||||
gunichar ch, cnum;
|
||||
gboolean substituted;
|
||||
|
||||
if (str == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = g_string_sized_new(strlen(str));
|
||||
|
||||
while ((ch = g_utf8_get_char(ptr)) != '\0') {
|
||||
substituted = FALSE;
|
||||
|
||||
if (ch == '$') {
|
||||
tmp = subst = g_utf8_next_char(ptr);
|
||||
|
||||
while ((cnum = g_utf8_get_char(subst)) && (cnum == '_' ||
|
||||
g_unichar_isalpha(cnum))) {
|
||||
subst = g_utf8_next_char(subst);
|
||||
}
|
||||
|
||||
prop = g_strndup(tmp, subst - tmp);
|
||||
|
||||
if (strcmp(prop, "ID") == 0) {
|
||||
tmp = g_strdup_printf("#%d", info->id);
|
||||
result = g_string_append(result, tmp);
|
||||
g_free(tmp);
|
||||
|
||||
substituted = TRUE;
|
||||
} else {
|
||||
value = gm_playerdb_player_info_get_prop(info, prop);
|
||||
|
||||
if (value) {
|
||||
for (; *value != '\0'; value = g_utf8_next_char(value)) {
|
||||
ch = g_utf8_get_char(value);
|
||||
|
||||
if (ch == '_') {
|
||||
result = g_string_append_c(result, '_');
|
||||
}
|
||||
|
||||
result = g_string_append_unichar(result, ch);
|
||||
}
|
||||
|
||||
substituted = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (substituted) {
|
||||
ptr = subst;
|
||||
}
|
||||
}
|
||||
|
||||
if (!substituted) {
|
||||
result = g_string_append_unichar(result, ch);
|
||||
}
|
||||
|
||||
if (*ptr == '\0') {
|
||||
break;
|
||||
}
|
||||
|
||||
ptr = g_utf8_next_char(ptr);
|
||||
}
|
||||
|
||||
ptr = result->str;
|
||||
g_string_free(result, FALSE);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
GmKeyValuePair *
|
||||
gm_mcp_icecrew_userlist_get_menu_item(GmMcpIcecrewUserlist *package,
|
||||
GmKeyValuePair *menuitem, GmPlayerdbPlayerInfo *info) {
|
||||
GmKeyValuePair *result = g_new0(GmKeyValuePair, 1);
|
||||
|
||||
if (!menuitem) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result->key = gm_mcp_icecrew_userlist_menu_item_subst(package,
|
||||
menuitem->key, info);
|
||||
result->value = gm_mcp_icecrew_userlist_menu_item_subst(package,
|
||||
menuitem->value, info);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
GList *
|
||||
gm_mcp_icecrew_userlist_get_menu(GmIUserlist *userlist, gint id) {
|
||||
GmMcpIcecrewUserlist *object = GM_MCP_ICECREW_USERLIST(userlist);
|
||||
GmMcpIcecrewPlayerdb *playerdb = GM_MCP_ICECREW_PLAYERDB(
|
||||
gm_mcp_session_find_package(GM_MCP_PACKAGE_SESSION(userlist),
|
||||
"dns-nl-icecrew-playerdb"));
|
||||
GmPlayerdbPlayerInfo *info = gm_mcp_icecrew_playerdb_find(playerdb, id);
|
||||
GList *item, *result = NULL;
|
||||
|
||||
for (item = object->priv->menu; item; item = item->next) {
|
||||
result = g_list_append(result, gm_mcp_icecrew_userlist_get_menu_item(
|
||||
object, (GmKeyValuePair *)(item->data), info));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
gm_mcp_icecrew_userlist_handle_menu(GmMcpIcecrewUserlist *package,
|
||||
GList *values) {
|
||||
GmKeyValuePair *pair;
|
||||
GList *item, *data;
|
||||
|
||||
gm_mcp_icecrew_userlist_free_menu(package);
|
||||
|
||||
for (item = values; item; item = item->next) {
|
||||
data = (GList *)(item->data);
|
||||
pair = g_new0(GmKeyValuePair, 1);
|
||||
|
||||
if (g_list_length(data) == 2) {
|
||||
pair->key = g_strdup(data->data);
|
||||
pair->value = g_strdup(data->next->data);
|
||||
}
|
||||
|
||||
package->priv->menu = g_list_append(package->priv->menu,
|
||||
pair);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gm_mcp_icecrew_userlist_handle_ranks_states(GmMcpIcecrewUserlist *package,
|
||||
GList *values, gboolean rank) {
|
||||
GList *tmp, *data, *new_list = NULL;
|
||||
gchar *name, **alternatives, *path, **ptr;
|
||||
gchar const *cpath;
|
||||
|
||||
|
||||
/* Abort a previous fetch if needed */
|
||||
if (rank && package->priv->rank_fetch) {
|
||||
package->priv->rank_fetch = NULL;
|
||||
gm_mcp_icecrew_userlist_free_list(package->priv->rank_alternatives);
|
||||
package->priv->rank_alternatives = NULL;
|
||||
package->priv->rank_fetch->aborted = TRUE;
|
||||
} else if (!rank && package->priv->state_fetch) {
|
||||
package->priv->state_fetch = NULL;
|
||||
gm_mcp_icecrew_userlist_free_list(package->priv->state_alternatives);
|
||||
package->priv->state_alternatives = NULL;
|
||||
package->priv->state_fetch->aborted = TRUE;
|
||||
}
|
||||
|
||||
for (tmp = values; tmp; tmp = tmp->next) {
|
||||
data = (GList *)(tmp->data);
|
||||
|
||||
|
@ -873,19 +1029,6 @@ gm_mcp_icecrew_userlist_handle_ranks_states(GmMcpIcecrewUserlist *package,
|
|||
package->priv->state_icons = new_list;
|
||||
}
|
||||
|
||||
/* Abort a previous fetch if needed */
|
||||
if (rank && package->priv->rank_fetch) {
|
||||
package->priv->rank_fetch->aborted = TRUE;
|
||||
} else if (!rank && package->priv->state_fetch) {
|
||||
package->priv->state_fetch->aborted = TRUE;
|
||||
}
|
||||
|
||||
/* Wait for vfs async to be aborted */
|
||||
while ((rank && package->priv->rank_fetch != NULL) ||
|
||||
(!rank && package->priv->state_fetch != NULL)) {
|
||||
gm_do_events();
|
||||
}
|
||||
|
||||
if (rank && package->priv->rank_alternatives) {
|
||||
gm_mcp_icecrew_userlist_fetch_next_alternatives(package, rank);
|
||||
} else if (!rank && package->priv->state_alternatives) {
|
||||
|
@ -921,6 +1064,8 @@ gm_mcp_icecrew_userlist_handle_multi(GmMcpPackage *package,
|
|||
gm_mcp_icecrew_userlist_handle_ranks_states(userlist, vals, TRUE);
|
||||
} else if (strcmp(key, "state") == 0) {
|
||||
gm_mcp_icecrew_userlist_handle_ranks_states(userlist, vals, FALSE);
|
||||
} else if (strcmp(key, "menu") == 0) {
|
||||
gm_mcp_icecrew_userlist_handle_menu(userlist, vals);
|
||||
}
|
||||
|
||||
gm_mcp_icecrew_userlist_remove_datatag(userlist, data_tag);
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include "gm-mcp-package.h"
|
||||
#include "gm-mcp-userlist-view.h"
|
||||
#include "gm-iuserlist.h"
|
||||
#include "../widgets/gm-world-view.h"
|
||||
#include "../gm-pixbuf.h"
|
||||
#include "../gm-debug.h"
|
||||
|
@ -23,25 +24,28 @@ typedef struct _GmMcpUserlistView {
|
|||
GtkListStore *store;
|
||||
GtkTreeView *tree_view;
|
||||
GtkScrolledWindow *scrolled_window;
|
||||
|
||||
GtkWidget *popup_menu;
|
||||
|
||||
gboolean initializing;
|
||||
} GmMcpUserlistView;
|
||||
|
||||
void on_gm_mcp_userlist_view_weak_notify(gpointer data, GObject *obj);
|
||||
static void on_gm_mcp_userlist_view_weak_notify(gpointer data, GObject *obj);
|
||||
|
||||
void on_gm_mcp_userlist_view_player_added(GmMcpPackage *package, gint id,
|
||||
static void on_gm_mcp_userlist_view_player_added(GmMcpPackage *package, gint id,
|
||||
gchar const *name, gchar const *icon, gchar const *sort,
|
||||
GmMcpUserlistView *view);
|
||||
void on_gm_mcp_userlist_view_player_removed(GmMcpPackage *package, gint id,
|
||||
static void on_gm_mcp_userlist_view_player_removed(GmMcpPackage *package, gint id,
|
||||
GmMcpUserlistView *view);
|
||||
void on_gm_mcp_userlist_view_name_changed(GmMcpPackage *package, gint id,
|
||||
static void on_gm_mcp_userlist_view_name_changed(GmMcpPackage *package, gint id,
|
||||
gchar const *name, gchar const *sort, GmMcpUserlistView *view);
|
||||
void on_gm_mcp_userlist_view_rank_changed(GmMcpPackage *package, gint id,
|
||||
static void on_gm_mcp_userlist_view_rank_changed(GmMcpPackage *package, gint id,
|
||||
gchar const *icon, gchar const *sort, GmMcpUserlistView *view);
|
||||
void on_gm_mcp_userlist_view_state_changed(GmMcpPackage *package, gint id,
|
||||
static void on_gm_mcp_userlist_view_state_changed(GmMcpPackage *package, gint id,
|
||||
gchar const *icon, gchar const *sort, GmMcpUserlistView *view);
|
||||
void on_gm_mcp_userlist_view_initializing(GmMcpPackage *package,
|
||||
gboolean initializing, GmMcpUserlistView *view);
|
||||
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);
|
||||
|
||||
GtkTreeModel *
|
||||
gm_mcp_userlist_view_model_create(GmMcpUserlistView *view) {
|
||||
|
@ -88,7 +92,13 @@ gm_mcp_userlist_view_create_userlist(GmMcpUserlistView *view) {
|
|||
gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(model),
|
||||
GM_USERLIST_SORT, GTK_SORT_ASCENDING);
|
||||
|
||||
GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(tree_view), GTK_CAN_FOCUS);
|
||||
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]));
|
||||
|
||||
gtk_tree_view_columns_autosize(GTK_TREE_VIEW(tree_view));
|
||||
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree_view), FALSE);
|
||||
|
||||
|
@ -108,7 +118,7 @@ gm_mcp_userlist_view_new(GmMcpPackage *package, GObject *parent) {
|
|||
return;
|
||||
}
|
||||
|
||||
view = g_new(GmMcpUserlistView, 1);
|
||||
view = g_new0(GmMcpUserlistView, 1);
|
||||
view->view = GM_WORLD_VIEW(parent);
|
||||
view->package = package;
|
||||
|
||||
|
@ -125,6 +135,11 @@ gm_mcp_userlist_view_new(GmMcpPackage *package, GObject *parent) {
|
|||
gtk_box_pack_end(GTK_BOX(vbox), child, TRUE, TRUE, 0);
|
||||
gtk_widget_show_all(vbox);
|
||||
|
||||
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);
|
||||
|
||||
g_signal_connect(package, "player_added",
|
||||
G_CALLBACK(on_gm_mcp_userlist_view_player_added), view);
|
||||
g_signal_connect(package, "player_removed",
|
||||
|
@ -141,7 +156,7 @@ gm_mcp_userlist_view_new(GmMcpPackage *package, GObject *parent) {
|
|||
}
|
||||
|
||||
/* Callbacks */
|
||||
void
|
||||
static void
|
||||
on_gm_mcp_userlist_view_weak_notify(gpointer data, GObject *obj) {
|
||||
GmMcpUserlistView *view = (GmMcpUserlistView *)(data);
|
||||
GtkWidget *vbox;
|
||||
|
@ -162,11 +177,11 @@ on_gm_mcp_userlist_view_weak_notify(gpointer data, GObject *obj) {
|
|||
g_list_free(children);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
g_free(data);
|
||||
}
|
||||
|
||||
gboolean
|
||||
static gboolean
|
||||
gm_mcp_userlist_view_find(GmMcpUserlistView *view, gint id, GtkTreeIter *iter) {
|
||||
GtkTreeModel *model = GTK_TREE_MODEL(view->store);
|
||||
gint iterid;
|
||||
|
@ -184,7 +199,7 @@ gm_mcp_userlist_view_find(GmMcpUserlistView *view, gint id, GtkTreeIter *iter) {
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
on_gm_mcp_userlist_view_player_added(GmMcpPackage *package, gint id,
|
||||
gchar const *name, gchar const *icon, gchar const *sort,
|
||||
GmMcpUserlistView *view) {
|
||||
|
@ -203,7 +218,7 @@ on_gm_mcp_userlist_view_player_added(GmMcpPackage *package, gint id,
|
|||
sort, -1);
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
on_gm_mcp_userlist_view_player_removed(GmMcpPackage *package, gint id,
|
||||
GmMcpUserlistView *view) {
|
||||
GtkTreeIter iter;
|
||||
|
@ -217,7 +232,8 @@ on_gm_mcp_userlist_view_player_removed(GmMcpPackage *package, gint id,
|
|||
gtk_list_store_remove(view->store, &iter);
|
||||
}
|
||||
|
||||
void on_gm_mcp_userlist_view_name_changed(GmMcpPackage *package, gint id,
|
||||
static void
|
||||
on_gm_mcp_userlist_view_name_changed(GmMcpPackage *package, gint id,
|
||||
gchar const *name, gchar const *sort, GmMcpUserlistView *view) {
|
||||
GtkTreeIter iter;
|
||||
|
||||
|
@ -234,7 +250,8 @@ void on_gm_mcp_userlist_view_name_changed(GmMcpPackage *package, gint id,
|
|||
}
|
||||
}
|
||||
|
||||
void on_gm_mcp_userlist_view_rank_changed(GmMcpPackage *package, gint id,
|
||||
static void
|
||||
on_gm_mcp_userlist_view_rank_changed(GmMcpPackage *package, gint id,
|
||||
gchar const *icon, gchar const *sort, GmMcpUserlistView *view) {
|
||||
GtkTreeIter iter;
|
||||
|
||||
|
@ -253,7 +270,8 @@ void on_gm_mcp_userlist_view_rank_changed(GmMcpPackage *package, gint id,
|
|||
}
|
||||
}
|
||||
|
||||
void on_gm_mcp_userlist_view_state_changed(GmMcpPackage *package, gint id,
|
||||
static void
|
||||
on_gm_mcp_userlist_view_state_changed(GmMcpPackage *package, gint id,
|
||||
gchar const *icon, gchar const *sort, GmMcpUserlistView *view) {
|
||||
GtkTreeIter iter;
|
||||
|
||||
|
@ -271,3 +289,121 @@ void on_gm_mcp_userlist_view_state_changed(GmMcpPackage *package, gint id,
|
|||
gtk_list_store_set(view->store, &iter, GM_USERLIST_SORT, sort, -1);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include <string.h>
|
||||
#include "gm-mcp-vmoo-userlist.h"
|
||||
#include "gm-mcp-userlist-view.h"
|
||||
#include "gm-iuserlist.h"
|
||||
#include "gm-mcp-session.h"
|
||||
#include "gm-mcp.h"
|
||||
#include "../gm-support.h"
|
||||
|
@ -44,7 +45,7 @@ struct _GmMcpVmooUserlistPrivate {
|
|||
GList *fields;
|
||||
GList *icons;
|
||||
GList *users;
|
||||
|
||||
GList *menu;
|
||||
gboolean initializing;
|
||||
};
|
||||
|
||||
|
@ -59,9 +60,12 @@ enum {
|
|||
NUM_SIGNALS
|
||||
};
|
||||
|
||||
static void gm_mcp_vmoo_userlist_iface_init(GmIUserlistInterface *iface);
|
||||
static guint gm_mcp_vmoo_userlist_signals[NUM_SIGNALS] = {0};
|
||||
|
||||
G_DEFINE_TYPE(GmMcpVmooUserlist, gm_mcp_vmoo_userlist, GM_TYPE_MCP_PACKAGE)
|
||||
G_DEFINE_TYPE_EXTENDED(GmMcpVmooUserlist, gm_mcp_vmoo_userlist, \
|
||||
GM_TYPE_MCP_PACKAGE, 0, G_IMPLEMENT_INTERFACE(GM_TYPE_IUSERLIST, \
|
||||
gm_mcp_vmoo_userlist_iface_init))
|
||||
|
||||
void gm_mcp_vmoo_userlist_handle_simple(GmMcpPackage *package,
|
||||
gchar *suffix, GList *fields);
|
||||
|
@ -71,6 +75,13 @@ gboolean gm_mcp_vmoo_userlist_handle_multi(GmMcpPackage *package,
|
|||
|
||||
void gm_mcp_vmoo_userlist_create_view(GmMcpPackage *package,
|
||||
GObject *parent);
|
||||
GList *gm_mcp_vmoo_userlist_get_menu(GmIUserlist *userlist, gint id);
|
||||
|
||||
static void
|
||||
gm_mcp_vmoo_userlist_iface_init(
|
||||
GmIUserlistInterface *iface) {
|
||||
iface->get_menu = gm_mcp_vmoo_userlist_get_menu;
|
||||
}
|
||||
|
||||
void
|
||||
gm_mcp_vmoo_userlist_remove_users(GmMcpVmooUserlist *package) {
|
||||
|
@ -89,6 +100,22 @@ gm_mcp_vmoo_userlist_remove_users(GmMcpVmooUserlist *package) {
|
|||
g_list_free(users);
|
||||
}
|
||||
|
||||
static void
|
||||
gm_mcp_vmoo_userlist_free_menu(GmMcpVmooUserlist *obj) {
|
||||
GList *field;
|
||||
GmKeyValuePair *pair;
|
||||
|
||||
for (field = obj->priv->menu; field; field = field->next) {
|
||||
pair = (GmKeyValuePair *)(field->data);
|
||||
|
||||
g_free(pair->key);
|
||||
g_free(pair->value);
|
||||
g_free(pair);
|
||||
}
|
||||
|
||||
obj->priv->menu = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gm_mcp_vmoo_userlist_finalize(GObject *object) {
|
||||
GmMcpVmooUserlist *obj = GM_MCP_VMOO_USERLIST(object);
|
||||
|
@ -105,6 +132,8 @@ gm_mcp_vmoo_userlist_finalize(GObject *object) {
|
|||
}
|
||||
|
||||
g_list_free(obj->priv->icons);
|
||||
|
||||
gm_mcp_vmoo_userlist_free_menu(obj);
|
||||
|
||||
gm_mcp_vmoo_userlist_remove_users(obj);
|
||||
g_list_free(obj->priv->users);
|
||||
|
@ -303,6 +332,27 @@ gm_mcp_vmoo_userlist_handle_icons(GmMcpVmooUserlist *package, MOOVar *list) {
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
gm_mcp_vmoo_userlist_handle_menu(GmMcpVmooUserlist *package, MOOVar *list) {
|
||||
MOOVar *field;
|
||||
GmKeyValuePair *pair;
|
||||
|
||||
for (field = list->list; field; field = field->next) {
|
||||
pair = g_new0(GmKeyValuePair, 1);
|
||||
|
||||
if (field->type == LIST && field->i == 2) {
|
||||
pair->key = g_strdup(field->list->s);
|
||||
pair->value = g_strdup(field->list->next->s);
|
||||
package->priv->menu = g_list_append(package->priv->menu,
|
||||
pair);
|
||||
} else if (field->type != LIST) {
|
||||
package->priv->menu = g_list_append(package->priv->menu, pair);
|
||||
} else {
|
||||
g_free(pair);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gchar *
|
||||
gm_mcp_vmoo_userlist_get_string(GmMcpVmooUserlist *package, MOOVar *v,
|
||||
MOOType type, gchar *cmp) {
|
||||
|
@ -359,6 +409,118 @@ gm_mcp_vmoo_userlist_find_user(GmMcpVmooUserlist *package, gint nr) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
gchar *
|
||||
gm_mcp_vmoo_userlist_menu_item_subst(GmMcpVmooUserlist *package,
|
||||
gchar *str, UserInfo *info) {
|
||||
GString *result;
|
||||
gchar *ptr = str, *subst, *tmp;
|
||||
gunichar ch, cnum;
|
||||
gint num;
|
||||
gboolean substituted;
|
||||
|
||||
if (str == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = g_string_sized_new(strlen(str));
|
||||
|
||||
while ((ch = g_utf8_get_char(ptr)) != '\0') {
|
||||
substituted = FALSE;
|
||||
|
||||
if (ch == '&') {
|
||||
result = g_string_append_c(result, '_');
|
||||
substituted = TRUE;
|
||||
} else if (ch == '$') {
|
||||
subst = g_utf8_next_char(ptr);
|
||||
|
||||
if (g_utf8_get_char(subst) == '(') {
|
||||
subst = g_utf8_next_char(subst);
|
||||
num = 0;
|
||||
|
||||
while (g_unichar_isdigit((cnum = g_utf8_get_char(subst)))) {
|
||||
num = (num * 10) + g_unichar_digit_value(cnum);
|
||||
subst = g_utf8_next_char(subst);
|
||||
}
|
||||
|
||||
if (g_utf8_get_char(subst) == ')') {
|
||||
switch (num) {
|
||||
case 1:
|
||||
tmp = g_strdup_printf("#%d", info->nr);
|
||||
result = g_string_append(result, tmp);
|
||||
g_free(tmp);
|
||||
break;
|
||||
case 2:
|
||||
for (tmp = info->name; *tmp != '\0';
|
||||
tmp = g_utf8_next_char(tmp)) {
|
||||
ch = g_utf8_get_char(tmp);
|
||||
|
||||
if (ch == '_') {
|
||||
result = g_string_append_c(result, '_');
|
||||
}
|
||||
|
||||
result = g_string_append_unichar(result, ch);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ptr = subst;
|
||||
substituted = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!substituted) {
|
||||
result = g_string_append_unichar(result, ch);
|
||||
}
|
||||
|
||||
ptr = g_utf8_next_char(ptr);
|
||||
}
|
||||
|
||||
ptr = result->str;
|
||||
g_string_free(result, FALSE);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
GmKeyValuePair *
|
||||
gm_mcp_vmoo_userlist_get_menu_item(GmMcpVmooUserlist *package,
|
||||
GmKeyValuePair *menuitem, UserInfo *info) {
|
||||
GmKeyValuePair *result = g_new0(GmKeyValuePair, 1);
|
||||
|
||||
if (!menuitem) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result->key = gm_mcp_vmoo_userlist_menu_item_subst(package,
|
||||
menuitem->key, info);
|
||||
result->value = gm_mcp_vmoo_userlist_menu_item_subst(package,
|
||||
menuitem->value, info);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
GList *
|
||||
gm_mcp_vmoo_userlist_get_menu(GmIUserlist *userlist, gint id) {
|
||||
GmMcpVmooUserlist *package = (GmMcpVmooUserlist *)(userlist);
|
||||
UserInfo *info = gm_mcp_vmoo_userlist_find_user(package, id);
|
||||
GList *item, *menu = NULL;
|
||||
GmKeyValuePair *pair;
|
||||
|
||||
if (!info) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (item = package->priv->menu; item; item = item->next) {
|
||||
pair = (GmKeyValuePair *)(item->data);
|
||||
menu = g_list_append(menu, gm_mcp_vmoo_userlist_get_menu_item(package,
|
||||
pair, info));
|
||||
}
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
void
|
||||
gm_mcp_vmoo_userlist_remove_user(GmMcpVmooUserlist *package, gint nr) {
|
||||
GList *elem;
|
||||
|
@ -573,10 +735,10 @@ gm_mcp_vmoo_userlist_handle_state(GmMcpVmooUserlist *package, MOOVar *v,
|
|||
|
||||
g_free(sort);
|
||||
} else {
|
||||
GM_DEBUG("User %d does not exist!", nr->i);
|
||||
gm_debug_msg(DEBUG_MCP, "User %d does not exist!", nr->i);
|
||||
}
|
||||
} else {
|
||||
GM_DEBUG("Nr is not an object: %d", nr->type);
|
||||
gm_debug_msg(DEBUG_MCP, "Nr is not an object: %d", nr->type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -584,20 +746,37 @@ gm_mcp_vmoo_userlist_handle_state(GmMcpVmooUserlist *package, MOOVar *v,
|
|||
void
|
||||
gm_mcp_vmoo_userlist_handle_simple(GmMcpPackage *package, gchar *suffix,
|
||||
GList *fields) {
|
||||
MOOVar *you;
|
||||
MOOVar *v = NULL;
|
||||
GmMcpVmooUserlist *userlist = GM_MCP_VMOO_USERLIST(package);
|
||||
gchar const *value;
|
||||
|
||||
if (suffix && strcmp(suffix, "you") == 0) {
|
||||
you = MOOVar_parse(gm_mcp_find_value(fields, "nr"));
|
||||
|
||||
if (you->type == OBJECT) {
|
||||
userlist->priv->you = you->i;
|
||||
MOOVar_free(you);
|
||||
} else {
|
||||
gm_debug_msg(DEBUG_MCP, "GmMcpVmooUserlist.HandleSimple: "
|
||||
"you is not an object!");
|
||||
if (suffix) {
|
||||
if (strcmp(suffix, "you") == 0) {
|
||||
v = MOOVar_parse(gm_mcp_find_value(fields, "nr"));
|
||||
|
||||
if (v->type == OBJECT) {
|
||||
userlist->priv->you = v->i;
|
||||
} else {
|
||||
gm_debug_msg(DEBUG_MCP, "GmMcpVmooUserlist.HandleSimple: "
|
||||
"you is not an object!");
|
||||
}
|
||||
} else if (strcmp(suffix, "menu") == 0) {
|
||||
value = gm_mcp_find_value(fields, "menu");
|
||||
v = MOOVar_parse(value);
|
||||
|
||||
if (!v || v->type != LIST) {
|
||||
gm_debug_msg(DEBUG_MCP, "GmMcpVmooUserlist.HandleMulti: "
|
||||
"invalid value: %s", value);
|
||||
} else {
|
||||
gm_mcp_vmoo_userlist_free_menu(userlist);
|
||||
gm_mcp_vmoo_userlist_handle_menu(userlist, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (v) {
|
||||
MOOVar_free(v);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
|
Reference in New Issue