Last active
May 14, 2023 04:44
-
-
Save angstyloop/6f809d96b66afc4feddf55ce19b7975c to your computer and use it in GitHub Desktop.
Example of how to show metadata with VIPS in a GTK4 GtkColumnView widget.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
ABOUT | |
Example of how to show metadata with VIPS in a GTK4 GtkColumnView widget. | |
Also supports css. | |
COMPILE | |
gcc `pkg-config --cflags gtk4 vips` -o metadata-columnview metadata-columnview.c `pkg-config --libs gtk4 vips` | |
RUN | |
./metadata-columnview | |
*/ | |
#include <gtk/gtk.h> | |
#include <vips/vips.h> | |
static VipsImage *image = NULL; | |
/* We could play the same game with the setup function, to produce a custom | |
* widget type for the items in each column, but for now we'll just use a | |
* GtkLabel for all items in the view. | |
*/ | |
static void | |
factory_setup( GtkListItemFactory *factory, GtkListItem *list_item ) | |
{ | |
GtkWidget *label = gtk_label_new( "" ); | |
gtk_widget_set_halign( label, GTK_ALIGN_START ); | |
gtk_list_item_set_child( list_item, label ); | |
} | |
/* The bind function for the field name factory, corresponding to the first | |
* column. In this case, the field name is the metadata field name. | |
*/ | |
static void | |
field_name_factory_bind( GtkListItemFactory *factory, GtkListItem *list_item ) | |
{ | |
GtkWidget *label; | |
GtkStringObject *string_object; | |
const char *field_name; | |
label = gtk_list_item_get_child( list_item ); | |
string_object = GTK_STRING_OBJECT( gtk_list_item_get_item( list_item ) ); | |
field_name = gtk_string_object_get_string( string_object ); | |
gtk_label_set_label( GTK_LABEL( label ), field_name ); | |
} | |
/* The bind function for the other factories, corresponding to columns after | |
* the field name column. | |
*/ | |
static void | |
value_factory_bind( GtkListItemFactory *factory, GtkListItem *list_item, gpointer user_data ) | |
{ | |
GtkWidget *label; | |
GtkStringObject *string_object; | |
const char *field_name, *column_name = (const char *) user_data; | |
char str[256]; | |
// It is crucial to zero the GValue whose address we pass to | |
// vips_image_get. Otherwise, we will get runtime errors. | |
GValue value = { 0 }; | |
VipsBuf buf = VIPS_BUF_STATIC( str ); | |
label = gtk_list_item_get_child( list_item ); | |
string_object = GTK_STRING_OBJECT( gtk_list_item_get_item( list_item ) ); | |
field_name = gtk_string_object_get_string( string_object ); | |
/* Get the value of the given metadata field from the (global) test | |
* image. | |
*/ | |
vips_image_get( image, field_name, &value ); | |
vips_buf_appendgv( &buf, &value ); | |
gtk_label_set_label( GTK_LABEL( label ), vips_buf_all( &buf ) ); | |
} | |
/* Callback that starts the application. | |
*/ | |
static void | |
activate (GtkApplication *app, gpointer user_data) | |
{ | |
GtkWidget *window, *view; | |
GtkColumnViewColumn* column; | |
GdkDisplay *display; | |
char *column_names[] = { "Field", "Value" }; | |
const int column_names_length = 2; | |
/* Create the (global) test image. | |
*/ | |
image = vips_image_new_temp_file("a.jpg"); | |
/* Create the application window. | |
*/ | |
window = gtk_application_window_new( app ); | |
gtk_window_set_title( GTK_WINDOW( window ), "Metadata" ); | |
gtk_window_set_default_size( GTK_WINDOW( window ), 200, 200 ); | |
display = gtk_widget_get_display( GTK_WIDGET( window ) ); | |
const char *css_path = "metadata-columnview.css"; | |
GtkCssProvider *provider = gtk_css_provider_new(); | |
gtk_css_provider_load_from_path( provider, css_path ); | |
gtk_style_context_add_provider_for_display( display, | |
GTK_STYLE_PROVIDER( provider ), | |
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION ); | |
/* Define the list items of the first column. For this example, these | |
* are exactly the names of the fields on the (global) test image. | |
*/ | |
char** field_names = vips_image_get_fields( image ); | |
/* Define the list model our selection model will use. | |
*/ | |
GtkStringList *list_model = gtk_string_list_new( (const char* const*) field_names ); | |
/* Create simple selection model, which does not have any selection | |
* logic. Curiously, you can still see the mouseover highlight effect | |
* and onclick highlight effect even for GtkNoSelection, perhaps for | |
* accessibility reasons. | |
*/ | |
GtkNoSelection *selection_model = gtk_no_selection_new( G_LIST_MODEL( list_model ) ); | |
/* Initialize the array of GtkListItemFactory - one for each column. | |
*/ | |
GtkListItemFactory *factories[column_names_length]; | |
for ( int i = 0; i < column_names_length; i++ ) | |
factories[i] = gtk_signal_list_item_factory_new(); | |
/* Connect handlers to the field name factory. | |
*/ | |
g_signal_connect( factories[0], "setup", G_CALLBACK( factory_setup ), NULL ); | |
g_signal_connect( factories[0], "bind", G_CALLBACK( field_name_factory_bind ), column_names[0] ); | |
/* Connect handlers to the other factories. | |
*/ | |
for ( int i = 1; i < column_names_length; i++ ) { | |
g_signal_connect( factories[i], "setup", G_CALLBACK( factory_setup ), NULL ); | |
g_signal_connect( factories[i], "bind", G_CALLBACK( value_factory_bind ), column_names[i] ); | |
} | |
/* Create the column view. | |
*/ | |
view = gtk_column_view_new( GTK_SELECTION_MODEL( selection_model ) ); | |
//gtk_column_view_set_show_column_separators( GTK_COLUMN_VIEW( view ), TRUE ); | |
//gtk_column_view_set_show_row_separators( GTK_COLUMN_VIEW( view ), TRUE ); | |
gtk_window_set_child( GTK_WINDOW( window ), view ); | |
/* Create the columns. | |
*/ | |
for ( int i = 0; i < column_names_length; i++ ) { | |
column = gtk_column_view_column_new( column_names[i], factories[i] ); | |
//gtk_column_view_column_set_resizable( column, TRUE ); | |
gtk_column_view_column_set_expand( column, TRUE ); | |
gtk_column_view_append_column( GTK_COLUMN_VIEW( view ), column ); | |
} | |
/* Show everything. | |
*/ | |
gtk_widget_show (window); | |
} | |
/* The main just function sets up a signal handler for "activate". | |
*/ | |
int | |
main (int argc, char **argv) { | |
GtkApplication *app; | |
int status; | |
VIPS_INIT( argv[0] ); | |
app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE); | |
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL); | |
status = g_application_run (G_APPLICATION (app), argc, argv); | |
g_object_unref (app); | |
return status; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Empty for now */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment