pidgin/pidgin

9b65f18443aa
Use G_DECLARE_FINAL_TYPE for BonjourProtocol

Testing Done:
Connected to a Bonjour account

Reviewed at https://reviews.imfreedom.org/r/617/
/*
* Pidgin - Internet Messenger
* Copyright (C) Pidgin Developers <devel@pidgin.im>
*
* Pidgin is the legal property of its developers, whose names are too numerous
* to list here. Please refer to the COPYRIGHT file distributed with this
* source distribution.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include "pidgin/pidginpresenceicon.h"
#include "pidgin/pidginpresence.h"
struct _PidginPresenceIcon {
GtkImage parent;
PurplePresence *presence;
gchar *fallback;
GtkIconSize icon_size;
};
enum {
PROP_0,
PROP_PRESENCE,
PROP_FALLBACK,
PROP_ICON_SIZE,
N_PROPERTIES
};
static GParamSpec *properties[N_PROPERTIES] = { NULL, };
G_DEFINE_TYPE(PidginPresenceIcon, pidgin_presence_icon, GTK_TYPE_IMAGE)
/******************************************************************************
* Implementation
*****************************************************************************/
static void
pidgin_presence_icon_update(PidginPresenceIcon *icon) {
const gchar *icon_name = NULL;
icon_name = pidgin_presence_get_icon_name(icon->presence, icon->fallback);
gtk_image_set_from_icon_name(GTK_IMAGE(icon), icon_name, icon->icon_size);
}
static void
pidgin_presence_icon_active_status_changed_cb(GObject *obj, GParamSpec *pspec,
gpointer data)
{
pidgin_presence_icon_update(PIDGIN_PRESENCE_ICON(data));
}
/******************************************************************************
* GObject Implementation
*****************************************************************************/
static void
pidgin_presence_icon_get_property(GObject *obj, guint param_id, GValue *value,
GParamSpec *pspec)
{
PidginPresenceIcon *icon = PIDGIN_PRESENCE_ICON(obj);
switch(param_id) {
case PROP_PRESENCE:
g_value_set_object(value, pidgin_presence_icon_get_presence(icon));
break;
case PROP_FALLBACK:
g_value_set_string(value, pidgin_presence_icon_get_fallback(icon));
break;
case PROP_ICON_SIZE:
g_value_set_enum(value, pidgin_presence_icon_get_icon_size(icon));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
break;
}
}
static void
pidgin_presence_icon_set_property(GObject *obj, guint param_id,
const GValue *value, GParamSpec *pspec)
{
PidginPresenceIcon *icon = PIDGIN_PRESENCE_ICON(obj);
switch(param_id) {
case PROP_PRESENCE:
pidgin_presence_icon_set_presence(icon, g_value_get_object(value));
break;
case PROP_FALLBACK:
pidgin_presence_icon_set_fallback(icon, g_value_get_string(value));
break;
case PROP_ICON_SIZE:
pidgin_presence_icon_set_icon_size(icon, g_value_get_enum(value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
break;
}
}
static void
pidgin_presence_icon_finalize(GObject *obj) {
PidginPresenceIcon *icon = PIDGIN_PRESENCE_ICON(obj);
g_clear_object(&icon->presence);
g_clear_pointer(&icon->fallback, g_free);
G_OBJECT_CLASS(pidgin_presence_icon_parent_class)->finalize(obj);
}
static void
pidgin_presence_icon_init(PidginPresenceIcon *presenceicon) {
/* Use the icon name fallback that we're expecting. */
g_object_set(G_OBJECT(presenceicon), "use-fallback", TRUE, NULL);
}
static void
pidgin_presence_icon_class_init(PidginPresenceIconClass *klass) {
GObjectClass *obj_class = G_OBJECT_CLASS(klass);
obj_class->finalize = pidgin_presence_icon_finalize;
obj_class->get_property = pidgin_presence_icon_get_property;
obj_class->set_property = pidgin_presence_icon_set_property;
/**
* PidginPresenceIcon::presence:
*
* The #PurplePresence that this icon will be representing.
*/
properties[PROP_PRESENCE] = g_param_spec_object(
"presence", "presence",
"The presence that this icon is representing",
PURPLE_TYPE_PRESENCE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
/**
* PidginPresenceIcon::fallback:
*
* The name of the icon to use as a fallback when no presence is set.
*/
properties[PROP_FALLBACK] = g_param_spec_string(
"fallback", "fallback",
"The name of the icon to use as a fallback",
"user-invisible",
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
/**
* PidginPresenceIcon::icon-size:
*
* The #GtkIconSize that should be used.
*/
properties[PROP_ICON_SIZE] = g_param_spec_enum(
"icon-size", "icon-size",
"The GtkIconSize to use",
GTK_TYPE_ICON_SIZE,
GTK_ICON_SIZE_MENU,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties(obj_class, N_PROPERTIES, properties);
}
/******************************************************************************
* Public API
*****************************************************************************/
GtkWidget *
pidgin_presence_icon_new(PurplePresence *presence, const gchar *fallback,
GtkIconSize icon_size)
{
return g_object_new(
PIDGIN_TYPE_PRESENCE_ICON,
"presence", presence,
"fallback", fallback,
"icon_size", icon_size,
NULL);
}
PurplePresence *
pidgin_presence_icon_get_presence(PidginPresenceIcon *icon) {
g_return_val_if_fail(PIDGIN_IS_PRESENCE_ICON(icon), NULL);
return icon->presence;
}
void
pidgin_presence_icon_set_presence(PidginPresenceIcon *icon,
PurplePresence *presence)
{
PurplePresence *old = NULL;
g_return_if_fail(PIDGIN_IS_PRESENCE_ICON(icon));
/* We only want to disconnect signal handlers if the presence was changed,
* but to do that, we need to keep a reference to the old presence.
*/
if(PURPLE_IS_PRESENCE(icon->presence)) {
old = g_object_ref(icon->presence);
}
if(g_set_object(&icon->presence, presence)) {
if(G_IS_OBJECT(old)) {
/* If we previously had a presence, disconnect our signal handlers.
*/
g_signal_handlers_disconnect_by_data(old, icon);
}
if(PURPLE_IS_PRESENCE(icon->presence)) {
g_signal_connect(icon->presence, "notify::active-status",
G_CALLBACK(pidgin_presence_icon_active_status_changed_cb),
icon);
}
g_object_freeze_notify(G_OBJECT(icon));
pidgin_presence_icon_update(icon);
g_object_notify_by_pspec(G_OBJECT(icon), properties[PROP_PRESENCE]);
g_object_thaw_notify(G_OBJECT(icon));
}
g_clear_object(&old);
}
const gchar *
pidgin_presence_icon_get_fallback(PidginPresenceIcon *icon) {
g_return_val_if_fail(PIDGIN_IS_PRESENCE_ICON(icon), NULL);
return icon->fallback;
}
void
pidgin_presence_icon_set_fallback(PidginPresenceIcon *icon,
const gchar *fallback)
{
g_return_if_fail(PIDGIN_IS_PRESENCE_ICON(icon));
g_return_if_fail(fallback != NULL);
g_free(icon->fallback);
icon->fallback = g_strdup(fallback);
g_object_freeze_notify(G_OBJECT(icon));
pidgin_presence_icon_update(icon);
g_object_notify_by_pspec(G_OBJECT(icon), properties[PROP_FALLBACK]);
g_object_thaw_notify(G_OBJECT(icon));
}
GtkIconSize
pidgin_presence_icon_get_icon_size(PidginPresenceIcon *icon) {
g_return_val_if_fail(PIDGIN_IS_PRESENCE_ICON(icon), GTK_ICON_SIZE_INVALID);
return icon->icon_size;
}
void
pidgin_presence_icon_set_icon_size(PidginPresenceIcon *icon,
GtkIconSize icon_size)
{
g_return_if_fail(PIDGIN_IS_PRESENCE_ICON(icon));
icon->icon_size = icon_size;
g_object_freeze_notify(G_OBJECT(icon));
pidgin_presence_icon_update(icon);
g_object_notify_by_pspec(G_OBJECT(icon), properties[PROP_ICON_SIZE]);
g_object_thaw_notify(G_OBJECT(icon));
}