From 180d65f45c4147619e89728ae7682d3064e5ec2d Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Sat, 2 Mar 2024 18:08:26 +0000 Subject: [PATCH 01/24] update feature list --- README.md | 52 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 57f9183..b2e32bd 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,8 @@ flatpak install flathub org.libvips.vipsdisp computed in the background by a pool of workers. The interface stays live even under very heavy load. -* It keeps a sparse pyramid of computed tiles as textures on the GPU. Each frame, +* It keeps a sparse pyramid of computed tiles as textures on the GPU. Each + frame, it computes the set of visible tiles, and then the GPU scales, positions and composites just those tiles to the screen. CPU load should be low (except for the background workers heh). Hold down i (for "in") or + to do a smooth @@ -82,28 +83,24 @@ flatpak install flathub org.libvips.vipsdisp amounts of metadata (useful for eg. DICOM) with filtering. * Use alt-Left and alt-Right to move between the set of images being - displayed, handy for browsing a directory of images. + displayed, handy for browsing a directory of images. If you drag or load a + set of images, it'll flip between the images in the set. If you drag or load + a single image, it'll flip between all the images in that directory. -* It uses the gtk4 GUI toolkit, so the interface is fast, attractive - and nicely animated. The image is rendered with the GPU, so display ought to - be quick. +* It keeps the most recent three views live, so you can flip between them very + quickly, and all view settings are preserved. This is handy for comparing + details on two images. -## Build from source +* `Duplicate window` crtl-D makes a copy of the window, so you can compare two + images side by side. -```shell -cd vipsdisp -meson setup build --prefix=~/vips -cd build -ninja -ninja install -``` - -And to run: +* It supports copy/paste and drag/drop of filenames, sets of filenames, and + textures. You can paste from the screenshot tool, or drag-drop images from + your file browser, for example. -```shell -export GSETTINGS_SCHEMA_DIR=/home/john/vips/share/glib-2.0/schemas -vipsdisp ~/pics/k2.jpg -``` +* It uses the gtk4 GUI toolkit, so the interface is fast, attractive + and nicely animated. The image is rendered with the GPU, so display ought to + be quick. ## Shortcuts @@ -131,6 +128,23 @@ vipsdisp ~/pics/k2.jpg Additionally, you can drag and drop filenames, lists of filenames and textures. +## Build from source + +```shell +cd vipsdisp +meson setup build --prefix=~/vips +cd build +ninja +ninja install +``` + +And to run: + +```shell +export GSETTINGS_SCHEMA_DIR=/home/john/vips/share/glib-2.0/schemas +vipsdisp ~/pics/k2.jpg +``` + ## Version bump checklist Version needs updating in the following places: From 196064cedac88840f851e08fe3ca6ba719b802b3 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Sat, 2 Mar 2024 20:09:33 +0000 Subject: [PATCH 02/24] try embedding a video --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index b2e32bd..0c0bdd0 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ It all works, though see the TODO list below. [![Screenshot](images/save-as.png)](images/save-as.png) + ## Install From ad8774b62a3f15b0a1df0599f870add312385a1e Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Sat, 2 Mar 2024 23:30:57 +0000 Subject: [PATCH 03/24] just a link to youtube --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0c0bdd0..8f1eb83 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ It all works, though see the TODO list below. [![Screenshot](images/save-as.png)](images/save-as.png) - +https://youtu.be/KSoBkO2_HtE ## Install From 9d5656b4f55158fb4ab4cc17a553ada76295ad17 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Sun, 3 Mar 2024 18:19:03 +0000 Subject: [PATCH 04/24] oop forgot a licence file See https://github.com/jcupitt/vipsdisp/issues/29 --- LICENCE.txt | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 LICENCE.txt diff --git a/LICENCE.txt b/LICENCE.txt new file mode 100644 index 0000000..e707d2f --- /dev/null +++ b/LICENCE.txt @@ -0,0 +1,19 @@ +Copyright (c) 2024 libvips.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From c41cdced7c8f0fa98d11553c91e106f0bc083b10 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 14 Mar 2024 02:23:55 +0000 Subject: [PATCH 05/24] improve handling of MATRIX images should help hist etc as well --- CHANGELOG.md | 4 ++++ meson.build | 2 +- src/tilesource.c | 29 ++++++++++++++++++++++++++--- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ba8f68..b47dbff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## master +- better behaviour for image interpretations like MATRIX + +# 3.0.4 1/3/24 + - add next image / previous image - add drag/drop and copy/paste of files, file lists, textures and strings - add "reload" diff --git a/meson.build b/meson.build index 9cbfe8f..55e1cec 100644 --- a/meson.build +++ b/meson.build @@ -1,6 +1,6 @@ project( 'vipsdisp', 'c', - version: '3.0.4', + version: '3.1.0', license: 'MIT', meson_version: '>=0.56', default_options: [ diff --git a/src/tilesource.c b/src/tilesource.c index 14258d2..7ab0742 100644 --- a/src/tilesource.c +++ b/src/tilesource.c @@ -543,12 +543,11 @@ tile_source_rgb_image(TileSource *tile_source, VipsImage *in) image = x; } - /* Force to uint8 sRGB. + /* Go to uint8 sRGB in a nice way. */ if (image->Type != VIPS_INTERPRETATION_sRGB && vips_colourspace_issupported(image)) { - if (vips_colourspace(image, &x, VIPS_INTERPRETATION_sRGB, - NULL)) + if (vips_colourspace(image, &x, VIPS_INTERPRETATION_sRGB, NULL)) return NULL; VIPS_UNREF(image); image = x; @@ -571,6 +570,30 @@ tile_source_rgb_image(TileSource *tile_source, VipsImage *in) image = x; } + /* The number of bands could still be wrong for unsupported spaces like + * MATRIX or FOURIER. + */ + if (image->Bands > 3) { + if (vips_extract_band(image, &x, 0, "n", 3, NULL)) + return NULL; + VIPS_UNREF(image); + image = x; + } + else if (image->Bands == 2) { + if (vips_bandjoin_const1(image, &x, 0, NULL)) + return NULL; + VIPS_UNREF(image); + image = x; + } + else if (image->Bands == 1) { + VipsImage *in[3] = { image, image, image }; + + if (vips_bandjoin(in, &x, 3, NULL)) + return NULL; + VIPS_UNREF(image); + image = x; + } + // reattach alpha if (alpha) { if (vips_cast(alpha, &x, image->BandFmt, NULL)) From 33ee3f8e6f84d9246bfd7a5989e2f56b39ee6376 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Wed, 3 Apr 2024 02:41:39 +0100 Subject: [PATCH 06/24] revise top line in menu see https://github.com/jcupitt/vipsdisp/issues/30 --- CHANGELOG.md | 1 + README.md | 9 +++++++++ src/gtk/imagewindow.ui | 16 ++++++++-------- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b47dbff..c7a9292 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## master - better behaviour for image interpretations like MATRIX +- window menu has next-image / prev-image in the top line [euzada] # 3.0.4 1/3/24 diff --git a/README.md b/README.md index 8f1eb83..de69e50 100644 --- a/README.md +++ b/README.md @@ -246,6 +246,15 @@ On success, merge to master. ## TODO +- skip unknown files on next / prev? + + - need to add the test to next-image, not glob, since we can't test the + whole dir on startup + + - need to use next-image to pick the start image (not always the first) + + - need to *not* do this if only one file specified, eg. `vipsdisp x.txt` + - PDF page change does not change image size if pages vary in size - ^C during a slow load leaves a file in /tmp, can we improve this? diff --git a/src/gtk/imagewindow.ui b/src/gtk/imagewindow.ui index 5605c90..84d6b84 100644 --- a/src/gtk/imagewindow.ui +++ b/src/gtk/imagewindow.ui @@ -19,13 +19,13 @@ view-fullscreen-symbolic - Previous page - win.prev + Previous image + win.prev_image go-previous-symbolic - Next page - win.next + Next image + win.next_image go-next-symbolic @@ -45,12 +45,12 @@ win.duplicate - Next image - win.next_image + Next page + win.next - Previous image - win.prev_image + Previous page + win.prev From cacd3366d8a5eb35c8aa369ca40c54116c4c06b6 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Wed, 3 Apr 2024 03:09:29 +0100 Subject: [PATCH 07/24] revise right-click menu again --- src/gtk/imagewindow.ui | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/src/gtk/imagewindow.ui b/src/gtk/imagewindow.ui index 84d6b84..1a49eca 100644 --- a/src/gtk/imagewindow.ui +++ b/src/gtk/imagewindow.ui @@ -4,19 +4,9 @@
horizontal-buttons - Copy - win.copy - edit-copy-symbolic - - - Paste - win.paste - edit-paste-symbolic - - - Fullscreen - win.fullscreen - view-fullscreen-symbolic + Open image + win.replace + document-open-symbolic Previous image @@ -33,6 +23,21 @@ win.reload view-refresh-symbolic + + Copy + win.copy + edit-copy-symbolic + + + Paste + win.paste + edit-paste-symbolic + + + Fullscreen + win.fullscreen + view-fullscreen-symbolic +
@@ -55,10 +60,6 @@
- - Replace image ... - win.replace - Save as ... win.saveas @@ -137,8 +138,9 @@ - Open + document-open-symbolic win.replace + Open image @@ -146,6 +148,7 @@ go-previous-symbolic win.prev_image + Previous image @@ -153,6 +156,7 @@ go-next-symbolic win.next_image + Next image @@ -160,6 +164,7 @@ view-refresh-symbolic win.reload + Reload From 32518d5217953831816e30286422eb37203f31bd Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 4 Apr 2024 06:33:57 +0100 Subject: [PATCH 08/24] start adding "preserve view settings" --- CHANGELOG.md | 1 + org.libvips.vipsdisp.gschema.xml | 8 +++ src/enumtypes.c.in | 38 +++++++++++ src/enumtypes.h.in | 22 ++++++ src/gtk/displaybar.ui | 6 ++ src/gtkutil.c | 23 +++++++ src/gtkutil.h | 1 + src/imagewindow.c | 111 +++++++++++++++---------------- src/meson.build | 57 ++++++++++++---- src/tilesource.c | 56 ++++------------ src/vipsdisp.h | 1 + 11 files changed, 209 insertions(+), 115 deletions(-) create mode 100644 src/enumtypes.c.in create mode 100644 src/enumtypes.h.in diff --git a/CHANGELOG.md b/CHANGELOG.md index c7a9292..22c0722 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ - better behaviour for image interpretations like MATRIX - window menu has next-image / prev-image in the top line [euzada] +- add "preserve view settings on new image" # 3.0.4 1/3/24 diff --git a/org.libvips.vipsdisp.gschema.xml b/org.libvips.vipsdisp.gschema.xml index 0db0caf..cdc8537 100644 --- a/org.libvips.vipsdisp.gschema.xml +++ b/org.libvips.vipsdisp.gschema.xml @@ -55,6 +55,14 @@ + + false + Preserve + + Preserve view settings on new image + + + false log diff --git a/src/enumtypes.c.in b/src/enumtypes.c.in new file mode 100644 index 0000000..6a3f403 --- /dev/null +++ b/src/enumtypes.c.in @@ -0,0 +1,38 @@ +/*** BEGIN file-header ***/ +/* auto-generated enums */ + +#include "vipsdisp.h" + +/*** END file-header ***/ + +/*** BEGIN file-production ***/ +/* enumerations from "@basename@" */ +/*** END file-production ***/ + +/*** BEGIN value-header ***/ +GType +@enum_name@_get_type(void) +{ + static gsize gtype_id = 0; + + if (g_once_init_enter(>ype_id)) { + static const G@Type@Value values[] = { +/*** END value-header ***/ + +/*** BEGIN value-production ***/ + { @VALUENAME@, "@VALUENAME@", "@valuenick@" }, +/*** END value-production ***/ + +/*** BEGIN value-tail ***/ + { 0, NULL, NULL } + }; + + GType new_type = + g_@type@_register_static(g_intern_static_string("@EnumName@"), values); + g_once_init_leave(>ype_id, new_type); + } + + return (GType) gtype_id; +} +/*** END value-tail ***/ + diff --git a/src/enumtypes.h.in b/src/enumtypes.h.in new file mode 100644 index 0000000..327106d --- /dev/null +++ b/src/enumtypes.h.in @@ -0,0 +1,22 @@ +/*** BEGIN file-header ***/ +#ifndef ENUM_TYPES_H +#define ENUM_TYPES_H + +G_BEGIN_DECLS + +/*** END file-header ***/ + +/*** BEGIN file-production ***/ +/* enumerations from "@basename@" */ +/*** END file-production ***/ + +/*** BEGIN value-header ***/ +GType @enum_name@_get_type(void) G_GNUC_CONST; +#define TYPE_@ENUMSHORT@ (@enum_name@_get_type()) +/*** END value-header ***/ + +/*** BEGIN file-tail ***/ +G_END_DECLS + +#endif /*ENUM_TYPES_H*/ +/*** END file-tail ***/ diff --git a/src/gtk/displaybar.ui b/src/gtk/displaybar.ui index e268bcd..0e9c0af 100644 --- a/src/gtk/displaybar.ui +++ b/src/gtk/displaybar.ui @@ -23,6 +23,12 @@ Enable colour management win.icc + + + Preserve view settings on new image + win.preserve + +
diff --git a/src/gtkutil.c b/src/gtkutil.c index efb8178..85c23da 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -156,6 +156,29 @@ copy_state(GtkWidget *to, GtkWidget *from, const char *name) change_state(to, name, state); } +void +set_property_from_state(GObject *to, GtkWidget *from, const char *name) +{ + g_autoptr(GVariant) state = get_state(from, name); + g_auto(GValue) value = { 0 }; + g_auto(GValue) to_value = { 0 }; + + g_dbus_gvariant_to_gvalue(state, &value); + + g_object_get_property(to, name, &to_value); + GType type = G_VALUE_TYPE(&to_value); + if (G_TYPE_FUNDAMENTAL(type) == G_TYPE_ENUM && + G_VALUE_TYPE(&value) == G_TYPE_STRING) { + // special case ... setting an enum from a string + const char *nick = g_value_get_string(&value); + int enum_v = vips_enum_from_nick("vipsdisp", type, nick); + + g_object_set(to, name, enum_v, NULL); + } + else + g_object_set_property(to, name, &value); +} + /* A 'safe' way to run a few events. */ void diff --git a/src/gtkutil.h b/src/gtkutil.h index 3ee130e..6d122ae 100644 --- a/src/gtkutil.h +++ b/src/gtkutil.h @@ -11,6 +11,7 @@ void change_state(GtkWidget *widget, const char *name, GVariant *state); GVariant *get_state(GtkWidget *widget, const char *name); void copy_state(GtkWidget *to, GtkWidget *from, const char *name); void set_state(GtkWidget *to, GSettings *settings, const char *name); +void set_property_from_state(GObject *to, GtkWidget *from, const char *name); void process_events(void); diff --git a/src/imagewindow.c b/src/imagewindow.c index 590b02c..43de171 100644 --- a/src/imagewindow.c +++ b/src/imagewindow.c @@ -38,6 +38,7 @@ struct _ImageWindow { char **files; int n_files; int current_file; + gboolean preserve; /* The current save and load directories. */ @@ -77,8 +78,8 @@ G_DEFINE_TYPE(ImageWindow, image_window, GTK_TYPE_APPLICATION_WINDOW); /* Our signals. */ enum { - SIG_CHANGED, /* A new imageui and tile_source */ - SIG_STATUS_CHANGED, /* New mouse position */ + SIG_CHANGED, /* A new imageui and tile_source */ + SIG_STATUS_CHANGED, /* New mouse position */ SIG_LAST }; @@ -377,6 +378,8 @@ image_window_reset_view(ImageWindow *win) { TileSource *tile_source = image_window_get_tile_source(win); + printf("image_window_reset_view:\n"); + if (tile_source) { g_object_set(tile_source, "falsecolour", FALSE, @@ -478,36 +481,42 @@ static void image_window_tile_source_changed(TileSource *tile_source, ImageWindow *win) { GVariant *state; - const char *str; #ifdef DEBUG - printf("image_window_tile_source_changed:\n"); #endif /*DEBUG*/ + printf("image_window_tile_source_changed:\n"); if (tile_source->load_error) image_window_set_error(win, tile_source->load_message); - state = g_variant_new_boolean(tile_source->falsecolour); - change_state(GTK_WIDGET(win), "falsecolour", state); + if (win->preserve) { + // update tile_source with our settings + set_property_from_state(G_OBJECT(tile_source), + GTK_WIDGET(win), "falsecolour"); + set_property_from_state(G_OBJECT(tile_source), + GTK_WIDGET(win), "log"); + set_property_from_state(G_OBJECT(tile_source), + GTK_WIDGET(win), "icc"); - state = g_variant_new_boolean(tile_source->log); - change_state(GTK_WIDGET(win), "log", state); + set_property_from_state(G_OBJECT(tile_source), + GTK_WIDGET(win), "mode"); - state = g_variant_new_boolean(tile_source->icc); - change_state(GTK_WIDGET(win), "icc", state); + } + else { + // update win settings from new tile source + printf("image_window_tile_source_changed: leaky!\n"); - if (tile_source->mode == TILE_SOURCE_MODE_TOILET_ROLL) - str = "toilet-roll"; - else if (tile_source->mode == TILE_SOURCE_MODE_MULTIPAGE) - str = "multipage"; - else if (tile_source->mode == TILE_SOURCE_MODE_ANIMATED) - str = "animated"; - else if (tile_source->mode == TILE_SOURCE_MODE_PAGES_AS_BANDS) - str = "pages-as-bands"; - else - str = NULL; - if (str) { - state = g_variant_new_string(str); + state = g_variant_new_boolean(tile_source->falsecolour); + change_state(GTK_WIDGET(win), "falsecolour", state); + + state = g_variant_new_boolean(tile_source->log); + change_state(GTK_WIDGET(win), "log", state); + + state = g_variant_new_boolean(tile_source->icc); + change_state(GTK_WIDGET(win), "icc", state); + + const char *name = vips_enum_nick(TYPE_SOURCE_MODE, tile_source->mode); + state = g_variant_new_string(name); change_state(GTK_WIDGET(win), "mode", state); } } @@ -1345,29 +1354,26 @@ image_window_falsecolour(GSimpleAction *action, g_simple_action_set_state(action, state); } +static void +image_window_preserve(GSimpleAction *action, + GVariant *state, gpointer user_data) +{ + ImageWindow *win = IMAGE_WINDOW(user_data); + + win->preserve = g_variant_get_boolean(state); + + g_simple_action_set_state(action, state); +} + static void image_window_mode(GSimpleAction *action, GVariant *state, gpointer user_data) { ImageWindow *win = IMAGE_WINDOW(user_data); TileSource *tile_source = image_window_get_tile_source(win); - - const gchar *str; - TileSourceMode mode; - - str = g_variant_get_string(state, NULL); - if (g_str_equal(str, "toilet-roll")) - mode = TILE_SOURCE_MODE_TOILET_ROLL; - else if (g_str_equal(str, "multipage")) - mode = TILE_SOURCE_MODE_MULTIPAGE; - else if (g_str_equal(str, "animated")) - mode = TILE_SOURCE_MODE_ANIMATED; - else if (g_str_equal(str, "pages-as-bands")) - mode = TILE_SOURCE_MODE_PAGES_AS_BANDS; - else - /* Ignore attempted change. - */ - return; + const gchar *str = g_variant_get_string(state, NULL); + TileSourceMode mode = + vips_enum_from_nick("vipsdisp", TYPE_SOURCE_MODE, str); if (tile_source) g_object_set(tile_source, @@ -1377,30 +1383,14 @@ image_window_mode(GSimpleAction *action, g_simple_action_set_state(action, state); } -static TileCacheBackground -background_to_enum(const char *str) -{ - TileCacheBackground background; - - if (g_str_equal(str, "checkerboard")) - background = TILE_CACHE_BACKGROUND_CHECKERBOARD; - else if (g_str_equal(str, "white")) - background = TILE_CACHE_BACKGROUND_WHITE; - else if (g_str_equal(str, "black")) - background = TILE_CACHE_BACKGROUND_BLACK; - else - background = TILE_CACHE_BACKGROUND_CHECKERBOARD; - - return background; -} - static void image_window_background(GSimpleAction *action, GVariant *state, gpointer user_data) { ImageWindow *win = IMAGE_WINDOW(user_data); - TileCacheBackground background = - background_to_enum(g_variant_get_string(state, NULL)); + const gchar *str = g_variant_get_string(state, NULL); + TileCacheBackground background = + vips_enum_from_nick("vipsdisp", TYPE_CACHE_BACKGROUND, str); if(win->imageui) g_object_set(win->imageui, @@ -1466,6 +1456,7 @@ static GActionEntry image_window_entries[] = { { "log", action_toggle, NULL, "false", image_window_log }, { "icc", action_toggle, NULL, "false", image_window_icc }, { "falsecolour", action_toggle, NULL, "false", image_window_falsecolour }, + { "preserve", action_toggle, NULL, "false", image_window_preserve }, { "mode", action_radio, "s", "'multipage'", image_window_mode }, { "background", action_radio, "s", "'checkerboard'", image_window_background }, @@ -1606,7 +1597,7 @@ image_window_pressed_cb(GtkGestureClick *gesture, static void image_window_class_init(ImageWindowClass *class) { - G_OBJECT_CLASS(class)->dispose = image_window_dispose; + GObjectClass *gobject_class = G_OBJECT_CLASS(class); gtk_widget_class_set_template_from_resource(GTK_WIDGET_CLASS(class), APP_PATH "/imagewindow.ui"); @@ -1629,6 +1620,8 @@ image_window_class_init(ImageWindowClass *class) gtk_widget_class_bind_template_callback(GTK_WIDGET_CLASS(class), image_window_pressed_cb); + gobject_class->dispose = image_window_dispose; + image_window_signals[SIG_STATUS_CHANGED] = g_signal_new( "status-changed", G_TYPE_FROM_CLASS(class), diff --git a/src/meson.build b/src/meson.build index a115fbb..c2fb189 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,18 +1,35 @@ marshal = gnome.genmarshal( - 'vipsdispmarshal', - prefix: 'vipsdisp', - sources: 'gtk/vipsdispmarshal.list', + 'vipsdispmarshal', + prefix: 'vipsdisp', + sources: 'gtk/vipsdispmarshal.list', ) resources = gnome.compile_resources( - 'vipsdisp-gresources', - 'gtk/vipsdisp.gresources.xml', - source_dir: 'gtk', + 'vipsdisp-gresources', + 'gtk/vipsdisp.gresources.xml', + source_dir: 'gtk', ) -executable('vipsdisp', [ - marshal, - resources, +headers = files ( + 'displaybar.h', + 'fuzzy.h', + 'gtkutil.h', + 'imagedisplay.h', + 'imageui.h', + 'imagewindow.h', + 'infobar.h', + 'properties.h', + 'saveoptions.h', + 'tilecache.h', + 'tile.h', + 'tilesource.h', + 'tslider.h', + 'vipsdispapp.h', + 'vipsdisp.h', + 'vipsdispmarshal.h', +) + +sources = files ( 'displaybar.c', 'gtkutil.c', 'imagedisplay.c', @@ -28,8 +45,22 @@ executable('vipsdisp', [ 'saveoptions.c', 'fuzzy.c', 'properties.c', - ], - dependencies: vipsdisp_deps, - win_subsystem: 'windows', - install: true, +) + +enumtypes = gnome.mkenums( + 'enumtypes', + sources: headers, + h_template: 'enumtypes.h.in', + c_template: 'enumtypes.c.in', +) + +executable('vipsdisp', [ + enumtypes, + marshal, + resources, + sources, + ], + dependencies: vipsdisp_deps, + win_subsystem: 'windows', + install: true, ) diff --git a/src/tilesource.c b/src/tilesource.c index 7ab0742..957dac8 100644 --- a/src/tilesource.c +++ b/src/tilesource.c @@ -793,11 +793,11 @@ tile_source_set_property(GObject *object, switch (prop_id) { case PROP_MODE: - i = g_value_get_int(value); - if (i >= 0 && - i < TILE_SOURCE_MODE_LAST && - tile_source->mode != i) { - tile_source->mode = i; + TileSourceMode mode = g_value_get_enum(value); + if (mode >= 0 && + mode < TILE_SOURCE_MODE_LAST && + tile_source->mode != mode) { + tile_source->mode = mode; tile_source->display_width = tile_source->width; tile_source->display_height = tile_source->height; if (tile_source->mode == TILE_SOURCE_MODE_TOILET_ROLL) @@ -926,7 +926,7 @@ tile_source_get_property(GObject *object, switch (prop_id) { case PROP_MODE: - g_value_set_int(value, tile_source->mode); + g_value_set_enum(value, tile_source->mode); break; case PROP_SCALE: @@ -1064,10 +1064,10 @@ tile_source_class_init(TileSourceClass *class) gobject_class->get_property = tile_source_get_property; g_object_class_install_property(gobject_class, PROP_MODE, - g_param_spec_int("mode", + g_param_spec_enum("mode", _("Mode"), _("Display mode"), - 0, TILE_SOURCE_MODE_LAST - 1, + TYPE_SOURCE_MODE, TILE_SOURCE_MODE_MULTIPAGE, G_PARAM_READWRITE)); @@ -1202,38 +1202,6 @@ tile_source_class_init(TileSourceClass *class) } #ifdef DEBUG -static const char * -type_name(TileSourceType type) -{ - switch (type) { - case TILE_SOURCE_TYPE_PAGE_PYRAMID: - return "pyramid"; - case TILE_SOURCE_TYPE_TOILET_ROLL: - return "toilet-roll"; - case TILE_SOURCE_TYPE_MULTIPAGE: - return "multipage"; - default: - return ""; - } -} - -static const char * -mode_name(TileSourceMode mode) -{ - switch (mode) { - case TILE_SOURCE_MODE_TOILET_ROLL: - return "toilet-roll"; - case TILE_SOURCE_MODE_MULTIPAGE: - return "multipage"; - case TILE_SOURCE_MODE_ANIMATED: - return "animated"; - case TILE_SOURCE_MODE_PAGES_AS_BANDS: - return "pages-as-bands"; - default: - return ""; - } -} - static void tile_source_print(TileSource *tile_source) { @@ -1257,8 +1225,10 @@ tile_source_print(TileSource *tile_source) printf("\tpages_same_size = %d\n", tile_source->pages_same_size); printf("\tall_mono = %d\n", tile_source->all_mono); - printf("\ttype = %s\n", type_name(tile_source->type)); - printf("\tmode = %s\n", mode_name(tile_source->mode)); + printf("\ttype = %s\n", + vips_enum_nick(TYPE_SOURCE_TYPE, tile_source->type)); + printf("\tmode = %s\n", + vips_enum_nick(TYPE_SOURCE_MODE, tile_source->mode)); printf("\tdelay = %p\n", tile_source->delay); printf("\tn_delay = %d\n", tile_source->n_delay); printf("\tdisplay_width = %d\n", tile_source->display_width); @@ -1894,7 +1864,7 @@ TileSource * tile_source_duplicate(TileSource *tile_source) { TileSource *new_tile_source; - int mode; + TileSourceMode mode; double scale; double offset; int page; diff --git a/src/vipsdisp.h b/src/vipsdisp.h index a4a8a47..6ecd038 100644 --- a/src/vipsdisp.h +++ b/src/vipsdisp.h @@ -42,6 +42,7 @@ G_GNUC_BEGIN_IGNORE_DEPRECATIONS } \ G_STMT_END +#include "enumtypes.h" #include "gtkutil.h" #include "tslider.h" #include "vipsdispapp.h" From 3cfb37951ce05b1106cf1cf5c4fdd3e5e499ad9b Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Sat, 6 Apr 2024 17:33:29 +0100 Subject: [PATCH 09/24] add a thing to represent view settings rename without _ to fix enum wrapping --- src/displaybar.c | 112 ++--- src/displaybar.h | 2 +- src/gtk/imagewindow.ui | 4 +- src/gtkutil.c | 2 +- src/imagedisplay.c | 108 ++--- src/imagedisplay.h | 8 +- src/imageui.c | 342 +++++++++------ src/imageui.h | 6 +- src/imagewindow.c | 866 ++++++++++++++++++++----------------- src/imagewindow.h | 52 +-- src/infobar.c | 73 ++-- src/infobar.h | 2 +- src/main.c | 2 +- src/properties.c | 48 +-- src/tilecache.c | 352 +++++++-------- src/tilecache.h | 66 +-- src/tilesource.c | 946 ++++++++++++++++++++--------------------- src/tilesource.h | 114 ++--- src/vipsdispapp.c | 16 +- 19 files changed, 1635 insertions(+), 1486 deletions(-) diff --git a/src/displaybar.c b/src/displaybar.c index ef2f556..ab0554e 100644 --- a/src/displaybar.c +++ b/src/displaybar.c @@ -8,13 +8,13 @@ struct _Displaybar { GtkWidget parent_instance; - /* The image_window we attach to. + /* The imagewindow we attach to. */ - ImageWindow *win; + Imagewindow *win; - /* A ref to the tile_source we are currently controlling. + /* A ref to the tilesource we are currently controlling. */ - TileSource *tile_source; + Tilesource *tilesource; GtkWidget *action_bar; GtkWidget *gears; @@ -23,7 +23,7 @@ struct _Displaybar { GtkWidget *offset; /* We have to disconnect and reconnect these when imagewindow gets a new - * tile_source. + * tilesource. */ guint changed_sid; guint tiles_changed_sid; @@ -33,110 +33,110 @@ struct _Displaybar { G_DEFINE_TYPE(Displaybar, displaybar, GTK_TYPE_WIDGET); enum { - PROP_IMAGE_WINDOW = 1, + PROP_IMAGEWINDOW = 1, PROP_REVEALED, SIG_LAST }; static void -displaybar_tile_source_changed(TileSource *tile_source, Displaybar *displaybar) +displaybar_tilesource_changed(Tilesource *tilesource, Displaybar *displaybar) { #ifdef DEBUG - printf("displaybar_tile_source_changed:\n"); + printf("displaybar_tilesource_changed:\n"); #endif /*DEBUG*/ - g_assert(tile_source == displaybar->tile_source); + g_assert(tilesource == displaybar->tilesource); - if (TSLIDER(displaybar->scale)->value != tile_source->scale) { - TSLIDER(displaybar->scale)->value = tile_source->scale; + if (TSLIDER(displaybar->scale)->value != tilesource->scale) { + TSLIDER(displaybar->scale)->value = tilesource->scale; tslider_changed(TSLIDER(displaybar->scale)); } - if (TSLIDER(displaybar->offset)->value != tile_source->offset) { - TSLIDER(displaybar->offset)->value = tile_source->offset; + if (TSLIDER(displaybar->offset)->value != tilesource->offset) { + TSLIDER(displaybar->offset)->value = tilesource->offset; tslider_changed(TSLIDER(displaybar->offset)); } gtk_spin_button_set_range(GTK_SPIN_BUTTON(displaybar->page), - 0, tile_source->n_pages - 1); + 0, tilesource->n_pages - 1); gtk_widget_set_sensitive(displaybar->page, - tile_source->n_pages > 1 && - tile_source->mode == TILE_SOURCE_MODE_MULTIPAGE); + tilesource->n_pages > 1 && + tilesource->mode == TILESOURCE_MODE_MULTIPAGE); } static void -displaybar_page_changed(TileSource *tile_source, Displaybar *displaybar) +displaybar_page_changed(Tilesource *tilesource, Displaybar *displaybar) { #ifdef DEBUG printf("displaybar_page_changed:\n"); #endif /*DEBUG*/ - g_assert(tile_source == displaybar->tile_source); + g_assert(tilesource == displaybar->tilesource); gtk_spin_button_set_value(GTK_SPIN_BUTTON(displaybar->page), - tile_source->page); + tilesource->page); } static void displaybar_disconnect(Displaybar *displaybar) { - if (displaybar->tile_source) { - FREESID(displaybar->changed_sid, displaybar->tile_source); - FREESID(displaybar->tiles_changed_sid, displaybar->tile_source); - FREESID(displaybar->page_changed_sid, displaybar->tile_source); + if (displaybar->tilesource) { + FREESID(displaybar->changed_sid, displaybar->tilesource); + FREESID(displaybar->tiles_changed_sid, displaybar->tilesource); + FREESID(displaybar->page_changed_sid, displaybar->tilesource); - VIPS_UNREF(displaybar->tile_source); + VIPS_UNREF(displaybar->tilesource); } } -/* Imagewindow has a new tile_source. +/* Imagewindow has a new tilesource. */ static void -displaybar_image_window_changed(ImageWindow *win, Displaybar *displaybar) +displaybar_imagewindow_changed(Imagewindow *win, Displaybar *displaybar) { #ifdef DEBUG - printf("displaybar_image_window_changed:\n"); + printf("displaybar_imagewindow_changed:\n"); #endif /*DEBUG*/ displaybar_disconnect(displaybar); - TileSource *new_tile_source = image_window_get_tile_source(win); - if (new_tile_source) { + Tilesource *new_tilesource = imagewindow_get_tilesource(win); + if (new_tilesource) { /* Set new source. */ - displaybar->changed_sid = g_signal_connect(new_tile_source, + displaybar->changed_sid = g_signal_connect(new_tilesource, "changed", - G_CALLBACK(displaybar_tile_source_changed), displaybar); - displaybar->tiles_changed_sid = g_signal_connect(new_tile_source, + G_CALLBACK(displaybar_tilesource_changed), displaybar); + displaybar->tiles_changed_sid = g_signal_connect(new_tilesource, "tiles-changed", - G_CALLBACK(displaybar_tile_source_changed), displaybar); - displaybar->page_changed_sid = g_signal_connect(new_tile_source, + G_CALLBACK(displaybar_tilesource_changed), displaybar); + displaybar->page_changed_sid = g_signal_connect(new_tilesource, "page-changed", G_CALLBACK(displaybar_page_changed), displaybar); - displaybar->tile_source = new_tile_source; - g_object_ref(new_tile_source); + displaybar->tilesource = new_tilesource; + g_object_ref(new_tilesource); /* Init from new source. */ - displaybar_tile_source_changed(new_tile_source, displaybar); - displaybar_page_changed(new_tile_source, displaybar); + displaybar_tilesource_changed(new_tilesource, displaybar); + displaybar_page_changed(new_tilesource, displaybar); } } static void -displaybar_set_image_window(Displaybar *displaybar, ImageWindow *win) +displaybar_set_imagewindow(Displaybar *displaybar, Imagewindow *win) { /* No need to ref ... win holds a ref to us. */ displaybar->win = win; g_signal_connect_object(win, "changed", - G_CALLBACK(displaybar_image_window_changed), + G_CALLBACK(displaybar_imagewindow_changed), displaybar, 0); - displaybar_image_window_changed(win, displaybar); + displaybar_imagewindow_changed(win, displaybar); } static void @@ -146,8 +146,8 @@ displaybar_set_property(GObject *object, Displaybar *displaybar = (Displaybar *) object; switch (prop_id) { - case PROP_IMAGE_WINDOW: - displaybar_set_image_window(displaybar, + case PROP_IMAGEWINDOW: + displaybar_set_imagewindow(displaybar, g_value_get_object(value)); break; @@ -171,7 +171,7 @@ displaybar_get_property(GObject *object, GtkActionBar *action_bar = GTK_ACTION_BAR(displaybar->action_bar); switch (prop_id) { - case PROP_IMAGE_WINDOW: + case PROP_IMAGEWINDOW: g_value_set_object(value, displaybar->win); break; @@ -205,15 +205,15 @@ static void displaybar_page_value_changed(GtkSpinButton *spin_button, Displaybar *displaybar) { - TileSource *tile_source = displaybar->tile_source; + Tilesource *tilesource = displaybar->tilesource; int new_page = gtk_spin_button_get_value_as_int(spin_button); #ifdef DEBUG printf("displaybar_page_value_changed: %d\n", new_page); #endif /*DEBUG*/ - if (tile_source) - g_object_set(tile_source, + if (tilesource) + g_object_set(tilesource, "page", new_page, NULL); } @@ -221,10 +221,10 @@ displaybar_page_value_changed(GtkSpinButton *spin_button, static void displaybar_scale_value_changed(Tslider *slider, Displaybar *displaybar) { - TileSource *tile_source = displaybar->tile_source; + Tilesource *tilesource = displaybar->tilesource; - if (tile_source) - g_object_set(tile_source, + if (tilesource) + g_object_set(tilesource, "scale", slider->value, NULL); } @@ -232,10 +232,10 @@ displaybar_scale_value_changed(Tslider *slider, Displaybar *displaybar) static void displaybar_offset_value_changed(Tslider *slider, Displaybar *displaybar) { - TileSource *tile_source = displaybar->tile_source; + Tilesource *tilesource = displaybar->tilesource; - if (tile_source) - g_object_set(tile_source, + if (tilesource) + g_object_set(tilesource, "offset", slider->value, NULL); } @@ -314,11 +314,11 @@ displaybar_class_init(DisplaybarClass *class) gobject_class->set_property = displaybar_set_property; gobject_class->get_property = displaybar_get_property; - g_object_class_install_property(gobject_class, PROP_IMAGE_WINDOW, + g_object_class_install_property(gobject_class, PROP_IMAGEWINDOW, g_param_spec_object("image-window", _("Image window"), _("The image window we display"), - IMAGE_WINDOW_TYPE, + IMAGEWINDOW_TYPE, G_PARAM_READWRITE)); g_object_class_install_property(gobject_class, PROP_REVEALED, @@ -330,7 +330,7 @@ displaybar_class_init(DisplaybarClass *class) } Displaybar * -displaybar_new(ImageWindow *win) +displaybar_new(Imagewindow *win) { Displaybar *displaybar; diff --git a/src/displaybar.h b/src/displaybar.h index f2ff38c..52ab082 100644 --- a/src/displaybar.h +++ b/src/displaybar.h @@ -10,6 +10,6 @@ G_DECLARE_FINAL_TYPE(Displaybar, displaybar, (G_TYPE_CHECK_INSTANCE_CAST((obj), \ DISPLAYBAR_TYPE, Displaybar)) -Displaybar *displaybar_new(ImageWindow *win); +Displaybar *displaybar_new(Imagewindow *win); #endif /* __DISPLAYBAR_H */ diff --git a/src/gtk/imagewindow.ui b/src/gtk/imagewindow.ui index 1a49eca..b578222 100644 --- a/src/gtk/imagewindow.ui +++ b/src/gtk/imagewindow.ui @@ -128,7 +128,7 @@ -