* Copyright (C) 2011-2020 Gary Kramlich <grim@reaperworld.com> * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see <https://www.gnu.org/licenses/>. #include <glib/gi18n-lib.h> #include <gplugin-gtk-plugin-info.h> * A widget that displays a [class@GPlugin.PluginInfo] in a user friendly way. /****************************************************************************** *****************************************************************************/ struct _GPluginGtkPluginInfo { GtkWidget *dependencies_box; GtkWidget *load_on_query; /*****************************************************************************s *****************************************************************************/ static GParamSpec *properties[N_PROPERTIES] = { G_DEFINE_TYPE(GPluginGtkPluginInfo, gplugin_gtk_plugin_info, GTK_TYPE_BOX) /****************************************************************************** *****************************************************************************/ gplugin_gtk_plugin_info_expander_activate( G_GNUC_UNUSED gpointer data) if(gtk_expander_get_expanded(expander)) gtk_expander_set_label(expander, "More"); gtk_expander_set_label(expander, "Less"); /****************************************************************************** *****************************************************************************/ _gplugin_gtk_plugin_info_refresh(GPluginGtkPluginInfo *info) GtkWidget *widget = NULL; GList *children = NULL, *iter = NULL; gchar *name = NULL, *version = NULL, *website = NULL; gchar *summary = NULL, *description = NULL, *id = NULL, *abi_version = NULL; gchar **dependencies = NULL; guint32 abi_version_uint; gboolean loq = FALSE, internal = FALSE; const gchar *filename = NULL; /* remove all the children from the authors box */ children = gtk_container_get_children(GTK_CONTAINER(info->authors_box)); for(iter = children; iter; iter = iter->next) gtk_widget_destroy(GTK_WIDGET(iter->data)); /* remove all the children from the dependencies box */ gtk_container_get_children(GTK_CONTAINER(info->dependencies_box)); for(iter = children; iter; iter = iter->next) gtk_widget_destroy(GTK_WIDGET(iter->data)); /* now get the info if we can */ if(GPLUGIN_IS_PLUGIN(info->plugin)) { GPluginPluginInfo *plugin_info = gplugin_plugin_get_info(info->plugin); GPluginLoader *plugin_loader = gplugin_plugin_get_loader(info->plugin); filename = gplugin_plugin_get_filename(info->plugin); error = gplugin_plugin_get_error(info->plugin); if(plugin_loader && GPLUGIN_IS_LOADER(plugin_loader)) { const char *loader_name = G_OBJECT_TYPE_NAME(plugin_loader); loader = g_strdup(loader_name); g_object_unref(G_OBJECT(plugin_loader)); "abi_version", &abi_version_uint, "description", &description, "dependencies", &dependencies, /* fanagle the plugin name */ markup = g_markup_printf_escaped( "<span font_size=\"large\" " "font_weight=\"bold\">%s</span>", (name) ? name : "Unnamed"); /* fanagle the website */ markup = g_markup_printf_escaped( /* fanagle the abi_version */ abi_version = g_strdup_printf("%08x", abi_version_uint); g_object_unref(G_OBJECT(plugin_info)); gtk_label_set_markup(GTK_LABEL(info->name), (name) ? name : "Unnamed"); gtk_label_set_text(GTK_LABEL(info->version), (version) ? version : ""); gtk_label_set_markup(GTK_LABEL(info->website), (website) ? website : ""); gtk_label_set_text(GTK_LABEL(info->summary), (summary) ? summary : ""); GTK_LABEL(info->description), (description) ? description : ""); gtk_label_set_text(GTK_LABEL(info->id), (id) ? id : ""); (error) ? error->message : "(none)"); gtk_label_set_text(GTK_LABEL(info->filename), (filename) ? filename : ""); GTK_LABEL(info->abi_version), (abi_version) ? abi_version : ""); gtk_label_set_text(GTK_LABEL(info->loader), (loader) ? loader : "Unknown"); gtk_label_set_text(GTK_LABEL(info->internal), (internal) ? "Yes" : "No"); gtk_label_set_text(GTK_LABEL(info->load_on_query), (loq) ? "Yes" : "No"); for(i = 0; authors[i]; i++) { widget = gtk_label_new(authors[i]); gtk_widget_set_halign(widget, GTK_ALIGN_START); gtk_widget_set_valign(widget, GTK_ALIGN_START); GTK_BOX(info->authors_box), /* set the dependencies */ for(i = 0; dependencies[i]; i++) { widget = gtk_label_new(dependencies[i]); gtk_widget_set_halign(widget, GTK_ALIGN_START); gtk_widget_set_valign(widget, GTK_ALIGN_START); GTK_BOX(info->dependencies_box), widget = gtk_label_new(_("(none)")); GTK_BOX(info->dependencies_box), g_strfreev(dependencies); /****************************************************************************** *****************************************************************************/ gplugin_gtk_plugin_info_state_cb( G_GNUC_UNUSED GObject *obj, G_GNUC_UNUSED GParamSpec *pspec, _gplugin_gtk_plugin_info_refresh(GPLUGIN_GTK_PLUGIN_INFO(data)); /****************************************************************************** *****************************************************************************/ gplugin_gtk_plugin_info_set_property( GPluginGtkPluginInfo *info = GPLUGIN_GTK_PLUGIN_INFO(obj); gplugin_gtk_plugin_info_set_plugin(info, g_value_get_object(value)); G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, prop_id, pspec); gplugin_gtk_plugin_info_get_property( GPluginGtkPluginInfo *info = GPLUGIN_GTK_PLUGIN_INFO(obj); g_value_set_object(value, gplugin_gtk_plugin_info_get_plugin(info)); G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, prop_id, pspec); gplugin_gtk_plugin_info_finalize(GObject *obj) GPluginGtkPluginInfo *info = GPLUGIN_GTK_PLUGIN_INFO(obj); if(info->signal_id != 0 && GPLUGIN_IS_PLUGIN(info->plugin)) { g_signal_handler_disconnect(G_OBJECT(info->plugin), info->signal_id); g_clear_object(&info->plugin); G_OBJECT_CLASS(gplugin_gtk_plugin_info_parent_class)->finalize(obj); gplugin_gtk_plugin_info_init(GPluginGtkPluginInfo *info) gtk_widget_init_template(GTK_WIDGET(info)); gplugin_gtk_plugin_info_class_init(GPluginGtkPluginInfoClass *klass) GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass); GObjectClass *obj_class = G_OBJECT_CLASS(klass); obj_class->get_property = gplugin_gtk_plugin_info_get_property; obj_class->set_property = gplugin_gtk_plugin_info_set_property; obj_class->finalize = gplugin_gtk_plugin_info_finalize; properties[PROP_PLUGIN] = g_param_spec_object( "The GPluginPlugin who's info should be displayed", G_PARAM_READWRITE | G_PARAM_CONSTRUCT); gtk_widget_class_set_template_from_resource( "/org/imfreedom/keep/gplugin/gplugin-gtk/plugin-info.ui"); gtk_widget_class_bind_template_child( gtk_widget_class_bind_template_child( gtk_widget_class_bind_template_child( gtk_widget_class_bind_template_child( gtk_widget_class_bind_template_child( gtk_widget_class_bind_template_child( gtk_widget_class_bind_template_child( gtk_widget_class_bind_template_child( gtk_widget_class_bind_template_child( gtk_widget_class_bind_template_child( gtk_widget_class_bind_template_child( gtk_widget_class_bind_template_child( gtk_widget_class_bind_template_child( gtk_widget_class_bind_template_child( gtk_widget_class_bind_template_child( gtk_widget_class_bind_template_callback( gplugin_gtk_plugin_info_expander_activate); /****************************************************************************** *****************************************************************************/ * gplugin_gtk_plugin_info_new: * Create a new widget which can be used to display info about a * [iface@GPlugin.Plugin]. * Returns: (transfer full): The new display widget. gplugin_gtk_plugin_info_new(void) return GTK_WIDGET(g_object_new(GPLUGIN_GTK_TYPE_PLUGIN_INFO, NULL)); * gplugin_gtk_plugin_info_set_plugin: * @info: The widget instance. * @plugin: The plugin instance. * Sets the plugin that should be displayed. * A @plugin value of %NULL will clear the widget. gplugin_gtk_plugin_info_set_plugin( GPluginGtkPluginInfo *info, g_return_if_fail(GPLUGIN_GTK_IS_PLUGIN_INFO(info)); if(info->signal_id != 0 && GPLUGIN_IS_PLUGIN(info->plugin)) { g_signal_handler_disconnect(info->plugin, info->signal_id); if(g_set_object(&info->plugin, plugin) && GPLUGIN_IS_PLUGIN(plugin)) { _gplugin_gtk_plugin_info_refresh(info); /* Connect a signal to refresh when the plugin's state changes. We * can't use g_signal_connect_object because the plugin object never * gets destroyed, as the manager and the loader both keep a reference * to it and the GPluginGtkPluginInfo widget is reused for all plugins * so that all means that we just have to manage the callback info->signal_id = g_signal_connect( G_CALLBACK(gplugin_gtk_plugin_info_state_cb), * gplugin_gtk_plugin_info_get_plugin: * @info: The widget instance. * Returns the plugin that's being displayed. * Returns: (transfer full): The plugin that's being displayed. gplugin_gtk_plugin_info_get_plugin(GPluginGtkPluginInfo *info) g_return_val_if_fail(GPLUGIN_GTK_IS_PLUGIN_INFO(info), NULL); return (info->plugin) ? GPLUGIN_PLUGIN(g_object_ref(G_OBJECT(info->plugin)))