Compare commits
	
		
			2 Commits
		
	
	
		
			098531073c
			...
			852cbfc1fb
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 852cbfc1fb | |||
| 3bbdd873ef | 
							
								
								
									
										100
									
								
								.gitlab-ci.yml
									
									
									
									
									
								
							
							
						
						
									
										100
									
								
								.gitlab-ci.yml
									
									
									
									
									
								
							@ -18,7 +18,8 @@
 | 
			
		||||
# - PIKA_CI_CROSSROAD_WIN64: trigger the crossroad/meson build for Win 64-bit.
 | 
			
		||||
# - PIKA_CI_MSYS2_WIN32: trigger the native MSYS2 build for Win 32-bit.
 | 
			
		||||
# - PIKA_CI_MSYS2_WIN64: trigger the native MSYS2 build for Win 64-bit.
 | 
			
		||||
# - PIKA_CI_WIN_INSTALLER: trigger both native MSYS2 builds then creates Windows installer.
 | 
			
		||||
# - PIKA_CI_MSYS2_WIN_AARCH64: trigger the native MSYS2 build for Windows/Aarch64.
 | 
			
		||||
# - PIKA_CI_WIN_INSTALLER: trigger all native MSYS2 builds then creates Windows installer.
 | 
			
		||||
# - PIKA_CI_SOURCES: trigger the meson/gcc build and the source tarball job.
 | 
			
		||||
# - PIKA_CI_CPPCHECK: trigger cppcheck static analysis.
 | 
			
		||||
# - PIKA_CI_FLATPAK: trigger the nightly flatpak build and publishing.
 | 
			
		||||
@ -375,7 +376,7 @@ pika-meson-raster-icons:
 | 
			
		||||
    - ninja -C _build
 | 
			
		||||
    - ninja -C _build test
 | 
			
		||||
 | 
			
		||||
## WINDOWS 64-bit CI (native MSYS2) ##
 | 
			
		||||
## WINDOWS x86_64 CI (native MSYS2) ##
 | 
			
		||||
 | 
			
		||||
deps-win64-native:
 | 
			
		||||
  rules:
 | 
			
		||||
@ -462,7 +463,7 @@ packaging-win64-native:
 | 
			
		||||
    - done-dll.list
 | 
			
		||||
  needs: ["pika-win64-native"]
 | 
			
		||||
 | 
			
		||||
## WINDOWS 32-bit CI (native MSYS2) ##
 | 
			
		||||
## WINDOWS x86 CI (native MSYS2) ##
 | 
			
		||||
 | 
			
		||||
deps-win32-native:
 | 
			
		||||
  rules:
 | 
			
		||||
@ -548,6 +549,96 @@ packaging-win32-native:
 | 
			
		||||
    - done-dll.list
 | 
			
		||||
  needs: ["pika-win32-native"]
 | 
			
		||||
 | 
			
		||||
## WINDOWS Aarch64 CI (native MSYS2) ##
 | 
			
		||||
 | 
			
		||||
deps-win-aarch64-native:
 | 
			
		||||
  rules:
 | 
			
		||||
    # On releases.
 | 
			
		||||
    - if: '$CI_COMMIT_TAG != null'
 | 
			
		||||
    # Custom builds though web GUI, API or schedules.
 | 
			
		||||
    - if: '$PIKA_CI_MSYS2_WIN_AARCH64 != null'
 | 
			
		||||
    - if: '$PIKA_CI_WIN_INSTALLER != null'
 | 
			
		||||
    # Merge requests with appropriate label.
 | 
			
		||||
    - if: '$CI_MERGE_REQUEST_LABELS =~ /.*5. Windows Installer.*/'
 | 
			
		||||
  stage: dependencies
 | 
			
		||||
  variables:
 | 
			
		||||
    MSYSTEM: "CLANGARM64"
 | 
			
		||||
    CHERE_INVOKING: "yes"
 | 
			
		||||
  tags:
 | 
			
		||||
    - windows-aarch64
 | 
			
		||||
  script:
 | 
			
		||||
    - C:\msys64\usr\bin\pacman --noconfirm -Syyuu
 | 
			
		||||
    - C:\msys64\usr\bin\bash -lc "bash -x ./build/windows/gitlab-ci/build-deps-msys2.sh"
 | 
			
		||||
  artifacts:
 | 
			
		||||
    name: "${CI_JOB_NAME}-${CI_COMMIT_REF_SLUG}"
 | 
			
		||||
    when: always
 | 
			
		||||
    expire_in: 2 hours
 | 
			
		||||
    paths:
 | 
			
		||||
      - _install-arm64
 | 
			
		||||
  needs: []
 | 
			
		||||
 | 
			
		||||
pika-win-aarch64-native:
 | 
			
		||||
  rules:
 | 
			
		||||
    # On releases.
 | 
			
		||||
    - if: '$CI_COMMIT_TAG != null'
 | 
			
		||||
    # Custom builds though web GUI, API or schedules.
 | 
			
		||||
    - if: '$PIKA_CI_MSYS2_WIN_AARCH64 != null'
 | 
			
		||||
    - if: '$PIKA_CI_WIN_INSTALLER != null'
 | 
			
		||||
    # Merge requests with appropriate label.
 | 
			
		||||
    - if: '$CI_MERGE_REQUEST_LABELS =~ /.*5. Windows Installer.*/'
 | 
			
		||||
  stage: pika
 | 
			
		||||
  variables:
 | 
			
		||||
    MSYSTEM: "CLANGARM64"
 | 
			
		||||
    CHERE_INVOKING: "yes"
 | 
			
		||||
  tags:
 | 
			
		||||
    - windows-aarch64
 | 
			
		||||
  script:
 | 
			
		||||
    # Temporary patch until we use the latest LLVM.
 | 
			
		||||
    - git apply ./build/windows/patches/0001-clang-rc-files-fix.patch
 | 
			
		||||
    - git apply ./build/windows/patches/0004-clang-windres.patch
 | 
			
		||||
    - C:\msys64\usr\bin\pacman --noconfirm -Syyuu
 | 
			
		||||
    - C:\msys64\usr\bin\bash -lc "bash -x ./build/windows/gitlab-ci/build-pika-msys2.sh"
 | 
			
		||||
  artifacts:
 | 
			
		||||
    name: "${CI_JOB_NAME}-${CI_COMMIT_REF_SLUG}"
 | 
			
		||||
    when: always
 | 
			
		||||
    expire_in: 1 day
 | 
			
		||||
    paths:
 | 
			
		||||
    - _install-arm64
 | 
			
		||||
    - _build-arm64/build/windows/installer/
 | 
			
		||||
    - _build-arm64/meson-*/
 | 
			
		||||
  cache:
 | 
			
		||||
    paths:
 | 
			
		||||
    - _ccache/
 | 
			
		||||
  needs: ["deps-win-aarch64-native"]
 | 
			
		||||
 | 
			
		||||
packaging-win-aarch64-native:
 | 
			
		||||
  rules:
 | 
			
		||||
    # On releases.
 | 
			
		||||
    - if: '$CI_COMMIT_TAG != null'
 | 
			
		||||
    # Custom builds though web GUI, API or schedules.
 | 
			
		||||
    - if: '$PIKA_CI_WIN_INSTALLER != null'
 | 
			
		||||
    # Merge requests with appropriate label.
 | 
			
		||||
    - if: '$CI_MERGE_REQUEST_LABELS =~ /.*5. Windows Installer.*/'
 | 
			
		||||
  stage: packaging
 | 
			
		||||
  variables:
 | 
			
		||||
    MSYSTEM: "CLANGARM64"
 | 
			
		||||
    CHERE_INVOKING: "yes"
 | 
			
		||||
  tags:
 | 
			
		||||
    - windows-aarch64
 | 
			
		||||
  script:
 | 
			
		||||
    - C:\msys64\usr\bin\pacman --noconfirm -Syyuu
 | 
			
		||||
    - C:\msys64\usr\bin\bash -lc "bash -x ./build/windows/gitlab-ci/package-pika-msys2.sh"
 | 
			
		||||
    - cd pika-arm64
 | 
			
		||||
    - C:\msys64\usr\bin\bash -lc "bash -x ../build/windows/gitlab-ci/split-debug-msys2.sh"
 | 
			
		||||
  artifacts:
 | 
			
		||||
    name: "${CI_JOB_NAME}-${CI_COMMIT_REF_SLUG}"
 | 
			
		||||
    when: always
 | 
			
		||||
    expire_in: 1 day
 | 
			
		||||
    paths:
 | 
			
		||||
    - pika-arm64
 | 
			
		||||
    - done-dll.list
 | 
			
		||||
  needs: ["pika-win-aarch64-native"]
 | 
			
		||||
 | 
			
		||||
## WINDOWS 64-bit CI (cross-build crossroad) ##
 | 
			
		||||
 | 
			
		||||
deps-win64:
 | 
			
		||||
@ -822,6 +913,7 @@ win-installer-nightly:
 | 
			
		||||
  dependencies:
 | 
			
		||||
    - packaging-win64-native
 | 
			
		||||
    - packaging-win32-native
 | 
			
		||||
    - packaging-win-aarch64-native
 | 
			
		||||
    # This is needed for the BMP image generation for the installer.
 | 
			
		||||
    # See commit e1203e9f76f.
 | 
			
		||||
    - pika-meson-debian
 | 
			
		||||
@ -835,7 +927,7 @@ win-installer-nightly:
 | 
			
		||||
  script:
 | 
			
		||||
    - C:\msys64\usr\bin\pacman --noconfirm -Syyuu
 | 
			
		||||
    - C:\msys64\usr\bin\bash -lc "bash -x ./build/windows/gitlab-ci/installer-pika-msys2.sh > installer.log 2>&1"
 | 
			
		||||
  needs: ["packaging-win32-native", "packaging-win64-native", "pika-meson-debian"]
 | 
			
		||||
  needs: ["packaging-win32-native", "packaging-win64-native", "packaging-win-aarch64-native", "pika-meson-debian"]
 | 
			
		||||
 | 
			
		||||
sources-meson:
 | 
			
		||||
  rules:
 | 
			
		||||
 | 
			
		||||
@ -34,6 +34,7 @@
 | 
			
		||||
#include "core/pikaimage-colormap.h"
 | 
			
		||||
 | 
			
		||||
#include "widgets/pikaactiongroup.h"
 | 
			
		||||
#include "widgets/pikacolormapeditor.h"
 | 
			
		||||
#include "widgets/pikahelp-ids.h"
 | 
			
		||||
 | 
			
		||||
#include "actions.h"
 | 
			
		||||
@ -49,6 +50,12 @@ static const PikaActionEntry colormap_actions[] =
 | 
			
		||||
    NC_("colormap-action", "_Edit Color..."), NULL, { NULL },
 | 
			
		||||
    NC_("colormap-action", "Edit this color"),
 | 
			
		||||
    colormap_edit_color_cmd_callback,
 | 
			
		||||
    PIKA_HELP_INDEXED_PALETTE_EDIT },
 | 
			
		||||
 | 
			
		||||
  { "colormap-delete-color", PIKA_ICON_EDIT_DELETE,
 | 
			
		||||
    NC_("colormap-action", "_Delete Color..."), NULL, { NULL },
 | 
			
		||||
    NC_("colormap-action", "Delete this color"),
 | 
			
		||||
    colormap_delete_color_cmd_callback,
 | 
			
		||||
    PIKA_HELP_INDEXED_PALETTE_EDIT }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -116,13 +123,14 @@ void
 | 
			
		||||
colormap_actions_update (PikaActionGroup *group,
 | 
			
		||||
                         gpointer         data)
 | 
			
		||||
{
 | 
			
		||||
  PikaImage   *image            = action_data_get_image (data);
 | 
			
		||||
  PikaContext *context          = action_data_get_context (data);
 | 
			
		||||
  gboolean     indexed          = FALSE;
 | 
			
		||||
  gboolean     drawable_indexed = FALSE;
 | 
			
		||||
  gint         num_colors       = 0;
 | 
			
		||||
  PikaRGB      fg;
 | 
			
		||||
  PikaRGB      bg;
 | 
			
		||||
  PikaColormapEditor *editor           = PIKA_COLORMAP_EDITOR (data);
 | 
			
		||||
  PikaImage          *image            = action_data_get_image (data);
 | 
			
		||||
  PikaContext        *context          = action_data_get_context (data);
 | 
			
		||||
  gboolean            indexed          = FALSE;
 | 
			
		||||
  gboolean            drawable_indexed = FALSE;
 | 
			
		||||
  gint                num_colors       = 0;
 | 
			
		||||
  PikaRGB             fg;
 | 
			
		||||
  PikaRGB             bg;
 | 
			
		||||
 | 
			
		||||
  if (image)
 | 
			
		||||
    {
 | 
			
		||||
@ -154,6 +162,9 @@ colormap_actions_update (PikaActionGroup *group,
 | 
			
		||||
 | 
			
		||||
  SET_SENSITIVE ("colormap-edit-color",
 | 
			
		||||
                 indexed && num_colors > 0);
 | 
			
		||||
  SET_SENSITIVE ("colormap-delete-color",
 | 
			
		||||
                 indexed && num_colors > 0 &&
 | 
			
		||||
                 pika_colormap_editor_is_color_deletable (editor));
 | 
			
		||||
 | 
			
		||||
  SET_SENSITIVE ("colormap-add-color-from-fg",
 | 
			
		||||
                 indexed && num_colors < 256);
 | 
			
		||||
 | 
			
		||||
@ -50,6 +50,16 @@ colormap_edit_color_cmd_callback (PikaAction *action,
 | 
			
		||||
  pika_colormap_editor_edit_color (editor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
colormap_delete_color_cmd_callback (PikaAction *action,
 | 
			
		||||
                                    GVariant   *value,
 | 
			
		||||
                                    gpointer    data)
 | 
			
		||||
{
 | 
			
		||||
  PikaColormapEditor *editor = PIKA_COLORMAP_EDITOR (data);
 | 
			
		||||
 | 
			
		||||
  pika_colormap_editor_delete_color (editor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
colormap_add_color_cmd_callback (PikaAction *action,
 | 
			
		||||
                                 GVariant   *value,
 | 
			
		||||
 | 
			
		||||
@ -26,6 +26,9 @@
 | 
			
		||||
void   colormap_edit_color_cmd_callback   (PikaAction *action,
 | 
			
		||||
                                           GVariant   *value,
 | 
			
		||||
                                           gpointer    data);
 | 
			
		||||
void   colormap_delete_color_cmd_callback (PikaAction *action,
 | 
			
		||||
                                           GVariant   *value,
 | 
			
		||||
                                           gpointer    data);
 | 
			
		||||
void   colormap_add_color_cmd_callback    (PikaAction *action,
 | 
			
		||||
                                           GVariant   *value,
 | 
			
		||||
                                           gpointer    data);
 | 
			
		||||
 | 
			
		||||
@ -446,7 +446,7 @@ pika_gegl_procedure_new (Pika        *pika,
 | 
			
		||||
                                                      FALSE,
 | 
			
		||||
                                                      PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               g_param_spec_int ("n-drawables",
 | 
			
		||||
                               g_param_spec_int ("num-drawables",
 | 
			
		||||
                                                 "N drawables",
 | 
			
		||||
                                                 "The number of drawables",
 | 
			
		||||
                                                 0, G_MAXINT32, 0,
 | 
			
		||||
 | 
			
		||||
@ -50,7 +50,7 @@ _("Timestamp of the last update check.")
 | 
			
		||||
"Defines the color management behavior."
 | 
			
		||||
 | 
			
		||||
#define COLOR_PROFILE_POLICY_BLURB \
 | 
			
		||||
_("How to handle embedded color profiles when opening a file.")
 | 
			
		||||
_("What to do when opening a file with an embedded ICC color profile.")
 | 
			
		||||
 | 
			
		||||
#define COLOR_PROFILE_PATH_BLURB \
 | 
			
		||||
_("Sets the default folder path for all color profile file dialogs.")
 | 
			
		||||
 | 
			
		||||
@ -1195,6 +1195,7 @@ pika_undo_type_get_type (void)
 | 
			
		||||
    { PIKA_UNDO_GROUP_IMAGE_VECTORS_MERGE, "PIKA_UNDO_GROUP_IMAGE_VECTORS_MERGE", "group-image-vectors-merge" },
 | 
			
		||||
    { PIKA_UNDO_GROUP_IMAGE_QUICK_MASK, "PIKA_UNDO_GROUP_IMAGE_QUICK_MASK", "group-image-quick-mask" },
 | 
			
		||||
    { PIKA_UNDO_GROUP_IMAGE_GRID, "PIKA_UNDO_GROUP_IMAGE_GRID", "group-image-grid" },
 | 
			
		||||
    { PIKA_UNDO_GROUP_IMAGE_COLORMAP_REMAP, "PIKA_UNDO_GROUP_IMAGE_COLORMAP_REMAP", "group-image-colormap-remap" },
 | 
			
		||||
    { PIKA_UNDO_GROUP_GUIDE, "PIKA_UNDO_GROUP_GUIDE", "group-guide" },
 | 
			
		||||
    { PIKA_UNDO_GROUP_SAMPLE_POINT, "PIKA_UNDO_GROUP_SAMPLE_POINT", "group-sample-point" },
 | 
			
		||||
    { PIKA_UNDO_GROUP_DRAWABLE, "PIKA_UNDO_GROUP_DRAWABLE", "group-drawable" },
 | 
			
		||||
@ -1303,6 +1304,7 @@ pika_undo_type_get_type (void)
 | 
			
		||||
    { PIKA_UNDO_GROUP_IMAGE_VECTORS_MERGE, NC_("undo-type", "Merge paths"), NULL },
 | 
			
		||||
    { PIKA_UNDO_GROUP_IMAGE_QUICK_MASK, NC_("undo-type", "Quick Mask"), NULL },
 | 
			
		||||
    { PIKA_UNDO_GROUP_IMAGE_GRID, NC_("undo-type", "Grid"), NULL },
 | 
			
		||||
    { PIKA_UNDO_GROUP_IMAGE_COLORMAP_REMAP, NC_("undo-type", "Colormap remapping"), NULL },
 | 
			
		||||
    { PIKA_UNDO_GROUP_GUIDE, NC_("undo-type", "Guide"), NULL },
 | 
			
		||||
    { PIKA_UNDO_GROUP_SAMPLE_POINT, NC_("undo-type", "Sample Point"), NULL },
 | 
			
		||||
    { PIKA_UNDO_GROUP_DRAWABLE, NC_("undo-type", "Layer/Channel"), NULL },
 | 
			
		||||
 | 
			
		||||
@ -548,6 +548,7 @@ typedef enum /*< pdb-skip >*/
 | 
			
		||||
  PIKA_UNDO_GROUP_IMAGE_VECTORS_MERGE,   /*< desc="Merge paths"                    >*/
 | 
			
		||||
  PIKA_UNDO_GROUP_IMAGE_QUICK_MASK,      /*< desc="Quick Mask"                     >*/
 | 
			
		||||
  PIKA_UNDO_GROUP_IMAGE_GRID,            /*< desc="Grid"                           >*/
 | 
			
		||||
  PIKA_UNDO_GROUP_IMAGE_COLORMAP_REMAP,  /*< desc="Colormap remapping"             >*/
 | 
			
		||||
  PIKA_UNDO_GROUP_GUIDE,                 /*< desc="Guide"                          >*/
 | 
			
		||||
  PIKA_UNDO_GROUP_SAMPLE_POINT,          /*< desc="Sample Point"                   >*/
 | 
			
		||||
  PIKA_UNDO_GROUP_DRAWABLE,              /*< desc="Layer/Channel"                  >*/
 | 
			
		||||
 | 
			
		||||
@ -33,8 +33,10 @@
 | 
			
		||||
#include "pikacontainer.h"
 | 
			
		||||
#include "pikacontext.h"
 | 
			
		||||
#include "pikadisplay.h"
 | 
			
		||||
#include "pikadrawable.h"
 | 
			
		||||
#include "pikaimage.h"
 | 
			
		||||
#include "pikaprogress.h"
 | 
			
		||||
#include "pikaresource.h"
 | 
			
		||||
#include "pikawaitable.h"
 | 
			
		||||
 | 
			
		||||
#include "about.h"
 | 
			
		||||
@ -325,17 +327,17 @@ pika_get_empty_display (Pika *pika)
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
guint32
 | 
			
		||||
GBytes *
 | 
			
		||||
pika_get_display_window_id (Pika        *pika,
 | 
			
		||||
                            PikaDisplay *display)
 | 
			
		||||
{
 | 
			
		||||
  g_return_val_if_fail (PIKA_IS_PIKA (pika), -1);
 | 
			
		||||
  g_return_val_if_fail (PIKA_IS_DISPLAY (display), -1);
 | 
			
		||||
  g_return_val_if_fail (PIKA_IS_PIKA (pika), NULL);
 | 
			
		||||
  g_return_val_if_fail (PIKA_IS_DISPLAY (display), NULL);
 | 
			
		||||
 | 
			
		||||
  if (pika->gui.display_get_window_id)
 | 
			
		||||
    return pika->gui.display_get_window_id (display);
 | 
			
		||||
 | 
			
		||||
  return -1;
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PikaDisplay *
 | 
			
		||||
@ -407,10 +409,11 @@ gboolean
 | 
			
		||||
pika_pdb_dialog_new (Pika          *pika,
 | 
			
		||||
                     PikaContext   *context,
 | 
			
		||||
                     PikaProgress  *progress,
 | 
			
		||||
                     PikaContainer *container,
 | 
			
		||||
                     GType          contents_type,
 | 
			
		||||
                     GBytes        *parent_handle,
 | 
			
		||||
                     const gchar   *title,
 | 
			
		||||
                     const gchar   *callback_name,
 | 
			
		||||
                     const gchar   *object_name,
 | 
			
		||||
                     PikaObject    *object,
 | 
			
		||||
                     ...)
 | 
			
		||||
{
 | 
			
		||||
  gboolean retval = FALSE;
 | 
			
		||||
@ -418,7 +421,10 @@ pika_pdb_dialog_new (Pika          *pika,
 | 
			
		||||
  g_return_val_if_fail (PIKA_IS_PIKA (pika), FALSE);
 | 
			
		||||
  g_return_val_if_fail (PIKA_IS_CONTEXT (context), FALSE);
 | 
			
		||||
  g_return_val_if_fail (progress == NULL || PIKA_IS_PROGRESS (progress), FALSE);
 | 
			
		||||
  g_return_val_if_fail (PIKA_IS_CONTAINER (container), FALSE);
 | 
			
		||||
  g_return_val_if_fail (g_type_is_a (contents_type, PIKA_TYPE_RESOURCE) ||
 | 
			
		||||
                        g_type_is_a (contents_type, PIKA_TYPE_DRAWABLE), FALSE);
 | 
			
		||||
  g_return_val_if_fail (object == NULL ||
 | 
			
		||||
                        g_type_is_a (G_TYPE_FROM_INSTANCE (object), contents_type), FALSE);
 | 
			
		||||
  g_return_val_if_fail (title != NULL, FALSE);
 | 
			
		||||
  g_return_val_if_fail (callback_name != NULL, FALSE);
 | 
			
		||||
 | 
			
		||||
@ -426,12 +432,11 @@ pika_pdb_dialog_new (Pika          *pika,
 | 
			
		||||
    {
 | 
			
		||||
      va_list args;
 | 
			
		||||
 | 
			
		||||
      va_start (args, object_name);
 | 
			
		||||
      va_start (args, object);
 | 
			
		||||
 | 
			
		||||
      retval = pika->gui.pdb_dialog_new (pika, context, progress,
 | 
			
		||||
                                         container, title,
 | 
			
		||||
                                         callback_name, object_name,
 | 
			
		||||
                                         args);
 | 
			
		||||
                                         contents_type, parent_handle, title,
 | 
			
		||||
                                         callback_name, object, args);
 | 
			
		||||
 | 
			
		||||
      va_end (args);
 | 
			
		||||
    }
 | 
			
		||||
@ -440,27 +445,28 @@ pika_pdb_dialog_new (Pika          *pika,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
pika_pdb_dialog_set (Pika          *pika,
 | 
			
		||||
                     PikaContainer *container,
 | 
			
		||||
                     const gchar   *callback_name,
 | 
			
		||||
                     const gchar   *object_name,
 | 
			
		||||
pika_pdb_dialog_set (Pika        *pika,
 | 
			
		||||
                     GType        contents_type,
 | 
			
		||||
                     const gchar *callback_name,
 | 
			
		||||
                     PikaObject  *object,
 | 
			
		||||
                     ...)
 | 
			
		||||
{
 | 
			
		||||
  gboolean retval = FALSE;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (PIKA_IS_PIKA (pika), FALSE);
 | 
			
		||||
  g_return_val_if_fail (PIKA_IS_CONTAINER (container), FALSE);
 | 
			
		||||
  g_return_val_if_fail (g_type_is_a (contents_type, PIKA_TYPE_RESOURCE) ||
 | 
			
		||||
                        contents_type == PIKA_TYPE_DRAWABLE, FALSE);
 | 
			
		||||
  g_return_val_if_fail (callback_name != NULL, FALSE);
 | 
			
		||||
  g_return_val_if_fail (object_name != NULL, FALSE);
 | 
			
		||||
  g_return_val_if_fail (object == NULL || g_type_is_a (G_TYPE_FROM_INSTANCE (object), contents_type), FALSE);
 | 
			
		||||
 | 
			
		||||
  if (pika->gui.pdb_dialog_set)
 | 
			
		||||
    {
 | 
			
		||||
      va_list args;
 | 
			
		||||
 | 
			
		||||
      va_start (args, object_name);
 | 
			
		||||
      va_start (args, object);
 | 
			
		||||
 | 
			
		||||
      retval = pika->gui.pdb_dialog_set (pika, container, callback_name,
 | 
			
		||||
                                         object_name, args);
 | 
			
		||||
      retval = pika->gui.pdb_dialog_set (pika, contents_type, callback_name,
 | 
			
		||||
                                         object, args);
 | 
			
		||||
 | 
			
		||||
      va_end (args);
 | 
			
		||||
    }
 | 
			
		||||
@ -470,15 +476,16 @@ pika_pdb_dialog_set (Pika          *pika,
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
pika_pdb_dialog_close (Pika          *pika,
 | 
			
		||||
                       PikaContainer *container,
 | 
			
		||||
                       GType          contents_type,
 | 
			
		||||
                       const gchar   *callback_name)
 | 
			
		||||
{
 | 
			
		||||
  g_return_val_if_fail (PIKA_IS_PIKA (pika), FALSE);
 | 
			
		||||
  g_return_val_if_fail (PIKA_IS_CONTAINER (container), FALSE);
 | 
			
		||||
  g_return_val_if_fail (g_type_is_a (contents_type, PIKA_TYPE_RESOURCE) ||
 | 
			
		||||
                        contents_type == PIKA_TYPE_DRAWABLE, FALSE);
 | 
			
		||||
  g_return_val_if_fail (callback_name != NULL, FALSE);
 | 
			
		||||
 | 
			
		||||
  if (pika->gui.pdb_dialog_close)
 | 
			
		||||
    return pika->gui.pdb_dialog_close (pika, container, callback_name);
 | 
			
		||||
    return pika->gui.pdb_dialog_close (pika, contents_type, callback_name);
 | 
			
		||||
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -58,7 +58,7 @@ struct _PikaGui
 | 
			
		||||
 | 
			
		||||
  PikaObject   * (* get_window_strategy)    (Pika                *pika);
 | 
			
		||||
  PikaDisplay  * (* get_empty_display)      (Pika                *pika);
 | 
			
		||||
  guint32        (* display_get_window_id)  (PikaDisplay         *display);
 | 
			
		||||
  GBytes       * (* display_get_window_id)  (PikaDisplay         *display);
 | 
			
		||||
  PikaDisplay  * (* display_create)         (Pika                *pika,
 | 
			
		||||
                                             PikaImage           *image,
 | 
			
		||||
                                             PikaUnit             unit,
 | 
			
		||||
@ -77,18 +77,19 @@ struct _PikaGui
 | 
			
		||||
  gboolean       (* pdb_dialog_new)         (Pika                *pika,
 | 
			
		||||
                                             PikaContext         *context,
 | 
			
		||||
                                             PikaProgress        *progress,
 | 
			
		||||
                                             PikaContainer       *container,
 | 
			
		||||
                                             GType                contents_type,
 | 
			
		||||
                                             GBytes              *parent_handle,
 | 
			
		||||
                                             const gchar         *title,
 | 
			
		||||
                                             const gchar         *callback_name,
 | 
			
		||||
                                             const gchar         *object_name,
 | 
			
		||||
                                             PikaObject          *object,
 | 
			
		||||
                                             va_list              args);
 | 
			
		||||
  gboolean       (* pdb_dialog_set)         (Pika                *pika,
 | 
			
		||||
                                             PikaContainer       *container,
 | 
			
		||||
                                             GType                contents_type,
 | 
			
		||||
                                             const gchar         *callback_name,
 | 
			
		||||
                                             const gchar         *object_name,
 | 
			
		||||
                                             PikaObject          *object,
 | 
			
		||||
                                             va_list              args);
 | 
			
		||||
  gboolean       (* pdb_dialog_close)       (Pika                *pika,
 | 
			
		||||
                                             PikaContainer       *container,
 | 
			
		||||
                                             GType                contents_type,
 | 
			
		||||
                                             const gchar         *callback_name);
 | 
			
		||||
  gboolean       (* recent_list_add_file)   (Pika                *pika,
 | 
			
		||||
                                             GFile               *file,
 | 
			
		||||
@ -126,7 +127,7 @@ PikaDisplay  * pika_get_display_by_id      (Pika                *pika,
 | 
			
		||||
                                            gint                 ID);
 | 
			
		||||
gint           pika_get_display_id         (Pika                *pika,
 | 
			
		||||
                                            PikaDisplay         *display);
 | 
			
		||||
guint32        pika_get_display_window_id  (Pika                *pika,
 | 
			
		||||
GBytes       * pika_get_display_window_id  (Pika                *pika,
 | 
			
		||||
                                            PikaDisplay         *display);
 | 
			
		||||
PikaDisplay  * pika_create_display         (Pika                *pika,
 | 
			
		||||
                                            PikaImage           *image,
 | 
			
		||||
@ -175,19 +176,21 @@ GFile        * pika_get_icon_theme_dir     (Pika                *pika);
 | 
			
		||||
gboolean       pika_pdb_dialog_new         (Pika                *pika,
 | 
			
		||||
                                            PikaContext         *context,
 | 
			
		||||
                                            PikaProgress        *progress,
 | 
			
		||||
                                            PikaContainer       *container,
 | 
			
		||||
                                            GType                contents_type,
 | 
			
		||||
                                            GBytes              *parent_handle,
 | 
			
		||||
                                            const gchar         *title,
 | 
			
		||||
                                            const gchar         *callback_name,
 | 
			
		||||
                                            const gchar         *object_name,
 | 
			
		||||
                                            PikaObject          *object,
 | 
			
		||||
                                            ...) G_GNUC_NULL_TERMINATED;
 | 
			
		||||
gboolean       pika_pdb_dialog_set         (Pika                *pika,
 | 
			
		||||
                                            PikaContainer       *container,
 | 
			
		||||
                                            GType                contents_type,
 | 
			
		||||
                                            const gchar         *callback_name,
 | 
			
		||||
                                            const gchar         *object_name,
 | 
			
		||||
                                            PikaObject          *object,
 | 
			
		||||
                                            ...) G_GNUC_NULL_TERMINATED;
 | 
			
		||||
gboolean       pika_pdb_dialog_close       (Pika                *pika,
 | 
			
		||||
                                            PikaContainer       *container,
 | 
			
		||||
                                            GType                contents_type,
 | 
			
		||||
                                            const gchar         *callback_name);
 | 
			
		||||
 | 
			
		||||
gboolean       pika_recent_list_add_file   (Pika                *pika,
 | 
			
		||||
                                            GFile               *file,
 | 
			
		||||
                                            const gchar         *mime_type);
 | 
			
		||||
 | 
			
		||||
@ -202,6 +202,7 @@ pika_container_class_init (PikaContainerClass *klass)
 | 
			
		||||
  klass->search                  = NULL;
 | 
			
		||||
  klass->get_unique_names        = NULL;
 | 
			
		||||
  klass->get_child_by_name       = NULL;
 | 
			
		||||
  klass->get_children_by_name    = NULL;
 | 
			
		||||
  klass->get_child_by_index      = NULL;
 | 
			
		||||
  klass->get_child_index         = NULL;
 | 
			
		||||
 | 
			
		||||
@ -885,6 +886,34 @@ pika_container_get_unique_names (PikaContainer *container)
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GList *
 | 
			
		||||
pika_container_get_children_by_name (PikaContainer *container,
 | 
			
		||||
                                     const gchar   *name)
 | 
			
		||||
{
 | 
			
		||||
  g_return_val_if_fail (PIKA_IS_CONTAINER (container), NULL);
 | 
			
		||||
 | 
			
		||||
  if (!name)
 | 
			
		||||
    return NULL;
 | 
			
		||||
 | 
			
		||||
  if (PIKA_CONTAINER_GET_CLASS (container)->get_children_by_name != NULL &&
 | 
			
		||||
      ! pika_container_get_unique_names (container))
 | 
			
		||||
    {
 | 
			
		||||
      return PIKA_CONTAINER_GET_CLASS (container)->get_children_by_name (container,
 | 
			
		||||
                                                                         name);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      PikaObject *child;
 | 
			
		||||
 | 
			
		||||
      child = PIKA_CONTAINER_GET_CLASS (container)->get_child_by_name (container, name);
 | 
			
		||||
 | 
			
		||||
      if (child != NULL)
 | 
			
		||||
        return g_list_prepend (NULL, child);
 | 
			
		||||
      else
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PikaObject *
 | 
			
		||||
pika_container_get_child_by_name (PikaContainer *container,
 | 
			
		||||
                                  const gchar   *name)
 | 
			
		||||
 | 
			
		||||
@ -79,6 +79,8 @@ struct _PikaContainerClass
 | 
			
		||||
  gboolean     (* get_unique_names)   (PikaContainer           *container);
 | 
			
		||||
  PikaObject * (* get_child_by_name)  (PikaContainer           *container,
 | 
			
		||||
                                       const gchar             *name);
 | 
			
		||||
  GList    * (* get_children_by_name) (PikaContainer           *container,
 | 
			
		||||
                                       const gchar             *name);
 | 
			
		||||
  PikaObject * (* get_child_by_index) (PikaContainer           *container,
 | 
			
		||||
                                       gint                     index);
 | 
			
		||||
  gint         (* get_child_index)    (PikaContainer           *container,
 | 
			
		||||
@ -121,6 +123,8 @@ PikaObject * pika_container_search             (PikaContainer           *contain
 | 
			
		||||
 | 
			
		||||
gboolean     pika_container_get_unique_names   (PikaContainer           *container);
 | 
			
		||||
 | 
			
		||||
GList    * pika_container_get_children_by_name (PikaContainer           *container,
 | 
			
		||||
                                                const gchar             *name);
 | 
			
		||||
PikaObject * pika_container_get_child_by_name  (PikaContainer           *container,
 | 
			
		||||
                                                const gchar             *name);
 | 
			
		||||
PikaObject * pika_container_get_child_by_index (PikaContainer           *container,
 | 
			
		||||
 | 
			
		||||
@ -34,6 +34,7 @@
 | 
			
		||||
#include "pika-memsize.h"
 | 
			
		||||
#include "pikadata.h"
 | 
			
		||||
#include "pikaidtable.h"
 | 
			
		||||
#include "pikaimage.h"
 | 
			
		||||
#include "pikatag.h"
 | 
			
		||||
#include "pikatagged.h"
 | 
			
		||||
 | 
			
		||||
@ -51,6 +52,7 @@ enum
 | 
			
		||||
  PROP_0,
 | 
			
		||||
  PROP_ID,
 | 
			
		||||
  PROP_FILE,
 | 
			
		||||
  PROP_IMAGE,
 | 
			
		||||
  PROP_WRITABLE,
 | 
			
		||||
  PROP_DELETABLE,
 | 
			
		||||
  PROP_MIME_TYPE
 | 
			
		||||
@ -59,8 +61,10 @@ enum
 | 
			
		||||
 | 
			
		||||
struct _PikaDataPrivate
 | 
			
		||||
{
 | 
			
		||||
  gint    ID;
 | 
			
		||||
  GFile  *file;
 | 
			
		||||
  gint       ID;
 | 
			
		||||
  GFile     *file;
 | 
			
		||||
  PikaImage *image;
 | 
			
		||||
 | 
			
		||||
  GQuark  mime_type;
 | 
			
		||||
  guint   writable  : 1;
 | 
			
		||||
  guint   deletable : 1;
 | 
			
		||||
@ -172,6 +176,11 @@ pika_data_class_init (PikaDataClass *klass)
 | 
			
		||||
                                                        G_TYPE_FILE,
 | 
			
		||||
                                                        PIKA_PARAM_READWRITE));
 | 
			
		||||
 | 
			
		||||
  g_object_class_install_property (object_class, PROP_IMAGE,
 | 
			
		||||
                                   g_param_spec_object ("image", NULL, NULL,
 | 
			
		||||
                                                        PIKA_TYPE_IMAGE,
 | 
			
		||||
                                                        PIKA_PARAM_READWRITE));
 | 
			
		||||
 | 
			
		||||
  g_object_class_install_property (object_class, PROP_WRITABLE,
 | 
			
		||||
                                   g_param_spec_boolean ("writable", NULL, NULL,
 | 
			
		||||
                                                         FALSE,
 | 
			
		||||
@ -268,6 +277,12 @@ pika_data_set_property (GObject      *object,
 | 
			
		||||
                          private->deletable);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case PROP_IMAGE:
 | 
			
		||||
      pika_data_set_image (data,
 | 
			
		||||
                           g_value_get_object (value),
 | 
			
		||||
                           private->writable,
 | 
			
		||||
                           private->deletable);
 | 
			
		||||
      break;
 | 
			
		||||
    case PROP_WRITABLE:
 | 
			
		||||
      private->writable = g_value_get_boolean (value);
 | 
			
		||||
      break;
 | 
			
		||||
@ -307,6 +322,10 @@ pika_data_get_property (GObject    *object,
 | 
			
		||||
      g_value_set_object (value, private->file);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case PROP_IMAGE:
 | 
			
		||||
      g_value_set_object (value, private->image);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case PROP_WRITABLE:
 | 
			
		||||
      g_value_set_boolean (value, private->writable);
 | 
			
		||||
      break;
 | 
			
		||||
@ -462,7 +481,7 @@ pika_data_get_identifier (PikaTagged *tagged)
 | 
			
		||||
  gchar           *identifier = NULL;
 | 
			
		||||
  gchar           *collection = NULL;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (private->internal || private->file != NULL, NULL);
 | 
			
		||||
  g_return_val_if_fail (private->internal || private->file != NULL || private->image != NULL, NULL);
 | 
			
		||||
 | 
			
		||||
  collection = pika_data_get_collection (data);
 | 
			
		||||
  /* The identifier is guaranteed to be unique because we use 2 directory
 | 
			
		||||
@ -503,7 +522,7 @@ pika_data_get_collection (PikaData *data)
 | 
			
		||||
  PikaDataPrivate *private    = PIKA_DATA_GET_PRIVATE (data);
 | 
			
		||||
  gchar           *collection = NULL;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (private->internal || private->file != NULL, NULL);
 | 
			
		||||
  g_return_val_if_fail (private->internal || private->file != NULL || private->image != NULL, NULL);
 | 
			
		||||
 | 
			
		||||
  if (private->file)
 | 
			
		||||
    {
 | 
			
		||||
@ -551,6 +570,10 @@ pika_data_get_collection (PikaData *data)
 | 
			
		||||
 | 
			
		||||
      g_free (path);
 | 
			
		||||
    }
 | 
			
		||||
  else if (private->image)
 | 
			
		||||
    {
 | 
			
		||||
      collection = g_strdup_printf ("[image-id-%d]", pika_image_get_id (private->image));
 | 
			
		||||
    }
 | 
			
		||||
  else if (private->internal)
 | 
			
		||||
    {
 | 
			
		||||
      collection = g_strdup (private->collection);
 | 
			
		||||
@ -603,7 +626,7 @@ pika_data_save (PikaData  *data,
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (private->writable == TRUE, FALSE);
 | 
			
		||||
 | 
			
		||||
  if (private->internal)
 | 
			
		||||
  if (private->internal || private->image != NULL)
 | 
			
		||||
    {
 | 
			
		||||
      private->dirty = FALSE;
 | 
			
		||||
      return TRUE;
 | 
			
		||||
@ -862,6 +885,8 @@ pika_data_set_file (PikaData *data,
 | 
			
		||||
  if (private->internal)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (private->image == NULL);
 | 
			
		||||
 | 
			
		||||
  g_set_object (&private->file, file);
 | 
			
		||||
 | 
			
		||||
  private->writable  = FALSE;
 | 
			
		||||
@ -937,6 +962,53 @@ pika_data_get_file (PikaData *data)
 | 
			
		||||
  return private->file;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * pika_data_set_image:
 | 
			
		||||
 * @data:     A #PikaData object
 | 
			
		||||
 * @image:    Image to assign to @data.
 | 
			
		||||
 * @writable: %TRUE if we want to be able to write to this file.
 | 
			
		||||
 * @deletable: %TRUE if we want to be able to delete this file.
 | 
			
		||||
 *
 | 
			
		||||
 * This function assigns an image to @data. This can only be done if no file has
 | 
			
		||||
 * been assigned (a non-internal data can be attached either to a file or to an
 | 
			
		||||
 * image).
 | 
			
		||||
 **/
 | 
			
		||||
void
 | 
			
		||||
pika_data_set_image (PikaData  *data,
 | 
			
		||||
                     PikaImage *image,
 | 
			
		||||
                     gboolean   writable,
 | 
			
		||||
                     gboolean   deletable)
 | 
			
		||||
{
 | 
			
		||||
  PikaDataPrivate *private;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (PIKA_IS_DATA (data));
 | 
			
		||||
  g_return_if_fail (PIKA_IS_IMAGE (image));
 | 
			
		||||
 | 
			
		||||
  private = PIKA_DATA_GET_PRIVATE (data);
 | 
			
		||||
 | 
			
		||||
  if (private->internal)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (private->file == NULL);
 | 
			
		||||
 | 
			
		||||
  g_set_object (&private->image, image);
 | 
			
		||||
 | 
			
		||||
  private->writable  = writable  ? TRUE : FALSE;
 | 
			
		||||
  private->deletable = deletable ? TRUE : FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PikaImage *
 | 
			
		||||
pika_data_get_image (PikaData *data)
 | 
			
		||||
{
 | 
			
		||||
  PikaDataPrivate *private;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (PIKA_IS_DATA (data), NULL);
 | 
			
		||||
 | 
			
		||||
  private = PIKA_DATA_GET_PRIVATE (data);
 | 
			
		||||
 | 
			
		||||
  return private->image;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * pika_data_create_filename:
 | 
			
		||||
 * @data:     a #Pikadata object.
 | 
			
		||||
 | 
			
		||||
@ -102,6 +102,11 @@ void          pika_data_set_file         (PikaData     *data,
 | 
			
		||||
                                          gboolean      writable,
 | 
			
		||||
                                          gboolean      deletable);
 | 
			
		||||
GFile       * pika_data_get_file         (PikaData     *data);
 | 
			
		||||
void          pika_data_set_image        (PikaData     *data,
 | 
			
		||||
                                          PikaImage    *image,
 | 
			
		||||
                                          gboolean      writable,
 | 
			
		||||
                                          gboolean      deletable);
 | 
			
		||||
PikaImage   * pika_data_get_image        (PikaData     *data);
 | 
			
		||||
 | 
			
		||||
void          pika_data_create_filename  (PikaData     *data,
 | 
			
		||||
                                          GFile        *dest_dir);
 | 
			
		||||
 | 
			
		||||
@ -403,6 +403,9 @@ pika_data_factory_real_data_save (PikaDataFactory *factory)
 | 
			
		||||
      PikaData *data  = list->data;
 | 
			
		||||
      GError   *error = NULL;
 | 
			
		||||
 | 
			
		||||
      if (pika_data_get_image (data))
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      if (! pika_data_get_file (data))
 | 
			
		||||
        pika_data_create_filename (data, writable_dir);
 | 
			
		||||
 | 
			
		||||
@ -460,6 +463,7 @@ pika_data_factory_real_data_duplicate (PikaDataFactory *factory,
 | 
			
		||||
      gint         copy_len;
 | 
			
		||||
      gint         number;
 | 
			
		||||
      gchar       *new_name;
 | 
			
		||||
      GError      *error = NULL;
 | 
			
		||||
 | 
			
		||||
      ext      = strrchr (name, '#');
 | 
			
		||||
      copy_len = strlen (_("copy"));
 | 
			
		||||
@ -479,8 +483,12 @@ pika_data_factory_real_data_duplicate (PikaDataFactory *factory,
 | 
			
		||||
 | 
			
		||||
      pika_object_take_name (PIKA_OBJECT (new_data), new_name);
 | 
			
		||||
 | 
			
		||||
      if (! pika_data_factory_data_save_single (factory, new_data, &error))
 | 
			
		||||
        g_critical ("%s: data saving failed: %s", G_STRFUNC, error->message);
 | 
			
		||||
 | 
			
		||||
      pika_container_add (priv->container, PIKA_OBJECT (new_data));
 | 
			
		||||
      g_object_unref (new_data);
 | 
			
		||||
      g_clear_error (&error);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return new_data;
 | 
			
		||||
@ -674,8 +682,14 @@ pika_data_factory_data_new (PikaDataFactory *factory,
 | 
			
		||||
 | 
			
		||||
      if (data)
 | 
			
		||||
        {
 | 
			
		||||
          GError *error = NULL;
 | 
			
		||||
 | 
			
		||||
          if (! pika_data_factory_data_save_single (factory, data, &error))
 | 
			
		||||
            g_critical ("%s: data saving failed: %s", G_STRFUNC, error->message);
 | 
			
		||||
 | 
			
		||||
          pika_container_add (priv->container, PIKA_OBJECT (data));
 | 
			
		||||
          g_object_unref (data);
 | 
			
		||||
          g_clear_error (&error);
 | 
			
		||||
 | 
			
		||||
          return data;
 | 
			
		||||
        }
 | 
			
		||||
@ -750,7 +764,7 @@ pika_data_factory_data_save_single (PikaDataFactory  *factory,
 | 
			
		||||
  g_return_val_if_fail (PIKA_IS_DATA (data), FALSE);
 | 
			
		||||
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 | 
			
		||||
 | 
			
		||||
  if (! pika_data_is_dirty (data))
 | 
			
		||||
  if (! pika_data_is_dirty (data) || pika_data_get_image (data))
 | 
			
		||||
    return TRUE;
 | 
			
		||||
 | 
			
		||||
  if (! pika_data_get_file (data))
 | 
			
		||||
 | 
			
		||||
@ -31,25 +31,43 @@
 | 
			
		||||
 | 
			
		||||
#include "core-types.h"
 | 
			
		||||
 | 
			
		||||
#include "config/pikageglconfig.h"
 | 
			
		||||
 | 
			
		||||
#include "gegl/pika-babl.h"
 | 
			
		||||
#include "gegl/pika-gegl-loops.h"
 | 
			
		||||
 | 
			
		||||
#include "pika.h"
 | 
			
		||||
#include "pikacontainer.h"
 | 
			
		||||
#include "pikadatafactory.h"
 | 
			
		||||
#include "pikadrawable.h"
 | 
			
		||||
#include "pikaimage.h"
 | 
			
		||||
#include "pikaimage-colormap.h"
 | 
			
		||||
#include "pikaimage-private.h"
 | 
			
		||||
#include "pikaimage-undo.h"
 | 
			
		||||
#include "pikaimage-undo-push.h"
 | 
			
		||||
#include "pikapalette.h"
 | 
			
		||||
 | 
			
		||||
#include "pika-intl.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
  GeglBuffer *buffer;
 | 
			
		||||
  const Babl *format;
 | 
			
		||||
 | 
			
		||||
  /* Shared by jobs. */
 | 
			
		||||
  gboolean   *found;
 | 
			
		||||
  GRWLock    *lock;
 | 
			
		||||
} IndexUsedJobData;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*  local function prototype  */
 | 
			
		||||
 | 
			
		||||
static void   pika_image_colormap_set_palette_entry (PikaImage     *image,
 | 
			
		||||
                                                     const PikaRGB *color,
 | 
			
		||||
                                                     gint           index);
 | 
			
		||||
static void   pika_image_colormap_set_palette_entry    (PikaImage        *image,
 | 
			
		||||
                                                        const PikaRGB    *color,
 | 
			
		||||
                                                        gint              index);
 | 
			
		||||
static void   pika_image_colormap_thread_is_index_used (IndexUsedJobData *data,
 | 
			
		||||
                                                        gint              index);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*  public functions  */
 | 
			
		||||
@ -80,7 +98,7 @@ pika_image_colormap_init (PikaImage *image)
 | 
			
		||||
 | 
			
		||||
  pika_palette_set_columns (private->palette, 16);
 | 
			
		||||
 | 
			
		||||
  pika_data_make_internal (PIKA_DATA (private->palette), palette_id);
 | 
			
		||||
  pika_data_set_image (PIKA_DATA (private->palette), image, TRUE, FALSE);
 | 
			
		||||
 | 
			
		||||
  palettes = pika_data_factory_get_container (image->pika->palette_factory);
 | 
			
		||||
 | 
			
		||||
@ -319,9 +337,8 @@ pika_image_set_colormap (PikaImage    *image,
 | 
			
		||||
      pika_image_colormap_set_palette_entry (image, &color, i);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  pika_data_thaw (PIKA_DATA (private->palette));
 | 
			
		||||
 | 
			
		||||
  pika_image_colormap_changed (image, -1);
 | 
			
		||||
  pika_data_thaw (PIKA_DATA (private->palette));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
@ -347,6 +364,45 @@ pika_image_unset_colormap (PikaImage *image,
 | 
			
		||||
  pika_image_colormap_changed (image, -1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
pika_image_colormap_is_index_used (PikaImage *image,
 | 
			
		||||
                                   gint       color_index)
 | 
			
		||||
{
 | 
			
		||||
  GList       *layers;
 | 
			
		||||
  GList       *iter;
 | 
			
		||||
  GThreadPool *pool;
 | 
			
		||||
  GRWLock      lock;
 | 
			
		||||
  gboolean     found = FALSE;
 | 
			
		||||
  gint         num_processors;
 | 
			
		||||
 | 
			
		||||
  g_rw_lock_init (&lock);
 | 
			
		||||
  num_processors = PIKA_GEGL_CONFIG (image->pika->config)->num_processors;
 | 
			
		||||
  layers         = pika_image_get_layer_list (image);
 | 
			
		||||
 | 
			
		||||
  pool = g_thread_pool_new_full ((GFunc) pika_image_colormap_thread_is_index_used,
 | 
			
		||||
                                 GINT_TO_POINTER (color_index),
 | 
			
		||||
                                 (GDestroyNotify) g_free,
 | 
			
		||||
                                 num_processors, TRUE, NULL);
 | 
			
		||||
  for (iter = layers; iter; iter = g_list_next (iter))
 | 
			
		||||
    {
 | 
			
		||||
      IndexUsedJobData *job_data;
 | 
			
		||||
 | 
			
		||||
      job_data = g_malloc (sizeof (IndexUsedJobData ));
 | 
			
		||||
      job_data->buffer = pika_drawable_get_buffer (iter->data);
 | 
			
		||||
      job_data->format = pika_drawable_get_format_without_alpha (iter->data);
 | 
			
		||||
      job_data->found  = &found;
 | 
			
		||||
      job_data->lock   = &lock;
 | 
			
		||||
 | 
			
		||||
      g_thread_pool_push (pool, job_data, NULL);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_thread_pool_free (pool, FALSE, TRUE);
 | 
			
		||||
  g_rw_lock_clear (&lock);
 | 
			
		||||
  g_list_free (layers);
 | 
			
		||||
 | 
			
		||||
  return found;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
pika_image_get_colormap_entry (PikaImage *image,
 | 
			
		||||
                               gint       color_index,
 | 
			
		||||
@ -420,6 +476,57 @@ pika_image_add_colormap_entry (PikaImage     *image,
 | 
			
		||||
  pika_image_colormap_changed (image, -1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
pika_image_delete_colormap_entry (PikaImage *image,
 | 
			
		||||
                                  gint       color_index,
 | 
			
		||||
                                  gboolean   push_undo)
 | 
			
		||||
{
 | 
			
		||||
  g_return_val_if_fail (PIKA_IS_IMAGE (image), FALSE);
 | 
			
		||||
 | 
			
		||||
  if (! pika_image_colormap_is_index_used (image, color_index))
 | 
			
		||||
    {
 | 
			
		||||
      PikaImagePrivate *private;
 | 
			
		||||
      PikaPaletteEntry *entry;
 | 
			
		||||
      GList            *layers;
 | 
			
		||||
      GList            *iter;
 | 
			
		||||
 | 
			
		||||
      if (push_undo)
 | 
			
		||||
        {
 | 
			
		||||
          pika_image_undo_group_start (image, PIKA_UNDO_GROUP_IMAGE_COLORMAP_REMAP,
 | 
			
		||||
                                       C_("undo-type", "Delete Colormap entry"));
 | 
			
		||||
 | 
			
		||||
          pika_image_undo_push_image_colormap (image, NULL);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      private = PIKA_IMAGE_GET_PRIVATE (image);
 | 
			
		||||
      layers  = pika_image_get_layer_list (image);
 | 
			
		||||
 | 
			
		||||
      for (iter = layers; iter; iter = g_list_next (iter))
 | 
			
		||||
        {
 | 
			
		||||
          if (push_undo)
 | 
			
		||||
            pika_image_undo_push_drawable_mod (image, NULL, iter->data, TRUE);
 | 
			
		||||
 | 
			
		||||
          pika_gegl_shift_index (pika_drawable_get_buffer (iter->data), NULL,
 | 
			
		||||
                                 pika_drawable_get_format (iter->data),
 | 
			
		||||
                                 color_index, -1);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      entry = pika_palette_get_entry (private->palette, color_index);
 | 
			
		||||
      pika_palette_delete_entry (private->palette, entry);
 | 
			
		||||
 | 
			
		||||
      g_list_free (layers);
 | 
			
		||||
 | 
			
		||||
      if (push_undo)
 | 
			
		||||
        pika_image_undo_group_end (image);
 | 
			
		||||
 | 
			
		||||
      pika_image_colormap_changed (image, -1);
 | 
			
		||||
 | 
			
		||||
      return TRUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*  private functions  */
 | 
			
		||||
 | 
			
		||||
@ -442,3 +549,22 @@ pika_image_colormap_set_palette_entry (PikaImage     *image,
 | 
			
		||||
 | 
			
		||||
  pika_palette_set_entry (private->palette, index, name, color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
pika_image_colormap_thread_is_index_used (IndexUsedJobData *data,
 | 
			
		||||
                                          gint              index)
 | 
			
		||||
{
 | 
			
		||||
  g_rw_lock_reader_lock (data->lock);
 | 
			
		||||
  if (*data->found)
 | 
			
		||||
    {
 | 
			
		||||
      g_rw_lock_reader_unlock (data->lock);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
  g_rw_lock_reader_unlock (data->lock);
 | 
			
		||||
  if (pika_gegl_is_index_used (data->buffer, NULL, data->format, index))
 | 
			
		||||
    {
 | 
			
		||||
      g_rw_lock_writer_lock (data->lock);
 | 
			
		||||
      *data->found = TRUE;
 | 
			
		||||
      g_rw_lock_writer_unlock (data->lock);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -49,6 +49,9 @@ void           pika_image_set_colormap             (PikaImage     *image,
 | 
			
		||||
void           pika_image_unset_colormap           (PikaImage     *image,
 | 
			
		||||
                                                    gboolean       push_undo);
 | 
			
		||||
 | 
			
		||||
gboolean       pika_image_colormap_is_index_used   (PikaImage     *image,
 | 
			
		||||
                                                    gint           color_index);
 | 
			
		||||
 | 
			
		||||
void           pika_image_get_colormap_entry       (PikaImage     *image,
 | 
			
		||||
                                                    gint           color_index,
 | 
			
		||||
                                                    PikaRGB       *color);
 | 
			
		||||
@ -59,6 +62,9 @@ void           pika_image_set_colormap_entry       (PikaImage     *image,
 | 
			
		||||
 | 
			
		||||
void           pika_image_add_colormap_entry       (PikaImage     *image,
 | 
			
		||||
                                                    const PikaRGB *color);
 | 
			
		||||
gboolean       pika_image_delete_colormap_entry    (PikaImage     *image,
 | 
			
		||||
                                                    gint           color_index,
 | 
			
		||||
                                                    gboolean       push_undo);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif /* __PIKA_IMAGE_COLORMAP_H__ */
 | 
			
		||||
 | 
			
		||||
@ -24,17 +24,22 @@
 | 
			
		||||
#include <cairo.h>
 | 
			
		||||
#include <gdk-pixbuf/gdk-pixbuf.h>
 | 
			
		||||
#include <gegl.h>
 | 
			
		||||
#include <gexiv2/gexiv2.h>
 | 
			
		||||
 | 
			
		||||
#include "libpikabase/pikabase.h"
 | 
			
		||||
#include "libpikacolor/pikacolor.h"
 | 
			
		||||
 | 
			
		||||
#include "core-types.h"
 | 
			
		||||
 | 
			
		||||
#include "pika.h"
 | 
			
		||||
#include "pikaimage.h"
 | 
			
		||||
#include "pikaimage-color-profile.h"
 | 
			
		||||
#include "pikaimage-metadata.h"
 | 
			
		||||
#include "pikaimage-private.h"
 | 
			
		||||
#include "pikaimage-rotate.h"
 | 
			
		||||
#include "pikaimage-undo.h"
 | 
			
		||||
#include "pikaimage-undo-push.h"
 | 
			
		||||
#include "pikalayer-new.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* public functions */
 | 
			
		||||
@ -186,3 +191,110 @@ pika_image_metadata_update_colorspace (PikaImage *image)
 | 
			
		||||
      pika_metadata_set_colorspace (metadata, space);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * pika_image_metadata_load_thumbnail:
 | 
			
		||||
 * @pika:              The #Pika object.
 | 
			
		||||
 * @file:              A #GFile image.
 | 
			
		||||
 * @full_image_width:  the width of the full image (not the thumbnail).
 | 
			
		||||
 * @full_image_height: the height of the full image (not the thumbnail).
 | 
			
		||||
 * @error:             Return location for error message
 | 
			
		||||
 *
 | 
			
		||||
 * Retrieves a thumbnail from metadata in @file if present.
 | 
			
		||||
 * It does not need to actually load the full image, only the metadata through
 | 
			
		||||
 * GExiv2, which makes it fast.
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: (transfer none) (nullable): a #PikaImage of the @file thumbnail.
 | 
			
		||||
 */
 | 
			
		||||
PikaImage *
 | 
			
		||||
pika_image_metadata_load_thumbnail (Pika        *pika,
 | 
			
		||||
                                    GFile       *file,
 | 
			
		||||
                                    gint        *full_image_width,
 | 
			
		||||
                                    gint        *full_image_height,
 | 
			
		||||
                                    const Babl **format,
 | 
			
		||||
                                    GError     **error)
 | 
			
		||||
{
 | 
			
		||||
  PikaMetadata *metadata;
 | 
			
		||||
  GInputStream *input_stream;
 | 
			
		||||
  GdkPixbuf    *pixbuf;
 | 
			
		||||
  guint8       *thumbnail_buffer;
 | 
			
		||||
  gint          thumbnail_size;
 | 
			
		||||
  PikaImage    *image = NULL;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (G_IS_FILE (file), NULL);
 | 
			
		||||
  g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 | 
			
		||||
 | 
			
		||||
  metadata = pika_metadata_load_from_file (file, error);
 | 
			
		||||
  if (! metadata)
 | 
			
		||||
    return NULL;
 | 
			
		||||
 | 
			
		||||
  if (! gexiv2_metadata_get_exif_thumbnail (GEXIV2_METADATA (metadata),
 | 
			
		||||
                                            &thumbnail_buffer,
 | 
			
		||||
                                            &thumbnail_size))
 | 
			
		||||
    {
 | 
			
		||||
      g_object_unref (metadata);
 | 
			
		||||
      return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  input_stream = g_memory_input_stream_new_from_data (thumbnail_buffer,
 | 
			
		||||
                                                      thumbnail_size,
 | 
			
		||||
                                                      (GDestroyNotify) g_free);
 | 
			
		||||
  pixbuf = gdk_pixbuf_new_from_stream (input_stream, NULL, error);
 | 
			
		||||
  g_object_unref (input_stream);
 | 
			
		||||
 | 
			
		||||
  if (pixbuf)
 | 
			
		||||
    {
 | 
			
		||||
      PikaLayer *layer;
 | 
			
		||||
 | 
			
		||||
      image = pika_image_new (pika,
 | 
			
		||||
                              gdk_pixbuf_get_width  (pixbuf),
 | 
			
		||||
                              gdk_pixbuf_get_height (pixbuf),
 | 
			
		||||
                              PIKA_RGB, PIKA_PRECISION_U8_NON_LINEAR);
 | 
			
		||||
      pika_image_undo_disable (image);
 | 
			
		||||
 | 
			
		||||
      /* XXX This is possibly wrong, because an image of a given color space may
 | 
			
		||||
       * have a thumbnail stored in a different colorspace. This is even more
 | 
			
		||||
       * true with PIKA which always exports RGB thumbnails (see code in
 | 
			
		||||
       * pika_image_metadata_save_filter()), even for say grayscale images.
 | 
			
		||||
       * Nevertheless other software may store thumbnail using the same
 | 
			
		||||
       * colorspace.
 | 
			
		||||
       */
 | 
			
		||||
      *format = pika_pixbuf_get_format (pixbuf);
 | 
			
		||||
      layer = pika_layer_new_from_pixbuf (pixbuf, image,
 | 
			
		||||
                                          pika_image_get_layer_format (image, FALSE),
 | 
			
		||||
                                          /* No need to localize; this image is short-lived. */
 | 
			
		||||
                                          "Background",
 | 
			
		||||
                                          PIKA_OPACITY_OPAQUE,
 | 
			
		||||
                                          pika_image_get_default_new_layer_mode (image));
 | 
			
		||||
      g_object_unref (pixbuf);
 | 
			
		||||
 | 
			
		||||
      pika_image_add_layer (image, layer, NULL, 0, FALSE);
 | 
			
		||||
 | 
			
		||||
      pika_image_apply_metadata_orientation (image, pika_get_user_context (pika), metadata, NULL);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  /* This is the unoriented dimensions. Should we switch when there is a 90 or
 | 
			
		||||
   * 270 degree rotation? We don't actually know if the metadata orientation is
 | 
			
		||||
   * correct.
 | 
			
		||||
   */
 | 
			
		||||
  *full_image_width  = gexiv2_metadata_get_pixel_width (GEXIV2_METADATA (metadata));
 | 
			
		||||
  *full_image_height = gexiv2_metadata_get_pixel_height (GEXIV2_METADATA (metadata));
 | 
			
		||||
 | 
			
		||||
  if (*full_image_width < 1 || *full_image_height < 1)
 | 
			
		||||
    {
 | 
			
		||||
      /* Dimensions stored in metadata might be less accurate, yet it's still
 | 
			
		||||
       * informational.
 | 
			
		||||
       */
 | 
			
		||||
      *full_image_width  = gexiv2_metadata_try_get_metadata_pixel_width (GEXIV2_METADATA (metadata), NULL);
 | 
			
		||||
      *full_image_height = gexiv2_metadata_try_get_metadata_pixel_width (GEXIV2_METADATA (metadata), NULL);
 | 
			
		||||
    }
 | 
			
		||||
  if (*full_image_width < 1 || *full_image_height < 1)
 | 
			
		||||
    {
 | 
			
		||||
      *full_image_width  = 0;
 | 
			
		||||
      *full_image_height = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_object_unref (metadata);
 | 
			
		||||
 | 
			
		||||
  return image;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -33,5 +33,12 @@ void           pika_image_metadata_update_bits_per_sample (PikaImage    *image);
 | 
			
		||||
void           pika_image_metadata_update_resolution      (PikaImage    *image);
 | 
			
		||||
void           pika_image_metadata_update_colorspace      (PikaImage    *image);
 | 
			
		||||
 | 
			
		||||
PikaImage    * pika_image_metadata_load_thumbnail         (Pika         *pika,
 | 
			
		||||
                                                           GFile        *file,
 | 
			
		||||
                                                           gint         *full_image_width,
 | 
			
		||||
                                                           gint         *full_image_height,
 | 
			
		||||
                                                           const Babl  **format,
 | 
			
		||||
                                                           GError      **error);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif /* __PIKA_IMAGE_METADATA_H__ */
 | 
			
		||||
 | 
			
		||||
@ -282,6 +282,17 @@ pika_image_import_rotation_metadata (PikaImage    *image,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
pika_image_apply_metadata_orientation (PikaImage         *image,
 | 
			
		||||
                                       PikaContext       *context,
 | 
			
		||||
                                       PikaMetadata      *metadata,
 | 
			
		||||
                                       PikaProgress      *progress)
 | 
			
		||||
{
 | 
			
		||||
  pika_image_metadata_rotate (image, context,
 | 
			
		||||
                              gexiv2_metadata_try_get_orientation (GEXIV2_METADATA (metadata), NULL),
 | 
			
		||||
                              progress);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Private Functions */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -23,14 +23,20 @@
 | 
			
		||||
#define __PIKA_IMAGE_ROTATE_H__
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void   pika_image_rotate                   (PikaImage        *image,
 | 
			
		||||
                                            PikaContext      *context,
 | 
			
		||||
                                            PikaRotationType  rotate_type,
 | 
			
		||||
                                            PikaProgress     *progress);
 | 
			
		||||
void   pika_image_rotate                     (PikaImage        *image,
 | 
			
		||||
                                              PikaContext      *context,
 | 
			
		||||
                                              PikaRotationType  rotate_type,
 | 
			
		||||
                                              PikaProgress     *progress);
 | 
			
		||||
 | 
			
		||||
void   pika_image_import_rotation_metadata   (PikaImage        *image,
 | 
			
		||||
                                              PikaContext      *context,
 | 
			
		||||
                                              PikaProgress     *progress,
 | 
			
		||||
                                              gboolean          interactive);
 | 
			
		||||
 | 
			
		||||
void   pika_image_apply_metadata_orientation (PikaImage         *image,
 | 
			
		||||
                                              PikaContext       *context,
 | 
			
		||||
                                              PikaMetadata      *metadata,
 | 
			
		||||
                                              PikaProgress      *progress);
 | 
			
		||||
 | 
			
		||||
void   pika_image_import_rotation_metadata (PikaImage        *image,
 | 
			
		||||
                                            PikaContext      *context,
 | 
			
		||||
                                            PikaProgress     *progress,
 | 
			
		||||
                                            gboolean          interactive);
 | 
			
		||||
 | 
			
		||||
#endif /* __PIKA_IMAGE_ROTATE_H__ */
 | 
			
		||||
 | 
			
		||||
@ -625,6 +625,9 @@ pika_image_undo_dirty_from_type (PikaUndoType undo_type)
 | 
			
		||||
    case PIKA_UNDO_GROUP_IMAGE_CONVERT:
 | 
			
		||||
      return PIKA_DIRTY_IMAGE | PIKA_DIRTY_DRAWABLE;
 | 
			
		||||
 | 
			
		||||
    case PIKA_UNDO_GROUP_IMAGE_COLORMAP_REMAP:
 | 
			
		||||
      return PIKA_DIRTY_IMAGE | PIKA_DIRTY_DRAWABLE;
 | 
			
		||||
 | 
			
		||||
    case PIKA_UNDO_GROUP_IMAGE_LAYERS_MERGE:
 | 
			
		||||
      return PIKA_DIRTY_IMAGE_STRUCTURE | PIKA_DIRTY_DRAWABLE;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -45,6 +45,7 @@
 | 
			
		||||
#include "pikacontainer.h"
 | 
			
		||||
#include "pikacontext.h"
 | 
			
		||||
#include "pikaimage.h"
 | 
			
		||||
#include "pikaimage-metadata.h"
 | 
			
		||||
#include "pikaimagefile.h"
 | 
			
		||||
#include "pikapickable.h"
 | 
			
		||||
#include "pikaprogress.h"
 | 
			
		||||
@ -486,19 +487,37 @@ pika_imagefile_create_thumbnail (PikaImagefile  *imagefile,
 | 
			
		||||
          if (error && *error)
 | 
			
		||||
            {
 | 
			
		||||
              g_printerr ("Info: Thumbnail load procedure failed: %s\n"
 | 
			
		||||
                          "      Falling back to file load procedure.\n",
 | 
			
		||||
                          "      Falling back to metadata or file load.\n",
 | 
			
		||||
                          (*error)->message);
 | 
			
		||||
              g_clear_error (error);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          image = file_open_image (private->pika, context, progress,
 | 
			
		||||
                                   private->file,
 | 
			
		||||
                                   FALSE, NULL, PIKA_RUN_NONINTERACTIVE,
 | 
			
		||||
                                   &status, &mime_type, error);
 | 
			
		||||
 | 
			
		||||
          image = pika_image_metadata_load_thumbnail (private->pika, private->file, &width, &height, &format, error);
 | 
			
		||||
          if (image)
 | 
			
		||||
            pika_thumbnail_set_info_from_image (private->thumbnail,
 | 
			
		||||
                                                mime_type, image);
 | 
			
		||||
            {
 | 
			
		||||
              pika_thumbnail_set_info (private->thumbnail,
 | 
			
		||||
                                       mime_type, width, height,
 | 
			
		||||
                                       format, 0);
 | 
			
		||||
            }
 | 
			
		||||
          else
 | 
			
		||||
            {
 | 
			
		||||
              if (error && *error)
 | 
			
		||||
                {
 | 
			
		||||
                  g_printerr ("Info: metadata load failed: %s\n"
 | 
			
		||||
                              "      Falling back to file load procedure.\n",
 | 
			
		||||
                              (*error)->message);
 | 
			
		||||
                  g_clear_error (error);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
              image = file_open_image (private->pika, context, progress,
 | 
			
		||||
                                       private->file,
 | 
			
		||||
                                       FALSE, NULL, PIKA_RUN_NONINTERACTIVE,
 | 
			
		||||
                                       &status, &mime_type, error);
 | 
			
		||||
 | 
			
		||||
              if (image)
 | 
			
		||||
                pika_thumbnail_set_info_from_image (private->thumbnail,
 | 
			
		||||
                                                    mime_type, image);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if (image)
 | 
			
		||||
 | 
			
		||||
@ -76,6 +76,8 @@ static PikaObject * pika_list_search             (PikaContainer           *conta
 | 
			
		||||
                                                  PikaContainerSearchFunc  func,
 | 
			
		||||
                                                  gpointer                 user_data);
 | 
			
		||||
static gboolean     pika_list_get_unique_names   (PikaContainer           *container);
 | 
			
		||||
static GList    * pika_list_get_children_by_name (PikaContainer           *container,
 | 
			
		||||
                                                  const gchar             *name);
 | 
			
		||||
static PikaObject * pika_list_get_child_by_name  (PikaContainer           *container,
 | 
			
		||||
                                                  const gchar             *name);
 | 
			
		||||
static PikaObject * pika_list_get_child_by_index (PikaContainer           *container,
 | 
			
		||||
@ -101,23 +103,24 @@ pika_list_class_init (PikaListClass *klass)
 | 
			
		||||
  PikaObjectClass    *pika_object_class = PIKA_OBJECT_CLASS (klass);
 | 
			
		||||
  PikaContainerClass *container_class   = PIKA_CONTAINER_CLASS (klass);
 | 
			
		||||
 | 
			
		||||
  object_class->finalize              = pika_list_finalize;
 | 
			
		||||
  object_class->set_property          = pika_list_set_property;
 | 
			
		||||
  object_class->get_property          = pika_list_get_property;
 | 
			
		||||
  object_class->finalize                = pika_list_finalize;
 | 
			
		||||
  object_class->set_property            = pika_list_set_property;
 | 
			
		||||
  object_class->get_property            = pika_list_get_property;
 | 
			
		||||
 | 
			
		||||
  pika_object_class->get_memsize      = pika_list_get_memsize;
 | 
			
		||||
  pika_object_class->get_memsize        = pika_list_get_memsize;
 | 
			
		||||
 | 
			
		||||
  container_class->add                = pika_list_add;
 | 
			
		||||
  container_class->remove             = pika_list_remove;
 | 
			
		||||
  container_class->reorder            = pika_list_reorder;
 | 
			
		||||
  container_class->clear              = pika_list_clear;
 | 
			
		||||
  container_class->have               = pika_list_have;
 | 
			
		||||
  container_class->foreach            = pika_list_foreach;
 | 
			
		||||
  container_class->search             = pika_list_search;
 | 
			
		||||
  container_class->get_unique_names   = pika_list_get_unique_names;
 | 
			
		||||
  container_class->get_child_by_name  = pika_list_get_child_by_name;
 | 
			
		||||
  container_class->get_child_by_index = pika_list_get_child_by_index;
 | 
			
		||||
  container_class->get_child_index    = pika_list_get_child_index;
 | 
			
		||||
  container_class->add                  = pika_list_add;
 | 
			
		||||
  container_class->remove               = pika_list_remove;
 | 
			
		||||
  container_class->reorder              = pika_list_reorder;
 | 
			
		||||
  container_class->clear                = pika_list_clear;
 | 
			
		||||
  container_class->have                 = pika_list_have;
 | 
			
		||||
  container_class->foreach              = pika_list_foreach;
 | 
			
		||||
  container_class->search               = pika_list_search;
 | 
			
		||||
  container_class->get_unique_names     = pika_list_get_unique_names;
 | 
			
		||||
  container_class->get_children_by_name = pika_list_get_children_by_name;
 | 
			
		||||
  container_class->get_child_by_name    = pika_list_get_child_by_name;
 | 
			
		||||
  container_class->get_child_by_index   = pika_list_get_child_by_index;
 | 
			
		||||
  container_class->get_child_index      = pika_list_get_child_index;
 | 
			
		||||
 | 
			
		||||
  g_object_class_install_property (object_class, PROP_UNIQUE_NAMES,
 | 
			
		||||
                                   g_param_spec_boolean ("unique-names",
 | 
			
		||||
@ -369,6 +372,29 @@ pika_list_get_unique_names (PikaContainer *container)
 | 
			
		||||
  return list->unique_names;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GList *
 | 
			
		||||
pika_list_get_children_by_name (PikaContainer *container,
 | 
			
		||||
                                const gchar   *name)
 | 
			
		||||
{
 | 
			
		||||
  PikaList *list     = PIKA_LIST (container);
 | 
			
		||||
  GList    *children = NULL;
 | 
			
		||||
  GList    *iter;
 | 
			
		||||
 | 
			
		||||
  for (iter = list->queue->head; iter; iter = g_list_next (iter))
 | 
			
		||||
    {
 | 
			
		||||
      PikaObject *object = iter->data;
 | 
			
		||||
 | 
			
		||||
      if (! strcmp (pika_object_get_name (object), name))
 | 
			
		||||
        {
 | 
			
		||||
          children = g_list_prepend (children, object);
 | 
			
		||||
          if (list->unique_names)
 | 
			
		||||
            return children;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return children;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static PikaObject *
 | 
			
		||||
pika_list_get_child_by_name (PikaContainer *container,
 | 
			
		||||
                             const gchar   *name)
 | 
			
		||||
 | 
			
		||||
@ -33,6 +33,8 @@
 | 
			
		||||
#include "core-types.h"
 | 
			
		||||
 | 
			
		||||
#include "pika-memsize.h"
 | 
			
		||||
#include "pikaimage.h"
 | 
			
		||||
#include "pikaimage-undo-push.h"
 | 
			
		||||
#include "pikapalette.h"
 | 
			
		||||
#include "pikapalette-load.h"
 | 
			
		||||
#include "pikapalette-save.h"
 | 
			
		||||
@ -44,6 +46,12 @@
 | 
			
		||||
 | 
			
		||||
#define RGB_EPSILON 1e-6
 | 
			
		||||
 | 
			
		||||
enum
 | 
			
		||||
{
 | 
			
		||||
  ENTRY_CHANGED,
 | 
			
		||||
  LAST_SIGNAL
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*  local function prototypes  */
 | 
			
		||||
 | 
			
		||||
@ -75,6 +83,8 @@ static gchar       * pika_palette_get_description   (PikaViewable         *viewa
 | 
			
		||||
static const gchar * pika_palette_get_extension     (PikaData             *data);
 | 
			
		||||
static void          pika_palette_copy              (PikaData             *data,
 | 
			
		||||
                                                     PikaData             *src_data);
 | 
			
		||||
static void          pika_palette_real_entry_changed (PikaPalette         *palette,
 | 
			
		||||
                                                      gint                 index);
 | 
			
		||||
 | 
			
		||||
static void          pika_palette_entry_free        (PikaPaletteEntry     *entry);
 | 
			
		||||
static gint64        pika_palette_entry_get_memsize (PikaPaletteEntry     *entry,
 | 
			
		||||
@ -88,6 +98,7 @@ G_DEFINE_TYPE_WITH_CODE (PikaPalette, pika_palette, PIKA_TYPE_DATA,
 | 
			
		||||
 | 
			
		||||
#define parent_class pika_palette_parent_class
 | 
			
		||||
 | 
			
		||||
static guint signals[LAST_SIGNAL] = { 0 };
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
pika_palette_class_init (PikaPaletteClass *klass)
 | 
			
		||||
@ -97,6 +108,14 @@ pika_palette_class_init (PikaPaletteClass *klass)
 | 
			
		||||
  PikaViewableClass *viewable_class    = PIKA_VIEWABLE_CLASS (klass);
 | 
			
		||||
  PikaDataClass     *data_class        = PIKA_DATA_CLASS (klass);
 | 
			
		||||
 | 
			
		||||
  signals[ENTRY_CHANGED] = g_signal_new ("entry-changed",
 | 
			
		||||
                                         G_TYPE_FROM_CLASS (klass),
 | 
			
		||||
                                         G_SIGNAL_RUN_FIRST,
 | 
			
		||||
                                         G_STRUCT_OFFSET (PikaPaletteClass, entry_changed),
 | 
			
		||||
                                         NULL, NULL, NULL,
 | 
			
		||||
                                         G_TYPE_NONE, 1,
 | 
			
		||||
                                         G_TYPE_INT);
 | 
			
		||||
 | 
			
		||||
  object_class->finalize            = pika_palette_finalize;
 | 
			
		||||
 | 
			
		||||
  pika_object_class->get_memsize    = pika_palette_get_memsize;
 | 
			
		||||
@ -110,6 +129,8 @@ pika_palette_class_init (PikaPaletteClass *klass)
 | 
			
		||||
  data_class->save                  = pika_palette_save;
 | 
			
		||||
  data_class->get_extension         = pika_palette_get_extension;
 | 
			
		||||
  data_class->copy                  = pika_palette_copy;
 | 
			
		||||
 | 
			
		||||
  klass->entry_changed              = pika_palette_real_entry_changed;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@ -344,6 +365,16 @@ pika_palette_copy (PikaData *data,
 | 
			
		||||
  pika_data_thaw (data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
pika_palette_real_entry_changed (PikaPalette *palette,
 | 
			
		||||
                                 gint         index)
 | 
			
		||||
{
 | 
			
		||||
  PikaImage *image = pika_data_get_image (PIKA_DATA (palette));
 | 
			
		||||
 | 
			
		||||
  if (image != NULL)
 | 
			
		||||
    pika_image_colormap_changed (image, index);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gchar *
 | 
			
		||||
pika_palette_get_checksum (PikaTagged *tagged)
 | 
			
		||||
{
 | 
			
		||||
@ -406,11 +437,17 @@ pika_palette_move_entry (PikaPalette      *palette,
 | 
			
		||||
 | 
			
		||||
  if (g_list_find (palette->colors, entry))
 | 
			
		||||
    {
 | 
			
		||||
      gint old_position = g_list_index (palette->colors, entry);
 | 
			
		||||
 | 
			
		||||
      palette->colors = g_list_remove (palette->colors,
 | 
			
		||||
                                       entry);
 | 
			
		||||
      palette->colors = g_list_insert (palette->colors,
 | 
			
		||||
                                       entry, position);
 | 
			
		||||
 | 
			
		||||
      if (! pika_data_is_frozen (PIKA_DATA (palette)))
 | 
			
		||||
        for (gint i = MIN (position, old_position); i <= MAX (position, old_position); i++)
 | 
			
		||||
          g_signal_emit (palette, signals[ENTRY_CHANGED], 0, i);
 | 
			
		||||
 | 
			
		||||
      pika_data_dirty (PIKA_DATA (palette));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -442,6 +479,10 @@ pika_palette_add_entry (PikaPalette   *palette,
 | 
			
		||||
 | 
			
		||||
  palette->n_colors += 1;
 | 
			
		||||
 | 
			
		||||
  if (! pika_data_is_frozen (PIKA_DATA (palette)))
 | 
			
		||||
    for (gint i = position; i < palette->n_colors; i++)
 | 
			
		||||
      g_signal_emit (palette, signals[ENTRY_CHANGED], 0, i);
 | 
			
		||||
 | 
			
		||||
  pika_data_dirty (PIKA_DATA (palette));
 | 
			
		||||
 | 
			
		||||
  return entry;
 | 
			
		||||
@ -456,12 +497,18 @@ pika_palette_delete_entry (PikaPalette      *palette,
 | 
			
		||||
 | 
			
		||||
  if (g_list_find (palette->colors, entry))
 | 
			
		||||
    {
 | 
			
		||||
      gint old_position = g_list_index (palette->colors, entry);
 | 
			
		||||
 | 
			
		||||
      pika_palette_entry_free (entry);
 | 
			
		||||
 | 
			
		||||
      palette->colors = g_list_remove (palette->colors, entry);
 | 
			
		||||
 | 
			
		||||
      palette->n_colors--;
 | 
			
		||||
 | 
			
		||||
      if (! pika_data_is_frozen (PIKA_DATA (palette)))
 | 
			
		||||
        for (gint i = old_position; i < palette->n_colors; i++)
 | 
			
		||||
          g_signal_emit (palette, signals[ENTRY_CHANGED], 0, i);
 | 
			
		||||
 | 
			
		||||
      pika_data_dirty (PIKA_DATA (palette));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -489,6 +536,9 @@ pika_palette_set_entry (PikaPalette   *palette,
 | 
			
		||||
 | 
			
		||||
  entry->name = g_strdup (name);
 | 
			
		||||
 | 
			
		||||
  if (! pika_data_is_frozen (PIKA_DATA (palette)))
 | 
			
		||||
    g_signal_emit (palette, signals[ENTRY_CHANGED], 0, position);
 | 
			
		||||
 | 
			
		||||
  pika_data_dirty (PIKA_DATA (palette));
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
@ -497,7 +547,8 @@ pika_palette_set_entry (PikaPalette   *palette,
 | 
			
		||||
gboolean
 | 
			
		||||
pika_palette_set_entry_color (PikaPalette   *palette,
 | 
			
		||||
                              gint           position,
 | 
			
		||||
                              const PikaRGB *color)
 | 
			
		||||
                              const PikaRGB *color,
 | 
			
		||||
                              gboolean       push_undo_if_image)
 | 
			
		||||
{
 | 
			
		||||
  PikaPaletteEntry *entry;
 | 
			
		||||
 | 
			
		||||
@ -509,8 +560,15 @@ pika_palette_set_entry_color (PikaPalette   *palette,
 | 
			
		||||
  if (! entry)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  if (push_undo_if_image && pika_data_get_image (PIKA_DATA (palette)))
 | 
			
		||||
    pika_image_undo_push_image_colormap (pika_data_get_image (PIKA_DATA (palette)),
 | 
			
		||||
                                         C_("undo-type", "Change Colormap entry"));
 | 
			
		||||
 | 
			
		||||
  entry->color = *color;
 | 
			
		||||
 | 
			
		||||
  if (! pika_data_is_frozen (PIKA_DATA (palette)))
 | 
			
		||||
    g_signal_emit (palette, signals[ENTRY_CHANGED], 0, position);
 | 
			
		||||
 | 
			
		||||
  pika_data_dirty (PIKA_DATA (palette));
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
@ -535,6 +593,9 @@ pika_palette_set_entry_name (PikaPalette *palette,
 | 
			
		||||
 | 
			
		||||
  entry->name = g_strdup (name);
 | 
			
		||||
 | 
			
		||||
  if (! pika_data_is_frozen (PIKA_DATA (palette)))
 | 
			
		||||
    g_signal_emit (palette, signals[ENTRY_CHANGED], 0, position);
 | 
			
		||||
 | 
			
		||||
  pika_data_dirty (PIKA_DATA (palette));
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
 | 
			
		||||
@ -56,6 +56,9 @@ struct _PikaPalette
 | 
			
		||||
struct _PikaPaletteClass
 | 
			
		||||
{
 | 
			
		||||
  PikaDataClass  parent_class;
 | 
			
		||||
 | 
			
		||||
  void (* entry_changed) (PikaPalette *palette,
 | 
			
		||||
                          gint         index);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -85,7 +88,8 @@ gboolean           pika_palette_set_entry       (PikaPalette      *palette,
 | 
			
		||||
                                                 const PikaRGB    *color);
 | 
			
		||||
gboolean           pika_palette_set_entry_color (PikaPalette      *palette,
 | 
			
		||||
                                                 gint              position,
 | 
			
		||||
                                                 const PikaRGB    *color);
 | 
			
		||||
                                                 const PikaRGB    *color,
 | 
			
		||||
                                                 gboolean          push_undo_if_image);
 | 
			
		||||
gboolean           pika_palette_set_entry_name  (PikaPalette      *palette,
 | 
			
		||||
                                                 gint              position,
 | 
			
		||||
                                                 const gchar      *name);
 | 
			
		||||
 | 
			
		||||
@ -217,7 +217,7 @@ pika_palette_mru_add (PikaPaletteMru *mru,
 | 
			
		||||
          /*  Even though they are nearly the same color, let's make them
 | 
			
		||||
           *  exactly equal.
 | 
			
		||||
           */
 | 
			
		||||
          pika_palette_set_entry_color (palette, 0, color);
 | 
			
		||||
          pika_palette_set_entry_color (palette, 0, color, FALSE);
 | 
			
		||||
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -78,7 +78,7 @@ static void     pika_pdb_progress_progress_set_value     (PikaProgress *progress
 | 
			
		||||
                                                          gdouble       percentage);
 | 
			
		||||
static gdouble  pika_pdb_progress_progress_get_value     (PikaProgress *progress);
 | 
			
		||||
static void     pika_pdb_progress_progress_pulse         (PikaProgress *progress);
 | 
			
		||||
static guint32  pika_pdb_progress_progress_get_window_id (PikaProgress *progress);
 | 
			
		||||
static GBytes * pika_pdb_progress_progress_get_window_id (PikaProgress *progress);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static GObjectClass *parent_class = NULL;
 | 
			
		||||
@ -241,14 +241,13 @@ pika_pdb_progress_set_property (GObject      *object,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gdouble
 | 
			
		||||
pika_pdb_progress_run_callback (PikaPdbProgress     *progress,
 | 
			
		||||
                                PikaProgressCommand  command,
 | 
			
		||||
                                const gchar         *text,
 | 
			
		||||
                                gdouble              value)
 | 
			
		||||
static void
 | 
			
		||||
pika_pdb_progress_run_callback (PikaPdbProgress      *progress,
 | 
			
		||||
                                PikaProgressCommand   command,
 | 
			
		||||
                                const gchar          *text,
 | 
			
		||||
                                gdouble               value,
 | 
			
		||||
                                GBytes              **handle)
 | 
			
		||||
{
 | 
			
		||||
  gdouble retval = 0;
 | 
			
		||||
 | 
			
		||||
  if (progress->callback_name && ! progress->callback_busy)
 | 
			
		||||
    {
 | 
			
		||||
      PikaValueArray *return_vals;
 | 
			
		||||
@ -274,17 +273,16 @@ pika_pdb_progress_run_callback (PikaPdbProgress     *progress,
 | 
			
		||||
                        g_type_name (G_TYPE_FROM_INSTANCE (progress)));
 | 
			
		||||
        }
 | 
			
		||||
      else if (pika_value_array_length (return_vals) >= 2 &&
 | 
			
		||||
               G_VALUE_HOLDS_DOUBLE (pika_value_array_index (return_vals, 1)))
 | 
			
		||||
               handle != NULL                             &&
 | 
			
		||||
               G_VALUE_HOLDS_BOXED (pika_value_array_index (return_vals, 1)))
 | 
			
		||||
        {
 | 
			
		||||
          retval = g_value_get_double (pika_value_array_index (return_vals, 1));
 | 
			
		||||
          *handle = g_value_dup_boxed (pika_value_array_index (return_vals, 1));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      pika_value_array_unref (return_vals);
 | 
			
		||||
 | 
			
		||||
      progress->callback_busy = FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static PikaProgress *
 | 
			
		||||
@ -298,7 +296,7 @@ pika_pdb_progress_progress_start (PikaProgress *progress,
 | 
			
		||||
    {
 | 
			
		||||
      pika_pdb_progress_run_callback (pdb_progress,
 | 
			
		||||
                                      PIKA_PROGRESS_COMMAND_START,
 | 
			
		||||
                                      message, 0.0);
 | 
			
		||||
                                      message, 0.0, NULL);
 | 
			
		||||
 | 
			
		||||
      pdb_progress->active = TRUE;
 | 
			
		||||
      pdb_progress->value  = 0.0;
 | 
			
		||||
@ -318,7 +316,7 @@ pika_pdb_progress_progress_end (PikaProgress *progress)
 | 
			
		||||
    {
 | 
			
		||||
      pika_pdb_progress_run_callback (pdb_progress,
 | 
			
		||||
                                      PIKA_PROGRESS_COMMAND_END,
 | 
			
		||||
                                      NULL, 0.0);
 | 
			
		||||
                                      NULL, 0.0, NULL);
 | 
			
		||||
 | 
			
		||||
      pdb_progress->active = FALSE;
 | 
			
		||||
      pdb_progress->value  = 0.0;
 | 
			
		||||
@ -342,7 +340,7 @@ pika_pdb_progress_progress_set_text (PikaProgress *progress,
 | 
			
		||||
  if (pdb_progress->active)
 | 
			
		||||
    pika_pdb_progress_run_callback (pdb_progress,
 | 
			
		||||
                                    PIKA_PROGRESS_COMMAND_SET_TEXT,
 | 
			
		||||
                                    message, 0.0);
 | 
			
		||||
                                    message, 0.0, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@ -355,7 +353,7 @@ pika_pdb_progress_progress_set_value (PikaProgress *progress,
 | 
			
		||||
    {
 | 
			
		||||
      pika_pdb_progress_run_callback (pdb_progress,
 | 
			
		||||
                                      PIKA_PROGRESS_COMMAND_SET_VALUE,
 | 
			
		||||
                                      NULL, percentage);
 | 
			
		||||
                                      NULL, percentage, NULL);
 | 
			
		||||
      pdb_progress->value = percentage;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -377,18 +375,19 @@ pika_pdb_progress_progress_pulse (PikaProgress *progress)
 | 
			
		||||
  if (pdb_progress->active)
 | 
			
		||||
    pika_pdb_progress_run_callback (pdb_progress,
 | 
			
		||||
                                    PIKA_PROGRESS_COMMAND_PULSE,
 | 
			
		||||
                                    NULL, 0.0);
 | 
			
		||||
                                    NULL, 0.0, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static guint32
 | 
			
		||||
static GBytes *
 | 
			
		||||
pika_pdb_progress_progress_get_window_id (PikaProgress *progress)
 | 
			
		||||
{
 | 
			
		||||
  PikaPdbProgress *pdb_progress = PIKA_PDB_PROGRESS (progress);
 | 
			
		||||
  GBytes          *handle       = NULL;
 | 
			
		||||
 | 
			
		||||
  return (guint32)
 | 
			
		||||
    pika_pdb_progress_run_callback (pdb_progress,
 | 
			
		||||
                                    PIKA_PROGRESS_COMMAND_GET_WINDOW,
 | 
			
		||||
                                    NULL, 0.0);
 | 
			
		||||
  pika_pdb_progress_run_callback (pdb_progress,
 | 
			
		||||
                                  PIKA_PROGRESS_COMMAND_GET_WINDOW,
 | 
			
		||||
                                  NULL, 0.0, &handle);
 | 
			
		||||
  return handle;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PikaPdbProgress *
 | 
			
		||||
 | 
			
		||||
@ -209,7 +209,7 @@ pika_progress_pulse (PikaProgress *progress)
 | 
			
		||||
    progress_iface->pulse (progress);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
guint32
 | 
			
		||||
GBytes *
 | 
			
		||||
pika_progress_get_window_id (PikaProgress *progress)
 | 
			
		||||
{
 | 
			
		||||
  PikaProgressInterface *progress_iface;
 | 
			
		||||
@ -221,7 +221,7 @@ pika_progress_get_window_id (PikaProgress *progress)
 | 
			
		||||
  if (progress_iface->get_window_id)
 | 
			
		||||
    return progress_iface->get_window_id (progress);
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
 | 
			
		||||
@ -48,7 +48,7 @@ struct _PikaProgressInterface
 | 
			
		||||
  gdouble        (* get_value)     (PikaProgress        *progress);
 | 
			
		||||
  void           (* pulse)         (PikaProgress        *progress);
 | 
			
		||||
 | 
			
		||||
  guint32        (* get_window_id) (PikaProgress        *progress);
 | 
			
		||||
  GBytes       * (* get_window_id) (PikaProgress        *progress);
 | 
			
		||||
 | 
			
		||||
  gboolean       (* message)       (PikaProgress        *progress,
 | 
			
		||||
                                    Pika                *pika,
 | 
			
		||||
@ -78,7 +78,7 @@ void           pika_progress_set_value        (PikaProgress        *progress,
 | 
			
		||||
gdouble        pika_progress_get_value        (PikaProgress        *progress);
 | 
			
		||||
void           pika_progress_pulse            (PikaProgress        *progress);
 | 
			
		||||
 | 
			
		||||
guint32        pika_progress_get_window_id    (PikaProgress        *progress);
 | 
			
		||||
GBytes       * pika_progress_get_window_id    (PikaProgress        *progress);
 | 
			
		||||
 | 
			
		||||
gboolean       pika_progress_message          (PikaProgress        *progress,
 | 
			
		||||
                                               Pika                *pika,
 | 
			
		||||
 | 
			
		||||
@ -59,7 +59,7 @@ static void           pika_sub_progress_set_value     (PikaProgress        *prog
 | 
			
		||||
                                                       gdouble              percentage);
 | 
			
		||||
static gdouble        pika_sub_progress_get_value     (PikaProgress        *progress);
 | 
			
		||||
static void           pika_sub_progress_pulse         (PikaProgress        *progress);
 | 
			
		||||
static guint32        pika_sub_progress_get_window_id (PikaProgress        *progress);
 | 
			
		||||
static GBytes       * pika_sub_progress_get_window_id (PikaProgress        *progress);
 | 
			
		||||
static gboolean       pika_sub_progress_message       (PikaProgress        *progress,
 | 
			
		||||
                                                       Pika                *pika,
 | 
			
		||||
                                                       PikaMessageSeverity  severity,
 | 
			
		||||
@ -228,7 +228,7 @@ pika_sub_progress_pulse (PikaProgress *progress)
 | 
			
		||||
    pika_progress_pulse (sub->progress);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static guint32
 | 
			
		||||
static GBytes *
 | 
			
		||||
pika_sub_progress_get_window_id (PikaProgress *progress)
 | 
			
		||||
{
 | 
			
		||||
  PikaSubProgress *sub = PIKA_SUB_PROGRESS (progress);
 | 
			
		||||
@ -236,7 +236,7 @@ pika_sub_progress_get_window_id (PikaProgress *progress)
 | 
			
		||||
  if (sub->progress)
 | 
			
		||||
    return pika_progress_get_window_id (sub->progress);
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
 | 
			
		||||
@ -221,7 +221,7 @@ dialogs_about_get (PikaDialogFactory *factory,
 | 
			
		||||
                   PikaUIManager     *ui_manager,
 | 
			
		||||
                   gint               view_size)
 | 
			
		||||
{
 | 
			
		||||
  return about_dialog_create (context->pika->edit_config);
 | 
			
		||||
  return about_dialog_create (context->pika);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GtkWidget *
 | 
			
		||||
 | 
			
		||||
@ -151,6 +151,13 @@ quit_close_all_dialog_new (Pika     *pika,
 | 
			
		||||
  GClosure              *closure;
 | 
			
		||||
  gint                   rows;
 | 
			
		||||
  gint                   view_size;
 | 
			
		||||
  GdkRectangle           geometry;
 | 
			
		||||
  GdkMonitor            *monitor;
 | 
			
		||||
  gint                   max_rows;
 | 
			
		||||
  gint                   scale_factor;
 | 
			
		||||
  const gfloat           rows_per_height   = 32 / 1440.0f;
 | 
			
		||||
  const gint             greatest_max_rows = 36;
 | 
			
		||||
  const gint             least_max_rows    = 6;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (PIKA_IS_PIKA (pika), NULL);
 | 
			
		||||
 | 
			
		||||
@ -206,8 +213,28 @@ quit_close_all_dialog_new (Pika     *pika,
 | 
			
		||||
 | 
			
		||||
  private->box = PIKA_MESSAGE_DIALOG (private->dialog)->box;
 | 
			
		||||
 | 
			
		||||
  monitor      = pika_widget_get_monitor (private->dialog);
 | 
			
		||||
  scale_factor = gdk_monitor_get_scale_factor (monitor);
 | 
			
		||||
  gdk_monitor_get_geometry (monitor, &geometry);
 | 
			
		||||
 | 
			
		||||
  if (scale_factor > 1)
 | 
			
		||||
    {
 | 
			
		||||
      #ifdef GDK_WINDOWING_WIN32
 | 
			
		||||
        max_rows = (geometry.height * scale_factor * rows_per_height)
 | 
			
		||||
                      / (scale_factor + 1);
 | 
			
		||||
      #else
 | 
			
		||||
        max_rows = (geometry.height * rows_per_height) / (scale_factor + 1);
 | 
			
		||||
      #endif
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      max_rows = geometry.height * rows_per_height;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  max_rows = CLAMP (max_rows, least_max_rows, greatest_max_rows);
 | 
			
		||||
 | 
			
		||||
  view_size = pika->config->layer_preview_size;
 | 
			
		||||
  rows      = CLAMP (pika_container_get_n_children (private->images), 3, 6);
 | 
			
		||||
  rows      = CLAMP (pika_container_get_n_children (private->images), 3, max_rows);
 | 
			
		||||
 | 
			
		||||
  view = pika_container_tree_view_new (private->images, private->context,
 | 
			
		||||
                                       view_size, 1);
 | 
			
		||||
 | 
			
		||||
@ -110,7 +110,7 @@ static void     pika_display_progress_set_value     (PikaProgress        *progre
 | 
			
		||||
                                                     gdouble              percentage);
 | 
			
		||||
static gdouble  pika_display_progress_get_value     (PikaProgress        *progress);
 | 
			
		||||
static void     pika_display_progress_pulse         (PikaProgress        *progress);
 | 
			
		||||
static guint32  pika_display_progress_get_window_id (PikaProgress        *progress);
 | 
			
		||||
static GBytes * pika_display_progress_get_window_id (PikaProgress        *progress);
 | 
			
		||||
static gboolean pika_display_progress_message       (PikaProgress        *progress,
 | 
			
		||||
                                                     Pika                *pika,
 | 
			
		||||
                                                     PikaMessageSeverity  severity,
 | 
			
		||||
@ -323,7 +323,7 @@ pika_display_progress_pulse (PikaProgress *progress)
 | 
			
		||||
    pika_progress_pulse (PIKA_PROGRESS (display->priv->shell));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static guint32
 | 
			
		||||
static GBytes *
 | 
			
		||||
pika_display_progress_get_window_id (PikaProgress *progress)
 | 
			
		||||
{
 | 
			
		||||
  PikaDisplayImpl *display = PIKA_DISPLAY_IMPL (progress);
 | 
			
		||||
@ -331,7 +331,7 @@ pika_display_progress_get_window_id (PikaProgress *progress)
 | 
			
		||||
  if (display->priv->shell)
 | 
			
		||||
    return pika_progress_get_window_id (PIKA_PROGRESS (display->priv->shell));
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
 | 
			
		||||
@ -103,15 +103,16 @@ pika_display_shell_progress_pulse (PikaProgress *progress)
 | 
			
		||||
  pika_progress_pulse (PIKA_PROGRESS (statusbar));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static guint32
 | 
			
		||||
static GBytes *
 | 
			
		||||
pika_display_shell_progress_get_window_id (PikaProgress *progress)
 | 
			
		||||
{
 | 
			
		||||
  GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (progress));
 | 
			
		||||
  PikaDisplayShell *shell = PIKA_DISPLAY_SHELL (progress);
 | 
			
		||||
  GBytes           *handle   = NULL;
 | 
			
		||||
 | 
			
		||||
  if (GTK_IS_WINDOW (toplevel))
 | 
			
		||||
    return pika_window_get_native_id (GTK_WINDOW (toplevel));
 | 
			
		||||
  if (shell->window_handle)
 | 
			
		||||
    handle = g_bytes_ref (shell->window_handle);
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
  return handle;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
 | 
			
		||||
@ -27,6 +27,10 @@
 | 
			
		||||
#include <gegl.h>
 | 
			
		||||
#include <gtk/gtk.h>
 | 
			
		||||
 | 
			
		||||
#ifdef GDK_WINDOWING_WAYLAND
 | 
			
		||||
#include <gdk/gdkwayland.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "libpikabase/pikabase.h"
 | 
			
		||||
#include "libpikamath/pikamath.h"
 | 
			
		||||
#include "libpikacolor/pikacolor.h"
 | 
			
		||||
@ -587,6 +591,8 @@ pika_display_shell_constructed (GObject *object)
 | 
			
		||||
                    G_CALLBACK (pika_display_shell_canvas_grab_notify),
 | 
			
		||||
                    shell);
 | 
			
		||||
 | 
			
		||||
  pika_widget_set_native_handle (GTK_WIDGET (shell), &shell->window_handle);
 | 
			
		||||
 | 
			
		||||
  g_signal_connect (shell->canvas, "realize",
 | 
			
		||||
                    G_CALLBACK (pika_display_shell_canvas_realize),
 | 
			
		||||
                    shell);
 | 
			
		||||
@ -851,6 +857,17 @@ pika_display_shell_dispose (GObject *object)
 | 
			
		||||
 | 
			
		||||
  shell->display = NULL;
 | 
			
		||||
 | 
			
		||||
  if (shell->window_handle != NULL)
 | 
			
		||||
    {
 | 
			
		||||
#ifdef GDK_WINDOWING_WAYLAND
 | 
			
		||||
      if (GDK_IS_WAYLAND_DISPLAY (gdk_display_get_default ()) &&
 | 
			
		||||
          /* The GdkWindow is likely already destroyed. */
 | 
			
		||||
          gtk_widget_get_window (GTK_WIDGET (shell)) != NULL)
 | 
			
		||||
        gdk_wayland_window_unexport_handle (gtk_widget_get_window (GTK_WIDGET (shell)));
 | 
			
		||||
#endif
 | 
			
		||||
      g_clear_pointer (&shell->window_handle, g_bytes_unref);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (parent_class)->dispose (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -55,6 +55,8 @@ struct _PikaDisplayShell
 | 
			
		||||
 | 
			
		||||
  PikaDisplay       *display;
 | 
			
		||||
 | 
			
		||||
  GBytes            *window_handle;
 | 
			
		||||
 | 
			
		||||
  PikaUIManager     *popup_manager;
 | 
			
		||||
  GdkMonitor        *initial_monitor;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1174,9 +1174,6 @@ pika_image_window_set_aux_info (PikaSessionManaged *session_managed,
 | 
			
		||||
  else if (StartupInfo.wShowWindow == SW_SHOWMINIMIZED   ||
 | 
			
		||||
           StartupInfo.wShowWindow == SW_SHOWMINNOACTIVE ||
 | 
			
		||||
           StartupInfo.wShowWindow == SW_MINIMIZE)
 | 
			
		||||
    /* XXX Iconification does not seem to work. I see the
 | 
			
		||||
     * window being iconified and immediately re-raised.
 | 
			
		||||
     * I leave this piece of code for later improvement. */
 | 
			
		||||
    gtk_window_iconify (GTK_WINDOW (session_managed));
 | 
			
		||||
  else
 | 
			
		||||
    /* Another show property not relevant to min/max.
 | 
			
		||||
 | 
			
		||||
@ -2026,8 +2026,10 @@ static void
 | 
			
		||||
pika_tool_rectangle_update_options (PikaToolRectangle *rectangle)
 | 
			
		||||
{
 | 
			
		||||
  PikaToolRectanglePrivate *private = rectangle->private;
 | 
			
		||||
  gdouble                   x1, y1;
 | 
			
		||||
  gdouble                   x2, y2;
 | 
			
		||||
  gdouble                   x1      = 0;
 | 
			
		||||
  gdouble                   y1      = 0;
 | 
			
		||||
  gdouble                   x2      = 0;
 | 
			
		||||
  gdouble                   y2      = 0;
 | 
			
		||||
 | 
			
		||||
  pika_tool_rectangle_get_public_rect (rectangle, &x1, &y1, &x2, &y2);
 | 
			
		||||
 | 
			
		||||
@ -2162,7 +2164,10 @@ static void
 | 
			
		||||
pika_tool_rectangle_update_status (PikaToolRectangle *rectangle)
 | 
			
		||||
{
 | 
			
		||||
  PikaToolRectanglePrivate *private = rectangle->private;
 | 
			
		||||
  gdouble                   x1, y1, x2, y2;
 | 
			
		||||
  gdouble                   x1      = 0;
 | 
			
		||||
  gdouble                   y1      = 0;
 | 
			
		||||
  gdouble                   x2      = 0;
 | 
			
		||||
  gdouble                   y2      = 0;
 | 
			
		||||
 | 
			
		||||
  pika_tool_rectangle_get_public_rect (rectangle, &x1, &y1, &x2, &y2);
 | 
			
		||||
 | 
			
		||||
@ -2436,7 +2441,10 @@ pika_tool_rectangle_coord_on_handle (PikaToolRectangle *rectangle,
 | 
			
		||||
{
 | 
			
		||||
  PikaToolRectanglePrivate *private = rectangle->private;
 | 
			
		||||
  PikaDisplayShell         *shell;
 | 
			
		||||
  gdouble                   x1, y1, x2, y2;
 | 
			
		||||
  gdouble                   x1 = 0;
 | 
			
		||||
  gdouble                   y1 = 0;
 | 
			
		||||
  gdouble                   x2 = 0;
 | 
			
		||||
  gdouble                   y2 = 0;
 | 
			
		||||
  gdouble                   rect_w, rect_h;
 | 
			
		||||
  gdouble                   handle_x          = 0;
 | 
			
		||||
  gdouble                   handle_y          = 0;
 | 
			
		||||
@ -2838,7 +2846,10 @@ pika_tool_rectangle_setup_snap_offsets (PikaToolRectangle *rectangle,
 | 
			
		||||
{
 | 
			
		||||
  PikaToolWidget           *widget  = PIKA_TOOL_WIDGET (rectangle);
 | 
			
		||||
  PikaToolRectanglePrivate *private = rectangle->private;
 | 
			
		||||
  gdouble                   x1, y1, x2, y2;
 | 
			
		||||
  gdouble                   x1      = 0;
 | 
			
		||||
  gdouble                   y1      = 0;
 | 
			
		||||
  gdouble                   x2      = 0;
 | 
			
		||||
  gdouble                   y2      = 0;
 | 
			
		||||
  gdouble                   coord_x, coord_y;
 | 
			
		||||
 | 
			
		||||
  pika_tool_rectangle_get_public_rect (rectangle, &x1, &y1, &x2, &y2);
 | 
			
		||||
@ -4185,7 +4196,10 @@ pika_tool_rectangle_point_in_rectangle (PikaToolRectangle *rectangle,
 | 
			
		||||
                                        gdouble            x,
 | 
			
		||||
                                        gdouble            y)
 | 
			
		||||
{
 | 
			
		||||
  gdouble  x1, y1, x2, y2;
 | 
			
		||||
  gdouble x1 = 0;
 | 
			
		||||
  gdouble y1 = 0;
 | 
			
		||||
  gdouble x2 = 0;
 | 
			
		||||
  gdouble y2 = 0;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (PIKA_IS_TOOL_RECTANGLE (rectangle), FALSE);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -35,11 +35,15 @@
 | 
			
		||||
#include "core/pikabrush.h"
 | 
			
		||||
#include "core/pikabrush-load.h"
 | 
			
		||||
#include "core/pikabrush-private.h"
 | 
			
		||||
#include "core/pikacontainer.h"
 | 
			
		||||
#include "core/pikadrawable.h"
 | 
			
		||||
#include "core/pikaimage.h"
 | 
			
		||||
#include "core/pikalayer-new.h"
 | 
			
		||||
#include "core/pikaimage-merge.h"
 | 
			
		||||
#include "core/pikaimage-new.h"
 | 
			
		||||
#include "core/pikaimage-resize.h"
 | 
			
		||||
#include "core/pikalayer-new.h"
 | 
			
		||||
#include "core/pikaparamspecs.h"
 | 
			
		||||
#include "core/pikapickable.h"
 | 
			
		||||
#include "core/pikatempbuf.h"
 | 
			
		||||
 | 
			
		||||
#include "pdb/pikaprocedure.h"
 | 
			
		||||
@ -51,12 +55,14 @@
 | 
			
		||||
 | 
			
		||||
/*  local function prototypes  */
 | 
			
		||||
 | 
			
		||||
static PikaImage * file_gbr_brush_to_image (Pika         *pika,
 | 
			
		||||
                                            PikaBrush    *brush);
 | 
			
		||||
static PikaBrush * file_gbr_image_to_brush (PikaImage    *image,
 | 
			
		||||
                                            PikaDrawable *drawable,
 | 
			
		||||
                                            const gchar  *name,
 | 
			
		||||
                                            gdouble       spacing);
 | 
			
		||||
static PikaImage * file_gbr_brush_to_image (Pika          *pika,
 | 
			
		||||
                                            PikaBrush     *brush);
 | 
			
		||||
static PikaBrush * file_gbr_image_to_brush (PikaImage     *image,
 | 
			
		||||
                                            PikaContext   *context,
 | 
			
		||||
                                            gint           n_drawables,
 | 
			
		||||
                                            PikaDrawable **drawables,
 | 
			
		||||
                                            const gchar   *name,
 | 
			
		||||
                                            gdouble        spacing);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*  public functions  */
 | 
			
		||||
@ -119,24 +125,26 @@ file_gbr_save_invoker (PikaProcedure         *procedure,
 | 
			
		||||
                       const PikaValueArray  *args,
 | 
			
		||||
                       GError               **error)
 | 
			
		||||
{
 | 
			
		||||
  PikaValueArray *return_vals;
 | 
			
		||||
  PikaImage      *image;
 | 
			
		||||
  PikaDrawable   *drawable;
 | 
			
		||||
  PikaBrush      *brush;
 | 
			
		||||
  const gchar    *name;
 | 
			
		||||
  GFile          *file;
 | 
			
		||||
  gint            spacing;
 | 
			
		||||
  gboolean        success;
 | 
			
		||||
  PikaValueArray  *return_vals;
 | 
			
		||||
  PikaImage       *image;
 | 
			
		||||
  PikaDrawable   **drawables;
 | 
			
		||||
  gint             n_drawables;
 | 
			
		||||
  PikaBrush       *brush;
 | 
			
		||||
  const gchar     *name;
 | 
			
		||||
  GFile           *file;
 | 
			
		||||
  gint             spacing;
 | 
			
		||||
  gboolean         success;
 | 
			
		||||
 | 
			
		||||
  pika_set_busy (pika);
 | 
			
		||||
 | 
			
		||||
  image    = g_value_get_object (pika_value_array_index (args, 1));
 | 
			
		||||
  drawable = g_value_get_object (pika_value_array_index (args, 2));
 | 
			
		||||
  file     = g_value_get_object (pika_value_array_index (args, 3));
 | 
			
		||||
  spacing  = g_value_get_int    (pika_value_array_index (args, 4));
 | 
			
		||||
  name     = g_value_get_string (pika_value_array_index (args, 5));
 | 
			
		||||
  image       = g_value_get_object (pika_value_array_index (args, 1));
 | 
			
		||||
  n_drawables = g_value_get_int (pika_value_array_index (args, 2));
 | 
			
		||||
  drawables   = (PikaDrawable **) pika_value_get_object_array (pika_value_array_index (args, 3));
 | 
			
		||||
  file        = g_value_get_object (pika_value_array_index (args, 4));
 | 
			
		||||
  spacing     = g_value_get_int    (pika_value_array_index (args, 5));
 | 
			
		||||
  name        = g_value_get_string (pika_value_array_index (args, 6));
 | 
			
		||||
 | 
			
		||||
  brush = file_gbr_image_to_brush (image, drawable, name, spacing);
 | 
			
		||||
  brush = file_gbr_image_to_brush (image, context, n_drawables, drawables, name, spacing);
 | 
			
		||||
 | 
			
		||||
  pika_data_set_file (PIKA_DATA (brush), file, TRUE, TRUE);
 | 
			
		||||
 | 
			
		||||
@ -417,15 +425,49 @@ file_gbr_brush_to_image (Pika      *pika,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static PikaBrush *
 | 
			
		||||
file_gbr_image_to_brush (PikaImage    *image,
 | 
			
		||||
                         PikaDrawable *drawable,
 | 
			
		||||
                         const gchar  *name,
 | 
			
		||||
                         gdouble       spacing)
 | 
			
		||||
file_gbr_image_to_brush (PikaImage     *image,
 | 
			
		||||
                         PikaContext   *context,
 | 
			
		||||
                         gint           n_drawables,
 | 
			
		||||
                         PikaDrawable **drawables,
 | 
			
		||||
                         const gchar   *name,
 | 
			
		||||
                         gdouble        spacing)
 | 
			
		||||
{
 | 
			
		||||
  gint width  = pika_item_get_width  (PIKA_ITEM (drawable));
 | 
			
		||||
  gint height = pika_item_get_height (PIKA_ITEM (drawable));
 | 
			
		||||
  PikaBrush    *brush;
 | 
			
		||||
  PikaImage    *subimage = NULL;
 | 
			
		||||
  PikaDrawable *drawable;
 | 
			
		||||
  gint          width;
 | 
			
		||||
  gint          height;
 | 
			
		||||
 | 
			
		||||
  return file_gbr_drawable_to_brush (drawable,
 | 
			
		||||
                                     GEGL_RECTANGLE (0, 0, width, height),
 | 
			
		||||
                                     name, spacing);
 | 
			
		||||
  g_return_val_if_fail (n_drawables > 0, NULL);
 | 
			
		||||
  g_return_val_if_fail (drawables != NULL, NULL);
 | 
			
		||||
 | 
			
		||||
  if (n_drawables > 1)
 | 
			
		||||
    {
 | 
			
		||||
      GList *drawable_list = NULL;
 | 
			
		||||
 | 
			
		||||
      for (gint i = 0; i < n_drawables; i++)
 | 
			
		||||
        drawable_list = g_list_prepend (drawable_list, drawables[i]);
 | 
			
		||||
 | 
			
		||||
      subimage = pika_image_new_from_drawables (image->pika, drawable_list, FALSE, FALSE);
 | 
			
		||||
      g_list_free (drawable_list);
 | 
			
		||||
      pika_container_remove (image->pika->images, PIKA_OBJECT (subimage));
 | 
			
		||||
      pika_image_resize_to_layers (subimage, context,
 | 
			
		||||
                                   NULL, NULL, NULL, NULL, NULL);
 | 
			
		||||
      drawable = PIKA_DRAWABLE (pika_image_merge_visible_layers (subimage, context, PIKA_CLIP_TO_IMAGE,
 | 
			
		||||
                                                                 FALSE, TRUE, NULL));
 | 
			
		||||
      pika_pickable_flush (PIKA_PICKABLE (subimage));
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      drawable = drawables[0];
 | 
			
		||||
    }
 | 
			
		||||
  width  = pika_item_get_width  (PIKA_ITEM (drawable));
 | 
			
		||||
  height = pika_item_get_height (PIKA_ITEM (drawable));
 | 
			
		||||
 | 
			
		||||
  brush = file_gbr_drawable_to_brush (drawable,
 | 
			
		||||
                                      GEGL_RECTANGLE (0, 0, width, height),
 | 
			
		||||
                                      name, spacing);
 | 
			
		||||
  g_clear_object (&subimage);
 | 
			
		||||
 | 
			
		||||
  return brush;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -260,6 +260,7 @@ file_pat_image_to_pattern (PikaImage     *image,
 | 
			
		||||
  gint         height;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (n_drawables > 0, NULL);
 | 
			
		||||
  g_return_val_if_fail (drawables != NULL, NULL);
 | 
			
		||||
 | 
			
		||||
  if (n_drawables > 1)
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
@ -87,7 +87,7 @@ file_data_init (Pika *pika)
 | 
			
		||||
                                         "1995-2019");
 | 
			
		||||
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               pika_param_spec_enum ("dummy-param",
 | 
			
		||||
                               pika_param_spec_enum ("run-mode",
 | 
			
		||||
                                                     "Dummy Param",
 | 
			
		||||
                                                     "Dummy parameter",
 | 
			
		||||
                                                     PIKA_TYPE_RUN_MODE,
 | 
			
		||||
@ -145,7 +145,7 @@ file_data_init (Pika *pika)
 | 
			
		||||
                                         "1995-2019");
 | 
			
		||||
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               pika_param_spec_enum ("dummy-param",
 | 
			
		||||
                               pika_param_spec_enum ("run-mode",
 | 
			
		||||
                                                     "Dummy Param",
 | 
			
		||||
                                                     "Dummy parameter",
 | 
			
		||||
                                                     PIKA_TYPE_RUN_MODE,
 | 
			
		||||
@ -158,12 +158,17 @@ file_data_init (Pika *pika)
 | 
			
		||||
                                                      FALSE,
 | 
			
		||||
                                                      PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               pika_param_spec_drawable ("drawable",
 | 
			
		||||
                                                         "Drawable",
 | 
			
		||||
                                                         "Active drawable "
 | 
			
		||||
                                                         "of input image",
 | 
			
		||||
                                                         FALSE,
 | 
			
		||||
                                                         PIKA_PARAM_READWRITE));
 | 
			
		||||
                               g_param_spec_int ("num-drawables",
 | 
			
		||||
                                                 "Num drawables",
 | 
			
		||||
                                                 "Number of drawables",
 | 
			
		||||
                                                 1, G_MAXINT, 1,
 | 
			
		||||
                                                 PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               pika_param_spec_object_array ("drawables",
 | 
			
		||||
                                                             "Drawables",
 | 
			
		||||
                                                             "Selected drawables",
 | 
			
		||||
                                                             PIKA_TYPE_DRAWABLE,
 | 
			
		||||
                                                             PIKA_PARAM_READWRITE | PIKA_PARAM_NO_VALIDATE));
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               g_param_spec_object ("file",
 | 
			
		||||
                                                    "File",
 | 
			
		||||
@ -219,7 +224,7 @@ file_data_init (Pika *pika)
 | 
			
		||||
                                         "1999-2019");
 | 
			
		||||
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               pika_param_spec_enum ("dummy-param",
 | 
			
		||||
                               pika_param_spec_enum ("run-mode",
 | 
			
		||||
                                                     "Dummy Param",
 | 
			
		||||
                                                     "Dummy parameter",
 | 
			
		||||
                                                     PIKA_TYPE_RUN_MODE,
 | 
			
		||||
@ -277,7 +282,7 @@ file_data_init (Pika *pika)
 | 
			
		||||
                                         "1999-2019");
 | 
			
		||||
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               pika_param_spec_enum ("dummy-param",
 | 
			
		||||
                               pika_param_spec_enum ("run-mode",
 | 
			
		||||
                                                     "Dummy Param",
 | 
			
		||||
                                                     "Dummy parameter",
 | 
			
		||||
                                                     PIKA_TYPE_RUN_MODE,
 | 
			
		||||
@ -363,7 +368,7 @@ file_data_init (Pika *pika)
 | 
			
		||||
                                         "1997-2019");
 | 
			
		||||
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               pika_param_spec_enum ("dummy-param",
 | 
			
		||||
                               pika_param_spec_enum ("run-mode",
 | 
			
		||||
                                                     "Dummy Param",
 | 
			
		||||
                                                     "Dummy parameter",
 | 
			
		||||
                                                     PIKA_TYPE_RUN_MODE,
 | 
			
		||||
@ -420,7 +425,7 @@ file_data_init (Pika *pika)
 | 
			
		||||
                                         "1995-2019");
 | 
			
		||||
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               pika_param_spec_enum ("dummy-param",
 | 
			
		||||
                               pika_param_spec_enum ("run-mode",
 | 
			
		||||
                                                     "Dummy Param",
 | 
			
		||||
                                                     "Dummy parameter",
 | 
			
		||||
                                                     PIKA_TYPE_RUN_MODE,
 | 
			
		||||
@ -433,7 +438,7 @@ file_data_init (Pika *pika)
 | 
			
		||||
                                                      FALSE,
 | 
			
		||||
                                                      PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               g_param_spec_int ("n-drawables",
 | 
			
		||||
                               g_param_spec_int ("num-drawables",
 | 
			
		||||
                                                 "Num drawables",
 | 
			
		||||
                                                 "Number of drawables",
 | 
			
		||||
                                                 1, G_MAXINT, 1,
 | 
			
		||||
@ -491,7 +496,7 @@ file_data_init (Pika *pika)
 | 
			
		||||
                                         "Jehan", "Jehan", "2019");
 | 
			
		||||
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               pika_param_spec_enum ("dummy-param",
 | 
			
		||||
                               pika_param_spec_enum ("run-mode",
 | 
			
		||||
                                                     "Dummy Param",
 | 
			
		||||
                                                     "Dummy parameter",
 | 
			
		||||
                                                     PIKA_TYPE_RUN_MODE,
 | 
			
		||||
 | 
			
		||||
@ -374,7 +374,7 @@ file_open_thumbnail (Pika           *pika,
 | 
			
		||||
        {
 | 
			
		||||
          image = g_value_get_object (pika_value_array_index (return_vals, 1));
 | 
			
		||||
 | 
			
		||||
          if (pika_value_array_length (return_vals) >= 3 &&
 | 
			
		||||
          if (pika_value_array_length (return_vals) >= 4 &&
 | 
			
		||||
              G_VALUE_HOLDS_INT (pika_value_array_index (return_vals, 2)) &&
 | 
			
		||||
              G_VALUE_HOLDS_INT (pika_value_array_index (return_vals, 3)))
 | 
			
		||||
            {
 | 
			
		||||
@ -385,11 +385,11 @@ file_open_thumbnail (Pika           *pika,
 | 
			
		||||
                MAX (0, g_value_get_int (pika_value_array_index (return_vals, 3)));
 | 
			
		||||
 | 
			
		||||
              if (pika_value_array_length (return_vals) >= 5 &&
 | 
			
		||||
                  G_VALUE_HOLDS_INT (pika_value_array_index (return_vals, 4)))
 | 
			
		||||
                  G_VALUE_HOLDS_ENUM (pika_value_array_index (return_vals, 4)))
 | 
			
		||||
                {
 | 
			
		||||
                  gint value = g_value_get_int (pika_value_array_index (return_vals, 4));
 | 
			
		||||
                  PikaImageType itype = g_value_get_enum (pika_value_array_index (return_vals, 4));
 | 
			
		||||
 | 
			
		||||
                  switch (value)
 | 
			
		||||
                  switch (itype)
 | 
			
		||||
                    {
 | 
			
		||||
                    case PIKA_RGB_IMAGE:
 | 
			
		||||
                      *format = pika_babl_format (PIKA_RGB,
 | 
			
		||||
@ -424,7 +424,7 @@ file_open_thumbnail (Pika           *pika,
 | 
			
		||||
                        babl_new_palette ("-pika-indexed-format-dummy",
 | 
			
		||||
                                          &rgb, &rgba);
 | 
			
		||||
 | 
			
		||||
                        if (value == PIKA_INDEXED_IMAGE)
 | 
			
		||||
                        if (itype == PIKA_INDEXED_IMAGE)
 | 
			
		||||
                          *format = rgb;
 | 
			
		||||
                        else
 | 
			
		||||
                          *format = rgba;
 | 
			
		||||
 | 
			
		||||
@ -918,6 +918,98 @@ pika_gegl_index_to_mask (GeglBuffer          *indexed_buffer,
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
pika_gegl_is_index_used (GeglBuffer          *indexed_buffer,
 | 
			
		||||
                         const GeglRectangle *indexed_rect,
 | 
			
		||||
                         const Babl          *indexed_format,
 | 
			
		||||
                         gint                 index)
 | 
			
		||||
{
 | 
			
		||||
  GeglBufferIterator *iter;
 | 
			
		||||
  gboolean            found = FALSE;
 | 
			
		||||
 | 
			
		||||
  if (! indexed_rect)
 | 
			
		||||
    indexed_rect = gegl_buffer_get_extent (indexed_buffer);
 | 
			
		||||
 | 
			
		||||
  iter = gegl_buffer_iterator_new (indexed_buffer, indexed_rect, 0,
 | 
			
		||||
                                   indexed_format,
 | 
			
		||||
                                   GEGL_ACCESS_READ, GEGL_ABYSS_NONE, 1);
 | 
			
		||||
 | 
			
		||||
  /* I initially had an implementation using gegl_parallel_distribute_area()
 | 
			
		||||
   * which turned out to be much slower than the simpler iteration on the whole
 | 
			
		||||
   * buffer at once. I think the cost of threading and using GRWLock is just far
 | 
			
		||||
   * too high for such very basic value check.
 | 
			
		||||
   * See gegl_parallel_distribute_area() implementation in commit dbaa8b6a1c.
 | 
			
		||||
   */
 | 
			
		||||
  while (gegl_buffer_iterator_next (iter))
 | 
			
		||||
    {
 | 
			
		||||
      const guchar *indexed = (const guchar *) iter->items[0].data;
 | 
			
		||||
      gint          count   = iter->length;
 | 
			
		||||
 | 
			
		||||
      while (count--)
 | 
			
		||||
        {
 | 
			
		||||
          if (*indexed == index)
 | 
			
		||||
            {
 | 
			
		||||
              /*
 | 
			
		||||
               * Position of one item using this color index:
 | 
			
		||||
               gint x = iter->items[0].roi.x + (iter->length - count - 1) % iter->items[0].roi.width;
 | 
			
		||||
               gint y = iter->items[0].roi.y + (gint) ((iter->length - count - 1) / iter->items[0].roi.width);
 | 
			
		||||
               */
 | 
			
		||||
              found = TRUE;
 | 
			
		||||
              break;
 | 
			
		||||
            }
 | 
			
		||||
          indexed++;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if (found)
 | 
			
		||||
        {
 | 
			
		||||
          gegl_buffer_iterator_stop (iter);
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return found;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
pika_gegl_shift_index (GeglBuffer          *indexed_buffer,
 | 
			
		||||
                       const GeglRectangle *indexed_rect,
 | 
			
		||||
                       const Babl          *indexed_format,
 | 
			
		||||
                       gint                 from_index,
 | 
			
		||||
                       gint                 shift)
 | 
			
		||||
{
 | 
			
		||||
  gboolean indexed_format_has_alpha;
 | 
			
		||||
 | 
			
		||||
  if (! indexed_rect)
 | 
			
		||||
    indexed_rect = gegl_buffer_get_extent (indexed_buffer);
 | 
			
		||||
 | 
			
		||||
  indexed_format_has_alpha = babl_format_has_alpha (indexed_format);
 | 
			
		||||
 | 
			
		||||
  gegl_parallel_distribute_area (
 | 
			
		||||
    indexed_rect, PIXELS_PER_THREAD,
 | 
			
		||||
    [=] (const GeglRectangle *indexed_area)
 | 
			
		||||
    {
 | 
			
		||||
      GeglBufferIterator *iter;
 | 
			
		||||
 | 
			
		||||
      iter = gegl_buffer_iterator_new (indexed_buffer, indexed_area, 0,
 | 
			
		||||
                                       indexed_format,
 | 
			
		||||
                                       GEGL_ACCESS_READWRITE, GEGL_ABYSS_NONE, 1);
 | 
			
		||||
 | 
			
		||||
      while (gegl_buffer_iterator_next (iter))
 | 
			
		||||
        {
 | 
			
		||||
          guchar *indexed = (guchar *) iter->items[0].data;
 | 
			
		||||
          gint    count   = iter->length;
 | 
			
		||||
 | 
			
		||||
          while (count--)
 | 
			
		||||
            {
 | 
			
		||||
              if (*indexed >= from_index)
 | 
			
		||||
                *indexed += shift;
 | 
			
		||||
 | 
			
		||||
              indexed += (indexed_format_has_alpha ? 2 : 1);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
pika_gegl_convert_color_profile_progress (PikaProgress *progress,
 | 
			
		||||
                                          gdouble       value)
 | 
			
		||||
 | 
			
		||||
@ -91,6 +91,15 @@ void   pika_gegl_index_to_mask         (GeglBuffer               *indexed_buffer
 | 
			
		||||
                                        GeglBuffer               *mask_buffer,
 | 
			
		||||
                                        const GeglRectangle      *mask_rect,
 | 
			
		||||
                                        gint                      index);
 | 
			
		||||
gboolean pika_gegl_is_index_used       (GeglBuffer               *indexed_buffer,
 | 
			
		||||
                                        const GeglRectangle      *indexed_rect,
 | 
			
		||||
                                        const Babl               *indexed_format,
 | 
			
		||||
                                        gint                      index);
 | 
			
		||||
void     pika_gegl_shift_index         (GeglBuffer               *indexed_buffer,
 | 
			
		||||
                                        const GeglRectangle      *indexed_rect,
 | 
			
		||||
                                        const Babl               *indexed_format,
 | 
			
		||||
                                        gint                      from_index,
 | 
			
		||||
                                        gint                      shift);
 | 
			
		||||
 | 
			
		||||
void   pika_gegl_convert_color_profile (GeglBuffer               *src_buffer,
 | 
			
		||||
                                        const GeglRectangle      *src_rect,
 | 
			
		||||
 | 
			
		||||
@ -287,10 +287,7 @@ progress_error_dialog (PikaProgress *progress)
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
          guint32 window_id = pika_progress_get_window_id (progress);
 | 
			
		||||
 | 
			
		||||
          if (window_id)
 | 
			
		||||
            pika_window_set_transient_for (GTK_WINDOW (dialog), window_id);
 | 
			
		||||
          pika_window_set_transient_for (GTK_WINDOW (dialog), progress);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -62,6 +62,8 @@
 | 
			
		||||
#include "core/pikacancelable.h"
 | 
			
		||||
#include "core/pikacontainer.h"
 | 
			
		||||
#include "core/pikacontext.h"
 | 
			
		||||
#include "core/pikadatafactory.h"
 | 
			
		||||
#include "core/pikadrawable.h"
 | 
			
		||||
#include "core/pikagradient.h"
 | 
			
		||||
#include "core/pikaimage.h"
 | 
			
		||||
#include "core/pikaimagefile.h"
 | 
			
		||||
@ -89,6 +91,7 @@
 | 
			
		||||
#include "widgets/pikamenufactory.h"
 | 
			
		||||
#include "widgets/pikapaletteselect.h"
 | 
			
		||||
#include "widgets/pikapatternselect.h"
 | 
			
		||||
#include "widgets/pikapickableselect.h"
 | 
			
		||||
#include "widgets/pikaprogressdialog.h"
 | 
			
		||||
#include "widgets/pikauimanager.h"
 | 
			
		||||
#include "widgets/pikawidgets-utils.h"
 | 
			
		||||
@ -136,7 +139,7 @@ static GFile        * gui_get_theme_dir          (Pika                *pika);
 | 
			
		||||
static GFile        * gui_get_icon_theme_dir     (Pika                *pika);
 | 
			
		||||
static PikaObject   * gui_get_window_strategy    (Pika                *pika);
 | 
			
		||||
static PikaDisplay  * gui_get_empty_display      (Pika                *pika);
 | 
			
		||||
static guint32        gui_display_get_window_id  (PikaDisplay         *display);
 | 
			
		||||
static GBytes       * gui_display_get_window_id  (PikaDisplay         *display);
 | 
			
		||||
static PikaDisplay  * gui_display_create         (Pika                *pika,
 | 
			
		||||
                                                  PikaImage           *image,
 | 
			
		||||
                                                  PikaUnit             unit,
 | 
			
		||||
@ -156,18 +159,19 @@ static void           gui_free_progress          (Pika                *pika,
 | 
			
		||||
static gboolean       gui_pdb_dialog_new         (Pika                *pika,
 | 
			
		||||
                                                  PikaContext         *context,
 | 
			
		||||
                                                  PikaProgress        *progress,
 | 
			
		||||
                                                  PikaContainer       *container,
 | 
			
		||||
                                                  GType                object_type,
 | 
			
		||||
                                                  GBytes              *parent_handle,
 | 
			
		||||
                                                  const gchar         *title,
 | 
			
		||||
                                                  const gchar         *callback_name,
 | 
			
		||||
                                                  const gchar         *object_name,
 | 
			
		||||
                                                  PikaObject          *object,
 | 
			
		||||
                                                  va_list              args);
 | 
			
		||||
static gboolean       gui_pdb_dialog_set         (Pika                *pika,
 | 
			
		||||
                                                  PikaContainer       *container,
 | 
			
		||||
                                                  GType                contents_type,
 | 
			
		||||
                                                  const gchar         *callback_name,
 | 
			
		||||
                                                  const gchar         *object_name,
 | 
			
		||||
                                                  PikaObject          *object,
 | 
			
		||||
                                                  va_list              args);
 | 
			
		||||
static gboolean       gui_pdb_dialog_close       (Pika                *pika,
 | 
			
		||||
                                                  PikaContainer       *container,
 | 
			
		||||
                                                  GType                contents_type,
 | 
			
		||||
                                                  const gchar         *callback_name);
 | 
			
		||||
static gboolean       gui_recent_list_add_file   (Pika                *pika,
 | 
			
		||||
                                                  GFile               *file,
 | 
			
		||||
@ -378,7 +382,7 @@ gui_get_empty_display (Pika *pika)
 | 
			
		||||
  return display;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static guint32
 | 
			
		||||
static GBytes *
 | 
			
		||||
gui_display_get_window_id (PikaDisplay *display)
 | 
			
		||||
{
 | 
			
		||||
  PikaDisplay      *disp  = PIKA_DISPLAY (display);
 | 
			
		||||
@ -386,13 +390,11 @@ gui_display_get_window_id (PikaDisplay *display)
 | 
			
		||||
 | 
			
		||||
  if (shell)
 | 
			
		||||
    {
 | 
			
		||||
      GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (shell));
 | 
			
		||||
 | 
			
		||||
      if (GTK_IS_WINDOW (toplevel))
 | 
			
		||||
        return pika_window_get_native_id (GTK_WINDOW (toplevel));
 | 
			
		||||
      if (shell)
 | 
			
		||||
        return g_bytes_ref (shell->window_handle);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static PikaDisplay *
 | 
			
		||||
@ -516,16 +518,16 @@ gui_wait (Pika         *pika,
 | 
			
		||||
  args = pika_procedure_get_arguments (procedure);
 | 
			
		||||
  pika_value_array_truncate (args, 5);
 | 
			
		||||
 | 
			
		||||
  g_value_set_enum   (pika_value_array_index (args, 0),
 | 
			
		||||
                      PIKA_RUN_INTERACTIVE);
 | 
			
		||||
  g_value_set_int    (pika_value_array_index (args, 1),
 | 
			
		||||
                      output_pipe[0]);
 | 
			
		||||
  g_value_set_int    (pika_value_array_index (args, 2),
 | 
			
		||||
                      input_pipe[1]);
 | 
			
		||||
  g_value_set_string (pika_value_array_index (args, 3),
 | 
			
		||||
                      message);
 | 
			
		||||
  g_value_set_int    (pika_value_array_index (args, 4),
 | 
			
		||||
                      PIKA_IS_CANCELABLE (waitable));
 | 
			
		||||
  g_value_set_enum    (pika_value_array_index (args, 0),
 | 
			
		||||
                       PIKA_RUN_INTERACTIVE);
 | 
			
		||||
  g_value_set_int     (pika_value_array_index (args, 1),
 | 
			
		||||
                       output_pipe[0]);
 | 
			
		||||
  g_value_set_int     (pika_value_array_index (args, 2),
 | 
			
		||||
                       input_pipe[1]);
 | 
			
		||||
  g_value_set_string  (pika_value_array_index (args, 3),
 | 
			
		||||
                       message);
 | 
			
		||||
  g_value_set_boolean (pika_value_array_index (args, 4),
 | 
			
		||||
                       PIKA_IS_CANCELABLE (waitable));
 | 
			
		||||
 | 
			
		||||
  pika_procedure_execute_async (procedure, pika,
 | 
			
		||||
                                pika_get_user_context (pika),
 | 
			
		||||
@ -616,65 +618,74 @@ static gboolean
 | 
			
		||||
gui_pdb_dialog_new (Pika          *pika,
 | 
			
		||||
                    PikaContext   *context,
 | 
			
		||||
                    PikaProgress  *progress,
 | 
			
		||||
                    PikaContainer *container,
 | 
			
		||||
                    GType          contents_type,
 | 
			
		||||
                    GBytes        *parent_handle,
 | 
			
		||||
                    const gchar   *title,
 | 
			
		||||
                    const gchar   *callback_name,
 | 
			
		||||
                    const gchar   *object_name,
 | 
			
		||||
                    PikaObject    *object,
 | 
			
		||||
                    va_list        args)
 | 
			
		||||
{
 | 
			
		||||
  GType        dialog_type = G_TYPE_NONE;
 | 
			
		||||
  const gchar *dialog_role = NULL;
 | 
			
		||||
  const gchar *help_id     = NULL;
 | 
			
		||||
 | 
			
		||||
  if (pika_container_get_children_type (container) == PIKA_TYPE_BRUSH)
 | 
			
		||||
  if (contents_type == PIKA_TYPE_BRUSH)
 | 
			
		||||
    {
 | 
			
		||||
      dialog_type = PIKA_TYPE_BRUSH_SELECT;
 | 
			
		||||
      dialog_role = "pika-brush-selection";
 | 
			
		||||
      help_id     = PIKA_HELP_BRUSH_DIALOG;
 | 
			
		||||
    }
 | 
			
		||||
  else if (pika_container_get_children_type (container) == PIKA_TYPE_FONT)
 | 
			
		||||
  else if (contents_type == PIKA_TYPE_FONT)
 | 
			
		||||
    {
 | 
			
		||||
      dialog_type = PIKA_TYPE_FONT_SELECT;
 | 
			
		||||
      dialog_role = "pika-font-selection";
 | 
			
		||||
      help_id     = PIKA_HELP_FONT_DIALOG;
 | 
			
		||||
    }
 | 
			
		||||
  else if (pika_container_get_children_type (container) == PIKA_TYPE_GRADIENT)
 | 
			
		||||
  else if (contents_type == PIKA_TYPE_GRADIENT)
 | 
			
		||||
    {
 | 
			
		||||
      dialog_type = PIKA_TYPE_GRADIENT_SELECT;
 | 
			
		||||
      dialog_role = "pika-gradient-selection";
 | 
			
		||||
      help_id     = PIKA_HELP_GRADIENT_DIALOG;
 | 
			
		||||
    }
 | 
			
		||||
  else if (pika_container_get_children_type (container) == PIKA_TYPE_PALETTE)
 | 
			
		||||
  else if (contents_type == PIKA_TYPE_PALETTE)
 | 
			
		||||
    {
 | 
			
		||||
      dialog_type = PIKA_TYPE_PALETTE_SELECT;
 | 
			
		||||
      dialog_role = "pika-palette-selection";
 | 
			
		||||
      help_id     = PIKA_HELP_PALETTE_DIALOG;
 | 
			
		||||
    }
 | 
			
		||||
  else if (pika_container_get_children_type (container) == PIKA_TYPE_PATTERN)
 | 
			
		||||
  else if (contents_type == PIKA_TYPE_PATTERN)
 | 
			
		||||
    {
 | 
			
		||||
      dialog_type = PIKA_TYPE_PATTERN_SELECT;
 | 
			
		||||
      dialog_role = "pika-pattern-selection";
 | 
			
		||||
      help_id     = PIKA_HELP_PATTERN_DIALOG;
 | 
			
		||||
    }
 | 
			
		||||
  else if (g_type_is_a (contents_type, PIKA_TYPE_DRAWABLE))
 | 
			
		||||
    {
 | 
			
		||||
      dialog_type = PIKA_TYPE_PICKABLE_SELECT;
 | 
			
		||||
      dialog_role = "pika-pickable-selection";
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      g_return_val_if_reached (FALSE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (dialog_type != G_TYPE_NONE)
 | 
			
		||||
    {
 | 
			
		||||
      PikaObject *object = NULL;
 | 
			
		||||
      if (! object && ! g_type_is_a (contents_type, PIKA_TYPE_DRAWABLE))
 | 
			
		||||
        object = pika_context_get_by_type (context, contents_type);
 | 
			
		||||
 | 
			
		||||
      if (object_name && strlen (object_name))
 | 
			
		||||
        object = pika_container_get_child_by_name (container, object_name);
 | 
			
		||||
 | 
			
		||||
      if (! object)
 | 
			
		||||
        object = pika_context_get_by_type (context,
 | 
			
		||||
                                           pika_container_get_children_type (container));
 | 
			
		||||
 | 
			
		||||
      if (object)
 | 
			
		||||
      if (object || g_type_is_a (contents_type, PIKA_TYPE_DRAWABLE))
 | 
			
		||||
        {
 | 
			
		||||
          gint        n_properties = 0;
 | 
			
		||||
          gchar     **names        = NULL;
 | 
			
		||||
          GValue     *values       = NULL;
 | 
			
		||||
          GtkWidget  *dialog;
 | 
			
		||||
          GtkWidget  *view;
 | 
			
		||||
          gboolean    use_header_bar;
 | 
			
		||||
 | 
			
		||||
          g_object_get (gtk_settings_get_default (),
 | 
			
		||||
                        "gtk-dialogs-use-header", &use_header_bar,
 | 
			
		||||
                        NULL);
 | 
			
		||||
 | 
			
		||||
          names = pika_properties_append (dialog_type,
 | 
			
		||||
                                          &n_properties, names, &values,
 | 
			
		||||
@ -684,10 +695,11 @@ gui_pdb_dialog_new (Pika          *pika,
 | 
			
		||||
                                          "help-id",        help_id,
 | 
			
		||||
                                          "pdb",            pika->pdb,
 | 
			
		||||
                                          "context",        context,
 | 
			
		||||
                                          "select-type",    pika_container_get_children_type (container),
 | 
			
		||||
                                          "select-type",    contents_type,
 | 
			
		||||
                                          "initial-object", object,
 | 
			
		||||
                                          "callback-name",  callback_name,
 | 
			
		||||
                                          "menu-factory",   menus_get_global_menu_factory (pika),
 | 
			
		||||
                                          "use-header-bar", use_header_bar,
 | 
			
		||||
                                          NULL);
 | 
			
		||||
 | 
			
		||||
          names = pika_properties_append_valist (dialog_type,
 | 
			
		||||
@ -707,27 +719,25 @@ gui_pdb_dialog_new (Pika          *pika,
 | 
			
		||||
            pika_docked_set_show_button_bar (PIKA_DOCKED (view), FALSE);
 | 
			
		||||
 | 
			
		||||
          if (progress)
 | 
			
		||||
            {
 | 
			
		||||
              guint32 window_id = pika_progress_get_window_id (progress);
 | 
			
		||||
 | 
			
		||||
              if (window_id)
 | 
			
		||||
                pika_window_set_transient_for (GTK_WINDOW (dialog), window_id);
 | 
			
		||||
            }
 | 
			
		||||
            pika_window_set_transient_for (GTK_WINDOW (dialog), progress);
 | 
			
		||||
 | 
			
		||||
          gtk_widget_show (dialog);
 | 
			
		||||
 | 
			
		||||
          /*  workaround for bug #360106  */
 | 
			
		||||
          {
 | 
			
		||||
            GSource  *source = g_timeout_source_new (100);
 | 
			
		||||
            GClosure *closure;
 | 
			
		||||
            {
 | 
			
		||||
              GSource  *source = g_timeout_source_new (100);
 | 
			
		||||
              GClosure *closure;
 | 
			
		||||
 | 
			
		||||
            closure = g_cclosure_new_object (G_CALLBACK (gui_pdb_dialog_present),
 | 
			
		||||
                                             G_OBJECT (dialog));
 | 
			
		||||
              closure = g_cclosure_new_object (G_CALLBACK (gui_pdb_dialog_present),
 | 
			
		||||
                                               G_OBJECT (dialog));
 | 
			
		||||
 | 
			
		||||
            g_source_set_closure (source, closure);
 | 
			
		||||
            g_source_attach (source, NULL);
 | 
			
		||||
            g_source_unref (source);
 | 
			
		||||
          }
 | 
			
		||||
              g_source_set_closure (source, closure);
 | 
			
		||||
              g_source_attach (source, NULL);
 | 
			
		||||
              g_source_unref (source);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          if (parent_handle != NULL)
 | 
			
		||||
            pika_window_set_transient_for_handle (GTK_WINDOW (dialog), parent_handle);
 | 
			
		||||
 | 
			
		||||
          return TRUE;
 | 
			
		||||
        }
 | 
			
		||||
@ -738,73 +748,96 @@ gui_pdb_dialog_new (Pika          *pika,
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
gui_pdb_dialog_set (Pika          *pika,
 | 
			
		||||
                    PikaContainer *container,
 | 
			
		||||
                    GType          contents_type,
 | 
			
		||||
                    const gchar   *callback_name,
 | 
			
		||||
                    const gchar   *object_name,
 | 
			
		||||
                    PikaObject    *object,
 | 
			
		||||
                    va_list        args)
 | 
			
		||||
{
 | 
			
		||||
  PikaPdbDialogClass *klass = NULL;
 | 
			
		||||
  PikaPdbDialogClass *klass     = NULL;
 | 
			
		||||
  PikaContainer      *container = NULL;
 | 
			
		||||
  PikaPdbDialog      *dialog;
 | 
			
		||||
 | 
			
		||||
  if (pika_container_get_children_type (container) == PIKA_TYPE_BRUSH)
 | 
			
		||||
    klass = g_type_class_peek (PIKA_TYPE_BRUSH_SELECT);
 | 
			
		||||
  else if (pika_container_get_children_type (container) == PIKA_TYPE_FONT)
 | 
			
		||||
    klass = g_type_class_peek (PIKA_TYPE_FONT_SELECT);
 | 
			
		||||
  else if (pika_container_get_children_type (container) == PIKA_TYPE_GRADIENT)
 | 
			
		||||
    klass = g_type_class_peek (PIKA_TYPE_GRADIENT_SELECT);
 | 
			
		||||
  else if (pika_container_get_children_type (container) == PIKA_TYPE_PALETTE)
 | 
			
		||||
    klass = g_type_class_peek (PIKA_TYPE_PALETTE_SELECT);
 | 
			
		||||
  else if (pika_container_get_children_type (container) == PIKA_TYPE_PATTERN)
 | 
			
		||||
    klass = g_type_class_peek (PIKA_TYPE_PATTERN_SELECT);
 | 
			
		||||
 | 
			
		||||
  if (klass)
 | 
			
		||||
  if (contents_type == PIKA_TYPE_BRUSH)
 | 
			
		||||
    {
 | 
			
		||||
      PikaPdbDialog *dialog;
 | 
			
		||||
      klass = g_type_class_peek (PIKA_TYPE_BRUSH_SELECT);
 | 
			
		||||
      container = pika_data_factory_get_container (pika->brush_factory);
 | 
			
		||||
    }
 | 
			
		||||
  else if (contents_type == PIKA_TYPE_FONT)
 | 
			
		||||
    {
 | 
			
		||||
      klass = g_type_class_peek (PIKA_TYPE_FONT_SELECT);
 | 
			
		||||
      container = pika_data_factory_get_container (pika->font_factory);
 | 
			
		||||
    }
 | 
			
		||||
  else if (contents_type == PIKA_TYPE_GRADIENT)
 | 
			
		||||
    {
 | 
			
		||||
      klass = g_type_class_peek (PIKA_TYPE_GRADIENT_SELECT);
 | 
			
		||||
      container = pika_data_factory_get_container (pika->gradient_factory);
 | 
			
		||||
    }
 | 
			
		||||
  else if (contents_type == PIKA_TYPE_PALETTE)
 | 
			
		||||
    {
 | 
			
		||||
      klass = g_type_class_peek (PIKA_TYPE_PALETTE_SELECT);
 | 
			
		||||
      container = pika_data_factory_get_container (pika->palette_factory);
 | 
			
		||||
    }
 | 
			
		||||
  else if (contents_type == PIKA_TYPE_PATTERN)
 | 
			
		||||
    {
 | 
			
		||||
      klass = g_type_class_peek (PIKA_TYPE_PATTERN_SELECT);
 | 
			
		||||
      container = pika_data_factory_get_container (pika->pattern_factory);
 | 
			
		||||
    }
 | 
			
		||||
  else if (contents_type == PIKA_TYPE_DRAWABLE)
 | 
			
		||||
    {
 | 
			
		||||
      klass = g_type_class_peek (PIKA_TYPE_PICKABLE_SELECT);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
      dialog = pika_pdb_dialog_get_by_callback (klass, callback_name);
 | 
			
		||||
  g_return_val_if_fail (klass != NULL, FALSE);
 | 
			
		||||
 | 
			
		||||
      if (dialog && dialog->select_type == pika_container_get_children_type (container))
 | 
			
		||||
  dialog = pika_pdb_dialog_get_by_callback (klass, callback_name);
 | 
			
		||||
 | 
			
		||||
  if (dialog != NULL                       &&
 | 
			
		||||
      dialog->select_type == contents_type &&
 | 
			
		||||
      (container == NULL || pika_container_get_child_index (container, object) != -1))
 | 
			
		||||
    {
 | 
			
		||||
      const gchar *prop_name = va_arg (args, const gchar *);
 | 
			
		||||
 | 
			
		||||
      if (g_type_is_a (contents_type, PIKA_TYPE_RESOURCE))
 | 
			
		||||
        {
 | 
			
		||||
          PikaObject *object;
 | 
			
		||||
 | 
			
		||||
          object = pika_container_get_child_by_name (container, object_name);
 | 
			
		||||
 | 
			
		||||
          if (object)
 | 
			
		||||
            {
 | 
			
		||||
              const gchar *prop_name = va_arg (args, const gchar *);
 | 
			
		||||
 | 
			
		||||
              pika_context_set_by_type (dialog->context, dialog->select_type,
 | 
			
		||||
                                        object);
 | 
			
		||||
 | 
			
		||||
              if (prop_name)
 | 
			
		||||
                g_object_set_valist (G_OBJECT (dialog), prop_name, args);
 | 
			
		||||
 | 
			
		||||
              gtk_window_present (GTK_WINDOW (dialog));
 | 
			
		||||
 | 
			
		||||
              return TRUE;
 | 
			
		||||
            }
 | 
			
		||||
          g_return_val_if_fail (container != NULL, FALSE);
 | 
			
		||||
          pika_context_set_by_type (dialog->context, dialog->select_type, object);
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
          g_return_val_if_fail (klass->set_object != NULL, FALSE);
 | 
			
		||||
          klass->set_object (dialog, object);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if (prop_name)
 | 
			
		||||
        g_object_set_valist (G_OBJECT (dialog), prop_name, args);
 | 
			
		||||
 | 
			
		||||
      gtk_window_present (GTK_WINDOW (dialog));
 | 
			
		||||
 | 
			
		||||
      return TRUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
gui_pdb_dialog_close (Pika          *pika,
 | 
			
		||||
                      PikaContainer *container,
 | 
			
		||||
                      const gchar   *callback_name)
 | 
			
		||||
gui_pdb_dialog_close (Pika        *pika,
 | 
			
		||||
                      GType        contents_type,
 | 
			
		||||
                      const gchar *callback_name)
 | 
			
		||||
{
 | 
			
		||||
  PikaPdbDialogClass *klass = NULL;
 | 
			
		||||
 | 
			
		||||
  if (pika_container_get_children_type (container) == PIKA_TYPE_BRUSH)
 | 
			
		||||
  if (contents_type == PIKA_TYPE_BRUSH)
 | 
			
		||||
    klass = g_type_class_peek (PIKA_TYPE_BRUSH_SELECT);
 | 
			
		||||
  else if (pika_container_get_children_type (container) == PIKA_TYPE_FONT)
 | 
			
		||||
  else if (contents_type == PIKA_TYPE_FONT)
 | 
			
		||||
    klass = g_type_class_peek (PIKA_TYPE_FONT_SELECT);
 | 
			
		||||
  else if (pika_container_get_children_type (container) == PIKA_TYPE_GRADIENT)
 | 
			
		||||
  else if (contents_type == PIKA_TYPE_GRADIENT)
 | 
			
		||||
    klass = g_type_class_peek (PIKA_TYPE_GRADIENT_SELECT);
 | 
			
		||||
  else if (pika_container_get_children_type (container) == PIKA_TYPE_PALETTE)
 | 
			
		||||
  else if (contents_type == PIKA_TYPE_PALETTE)
 | 
			
		||||
    klass = g_type_class_peek (PIKA_TYPE_PALETTE_SELECT);
 | 
			
		||||
  else if (pika_container_get_children_type (container) == PIKA_TYPE_PATTERN)
 | 
			
		||||
  else if (contents_type == PIKA_TYPE_PATTERN)
 | 
			
		||||
    klass = g_type_class_peek (PIKA_TYPE_PATTERN_SELECT);
 | 
			
		||||
  else if (contents_type == PIKA_TYPE_DRAWABLE)
 | 
			
		||||
    klass = g_type_class_peek (PIKA_TYPE_PICKABLE_SELECT);
 | 
			
		||||
 | 
			
		||||
  if (klass)
 | 
			
		||||
    {
 | 
			
		||||
@ -812,7 +845,7 @@ gui_pdb_dialog_close (Pika          *pika,
 | 
			
		||||
 | 
			
		||||
      dialog = pika_pdb_dialog_get_by_callback (klass, callback_name);
 | 
			
		||||
 | 
			
		||||
      if (dialog && dialog->select_type == pika_container_get_children_type (container))
 | 
			
		||||
      if (dialog && dialog->select_type == contents_type)
 | 
			
		||||
        {
 | 
			
		||||
          gtk_widget_destroy (GTK_WIDGET (dialog));
 | 
			
		||||
          return TRUE;
 | 
			
		||||
 | 
			
		||||
@ -90,6 +90,12 @@
 | 
			
		||||
#include "splash.h"
 | 
			
		||||
#include "themes.h"
 | 
			
		||||
 | 
			
		||||
#ifdef G_OS_WIN32
 | 
			
		||||
#include <windef.h>
 | 
			
		||||
#include <winbase.h>
 | 
			
		||||
#include <windows.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef GDK_WINDOWING_QUARTZ
 | 
			
		||||
#import <AppKit/AppKit.h>
 | 
			
		||||
 | 
			
		||||
@ -543,6 +549,11 @@ gui_restore_after_callback (Pika               *pika,
 | 
			
		||||
  PikaGuiConfig *gui_config = PIKA_GUI_CONFIG (pika->config);
 | 
			
		||||
  PikaUIManager *image_ui_manager;
 | 
			
		||||
  PikaDisplay   *display;
 | 
			
		||||
#ifdef G_OS_WIN32
 | 
			
		||||
  STARTUPINFO    StartupInfo;
 | 
			
		||||
 | 
			
		||||
  GetStartupInfo (&StartupInfo);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  if (pika->be_verbose)
 | 
			
		||||
    g_print ("INIT: %s\n", G_STRFUNC);
 | 
			
		||||
@ -610,11 +621,23 @@ gui_restore_after_callback (Pika               *pika,
 | 
			
		||||
 | 
			
		||||
      shell = pika_display_get_shell (display);
 | 
			
		||||
 | 
			
		||||
#ifdef G_OS_WIN32
 | 
			
		||||
      themes_set_title_bar (pika);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
      if (gui_config->restore_session)
 | 
			
		||||
        session_restore (pika, initial_monitor);
 | 
			
		||||
 | 
			
		||||
      toplevel = gtk_widget_get_toplevel (GTK_WIDGET (shell));
 | 
			
		||||
 | 
			
		||||
#ifdef G_OS_WIN32
 | 
			
		||||
      /* Prevents window from reappearing on start-up if the user
 | 
			
		||||
       * requested it to be minimized via window hints
 | 
			
		||||
       */
 | 
			
		||||
      if (StartupInfo.wShowWindow != SW_SHOWMINIMIZED   &&
 | 
			
		||||
          StartupInfo.wShowWindow != SW_SHOWMINNOACTIVE &&
 | 
			
		||||
          StartupInfo.wShowWindow != SW_MINIMIZE)
 | 
			
		||||
#endif
 | 
			
		||||
      /*  move keyboard focus to the display  */
 | 
			
		||||
      gtk_window_present (GTK_WINDOW (toplevel));
 | 
			
		||||
    }
 | 
			
		||||
@ -925,12 +948,26 @@ gui_check_unique_accelerators (Pika *pika)
 | 
			
		||||
                      gchar   **disabled_accels;
 | 
			
		||||
                      gint      len;
 | 
			
		||||
                      gint      remove;
 | 
			
		||||
                      gboolean  print_warning = TRUE;
 | 
			
		||||
 | 
			
		||||
                      action = g_action_map_lookup_action (G_ACTION_MAP (pika->app),
 | 
			
		||||
                                                           actions[i]);
 | 
			
		||||
                      /* Just keep the first one (no reason other than we have
 | 
			
		||||
                       * to choose), unless it's a secondary shortcut, and the
 | 
			
		||||
                       * second is a primary shortcut.
 | 
			
		||||
                       */
 | 
			
		||||
                      if (l == 0 && j != 0)
 | 
			
		||||
                      if ((l == 0 && j != 0) ||
 | 
			
		||||
                          /* If the first action is one of "view-zoom-1-*" and
 | 
			
		||||
                           * the shortcut default, we assume it's because of our
 | 
			
		||||
                           * trick to transform `Shift+num` shortcuts based on
 | 
			
		||||
                           * layout and we happen to be on a layout where it
 | 
			
		||||
                           * clashes with other shortcuts. In this case, we
 | 
			
		||||
                           * drop the duplicate shortcut on the zoom action. See
 | 
			
		||||
                           * special code in
 | 
			
		||||
                           * pika_action_group_add_action_with_accel()
 | 
			
		||||
                           */
 | 
			
		||||
                          (g_str_has_prefix (actions[i], "view-zoom-1-") &&
 | 
			
		||||
                           pika_action_is_default_accel (PIKA_ACTION (action), accels[j])))
 | 
			
		||||
                        {
 | 
			
		||||
                          disabled_action = actions[i];
 | 
			
		||||
                          disabled_accels = accels;
 | 
			
		||||
@ -942,6 +979,20 @@ gui_check_unique_accelerators (Pika *pika)
 | 
			
		||||
                          disabled_accels = accels2;
 | 
			
		||||
                          remove = l;
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                      action = g_action_map_lookup_action (G_ACTION_MAP (pika->app),
 | 
			
		||||
                                                           disabled_action);
 | 
			
		||||
 | 
			
		||||
                      if (g_str_has_prefix (disabled_action, "view-zoom-1-") &&
 | 
			
		||||
                          pika_action_is_default_accel (PIKA_ACTION (action), disabled_accels[remove]))
 | 
			
		||||
                        /* We drop the shortcut **silently** because it will be
 | 
			
		||||
                         * a case where we have 2 default accelerators clashing
 | 
			
		||||
                         * (because of the conversion code) while not being a
 | 
			
		||||
                         * real bug. Clashes with custom accelerators are
 | 
			
		||||
                         * handled by shortcuts_action_deserialize().
 | 
			
		||||
                         */
 | 
			
		||||
                        print_warning = FALSE;
 | 
			
		||||
 | 
			
		||||
                      /* Remove only the duplicate shortcut but keep others. */
 | 
			
		||||
                      len = g_strv_length (disabled_accels);
 | 
			
		||||
                      g_free (disabled_accels[remove]);
 | 
			
		||||
@ -949,12 +1000,11 @@ gui_check_unique_accelerators (Pika *pika)
 | 
			
		||||
                               &disabled_accels[remove + 1],
 | 
			
		||||
                               sizeof (char *) * (len - remove));
 | 
			
		||||
 | 
			
		||||
                      g_printerr ("Actions \"%s\" and \"%s\" use the same accelerator.\n"
 | 
			
		||||
                                  "  Disabling the accelerator on \"%s\".\n",
 | 
			
		||||
                                  actions[i], actions[k], disabled_action);
 | 
			
		||||
                      if (print_warning)
 | 
			
		||||
                        g_printerr ("Actions \"%s\" and \"%s\" use the same accelerator.\n"
 | 
			
		||||
                                    "  Disabling the accelerator on \"%s\".\n",
 | 
			
		||||
                                    actions[i], actions[k], disabled_action);
 | 
			
		||||
 | 
			
		||||
                      action = g_action_map_lookup_action (G_ACTION_MAP (pika->app),
 | 
			
		||||
                                                           disabled_action);
 | 
			
		||||
                      pika_action_set_accels (PIKA_ACTION (action),
 | 
			
		||||
                                              (const gchar **) disabled_accels);
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
@ -29,6 +29,12 @@
 | 
			
		||||
#include <gdk/gdkwayland.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef G_OS_WIN32
 | 
			
		||||
#include <windef.h>
 | 
			
		||||
#include <winbase.h>
 | 
			
		||||
#include <windows.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "libpikabase/pikabase.h"
 | 
			
		||||
#include "libpikamath/pikamath.h"
 | 
			
		||||
#include "libpikacolor/pikacolor.h"
 | 
			
		||||
@ -125,6 +131,11 @@ splash_create (Pika         *pika,
 | 
			
		||||
  GdkRectangle        workarea;
 | 
			
		||||
  gint                max_width;
 | 
			
		||||
  gint                max_height;
 | 
			
		||||
#ifdef G_OS_WIN32
 | 
			
		||||
  STARTUPINFO         StartupInfo;
 | 
			
		||||
 | 
			
		||||
  GetStartupInfo (&StartupInfo);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (splash == NULL);
 | 
			
		||||
  g_return_if_fail (GDK_IS_MONITOR (monitor));
 | 
			
		||||
@ -255,6 +266,13 @@ splash_create (Pika         *pika,
 | 
			
		||||
 | 
			
		||||
  gtk_widget_show (splash->window);
 | 
			
		||||
 | 
			
		||||
#ifdef G_OS_WIN32
 | 
			
		||||
  if (StartupInfo.wShowWindow == SW_SHOWMINIMIZED   ||
 | 
			
		||||
      StartupInfo.wShowWindow == SW_SHOWMINNOACTIVE ||
 | 
			
		||||
      StartupInfo.wShowWindow == SW_MINIMIZE)
 | 
			
		||||
    gtk_window_iconify (GTK_WINDOW (splash->window));
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  if (FALSE)
 | 
			
		||||
    splash->timer = g_timer_new ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -35,6 +35,10 @@
 | 
			
		||||
 | 
			
		||||
#include "core/pika.h"
 | 
			
		||||
 | 
			
		||||
#include "display/pikaimagewindow.h"
 | 
			
		||||
 | 
			
		||||
#include "widgets/pikawidgets-utils.h"
 | 
			
		||||
 | 
			
		||||
#include "themes.h"
 | 
			
		||||
 | 
			
		||||
#include "pika-intl.h"
 | 
			
		||||
@ -109,6 +113,10 @@ themes_init (Pika *pika)
 | 
			
		||||
                    pika);
 | 
			
		||||
 | 
			
		||||
  themes_theme_change_notify (config, NULL, pika);
 | 
			
		||||
 | 
			
		||||
#ifdef G_OS_WIN32
 | 
			
		||||
  themes_set_title_bar (pika);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
@ -473,6 +481,10 @@ themes_theme_change_notify (PikaGuiConfig *config,
 | 
			
		||||
  g_object_unref (theme_css);
 | 
			
		||||
 | 
			
		||||
  gtk_style_context_reset_widgets (gdk_screen_get_default ());
 | 
			
		||||
 | 
			
		||||
#ifdef G_OS_WIN32
 | 
			
		||||
  themes_set_title_bar (pika);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@ -553,3 +565,22 @@ themes_theme_paths_notify (PikaExtensionManager *manager,
 | 
			
		||||
      g_list_free_full (path, (GDestroyNotify) g_object_unref);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
themes_set_title_bar (Pika *pika)
 | 
			
		||||
{
 | 
			
		||||
#ifdef G_OS_WIN32
 | 
			
		||||
  GList *windows = pika_get_image_windows (pika);
 | 
			
		||||
  GList *iter;
 | 
			
		||||
 | 
			
		||||
  for (iter = windows; iter; iter = g_list_next (iter))
 | 
			
		||||
    {
 | 
			
		||||
      GtkWidget *window = GTK_WIDGET (windows->data);
 | 
			
		||||
 | 
			
		||||
      pika_window_set_title_bar_theme (pika, window, TRUE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (windows)
 | 
			
		||||
    g_list_free (windows);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -34,5 +34,6 @@ GFile  * themes_get_theme_file (Pika        *pika,
 | 
			
		||||
                                const gchar *first_component,
 | 
			
		||||
                                ...) G_GNUC_NULL_TERMINATED;
 | 
			
		||||
 | 
			
		||||
void     themes_set_title_bar  (Pika        *pika);
 | 
			
		||||
 | 
			
		||||
#endif /* __THEMES_H__ */
 | 
			
		||||
 | 
			
		||||
@ -28,7 +28,6 @@
 | 
			
		||||
#include <gtk/gtk.h>
 | 
			
		||||
 | 
			
		||||
#include "libpikabase/pikabase.h"
 | 
			
		||||
#include "libpikabase/pikaprotocol.h"
 | 
			
		||||
#include "libpikaconfig/pikaconfig.h"
 | 
			
		||||
 | 
			
		||||
#include "menus-types.h"
 | 
			
		||||
@ -56,8 +55,7 @@ static GTokenType shortcuts_action_deserialize (GScanner       *scanner,
 | 
			
		||||
 | 
			
		||||
enum
 | 
			
		||||
{
 | 
			
		||||
  PROTOCOL_VERSION = 1,
 | 
			
		||||
  FILE_VERSION,
 | 
			
		||||
  FILE_VERSION = 1,
 | 
			
		||||
  ACTION,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -68,8 +66,7 @@ shortcuts_rc_parse (GtkApplication  *application,
 | 
			
		||||
                    GError         **error)
 | 
			
		||||
{
 | 
			
		||||
  GScanner   *scanner;
 | 
			
		||||
  gint        protocol_version = PIKA_PROTOCOL_VERSION;
 | 
			
		||||
  gint        file_version     = SHORTCUTS_RC_FILE_VERSION;
 | 
			
		||||
  gint        file_version = SHORTCUTS_RC_FILE_VERSION;
 | 
			
		||||
  GTokenType  token;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (GTK_IS_APPLICATION (application), FALSE);
 | 
			
		||||
@ -81,9 +78,6 @@ shortcuts_rc_parse (GtkApplication  *application,
 | 
			
		||||
  if (! scanner)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  g_scanner_scope_add_symbol (scanner, 0,
 | 
			
		||||
                              "protocol-version",
 | 
			
		||||
                              GINT_TO_POINTER (PROTOCOL_VERSION));
 | 
			
		||||
  g_scanner_scope_add_symbol (scanner, 0,
 | 
			
		||||
                              "file-version",
 | 
			
		||||
                              GINT_TO_POINTER (FILE_VERSION));
 | 
			
		||||
@ -92,9 +86,9 @@ shortcuts_rc_parse (GtkApplication  *application,
 | 
			
		||||
 | 
			
		||||
  token = G_TOKEN_LEFT_PAREN;
 | 
			
		||||
 | 
			
		||||
  while (protocol_version == PIKA_PROTOCOL_VERSION     &&
 | 
			
		||||
         file_version     == SHORTCUTS_RC_FILE_VERSION &&
 | 
			
		||||
         g_scanner_peek_next_token (scanner) == token)
 | 
			
		||||
  while (g_scanner_peek_next_token (scanner) == token ||
 | 
			
		||||
         (token == G_TOKEN_SYMBOL &&
 | 
			
		||||
          g_scanner_peek_next_token (scanner) == G_TOKEN_IDENTIFIER))
 | 
			
		||||
    {
 | 
			
		||||
      token = g_scanner_get_next_token (scanner);
 | 
			
		||||
 | 
			
		||||
@ -107,12 +101,6 @@ shortcuts_rc_parse (GtkApplication  *application,
 | 
			
		||||
        case G_TOKEN_SYMBOL:
 | 
			
		||||
          switch (GPOINTER_TO_INT (scanner->value.v_symbol))
 | 
			
		||||
            {
 | 
			
		||||
            case PROTOCOL_VERSION:
 | 
			
		||||
              token = G_TOKEN_INT;
 | 
			
		||||
              if (pika_scanner_parse_int (scanner, &protocol_version))
 | 
			
		||||
                token = G_TOKEN_RIGHT_PAREN;
 | 
			
		||||
              break;
 | 
			
		||||
 | 
			
		||||
            case FILE_VERSION:
 | 
			
		||||
              token = G_TOKEN_INT;
 | 
			
		||||
              if (pika_scanner_parse_int (scanner, &file_version))
 | 
			
		||||
@ -127,7 +115,17 @@ shortcuts_rc_parse (GtkApplication  *application,
 | 
			
		||||
            default:
 | 
			
		||||
              break;
 | 
			
		||||
            }
 | 
			
		||||
              break;
 | 
			
		||||
          break;
 | 
			
		||||
 | 
			
		||||
        case G_TOKEN_IDENTIFIER:
 | 
			
		||||
          g_printerr ("%s: ignoring unknown symbol '%s'.\n", G_STRFUNC, scanner->value.v_string);
 | 
			
		||||
          while ((token = g_scanner_get_next_token (scanner)) != G_TOKEN_EOF)
 | 
			
		||||
            {
 | 
			
		||||
              if (token == G_TOKEN_RIGHT_PAREN)
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
          token = G_TOKEN_LEFT_PAREN;
 | 
			
		||||
          break;
 | 
			
		||||
 | 
			
		||||
        case G_TOKEN_RIGHT_PAREN:
 | 
			
		||||
          token = G_TOKEN_LEFT_PAREN;
 | 
			
		||||
@ -138,25 +136,16 @@ shortcuts_rc_parse (GtkApplication  *application,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (protocol_version != PIKA_PROTOCOL_VERSION     ||
 | 
			
		||||
      file_version     != SHORTCUTS_RC_FILE_VERSION ||
 | 
			
		||||
      token            != G_TOKEN_LEFT_PAREN)
 | 
			
		||||
  if (file_version != SHORTCUTS_RC_FILE_VERSION)
 | 
			
		||||
    {
 | 
			
		||||
      if (protocol_version != PIKA_PROTOCOL_VERSION)
 | 
			
		||||
        {
 | 
			
		||||
          g_set_error (error,
 | 
			
		||||
                       PIKA_CONFIG_ERROR, PIKA_CONFIG_ERROR_VERSION,
 | 
			
		||||
                       _("Skipping '%s': wrong PIKA protocol version."),
 | 
			
		||||
                       pika_file_get_utf8_name (file));
 | 
			
		||||
        }
 | 
			
		||||
      else if (file_version != SHORTCUTS_RC_FILE_VERSION)
 | 
			
		||||
        {
 | 
			
		||||
          g_set_error (error,
 | 
			
		||||
                       PIKA_CONFIG_ERROR, PIKA_CONFIG_ERROR_VERSION,
 | 
			
		||||
                       _("Skipping '%s': wrong shortcutsrc file format version."),
 | 
			
		||||
                       pika_file_get_utf8_name (file));
 | 
			
		||||
        }
 | 
			
		||||
      else if (token != G_TOKEN_ERROR)
 | 
			
		||||
      g_printerr (_("Wrong shortcutsrc (%s) file format version: %d (expected: %d). "
 | 
			
		||||
                    "We tried to load shortcuts as well as possible.\n"),
 | 
			
		||||
                   pika_file_get_utf8_name (file),
 | 
			
		||||
                   file_version, SHORTCUTS_RC_FILE_VERSION);
 | 
			
		||||
    }
 | 
			
		||||
  if (token != G_TOKEN_LEFT_PAREN)
 | 
			
		||||
    {
 | 
			
		||||
      if (token != G_TOKEN_ERROR)
 | 
			
		||||
        {
 | 
			
		||||
          g_scanner_get_next_token (scanner);
 | 
			
		||||
          g_scanner_unexp_token (scanner, token, NULL, NULL, NULL,
 | 
			
		||||
@ -194,10 +183,6 @@ shortcuts_rc_write (GtkApplication  *application,
 | 
			
		||||
 | 
			
		||||
  actions = g_action_group_list_actions (G_ACTION_GROUP (application));
 | 
			
		||||
 | 
			
		||||
  pika_config_writer_open (writer, "protocol-version");
 | 
			
		||||
  pika_config_writer_printf (writer, "%d", PIKA_PROTOCOL_VERSION);
 | 
			
		||||
  pika_config_writer_close (writer);
 | 
			
		||||
 | 
			
		||||
  pika_config_writer_open (writer, "file-version");
 | 
			
		||||
  pika_config_writer_printf (writer, "%d", SHORTCUTS_RC_FILE_VERSION);
 | 
			
		||||
  pika_config_writer_close (writer);
 | 
			
		||||
 | 
			
		||||
@ -34,6 +34,8 @@
 | 
			
		||||
#include "pdb-types.h"
 | 
			
		||||
 | 
			
		||||
#include "core/pika.h"
 | 
			
		||||
#include "core/pikabrush.h"
 | 
			
		||||
#include "core/pikacontainer.h"
 | 
			
		||||
#include "core/pikadatafactory.h"
 | 
			
		||||
#include "core/pikaparamspecs.h"
 | 
			
		||||
 | 
			
		||||
@ -53,20 +55,24 @@ brushes_popup_invoker (PikaProcedure         *procedure,
 | 
			
		||||
  gboolean success = TRUE;
 | 
			
		||||
  const gchar *brush_callback;
 | 
			
		||||
  const gchar *popup_title;
 | 
			
		||||
  const gchar *initial_brush_name;
 | 
			
		||||
  PikaBrush *initial_brush;
 | 
			
		||||
  GBytes *parent_window;
 | 
			
		||||
 | 
			
		||||
  brush_callback = g_value_get_string (pika_value_array_index (args, 0));
 | 
			
		||||
  popup_title = g_value_get_string (pika_value_array_index (args, 1));
 | 
			
		||||
  initial_brush_name = g_value_get_string (pika_value_array_index (args, 2));
 | 
			
		||||
  initial_brush = g_value_get_object (pika_value_array_index (args, 2));
 | 
			
		||||
  parent_window = g_value_get_boxed (pika_value_array_index (args, 3));
 | 
			
		||||
 | 
			
		||||
  if (success)
 | 
			
		||||
    {
 | 
			
		||||
        if (pika->no_interface ||
 | 
			
		||||
      PikaContainer *container = pika_data_factory_get_container (pika->brush_factory);
 | 
			
		||||
 | 
			
		||||
      if (pika->no_interface ||
 | 
			
		||||
          ! pika_pdb_lookup_procedure (pika->pdb, brush_callback) ||
 | 
			
		||||
          ! pika_pdb_dialog_new (pika, context, progress,
 | 
			
		||||
                                 pika_data_factory_get_container (pika->brush_factory),
 | 
			
		||||
                                 popup_title, brush_callback, initial_brush_name,
 | 
			
		||||
                                 NULL))
 | 
			
		||||
                                 pika_container_get_children_type (container),
 | 
			
		||||
                                 parent_window, popup_title, brush_callback,
 | 
			
		||||
                                 PIKA_OBJECT (initial_brush), NULL))
 | 
			
		||||
        success = FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -89,9 +95,12 @@ brushes_close_popup_invoker (PikaProcedure         *procedure,
 | 
			
		||||
 | 
			
		||||
  if (success)
 | 
			
		||||
    {
 | 
			
		||||
      PikaContainer *container = pika_data_factory_get_container (pika->brush_factory);
 | 
			
		||||
 | 
			
		||||
      if (pika->no_interface ||
 | 
			
		||||
          ! pika_pdb_lookup_procedure (pika->pdb, brush_callback) ||
 | 
			
		||||
          ! pika_pdb_dialog_close (pika, pika_data_factory_get_container (pika->brush_factory),
 | 
			
		||||
          ! pika_pdb_dialog_close (pika,
 | 
			
		||||
                                   pika_container_get_children_type (container),
 | 
			
		||||
                                   brush_callback))
 | 
			
		||||
        success = FALSE;
 | 
			
		||||
    }
 | 
			
		||||
@ -110,18 +119,20 @@ brushes_set_popup_invoker (PikaProcedure         *procedure,
 | 
			
		||||
{
 | 
			
		||||
  gboolean success = TRUE;
 | 
			
		||||
  const gchar *brush_callback;
 | 
			
		||||
  const gchar *brush_name;
 | 
			
		||||
  PikaBrush *brush;
 | 
			
		||||
 | 
			
		||||
  brush_callback = g_value_get_string (pika_value_array_index (args, 0));
 | 
			
		||||
  brush_name = g_value_get_string (pika_value_array_index (args, 1));
 | 
			
		||||
  brush = g_value_get_object (pika_value_array_index (args, 1));
 | 
			
		||||
 | 
			
		||||
  if (success)
 | 
			
		||||
    {
 | 
			
		||||
      PikaContainer *container = pika_data_factory_get_container (pika->brush_factory);
 | 
			
		||||
 | 
			
		||||
      if (pika->no_interface ||
 | 
			
		||||
          ! pika_pdb_lookup_procedure (pika->pdb, brush_callback) ||
 | 
			
		||||
          ! pika_pdb_dialog_set (pika, pika_data_factory_get_container (pika->brush_factory),
 | 
			
		||||
                                 brush_callback, brush_name,
 | 
			
		||||
                                 NULL))
 | 
			
		||||
          ! pika_pdb_dialog_set (pika,
 | 
			
		||||
                                 pika_container_get_children_type (container),
 | 
			
		||||
                                 brush_callback, PIKA_OBJECT (brush), NULL))
 | 
			
		||||
        success = FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -163,12 +174,17 @@ register_brush_select_procs (PikaPDB *pdb)
 | 
			
		||||
                                                       NULL,
 | 
			
		||||
                                                       PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               pika_param_spec_string ("initial-brush-name",
 | 
			
		||||
                                                       "initial brush name",
 | 
			
		||||
                                                       "The name of the brush to set as the initial choice",
 | 
			
		||||
                                                       FALSE, TRUE, FALSE,
 | 
			
		||||
                                                       NULL,
 | 
			
		||||
                                                       PIKA_PARAM_READWRITE));
 | 
			
		||||
                               pika_param_spec_brush ("initial-brush",
 | 
			
		||||
                                                      "initial brush",
 | 
			
		||||
                                                      "The brush to set as the initial choice",
 | 
			
		||||
                                                      FALSE,
 | 
			
		||||
                                                      PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               g_param_spec_boxed ("parent-window",
 | 
			
		||||
                                                   "parent window",
 | 
			
		||||
                                                   "An optional parent window handle for the popup to be set transient to",
 | 
			
		||||
                                                   G_TYPE_BYTES,
 | 
			
		||||
                                                   PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_pdb_register_procedure (pdb, procedure);
 | 
			
		||||
  g_object_unref (procedure);
 | 
			
		||||
 | 
			
		||||
@ -218,12 +234,11 @@ register_brush_select_procs (PikaPDB *pdb)
 | 
			
		||||
                                                       NULL,
 | 
			
		||||
                                                       PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               pika_param_spec_string ("brush-name",
 | 
			
		||||
                                                       "brush name",
 | 
			
		||||
                                                       "The name of the brush to set as selected",
 | 
			
		||||
                                                       FALSE, FALSE, FALSE,
 | 
			
		||||
                                                       NULL,
 | 
			
		||||
                                                       PIKA_PARAM_READWRITE));
 | 
			
		||||
                               pika_param_spec_brush ("brush",
 | 
			
		||||
                                                      "brush",
 | 
			
		||||
                                                      "The brush to set as selected",
 | 
			
		||||
                                                      FALSE,
 | 
			
		||||
                                                      PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_pdb_register_procedure (pdb, procedure);
 | 
			
		||||
  g_object_unref (procedure);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -148,20 +148,20 @@ display_get_window_handle_invoker (PikaProcedure         *procedure,
 | 
			
		||||
  gboolean success = TRUE;
 | 
			
		||||
  PikaValueArray *return_vals;
 | 
			
		||||
  PikaDisplay *display;
 | 
			
		||||
  gint window = 0;
 | 
			
		||||
  GBytes *handle = NULL;
 | 
			
		||||
 | 
			
		||||
  display = g_value_get_object (pika_value_array_index (args, 0));
 | 
			
		||||
 | 
			
		||||
  if (success)
 | 
			
		||||
    {
 | 
			
		||||
      window = (gint32) pika_get_display_window_id (pika, display);
 | 
			
		||||
      handle = pika_get_display_window_id (pika, display);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return_vals = pika_procedure_get_return_values (procedure, success,
 | 
			
		||||
                                                  error ? *error : NULL);
 | 
			
		||||
 | 
			
		||||
  if (success)
 | 
			
		||||
    g_value_set_int (pika_value_array_index (return_vals, 1), window);
 | 
			
		||||
    g_value_take_boxed (pika_value_array_index (return_vals, 1), handle);
 | 
			
		||||
 | 
			
		||||
  return return_vals;
 | 
			
		||||
}
 | 
			
		||||
@ -330,7 +330,8 @@ register_display_procs (PikaPDB *pdb)
 | 
			
		||||
                               "pika-display-get-window-handle");
 | 
			
		||||
  pika_procedure_set_static_help (procedure,
 | 
			
		||||
                                  "Get a handle to the native window for an image display.",
 | 
			
		||||
                                  "This procedure returns a handle to the native window for a given image display. For example in the X backend of GDK, a native window handle is an Xlib XID. A value of 0 is returned for an invalid display or if this function is unimplemented for the windowing system that is being used.",
 | 
			
		||||
                                  "This procedure returns a handle to the native window for a given image display.\n"
 | 
			
		||||
                                  "It can be different types of data depending on the platform you are running on. For example in the X backend of GDK, a native window handle is an Xlib XID whereas on Wayland, it is a string handle. A value of NULL is returned for an invalid display or if this function is unimplemented for the windowing system that is being used.",
 | 
			
		||||
                                  NULL);
 | 
			
		||||
  pika_procedure_set_static_attribution (procedure,
 | 
			
		||||
                                         "Sven Neumann <sven@gimp.org>",
 | 
			
		||||
@ -343,11 +344,11 @@ register_display_procs (PikaPDB *pdb)
 | 
			
		||||
                                                        FALSE,
 | 
			
		||||
                                                        PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_return_value (procedure,
 | 
			
		||||
                                   g_param_spec_int ("window",
 | 
			
		||||
                                                     "window",
 | 
			
		||||
                                                     "The native window handle or 0",
 | 
			
		||||
                                                     G_MININT32, G_MAXINT32, 0,
 | 
			
		||||
                                                     PIKA_PARAM_READWRITE));
 | 
			
		||||
                                   g_param_spec_boxed ("handle",
 | 
			
		||||
                                                       "handle",
 | 
			
		||||
                                                       "The native window handle or NULL",
 | 
			
		||||
                                                       G_TYPE_BYTES,
 | 
			
		||||
                                                       PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_pdb_register_procedure (pdb, procedure);
 | 
			
		||||
  g_object_unref (procedure);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										243
									
								
								app/pdb/drawable-select-cmds.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										243
									
								
								app/pdb/drawable-select-cmds.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,243 @@
 | 
			
		||||
/* PIKA - Photo and Image Kooker Application
 | 
			
		||||
 * a rebranding of The GNU Image Manipulation Program (created with heckimp)
 | 
			
		||||
 * A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
 | 
			
		||||
 *
 | 
			
		||||
 * Original copyright, applying to most contents (license remains unchanged): 
 | 
			
		||||
 * Copyright (C) 1995-2003 Spencer Kimball and Peter Mattis
 | 
			
		||||
 *
 | 
			
		||||
 * 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 3 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/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* NOTE: This file is auto-generated by pdbgen.pl. */
 | 
			
		||||
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#include "stamp-pdbgen.h"
 | 
			
		||||
 | 
			
		||||
#include <gegl.h>
 | 
			
		||||
 | 
			
		||||
#include <gdk-pixbuf/gdk-pixbuf.h>
 | 
			
		||||
 | 
			
		||||
#include "libpikabase/pikabase.h"
 | 
			
		||||
 | 
			
		||||
#include "pdb-types.h"
 | 
			
		||||
 | 
			
		||||
#include "core/pika.h"
 | 
			
		||||
#include "core/pikadatafactory.h"
 | 
			
		||||
#include "core/pikadrawable.h"
 | 
			
		||||
#include "core/pikaparamspecs.h"
 | 
			
		||||
 | 
			
		||||
#include "pikapdb.h"
 | 
			
		||||
#include "pikaprocedure.h"
 | 
			
		||||
#include "internal-procs.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static PikaValueArray *
 | 
			
		||||
drawables_popup_invoker (PikaProcedure         *procedure,
 | 
			
		||||
                         Pika                  *pika,
 | 
			
		||||
                         PikaContext           *context,
 | 
			
		||||
                         PikaProgress          *progress,
 | 
			
		||||
                         const PikaValueArray  *args,
 | 
			
		||||
                         GError               **error)
 | 
			
		||||
{
 | 
			
		||||
  gboolean success = TRUE;
 | 
			
		||||
  const gchar *callback;
 | 
			
		||||
  const gchar *popup_title;
 | 
			
		||||
  const gchar *drawable_type;
 | 
			
		||||
  PikaDrawable *initial_drawable;
 | 
			
		||||
  GBytes *parent_window;
 | 
			
		||||
 | 
			
		||||
  callback = g_value_get_string (pika_value_array_index (args, 0));
 | 
			
		||||
  popup_title = g_value_get_string (pika_value_array_index (args, 1));
 | 
			
		||||
  drawable_type = g_value_get_string (pika_value_array_index (args, 2));
 | 
			
		||||
  initial_drawable = g_value_get_object (pika_value_array_index (args, 3));
 | 
			
		||||
  parent_window = g_value_get_boxed (pika_value_array_index (args, 4));
 | 
			
		||||
 | 
			
		||||
  if (success)
 | 
			
		||||
    {
 | 
			
		||||
      if (pika->no_interface ||
 | 
			
		||||
          ! pika_pdb_lookup_procedure (pika->pdb, callback) ||
 | 
			
		||||
          ! pika_pdb_dialog_new (pika, context, progress,
 | 
			
		||||
                                 g_type_from_name (drawable_type),
 | 
			
		||||
                                 parent_window, popup_title, callback,
 | 
			
		||||
                                 PIKA_OBJECT (initial_drawable),
 | 
			
		||||
                                 NULL))
 | 
			
		||||
        success = FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return pika_procedure_get_return_values (procedure, success,
 | 
			
		||||
                                           error ? *error : NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static PikaValueArray *
 | 
			
		||||
drawables_close_popup_invoker (PikaProcedure         *procedure,
 | 
			
		||||
                               Pika                  *pika,
 | 
			
		||||
                               PikaContext           *context,
 | 
			
		||||
                               PikaProgress          *progress,
 | 
			
		||||
                               const PikaValueArray  *args,
 | 
			
		||||
                               GError               **error)
 | 
			
		||||
{
 | 
			
		||||
  gboolean success = TRUE;
 | 
			
		||||
  const gchar *callback;
 | 
			
		||||
 | 
			
		||||
  callback = g_value_get_string (pika_value_array_index (args, 0));
 | 
			
		||||
 | 
			
		||||
  if (success)
 | 
			
		||||
    {
 | 
			
		||||
      if (pika->no_interface ||
 | 
			
		||||
          ! pika_pdb_lookup_procedure (pika->pdb, callback) ||
 | 
			
		||||
          ! pika_pdb_dialog_close (pika, PIKA_TYPE_DRAWABLE, callback))
 | 
			
		||||
        success = FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return pika_procedure_get_return_values (procedure, success,
 | 
			
		||||
                                           error ? *error : NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static PikaValueArray *
 | 
			
		||||
drawables_set_popup_invoker (PikaProcedure         *procedure,
 | 
			
		||||
                             Pika                  *pika,
 | 
			
		||||
                             PikaContext           *context,
 | 
			
		||||
                             PikaProgress          *progress,
 | 
			
		||||
                             const PikaValueArray  *args,
 | 
			
		||||
                             GError               **error)
 | 
			
		||||
{
 | 
			
		||||
  gboolean success = TRUE;
 | 
			
		||||
  const gchar *callback;
 | 
			
		||||
  PikaDrawable *drawable;
 | 
			
		||||
 | 
			
		||||
  callback = g_value_get_string (pika_value_array_index (args, 0));
 | 
			
		||||
  drawable = g_value_get_object (pika_value_array_index (args, 1));
 | 
			
		||||
 | 
			
		||||
  if (success)
 | 
			
		||||
    {
 | 
			
		||||
      if (pika->no_interface ||
 | 
			
		||||
          ! pika_pdb_lookup_procedure (pika->pdb, callback) ||
 | 
			
		||||
          ! pika_pdb_dialog_set (pika, PIKA_TYPE_DRAWABLE, callback, PIKA_OBJECT (drawable), NULL))
 | 
			
		||||
        success = FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return pika_procedure_get_return_values (procedure, success,
 | 
			
		||||
                                           error ? *error : NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
register_drawable_select_procs (PikaPDB *pdb)
 | 
			
		||||
{
 | 
			
		||||
  PikaProcedure *procedure;
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
   * pika-drawables-popup
 | 
			
		||||
   */
 | 
			
		||||
  procedure = pika_procedure_new (drawables_popup_invoker);
 | 
			
		||||
  pika_object_set_static_name (PIKA_OBJECT (procedure),
 | 
			
		||||
                               "pika-drawables-popup");
 | 
			
		||||
  pika_procedure_set_static_help (procedure,
 | 
			
		||||
                                  "Invokes the drawable selection dialog.",
 | 
			
		||||
                                  "Opens a dialog letting a user choose an drawable.",
 | 
			
		||||
                                  NULL);
 | 
			
		||||
  pika_procedure_set_static_attribution (procedure,
 | 
			
		||||
                                         "Jehan",
 | 
			
		||||
                                         "Jehan",
 | 
			
		||||
                                         "2023");
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               pika_param_spec_string ("callback",
 | 
			
		||||
                                                       "callback",
 | 
			
		||||
                                                       "The callback PDB proc to call when user chooses an drawable",
 | 
			
		||||
                                                       FALSE, FALSE, TRUE,
 | 
			
		||||
                                                       NULL,
 | 
			
		||||
                                                       PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               pika_param_spec_string ("popup-title",
 | 
			
		||||
                                                       "popup title",
 | 
			
		||||
                                                       "Title of the drawable selection dialog",
 | 
			
		||||
                                                       FALSE, FALSE, FALSE,
 | 
			
		||||
                                                       NULL,
 | 
			
		||||
                                                       PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               pika_param_spec_string ("drawable-type",
 | 
			
		||||
                                                       "drawable type",
 | 
			
		||||
                                                       "The name of the PIKA_TYPE_DRAWABLE subtype",
 | 
			
		||||
                                                       FALSE, FALSE, TRUE,
 | 
			
		||||
                                                       NULL,
 | 
			
		||||
                                                       PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               pika_param_spec_drawable ("initial-drawable",
 | 
			
		||||
                                                         "initial drawable",
 | 
			
		||||
                                                         "The drawable to set as the initial choice",
 | 
			
		||||
                                                         FALSE,
 | 
			
		||||
                                                         PIKA_PARAM_READWRITE | PIKA_PARAM_NO_VALIDATE));
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               g_param_spec_boxed ("parent-window",
 | 
			
		||||
                                                   "parent window",
 | 
			
		||||
                                                   "An optional parent window handle for the popup to be set transient to",
 | 
			
		||||
                                                   G_TYPE_BYTES,
 | 
			
		||||
                                                   PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_pdb_register_procedure (pdb, procedure);
 | 
			
		||||
  g_object_unref (procedure);
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
   * pika-drawables-close-popup
 | 
			
		||||
   */
 | 
			
		||||
  procedure = pika_procedure_new (drawables_close_popup_invoker);
 | 
			
		||||
  pika_object_set_static_name (PIKA_OBJECT (procedure),
 | 
			
		||||
                               "pika-drawables-close-popup");
 | 
			
		||||
  pika_procedure_set_static_help (procedure,
 | 
			
		||||
                                  "Close the drawable selection dialog.",
 | 
			
		||||
                                  "Closes an open drawable selection dialog.",
 | 
			
		||||
                                  NULL);
 | 
			
		||||
  pika_procedure_set_static_attribution (procedure,
 | 
			
		||||
                                         "Jehan",
 | 
			
		||||
                                         "Jehan",
 | 
			
		||||
                                         "2023");
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               pika_param_spec_string ("callback",
 | 
			
		||||
                                                       "callback",
 | 
			
		||||
                                                       "The name of the callback registered for this pop-up",
 | 
			
		||||
                                                       FALSE, FALSE, TRUE,
 | 
			
		||||
                                                       NULL,
 | 
			
		||||
                                                       PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_pdb_register_procedure (pdb, procedure);
 | 
			
		||||
  g_object_unref (procedure);
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
   * pika-drawables-set-popup
 | 
			
		||||
   */
 | 
			
		||||
  procedure = pika_procedure_new (drawables_set_popup_invoker);
 | 
			
		||||
  pika_object_set_static_name (PIKA_OBJECT (procedure),
 | 
			
		||||
                               "pika-drawables-set-popup");
 | 
			
		||||
  pika_procedure_set_static_help (procedure,
 | 
			
		||||
                                  "Sets the selected drawable in a drawable selection dialog.",
 | 
			
		||||
                                  "Sets the selected drawable in a drawable selection dialog.",
 | 
			
		||||
                                  NULL);
 | 
			
		||||
  pika_procedure_set_static_attribution (procedure,
 | 
			
		||||
                                         "Jehan",
 | 
			
		||||
                                         "Jehan",
 | 
			
		||||
                                         "2023");
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               pika_param_spec_string ("callback",
 | 
			
		||||
                                                       "callback",
 | 
			
		||||
                                                       "The name of the callback registered for this pop-up",
 | 
			
		||||
                                                       FALSE, FALSE, TRUE,
 | 
			
		||||
                                                       NULL,
 | 
			
		||||
                                                       PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               pika_param_spec_drawable ("drawable",
 | 
			
		||||
                                                         "drawable",
 | 
			
		||||
                                                         "The drawable to set as selected",
 | 
			
		||||
                                                         FALSE,
 | 
			
		||||
                                                         PIKA_PARAM_READWRITE | PIKA_PARAM_NO_VALIDATE));
 | 
			
		||||
  pika_pdb_register_procedure (pdb, procedure);
 | 
			
		||||
  g_object_unref (procedure);
 | 
			
		||||
}
 | 
			
		||||
@ -75,6 +75,57 @@ font_get_by_name_invoker (PikaProcedure         *procedure,
 | 
			
		||||
  return return_vals;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static PikaValueArray *
 | 
			
		||||
fonts_get_by_name_invoker (PikaProcedure         *procedure,
 | 
			
		||||
                           Pika                  *pika,
 | 
			
		||||
                           PikaContext           *context,
 | 
			
		||||
                           PikaProgress          *progress,
 | 
			
		||||
                           const PikaValueArray  *args,
 | 
			
		||||
                           GError               **error)
 | 
			
		||||
{
 | 
			
		||||
  gboolean success = TRUE;
 | 
			
		||||
  PikaValueArray *return_vals;
 | 
			
		||||
  const gchar *name;
 | 
			
		||||
  gint num_fonts = 0;
 | 
			
		||||
  PikaFont **fonts = NULL;
 | 
			
		||||
 | 
			
		||||
  name = g_value_get_string (pika_value_array_index (args, 0));
 | 
			
		||||
 | 
			
		||||
  if (success)
 | 
			
		||||
    {
 | 
			
		||||
      GList *list;
 | 
			
		||||
 | 
			
		||||
      list = pika_pdb_get_resources (pika, PIKA_TYPE_FONT, name, PIKA_PDB_DATA_ACCESS_READ, error);
 | 
			
		||||
 | 
			
		||||
      if (list == NULL)
 | 
			
		||||
        success = FALSE;
 | 
			
		||||
 | 
			
		||||
      num_fonts = g_list_length (list);
 | 
			
		||||
 | 
			
		||||
      if (num_fonts > 0)
 | 
			
		||||
        {
 | 
			
		||||
          gint i = 0;
 | 
			
		||||
 | 
			
		||||
          fonts = g_new (PikaFont *, num_fonts);
 | 
			
		||||
 | 
			
		||||
          for (GList *iter = list; i < num_fonts; i++, iter = g_list_next (iter))
 | 
			
		||||
            fonts[i] = g_object_ref (iter->data);
 | 
			
		||||
        }
 | 
			
		||||
      g_list_free (list);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return_vals = pika_procedure_get_return_values (procedure, success,
 | 
			
		||||
                                                  error ? *error : NULL);
 | 
			
		||||
 | 
			
		||||
  if (success)
 | 
			
		||||
    {
 | 
			
		||||
      g_value_set_int (pika_value_array_index (return_vals, 1), num_fonts);
 | 
			
		||||
      pika_value_take_object_array (pika_value_array_index (return_vals, 2), PIKA_TYPE_FONT, (GObject **) fonts, num_fonts);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return return_vals;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
register_font_procs (PikaPDB *pdb)
 | 
			
		||||
{
 | 
			
		||||
@ -87,8 +138,9 @@ register_font_procs (PikaPDB *pdb)
 | 
			
		||||
  pika_object_set_static_name (PIKA_OBJECT (procedure),
 | 
			
		||||
                               "pika-font-get-by-name");
 | 
			
		||||
  pika_procedure_set_static_help (procedure,
 | 
			
		||||
                                  "Returns the font with the given name.",
 | 
			
		||||
                                  "Returns the font with the given name.",
 | 
			
		||||
                                  "Returns a font with the given name.",
 | 
			
		||||
                                  "If several fonts are named identically, the one which is returned by this function should be considered random. This can be used when you know you won't have multiple fonts of this name or that you don't want to choose (non-interactive scripts, etc.).\n"
 | 
			
		||||
                                  "If you need more control, you should use 'pika-fonts-get-by-name' instead.",
 | 
			
		||||
                                  NULL);
 | 
			
		||||
  pika_procedure_set_static_attribution (procedure,
 | 
			
		||||
                                         "Michael Natterer <mitch@gimp.org>",
 | 
			
		||||
@ -109,4 +161,40 @@ register_font_procs (PikaPDB *pdb)
 | 
			
		||||
                                                         PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_pdb_register_procedure (pdb, procedure);
 | 
			
		||||
  g_object_unref (procedure);
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
   * pika-fonts-get-by-name
 | 
			
		||||
   */
 | 
			
		||||
  procedure = pika_procedure_new (fonts_get_by_name_invoker);
 | 
			
		||||
  pika_object_set_static_name (PIKA_OBJECT (procedure),
 | 
			
		||||
                               "pika-fonts-get-by-name");
 | 
			
		||||
  pika_procedure_set_static_help (procedure,
 | 
			
		||||
                                  "Returns the fonts with the given name.",
 | 
			
		||||
                                  "Returns the fonts with the given name. There may be more than one.",
 | 
			
		||||
                                  NULL);
 | 
			
		||||
  pika_procedure_set_static_attribution (procedure,
 | 
			
		||||
                                         "Jehan",
 | 
			
		||||
                                         "Jehan",
 | 
			
		||||
                                         "2023");
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               pika_param_spec_string ("name",
 | 
			
		||||
                                                       "name",
 | 
			
		||||
                                                       "The name of the font",
 | 
			
		||||
                                                       FALSE, FALSE, TRUE,
 | 
			
		||||
                                                       NULL,
 | 
			
		||||
                                                       PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_return_value (procedure,
 | 
			
		||||
                                   g_param_spec_int ("num-fonts",
 | 
			
		||||
                                                     "num fonts",
 | 
			
		||||
                                                     "The number of fonts with the given name",
 | 
			
		||||
                                                     0, G_MAXINT32, 0,
 | 
			
		||||
                                                     PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_return_value (procedure,
 | 
			
		||||
                                   pika_param_spec_object_array ("fonts",
 | 
			
		||||
                                                                 "fonts",
 | 
			
		||||
                                                                 "The fonts with the given name",
 | 
			
		||||
                                                                 PIKA_TYPE_FONT,
 | 
			
		||||
                                                                 PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_pdb_register_procedure (pdb, procedure);
 | 
			
		||||
  g_object_unref (procedure);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -34,8 +34,10 @@
 | 
			
		||||
#include "pdb-types.h"
 | 
			
		||||
 | 
			
		||||
#include "core/pika.h"
 | 
			
		||||
#include "core/pikacontainer.h"
 | 
			
		||||
#include "core/pikadatafactory.h"
 | 
			
		||||
#include "core/pikaparamspecs.h"
 | 
			
		||||
#include "text/pikafont.h"
 | 
			
		||||
 | 
			
		||||
#include "pikapdb.h"
 | 
			
		||||
#include "pikaprocedure.h"
 | 
			
		||||
@ -53,21 +55,25 @@ fonts_popup_invoker (PikaProcedure         *procedure,
 | 
			
		||||
  gboolean success = TRUE;
 | 
			
		||||
  const gchar *font_callback;
 | 
			
		||||
  const gchar *popup_title;
 | 
			
		||||
  const gchar *initial_font_name;
 | 
			
		||||
  PikaFont *initial_font;
 | 
			
		||||
  GBytes *parent_window;
 | 
			
		||||
 | 
			
		||||
  font_callback = g_value_get_string (pika_value_array_index (args, 0));
 | 
			
		||||
  popup_title = g_value_get_string (pika_value_array_index (args, 1));
 | 
			
		||||
  initial_font_name = g_value_get_string (pika_value_array_index (args, 2));
 | 
			
		||||
  initial_font = g_value_get_object (pika_value_array_index (args, 2));
 | 
			
		||||
  parent_window = g_value_get_boxed (pika_value_array_index (args, 3));
 | 
			
		||||
 | 
			
		||||
  if (success)
 | 
			
		||||
    {
 | 
			
		||||
      PikaContainer *container = pika_data_factory_get_container (pika->font_factory);
 | 
			
		||||
 | 
			
		||||
      if (pika->no_interface ||
 | 
			
		||||
          ! pika_pdb_lookup_procedure (pika->pdb, font_callback) ||
 | 
			
		||||
          ! pika_data_factory_data_wait (pika->font_factory)     ||
 | 
			
		||||
          ! pika_pdb_dialog_new (pika, context, progress,
 | 
			
		||||
                                 pika_data_factory_get_container (pika->font_factory),
 | 
			
		||||
                                 popup_title, font_callback, initial_font_name,
 | 
			
		||||
                                 NULL))
 | 
			
		||||
                                 pika_container_get_children_type (container),
 | 
			
		||||
                                 parent_window, popup_title, font_callback,
 | 
			
		||||
                                 PIKA_OBJECT (initial_font), NULL))
 | 
			
		||||
        success = FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -90,10 +96,12 @@ fonts_close_popup_invoker (PikaProcedure         *procedure,
 | 
			
		||||
 | 
			
		||||
  if (success)
 | 
			
		||||
    {
 | 
			
		||||
      PikaContainer *container = pika_data_factory_get_container (pika->font_factory);
 | 
			
		||||
 | 
			
		||||
      if (pika->no_interface ||
 | 
			
		||||
          ! pika_pdb_lookup_procedure (pika->pdb, font_callback) ||
 | 
			
		||||
          ! pika_pdb_dialog_close (pika,
 | 
			
		||||
                                   pika_data_factory_get_container (pika->font_factory),
 | 
			
		||||
                                   pika_container_get_children_type (container),
 | 
			
		||||
                                   font_callback))
 | 
			
		||||
        success = FALSE;
 | 
			
		||||
    }
 | 
			
		||||
@ -112,20 +120,21 @@ fonts_set_popup_invoker (PikaProcedure         *procedure,
 | 
			
		||||
{
 | 
			
		||||
  gboolean success = TRUE;
 | 
			
		||||
  const gchar *font_callback;
 | 
			
		||||
  const gchar *font_name;
 | 
			
		||||
  PikaFont *font;
 | 
			
		||||
 | 
			
		||||
  font_callback = g_value_get_string (pika_value_array_index (args, 0));
 | 
			
		||||
  font_name = g_value_get_string (pika_value_array_index (args, 1));
 | 
			
		||||
  font = g_value_get_object (pika_value_array_index (args, 1));
 | 
			
		||||
 | 
			
		||||
  if (success)
 | 
			
		||||
    {
 | 
			
		||||
      PikaContainer *container = pika_data_factory_get_container (pika->font_factory);
 | 
			
		||||
 | 
			
		||||
      if (pika->no_interface ||
 | 
			
		||||
          ! pika_pdb_lookup_procedure (pika->pdb, font_callback) ||
 | 
			
		||||
          ! pika_data_factory_data_wait (pika->font_factory)     ||
 | 
			
		||||
          ! pika_pdb_dialog_set (pika,
 | 
			
		||||
                                 pika_data_factory_get_container (pika->font_factory),
 | 
			
		||||
                                 font_callback, font_name,
 | 
			
		||||
                                 NULL))
 | 
			
		||||
                                 pika_container_get_children_type (container),
 | 
			
		||||
                                 font_callback, PIKA_OBJECT (font), NULL))
 | 
			
		||||
        success = FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -167,12 +176,17 @@ register_font_select_procs (PikaPDB *pdb)
 | 
			
		||||
                                                       NULL,
 | 
			
		||||
                                                       PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               pika_param_spec_string ("initial-font-name",
 | 
			
		||||
                                                       "initial font name",
 | 
			
		||||
                                                       "The name of the initial font choice.",
 | 
			
		||||
                                                       FALSE, TRUE, FALSE,
 | 
			
		||||
                                                       NULL,
 | 
			
		||||
                                                       PIKA_PARAM_READWRITE));
 | 
			
		||||
                               pika_param_spec_font ("initial-font",
 | 
			
		||||
                                                     "initial font",
 | 
			
		||||
                                                     "The name of the initial font choice.",
 | 
			
		||||
                                                     FALSE,
 | 
			
		||||
                                                     PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               g_param_spec_boxed ("parent-window",
 | 
			
		||||
                                                   "parent window",
 | 
			
		||||
                                                   "An optional parent window handle for the popup to be set transient to",
 | 
			
		||||
                                                   G_TYPE_BYTES,
 | 
			
		||||
                                                   PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_pdb_register_procedure (pdb, procedure);
 | 
			
		||||
  g_object_unref (procedure);
 | 
			
		||||
 | 
			
		||||
@ -222,12 +236,11 @@ register_font_select_procs (PikaPDB *pdb)
 | 
			
		||||
                                                       NULL,
 | 
			
		||||
                                                       PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               pika_param_spec_string ("font-name",
 | 
			
		||||
                                                       "font name",
 | 
			
		||||
                                                       "The name of the font to set as selected",
 | 
			
		||||
                                                       FALSE, FALSE, FALSE,
 | 
			
		||||
                                                       NULL,
 | 
			
		||||
                                                       PIKA_PARAM_READWRITE));
 | 
			
		||||
                               pika_param_spec_font ("font",
 | 
			
		||||
                                                     "font",
 | 
			
		||||
                                                     "The font to set as selected",
 | 
			
		||||
                                                     FALSE,
 | 
			
		||||
                                                     PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_pdb_register_procedure (pdb, procedure);
 | 
			
		||||
  g_object_unref (procedure);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -34,6 +34,7 @@
 | 
			
		||||
#include "pdb-types.h"
 | 
			
		||||
 | 
			
		||||
#include "core/pika.h"
 | 
			
		||||
#include "core/pikacontainer.h"
 | 
			
		||||
#include "core/pikadatafactory.h"
 | 
			
		||||
#include "core/pikagradient.h"
 | 
			
		||||
#include "core/pikaparamspecs.h"
 | 
			
		||||
@ -54,14 +55,18 @@ gradients_popup_invoker (PikaProcedure         *procedure,
 | 
			
		||||
  gboolean success = TRUE;
 | 
			
		||||
  const gchar *gradient_callback;
 | 
			
		||||
  const gchar *popup_title;
 | 
			
		||||
  const gchar *initial_gradient_name;
 | 
			
		||||
  PikaGradient *initial_gradient;
 | 
			
		||||
  GBytes *parent_window;
 | 
			
		||||
 | 
			
		||||
  gradient_callback = g_value_get_string (pika_value_array_index (args, 0));
 | 
			
		||||
  popup_title = g_value_get_string (pika_value_array_index (args, 1));
 | 
			
		||||
  initial_gradient_name = g_value_get_string (pika_value_array_index (args, 2));
 | 
			
		||||
  initial_gradient = g_value_get_object (pika_value_array_index (args, 2));
 | 
			
		||||
  parent_window = g_value_get_boxed (pika_value_array_index (args, 3));
 | 
			
		||||
 | 
			
		||||
  if (success)
 | 
			
		||||
    {
 | 
			
		||||
      PikaContainer *container = pika_data_factory_get_container (pika->gradient_factory);
 | 
			
		||||
 | 
			
		||||
      /* Formerly, this procedure had another parameter:
 | 
			
		||||
       * the sample size of the gradient's data passed in the changed callback.
 | 
			
		||||
       * Now the sample size is determined by core, and in the future,
 | 
			
		||||
@ -71,9 +76,9 @@ gradients_popup_invoker (PikaProcedure         *procedure,
 | 
			
		||||
      if (pika->no_interface ||
 | 
			
		||||
          ! pika_pdb_lookup_procedure (pika->pdb, gradient_callback) ||
 | 
			
		||||
          ! pika_pdb_dialog_new (pika, context, progress,
 | 
			
		||||
                                 pika_data_factory_get_container (pika->gradient_factory),
 | 
			
		||||
                                 popup_title, gradient_callback, initial_gradient_name,
 | 
			
		||||
                                 NULL))
 | 
			
		||||
                                 pika_container_get_children_type (container),
 | 
			
		||||
                                 parent_window, popup_title, gradient_callback,
 | 
			
		||||
                                 PIKA_OBJECT (initial_gradient), NULL))
 | 
			
		||||
        success = FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -96,9 +101,12 @@ gradients_close_popup_invoker (PikaProcedure         *procedure,
 | 
			
		||||
 | 
			
		||||
  if (success)
 | 
			
		||||
    {
 | 
			
		||||
      PikaContainer *container = pika_data_factory_get_container (pika->gradient_factory);
 | 
			
		||||
 | 
			
		||||
      if (pika->no_interface ||
 | 
			
		||||
          ! pika_pdb_lookup_procedure (pika->pdb, gradient_callback) ||
 | 
			
		||||
          ! pika_pdb_dialog_close (pika, pika_data_factory_get_container (pika->gradient_factory),
 | 
			
		||||
          ! pika_pdb_dialog_close (pika,
 | 
			
		||||
                                   pika_container_get_children_type (container),
 | 
			
		||||
                                   gradient_callback))
 | 
			
		||||
        success = FALSE;
 | 
			
		||||
    }
 | 
			
		||||
@ -117,18 +125,20 @@ gradients_set_popup_invoker (PikaProcedure         *procedure,
 | 
			
		||||
{
 | 
			
		||||
  gboolean success = TRUE;
 | 
			
		||||
  const gchar *gradient_callback;
 | 
			
		||||
  const gchar *gradient_name;
 | 
			
		||||
  PikaGradient *gradient;
 | 
			
		||||
 | 
			
		||||
  gradient_callback = g_value_get_string (pika_value_array_index (args, 0));
 | 
			
		||||
  gradient_name = g_value_get_string (pika_value_array_index (args, 1));
 | 
			
		||||
  gradient = g_value_get_object (pika_value_array_index (args, 1));
 | 
			
		||||
 | 
			
		||||
  if (success)
 | 
			
		||||
    {
 | 
			
		||||
      PikaContainer *container = pika_data_factory_get_container (pika->gradient_factory);
 | 
			
		||||
 | 
			
		||||
      if (pika->no_interface ||
 | 
			
		||||
          ! pika_pdb_lookup_procedure (pika->pdb, gradient_callback) ||
 | 
			
		||||
          ! pika_pdb_dialog_set (pika, pika_data_factory_get_container (pika->gradient_factory),
 | 
			
		||||
                                 gradient_callback, gradient_name,
 | 
			
		||||
                                 NULL))
 | 
			
		||||
          ! pika_pdb_dialog_set (pika,
 | 
			
		||||
                                 pika_container_get_children_type (container),
 | 
			
		||||
                                 gradient_callback, PIKA_OBJECT (gradient), NULL))
 | 
			
		||||
        success = FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -170,12 +180,17 @@ register_gradient_select_procs (PikaPDB *pdb)
 | 
			
		||||
                                                       NULL,
 | 
			
		||||
                                                       PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               pika_param_spec_string ("initial-gradient-name",
 | 
			
		||||
                                                       "initial gradient name",
 | 
			
		||||
                                                       "The name of the initial gradient choice",
 | 
			
		||||
                                                       FALSE, TRUE, FALSE,
 | 
			
		||||
                                                       NULL,
 | 
			
		||||
                                                       PIKA_PARAM_READWRITE));
 | 
			
		||||
                               pika_param_spec_gradient ("initial-gradient",
 | 
			
		||||
                                                         "initial gradient",
 | 
			
		||||
                                                         "The initial gradient choice",
 | 
			
		||||
                                                         FALSE,
 | 
			
		||||
                                                         PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               g_param_spec_boxed ("parent-window",
 | 
			
		||||
                                                   "parent window",
 | 
			
		||||
                                                   "An optional parent window handle for the popup to be set transient to",
 | 
			
		||||
                                                   G_TYPE_BYTES,
 | 
			
		||||
                                                   PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_pdb_register_procedure (pdb, procedure);
 | 
			
		||||
  g_object_unref (procedure);
 | 
			
		||||
 | 
			
		||||
@ -225,12 +240,11 @@ register_gradient_select_procs (PikaPDB *pdb)
 | 
			
		||||
                                                       NULL,
 | 
			
		||||
                                                       PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               pika_param_spec_string ("gradient-name",
 | 
			
		||||
                                                       "gradient name",
 | 
			
		||||
                                                       "The name of the gradient to set as selected",
 | 
			
		||||
                                                       FALSE, FALSE, FALSE,
 | 
			
		||||
                                                       NULL,
 | 
			
		||||
                                                       PIKA_PARAM_READWRITE));
 | 
			
		||||
                               pika_param_spec_gradient ("gradient",
 | 
			
		||||
                                                         "gradient",
 | 
			
		||||
                                                         "The gradient to set as selected",
 | 
			
		||||
                                                         FALSE,
 | 
			
		||||
                                                         PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_pdb_register_procedure (pdb, procedure);
 | 
			
		||||
  g_object_unref (procedure);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -55,6 +55,7 @@
 | 
			
		||||
#include "core/pikaimage.h"
 | 
			
		||||
#include "core/pikaitem.h"
 | 
			
		||||
#include "core/pikalayer.h"
 | 
			
		||||
#include "core/pikapalette.h"
 | 
			
		||||
#include "core/pikaparamspecs.h"
 | 
			
		||||
#include "core/pikapickable.h"
 | 
			
		||||
#include "core/pikaprogress.h"
 | 
			
		||||
@ -1575,6 +1576,35 @@ image_set_colormap_invoker (PikaProcedure         *procedure,
 | 
			
		||||
                                           error ? *error : NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static PikaValueArray *
 | 
			
		||||
image_get_palette_invoker (PikaProcedure         *procedure,
 | 
			
		||||
                           Pika                  *pika,
 | 
			
		||||
                           PikaContext           *context,
 | 
			
		||||
                           PikaProgress          *progress,
 | 
			
		||||
                           const PikaValueArray  *args,
 | 
			
		||||
                           GError               **error)
 | 
			
		||||
{
 | 
			
		||||
  gboolean success = TRUE;
 | 
			
		||||
  PikaValueArray *return_vals;
 | 
			
		||||
  PikaImage *image;
 | 
			
		||||
  PikaPalette *colormap = NULL;
 | 
			
		||||
 | 
			
		||||
  image = g_value_get_object (pika_value_array_index (args, 0));
 | 
			
		||||
 | 
			
		||||
  if (success)
 | 
			
		||||
    {
 | 
			
		||||
      colormap = pika_image_get_colormap_palette (image);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return_vals = pika_procedure_get_return_values (procedure, success,
 | 
			
		||||
                                                  error ? *error : NULL);
 | 
			
		||||
 | 
			
		||||
  if (success)
 | 
			
		||||
    g_value_set_object (pika_value_array_index (return_vals, 1), colormap);
 | 
			
		||||
 | 
			
		||||
  return return_vals;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static PikaValueArray *
 | 
			
		||||
image_get_metadata_invoker (PikaProcedure         *procedure,
 | 
			
		||||
                            Pika                  *pika,
 | 
			
		||||
@ -4356,6 +4386,35 @@ register_image_procs (PikaPDB *pdb)
 | 
			
		||||
  pika_pdb_register_procedure (pdb, procedure);
 | 
			
		||||
  g_object_unref (procedure);
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
   * pika-image-get-palette
 | 
			
		||||
   */
 | 
			
		||||
  procedure = pika_procedure_new (image_get_palette_invoker);
 | 
			
		||||
  pika_object_set_static_name (PIKA_OBJECT (procedure),
 | 
			
		||||
                               "pika-image-get-palette");
 | 
			
		||||
  pika_procedure_set_static_help (procedure,
 | 
			
		||||
                                  "Returns the image's colormap",
 | 
			
		||||
                                  "This procedure returns the image's colormap as a PikaPalette. If the image is not in Indexed color mode, %NULL is returned.",
 | 
			
		||||
                                  NULL);
 | 
			
		||||
  pika_procedure_set_static_attribution (procedure,
 | 
			
		||||
                                         "Jehan",
 | 
			
		||||
                                         "Jehan",
 | 
			
		||||
                                         "2023");
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               pika_param_spec_image ("image",
 | 
			
		||||
                                                      "image",
 | 
			
		||||
                                                      "The image",
 | 
			
		||||
                                                      FALSE,
 | 
			
		||||
                                                      PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_return_value (procedure,
 | 
			
		||||
                                   pika_param_spec_palette ("colormap",
 | 
			
		||||
                                                            "colormap",
 | 
			
		||||
                                                            "The image's colormap.",
 | 
			
		||||
                                                            FALSE,
 | 
			
		||||
                                                            PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_pdb_register_procedure (pdb, procedure);
 | 
			
		||||
  g_object_unref (procedure);
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
   * pika-image-get-metadata
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
@ -34,7 +34,7 @@
 | 
			
		||||
#include "internal-procs.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* 775 procedures registered total */
 | 
			
		||||
/* 779 procedures registered total */
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
internal_procs_init (PikaPDB *pdb)
 | 
			
		||||
@ -52,6 +52,7 @@ internal_procs_init (PikaPDB *pdb)
 | 
			
		||||
  register_drawable_procs (pdb);
 | 
			
		||||
  register_drawable_color_procs (pdb);
 | 
			
		||||
  register_drawable_edit_procs (pdb);
 | 
			
		||||
  register_drawable_select_procs (pdb);
 | 
			
		||||
  register_dynamics_procs (pdb);
 | 
			
		||||
  register_edit_procs (pdb);
 | 
			
		||||
  register_file_procs (pdb);
 | 
			
		||||
 | 
			
		||||
@ -39,6 +39,7 @@ void   register_display_procs             (PikaPDB *pdb);
 | 
			
		||||
void   register_drawable_procs            (PikaPDB *pdb);
 | 
			
		||||
void   register_drawable_color_procs      (PikaPDB *pdb);
 | 
			
		||||
void   register_drawable_edit_procs       (PikaPDB *pdb);
 | 
			
		||||
void   register_drawable_select_procs     (PikaPDB *pdb);
 | 
			
		||||
void   register_dynamics_procs            (PikaPDB *pdb);
 | 
			
		||||
void   register_edit_procs                (PikaPDB *pdb);
 | 
			
		||||
void   register_file_procs                (PikaPDB *pdb);
 | 
			
		||||
 | 
			
		||||
@ -19,6 +19,7 @@ libappinternalprocs_sources = [
 | 
			
		||||
  'drawable-cmds.c',
 | 
			
		||||
  'drawable-color-cmds.c',
 | 
			
		||||
  'drawable-edit-cmds.c',
 | 
			
		||||
  'drawable-select-cmds.c',
 | 
			
		||||
  'dynamics-cmds.c',
 | 
			
		||||
  'edit-cmds.c',
 | 
			
		||||
  'file-cmds.c',
 | 
			
		||||
 | 
			
		||||
@ -41,6 +41,7 @@
 | 
			
		||||
#include "core/pika.h"
 | 
			
		||||
#include "core/pikacontext.h"
 | 
			
		||||
#include "core/pikadatafactory.h"
 | 
			
		||||
#include "core/pikaimage-colormap.h"
 | 
			
		||||
#include "core/pikapalette.h"
 | 
			
		||||
#include "core/pikaparamspecs.h"
 | 
			
		||||
 | 
			
		||||
@ -308,9 +309,18 @@ palette_delete_entry_invoker (PikaProcedure         *procedure,
 | 
			
		||||
          PikaPaletteEntry *entry = pika_palette_get_entry (palette, entry_num);
 | 
			
		||||
 | 
			
		||||
          if (entry)
 | 
			
		||||
            pika_palette_delete_entry (palette, entry);
 | 
			
		||||
            {
 | 
			
		||||
              PikaImage *image = pika_data_get_image (PIKA_DATA (palette));
 | 
			
		||||
 | 
			
		||||
              if (image != NULL)
 | 
			
		||||
                success = pika_image_delete_colormap_entry (image, entry_num, TRUE);
 | 
			
		||||
              else
 | 
			
		||||
                pika_palette_delete_entry (palette, entry);
 | 
			
		||||
            }
 | 
			
		||||
          else
 | 
			
		||||
            success = FALSE;
 | 
			
		||||
            {
 | 
			
		||||
              success = FALSE;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        success = FALSE;
 | 
			
		||||
@ -376,7 +386,7 @@ palette_entry_set_color_invoker (PikaProcedure         *procedure,
 | 
			
		||||
  if (success)
 | 
			
		||||
    {
 | 
			
		||||
      if (pika_data_is_writable (PIKA_DATA (palette)))
 | 
			
		||||
        success = pika_palette_set_entry_color (palette, entry_num, &color);
 | 
			
		||||
        success = pika_palette_set_entry_color (palette, entry_num, &color, TRUE);
 | 
			
		||||
      else
 | 
			
		||||
        success = FALSE;
 | 
			
		||||
    }
 | 
			
		||||
@ -687,7 +697,8 @@ register_palette_procs (PikaPDB *pdb)
 | 
			
		||||
                               "pika-palette-delete-entry");
 | 
			
		||||
  pika_procedure_set_static_help (procedure,
 | 
			
		||||
                                  "Deletes an entry from the palette.",
 | 
			
		||||
                                  "Deletes an entry from the palette. Returns an error if the index is out or range. Returns an error if the palette is not editable.",
 | 
			
		||||
                                  "This function will fail and return %FALSE if the index is out or range or if the palette is not editable.\n"
 | 
			
		||||
                                  "Additionally if the palette belongs to an indexed image, it will only be possible to delete palette colors not in use in the image.",
 | 
			
		||||
                                  NULL);
 | 
			
		||||
  pika_procedure_set_static_attribution (procedure,
 | 
			
		||||
                                         "Michael Natterer <mitch@gimp.org>",
 | 
			
		||||
 | 
			
		||||
@ -34,7 +34,9 @@
 | 
			
		||||
#include "pdb-types.h"
 | 
			
		||||
 | 
			
		||||
#include "core/pika.h"
 | 
			
		||||
#include "core/pikacontainer.h"
 | 
			
		||||
#include "core/pikadatafactory.h"
 | 
			
		||||
#include "core/pikapalette.h"
 | 
			
		||||
#include "core/pikaparamspecs.h"
 | 
			
		||||
 | 
			
		||||
#include "pikapdb.h"
 | 
			
		||||
@ -53,20 +55,24 @@ palettes_popup_invoker (PikaProcedure         *procedure,
 | 
			
		||||
  gboolean success = TRUE;
 | 
			
		||||
  const gchar *palette_callback;
 | 
			
		||||
  const gchar *popup_title;
 | 
			
		||||
  const gchar *initial_palette_name;
 | 
			
		||||
  PikaPalette *initial_palette;
 | 
			
		||||
  GBytes *parent_window;
 | 
			
		||||
 | 
			
		||||
  palette_callback = g_value_get_string (pika_value_array_index (args, 0));
 | 
			
		||||
  popup_title = g_value_get_string (pika_value_array_index (args, 1));
 | 
			
		||||
  initial_palette_name = g_value_get_string (pika_value_array_index (args, 2));
 | 
			
		||||
  initial_palette = g_value_get_object (pika_value_array_index (args, 2));
 | 
			
		||||
  parent_window = g_value_get_boxed (pika_value_array_index (args, 3));
 | 
			
		||||
 | 
			
		||||
  if (success)
 | 
			
		||||
    {
 | 
			
		||||
      PikaContainer *container = pika_data_factory_get_container (pika->palette_factory);
 | 
			
		||||
 | 
			
		||||
      if (pika->no_interface ||
 | 
			
		||||
          ! pika_pdb_lookup_procedure (pika->pdb, palette_callback) ||
 | 
			
		||||
          ! pika_pdb_dialog_new (pika, context, progress,
 | 
			
		||||
                                 pika_data_factory_get_container (pika->palette_factory),
 | 
			
		||||
                                 popup_title, palette_callback, initial_palette_name,
 | 
			
		||||
                                 NULL))
 | 
			
		||||
                                 pika_container_get_children_type (container),
 | 
			
		||||
                                 parent_window, popup_title, palette_callback,
 | 
			
		||||
                                 PIKA_OBJECT (initial_palette), NULL))
 | 
			
		||||
        success = FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -89,9 +95,12 @@ palettes_close_popup_invoker (PikaProcedure         *procedure,
 | 
			
		||||
 | 
			
		||||
  if (success)
 | 
			
		||||
    {
 | 
			
		||||
      PikaContainer *container = pika_data_factory_get_container (pika->palette_factory);
 | 
			
		||||
 | 
			
		||||
      if (pika->no_interface ||
 | 
			
		||||
          ! pika_pdb_lookup_procedure (pika->pdb, palette_callback) ||
 | 
			
		||||
          ! pika_pdb_dialog_close (pika, pika_data_factory_get_container (pika->palette_factory),
 | 
			
		||||
          ! pika_pdb_dialog_close (pika,
 | 
			
		||||
                                   pika_container_get_children_type (container),
 | 
			
		||||
                                   palette_callback))
 | 
			
		||||
        success = FALSE;
 | 
			
		||||
    }
 | 
			
		||||
@ -110,18 +119,20 @@ palettes_set_popup_invoker (PikaProcedure         *procedure,
 | 
			
		||||
{
 | 
			
		||||
  gboolean success = TRUE;
 | 
			
		||||
  const gchar *palette_callback;
 | 
			
		||||
  const gchar *palette_name;
 | 
			
		||||
  PikaPalette *palette;
 | 
			
		||||
 | 
			
		||||
  palette_callback = g_value_get_string (pika_value_array_index (args, 0));
 | 
			
		||||
  palette_name = g_value_get_string (pika_value_array_index (args, 1));
 | 
			
		||||
  palette = g_value_get_object (pika_value_array_index (args, 1));
 | 
			
		||||
 | 
			
		||||
  if (success)
 | 
			
		||||
    {
 | 
			
		||||
      PikaContainer *container = pika_data_factory_get_container (pika->palette_factory);
 | 
			
		||||
 | 
			
		||||
      if (pika->no_interface ||
 | 
			
		||||
          ! pika_pdb_lookup_procedure (pika->pdb, palette_callback) ||
 | 
			
		||||
          ! pika_pdb_dialog_set (pika, pika_data_factory_get_container (pika->palette_factory),
 | 
			
		||||
                                 palette_callback, palette_name,
 | 
			
		||||
                                 NULL))
 | 
			
		||||
          ! pika_pdb_dialog_set (pika,
 | 
			
		||||
                                 pika_container_get_children_type (container),
 | 
			
		||||
                                 palette_callback, PIKA_OBJECT (palette), NULL))
 | 
			
		||||
        success = FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -163,12 +174,17 @@ register_palette_select_procs (PikaPDB *pdb)
 | 
			
		||||
                                                       NULL,
 | 
			
		||||
                                                       PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               pika_param_spec_string ("initial-palette-name",
 | 
			
		||||
                                                       "initial palette name",
 | 
			
		||||
                                                       "The name of the palette to set as the initial choice.",
 | 
			
		||||
                                                       FALSE, TRUE, FALSE,
 | 
			
		||||
                                                       NULL,
 | 
			
		||||
                                                       PIKA_PARAM_READWRITE));
 | 
			
		||||
                               pika_param_spec_palette ("initial-palette",
 | 
			
		||||
                                                        "initial palette",
 | 
			
		||||
                                                        "The palette to set as the initial choice.",
 | 
			
		||||
                                                        FALSE,
 | 
			
		||||
                                                        PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               g_param_spec_boxed ("parent-window",
 | 
			
		||||
                                                   "parent window",
 | 
			
		||||
                                                   "An optional parent window handle for the popup to be set transient to",
 | 
			
		||||
                                                   G_TYPE_BYTES,
 | 
			
		||||
                                                   PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_pdb_register_procedure (pdb, procedure);
 | 
			
		||||
  g_object_unref (procedure);
 | 
			
		||||
 | 
			
		||||
@ -218,12 +234,11 @@ register_palette_select_procs (PikaPDB *pdb)
 | 
			
		||||
                                                       NULL,
 | 
			
		||||
                                                       PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               pika_param_spec_string ("palette-name",
 | 
			
		||||
                                                       "palette name",
 | 
			
		||||
                                                       "The name of the palette to set as selected",
 | 
			
		||||
                                                       FALSE, FALSE, FALSE,
 | 
			
		||||
                                                       NULL,
 | 
			
		||||
                                                       PIKA_PARAM_READWRITE));
 | 
			
		||||
                               pika_param_spec_palette ("palette",
 | 
			
		||||
                                                        "palette",
 | 
			
		||||
                                                        "The palette to set as selected",
 | 
			
		||||
                                                        FALSE,
 | 
			
		||||
                                                        PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_pdb_register_procedure (pdb, procedure);
 | 
			
		||||
  g_object_unref (procedure);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -256,7 +256,7 @@ register_pattern_procs (PikaPDB *pdb)
 | 
			
		||||
                               "pika-pattern-get-pixels");
 | 
			
		||||
  pika_procedure_set_static_help (procedure,
 | 
			
		||||
                                  "Gets information about the pattern (including pixels).",
 | 
			
		||||
                                  "Gets information about the pattern: the pattern extents (width and height), its bpp, and its pixel data. The pixel data is an array in C or a list in some languages.",
 | 
			
		||||
                                  "Gets information about the pattern: the pattern extents (width and height), its bpp, and its pixel data.",
 | 
			
		||||
                                  NULL);
 | 
			
		||||
  pika_procedure_set_static_attribution (procedure,
 | 
			
		||||
                                         "Michael Natterer <mitch@gimp.org>",
 | 
			
		||||
 | 
			
		||||
@ -34,8 +34,10 @@
 | 
			
		||||
#include "pdb-types.h"
 | 
			
		||||
 | 
			
		||||
#include "core/pika.h"
 | 
			
		||||
#include "core/pikacontainer.h"
 | 
			
		||||
#include "core/pikadatafactory.h"
 | 
			
		||||
#include "core/pikaparamspecs.h"
 | 
			
		||||
#include "core/pikapattern.h"
 | 
			
		||||
 | 
			
		||||
#include "pikapdb.h"
 | 
			
		||||
#include "pikaprocedure.h"
 | 
			
		||||
@ -53,20 +55,24 @@ patterns_popup_invoker (PikaProcedure         *procedure,
 | 
			
		||||
  gboolean success = TRUE;
 | 
			
		||||
  const gchar *pattern_callback;
 | 
			
		||||
  const gchar *popup_title;
 | 
			
		||||
  const gchar *initial_pattern_name;
 | 
			
		||||
  PikaPattern *initial_pattern;
 | 
			
		||||
  GBytes *parent_window;
 | 
			
		||||
 | 
			
		||||
  pattern_callback = g_value_get_string (pika_value_array_index (args, 0));
 | 
			
		||||
  popup_title = g_value_get_string (pika_value_array_index (args, 1));
 | 
			
		||||
  initial_pattern_name = g_value_get_string (pika_value_array_index (args, 2));
 | 
			
		||||
  initial_pattern = g_value_get_object (pika_value_array_index (args, 2));
 | 
			
		||||
  parent_window = g_value_get_boxed (pika_value_array_index (args, 3));
 | 
			
		||||
 | 
			
		||||
  if (success)
 | 
			
		||||
    {
 | 
			
		||||
      PikaContainer *container = pika_data_factory_get_container (pika->pattern_factory);
 | 
			
		||||
 | 
			
		||||
      if (pika->no_interface ||
 | 
			
		||||
          ! pika_pdb_lookup_procedure (pika->pdb, pattern_callback) ||
 | 
			
		||||
          ! pika_pdb_dialog_new (pika, context, progress,
 | 
			
		||||
                                 pika_data_factory_get_container (pika->pattern_factory),
 | 
			
		||||
                                 popup_title, pattern_callback, initial_pattern_name,
 | 
			
		||||
                                 NULL))
 | 
			
		||||
                                 pika_container_get_children_type (container),
 | 
			
		||||
                                 parent_window, popup_title, pattern_callback,
 | 
			
		||||
                                 PIKA_OBJECT (initial_pattern), NULL))
 | 
			
		||||
        success = FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -89,9 +95,12 @@ patterns_close_popup_invoker (PikaProcedure         *procedure,
 | 
			
		||||
 | 
			
		||||
  if (success)
 | 
			
		||||
    {
 | 
			
		||||
      PikaContainer *container = pika_data_factory_get_container (pika->pattern_factory);
 | 
			
		||||
 | 
			
		||||
      if (pika->no_interface ||
 | 
			
		||||
          ! pika_pdb_lookup_procedure (pika->pdb, pattern_callback) ||
 | 
			
		||||
          ! pika_pdb_dialog_close (pika, pika_data_factory_get_container (pika->pattern_factory),
 | 
			
		||||
          ! pika_pdb_dialog_close (pika,
 | 
			
		||||
                                   pika_container_get_children_type (container),
 | 
			
		||||
                                   pattern_callback))
 | 
			
		||||
        success = FALSE;
 | 
			
		||||
    }
 | 
			
		||||
@ -110,18 +119,20 @@ patterns_set_popup_invoker (PikaProcedure         *procedure,
 | 
			
		||||
{
 | 
			
		||||
  gboolean success = TRUE;
 | 
			
		||||
  const gchar *pattern_callback;
 | 
			
		||||
  const gchar *pattern_name;
 | 
			
		||||
  PikaPattern *pattern;
 | 
			
		||||
 | 
			
		||||
  pattern_callback = g_value_get_string (pika_value_array_index (args, 0));
 | 
			
		||||
  pattern_name = g_value_get_string (pika_value_array_index (args, 1));
 | 
			
		||||
  pattern = g_value_get_object (pika_value_array_index (args, 1));
 | 
			
		||||
 | 
			
		||||
  if (success)
 | 
			
		||||
    {
 | 
			
		||||
      PikaContainer *container = pika_data_factory_get_container (pika->pattern_factory);
 | 
			
		||||
 | 
			
		||||
      if (pika->no_interface ||
 | 
			
		||||
          ! pika_pdb_lookup_procedure (pika->pdb, pattern_callback) ||
 | 
			
		||||
          ! pika_pdb_dialog_set (pika, pika_data_factory_get_container (pika->pattern_factory),
 | 
			
		||||
                                 pattern_callback, pattern_name,
 | 
			
		||||
                                 NULL))
 | 
			
		||||
          ! pika_pdb_dialog_set (pika,
 | 
			
		||||
                                 pika_container_get_children_type (container),
 | 
			
		||||
                                 pattern_callback, PIKA_OBJECT (pattern), NULL))
 | 
			
		||||
        success = FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -163,12 +174,17 @@ register_pattern_select_procs (PikaPDB *pdb)
 | 
			
		||||
                                                       NULL,
 | 
			
		||||
                                                       PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               pika_param_spec_string ("initial-pattern-name",
 | 
			
		||||
                                                       "initial pattern name",
 | 
			
		||||
                                                       "The name of the pattern to set as the initial choice",
 | 
			
		||||
                                                       FALSE, TRUE, FALSE,
 | 
			
		||||
                                                       NULL,
 | 
			
		||||
                                                       PIKA_PARAM_READWRITE));
 | 
			
		||||
                               pika_param_spec_pattern ("initial-pattern",
 | 
			
		||||
                                                        "initial pattern",
 | 
			
		||||
                                                        "The pattern to set as the initial choice",
 | 
			
		||||
                                                        FALSE,
 | 
			
		||||
                                                        PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               g_param_spec_boxed ("parent-window",
 | 
			
		||||
                                                   "parent window",
 | 
			
		||||
                                                   "An optional parent window handle for the popup to be set transient to",
 | 
			
		||||
                                                   G_TYPE_BYTES,
 | 
			
		||||
                                                   PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_pdb_register_procedure (pdb, procedure);
 | 
			
		||||
  g_object_unref (procedure);
 | 
			
		||||
 | 
			
		||||
@ -218,12 +234,11 @@ register_pattern_select_procs (PikaPDB *pdb)
 | 
			
		||||
                                                       NULL,
 | 
			
		||||
                                                       PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               pika_param_spec_string ("pattern-name",
 | 
			
		||||
                                                       "pattern name",
 | 
			
		||||
                                                       "The name of the pattern to set as selected",
 | 
			
		||||
                                                       FALSE, FALSE, FALSE,
 | 
			
		||||
                                                       NULL,
 | 
			
		||||
                                                       PIKA_PARAM_READWRITE));
 | 
			
		||||
                               pika_param_spec_pattern ("pattern",
 | 
			
		||||
                                                        "pattern",
 | 
			
		||||
                                                        "The pattern to set as selected",
 | 
			
		||||
                                                        FALSE,
 | 
			
		||||
                                                        PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_pdb_register_procedure (pdb, procedure);
 | 
			
		||||
  g_object_unref (procedure);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1167,47 +1167,6 @@ pdb_get_data_invoker (PikaProcedure         *procedure,
 | 
			
		||||
  return return_vals;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static PikaValueArray *
 | 
			
		||||
pdb_get_data_size_invoker (PikaProcedure         *procedure,
 | 
			
		||||
                           Pika                  *pika,
 | 
			
		||||
                           PikaContext           *context,
 | 
			
		||||
                           PikaProgress          *progress,
 | 
			
		||||
                           const PikaValueArray  *args,
 | 
			
		||||
                           GError               **error)
 | 
			
		||||
{
 | 
			
		||||
  gboolean success = TRUE;
 | 
			
		||||
  PikaValueArray *return_vals;
 | 
			
		||||
  const gchar *identifier;
 | 
			
		||||
  gint bytes = 0;
 | 
			
		||||
 | 
			
		||||
  identifier = g_value_get_string (pika_value_array_index (args, 0));
 | 
			
		||||
 | 
			
		||||
  if (success)
 | 
			
		||||
    {
 | 
			
		||||
      if (pika_is_canonical_identifier (identifier))
 | 
			
		||||
        {
 | 
			
		||||
          if (! pika_plug_in_manager_get_data (pika->plug_in_manager,
 | 
			
		||||
                                               identifier, &bytes))
 | 
			
		||||
            success = FALSE;
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
          g_set_error (error, PIKA_PDB_ERROR, PIKA_PDB_ERROR_INVALID_ARGUMENT,
 | 
			
		||||
                       _("Data label '%s' is not a canonical identifier"),
 | 
			
		||||
                       identifier);
 | 
			
		||||
          success = FALSE;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return_vals = pika_procedure_get_return_values (procedure, success,
 | 
			
		||||
                                                  error ? *error : NULL);
 | 
			
		||||
 | 
			
		||||
  if (success)
 | 
			
		||||
    g_value_set_int (pika_value_array_index (return_vals, 1), bytes);
 | 
			
		||||
 | 
			
		||||
  return return_vals;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static PikaValueArray *
 | 
			
		||||
pdb_set_data_invoker (PikaProcedure         *procedure,
 | 
			
		||||
                      Pika                  *pika,
 | 
			
		||||
@ -2230,36 +2189,6 @@ register_pdb_procs (PikaPDB *pdb)
 | 
			
		||||
  pika_pdb_register_procedure (pdb, procedure);
 | 
			
		||||
  g_object_unref (procedure);
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
   * pika-pdb-get-data-size
 | 
			
		||||
   */
 | 
			
		||||
  procedure = pika_procedure_new (pdb_get_data_size_invoker);
 | 
			
		||||
  pika_object_set_static_name (PIKA_OBJECT (procedure),
 | 
			
		||||
                               "pika-pdb-get-data-size");
 | 
			
		||||
  pika_procedure_set_static_help (procedure,
 | 
			
		||||
                                  "Returns size of data associated with the specified identifier.",
 | 
			
		||||
                                  "This procedure returns the size of any data which may have been associated with the specified identifier. If no data has been associated with the identifier, an error is returned.",
 | 
			
		||||
                                  NULL);
 | 
			
		||||
  pika_procedure_set_static_attribution (procedure,
 | 
			
		||||
                                         "Nick Lamb",
 | 
			
		||||
                                         "Nick Lamb",
 | 
			
		||||
                                         "1998");
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               pika_param_spec_string ("identifier",
 | 
			
		||||
                                                       "identifier",
 | 
			
		||||
                                                       "The identifier associated with data",
 | 
			
		||||
                                                       FALSE, FALSE, TRUE,
 | 
			
		||||
                                                       NULL,
 | 
			
		||||
                                                       PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_return_value (procedure,
 | 
			
		||||
                                   g_param_spec_int ("bytes",
 | 
			
		||||
                                                     "bytes",
 | 
			
		||||
                                                     "The number of bytes in the data",
 | 
			
		||||
                                                     1, G_MAXINT32, 1,
 | 
			
		||||
                                                     PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_pdb_register_procedure (pdb, procedure);
 | 
			
		||||
  g_object_unref (procedure);
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
   * pika-pdb-set-data
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
@ -105,6 +105,91 @@ pika_pdb_get_data_factory (Pika  *pika,
 | 
			
		||||
  g_return_val_if_reached (NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GList *
 | 
			
		||||
pika_pdb_get_resources (Pika               *pika,
 | 
			
		||||
                        GType               data_type,
 | 
			
		||||
                        const gchar        *name,
 | 
			
		||||
                        PikaPDBDataAccess   access,
 | 
			
		||||
                        GError            **error)
 | 
			
		||||
{
 | 
			
		||||
  GList           *resources;
 | 
			
		||||
  PikaDataFactory *factory;
 | 
			
		||||
  PikaContainer   *container;
 | 
			
		||||
  const gchar     *label;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (PIKA_IS_PIKA (pika), NULL);
 | 
			
		||||
  g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 | 
			
		||||
 | 
			
		||||
  label = pika_pdb_get_data_label (data_type);
 | 
			
		||||
 | 
			
		||||
  if (! name || ! strlen (name))
 | 
			
		||||
    {
 | 
			
		||||
      g_set_error (error, PIKA_PDB_ERROR, PIKA_PDB_ERROR_INVALID_ARGUMENT,
 | 
			
		||||
                   /* TRANSLATOR: %s is a data label from the
 | 
			
		||||
                    * PDB-error-data-label context.
 | 
			
		||||
                    */
 | 
			
		||||
                   C_("PDB-error-message", "%s name cannot be empty"),
 | 
			
		||||
                   g_type_name (data_type));
 | 
			
		||||
      return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  factory = pika_pdb_get_data_factory (pika, data_type);
 | 
			
		||||
  g_return_val_if_fail (PIKA_IS_DATA_FACTORY (factory), NULL);
 | 
			
		||||
 | 
			
		||||
  container = pika_data_factory_get_container (factory);
 | 
			
		||||
  resources = pika_container_get_children_by_name (container, name);
 | 
			
		||||
 | 
			
		||||
  if (! resources && ! strcmp (name, "Standard"))
 | 
			
		||||
    {
 | 
			
		||||
      PikaData *resource;
 | 
			
		||||
 | 
			
		||||
      resource = pika_data_factory_data_get_standard (factory, pika_get_user_context (pika));
 | 
			
		||||
      g_return_val_if_fail (resource != NULL, NULL);
 | 
			
		||||
      resources = g_list_prepend (NULL, resource);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (! resources)
 | 
			
		||||
    {
 | 
			
		||||
      g_set_error (error, PIKA_PDB_ERROR, PIKA_PDB_ERROR_INVALID_ARGUMENT,
 | 
			
		||||
                   /* TRANSLATOR: the first %s is a data label from the
 | 
			
		||||
                    * PDB-error-data-label context. The second %s is a data
 | 
			
		||||
                    * name.
 | 
			
		||||
                    */
 | 
			
		||||
                   C_("PDB-error-message", "%s '%s' not found"), label, name);
 | 
			
		||||
    }
 | 
			
		||||
  else if ((access & PIKA_PDB_DATA_ACCESS_WRITE) ||
 | 
			
		||||
           (access & PIKA_PDB_DATA_ACCESS_RENAME))
 | 
			
		||||
    {
 | 
			
		||||
      for (GList *iter = resources; iter; iter = iter->next)
 | 
			
		||||
        {
 | 
			
		||||
          if ((access & PIKA_PDB_DATA_ACCESS_WRITE) &&
 | 
			
		||||
              ! pika_data_is_writable (PIKA_DATA (iter->data)))
 | 
			
		||||
            {
 | 
			
		||||
              g_set_error (error, PIKA_PDB_ERROR, PIKA_PDB_ERROR_INVALID_ARGUMENT,
 | 
			
		||||
                           /* TRANSLATOR: the first %s is a data label from the
 | 
			
		||||
                            * PDB-error-data-label context. The second %s is a data
 | 
			
		||||
                            * name.
 | 
			
		||||
                            */
 | 
			
		||||
                           C_("PDB-error-message", "%s '%s' is not editable"), label, name);
 | 
			
		||||
              return NULL;
 | 
			
		||||
            }
 | 
			
		||||
          else if ((access & PIKA_PDB_DATA_ACCESS_RENAME) &&
 | 
			
		||||
                   ! pika_viewable_is_name_editable (PIKA_VIEWABLE (iter->data)))
 | 
			
		||||
            {
 | 
			
		||||
              g_set_error (error, PIKA_PDB_ERROR, PIKA_PDB_ERROR_INVALID_ARGUMENT,
 | 
			
		||||
                           /* TRANSLATOR: the first %s is a data label from the
 | 
			
		||||
                            * PDB-error-data-label context. The second %s is a data
 | 
			
		||||
                            * name.
 | 
			
		||||
                            */
 | 
			
		||||
                           C_("PDB-error-message", "%s '%s' is not renamable"), label, name);
 | 
			
		||||
              return NULL;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return resources;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PikaResource *
 | 
			
		||||
pika_pdb_get_resource (Pika               *pika,
 | 
			
		||||
                       GType               data_type,
 | 
			
		||||
 | 
			
		||||
@ -26,6 +26,11 @@
 | 
			
		||||
PikaDataFactory * pika_pdb_get_data_factory       (Pika               *pika,
 | 
			
		||||
                                                   GType               data_type);
 | 
			
		||||
 | 
			
		||||
GList           * pika_pdb_get_resources          (Pika               *pika,
 | 
			
		||||
                                                   GType               data_type,
 | 
			
		||||
                                                   const gchar        *name,
 | 
			
		||||
                                                   PikaPDBDataAccess   access,
 | 
			
		||||
                                                   GError            **error);
 | 
			
		||||
PikaResource    * pika_pdb_get_resource           (Pika               *pika,
 | 
			
		||||
                                                   GType               data_type,
 | 
			
		||||
                                                   const gchar        *name,
 | 
			
		||||
 | 
			
		||||
@ -193,14 +193,14 @@ progress_get_window_handle_invoker (PikaProcedure         *procedure,
 | 
			
		||||
{
 | 
			
		||||
  gboolean success = TRUE;
 | 
			
		||||
  PikaValueArray *return_vals;
 | 
			
		||||
  gint window = 0;
 | 
			
		||||
  GBytes *handle = NULL;
 | 
			
		||||
 | 
			
		||||
  PikaPlugIn *plug_in = pika->plug_in_manager->current_plug_in;
 | 
			
		||||
 | 
			
		||||
  if (plug_in && plug_in->open)
 | 
			
		||||
    {
 | 
			
		||||
      if (! pika->no_interface)
 | 
			
		||||
        window = pika_plug_in_progress_get_window_id (plug_in);
 | 
			
		||||
        handle = pika_plug_in_progress_get_window_id (plug_in);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    success = FALSE;
 | 
			
		||||
@ -209,7 +209,7 @@ progress_get_window_handle_invoker (PikaProcedure         *procedure,
 | 
			
		||||
                                                  error ? *error : NULL);
 | 
			
		||||
 | 
			
		||||
  if (success)
 | 
			
		||||
    g_value_set_int (pika_value_array_index (return_vals, 1), window);
 | 
			
		||||
    g_value_take_boxed (pika_value_array_index (return_vals, 1), handle);
 | 
			
		||||
 | 
			
		||||
  return return_vals;
 | 
			
		||||
}
 | 
			
		||||
@ -418,19 +418,20 @@ register_progress_procs (PikaPDB *pdb)
 | 
			
		||||
  pika_object_set_static_name (PIKA_OBJECT (procedure),
 | 
			
		||||
                               "pika-progress-get-window-handle");
 | 
			
		||||
  pika_procedure_set_static_help (procedure,
 | 
			
		||||
                                  "Returns the native window ID of the toplevel window this plug-in's progress is displayed in.",
 | 
			
		||||
                                  "This function returns the native window ID of the toplevel window this plug-in\'s progress is displayed in.",
 | 
			
		||||
                                  "Returns the native handle of the toplevel window this plug-in's progress is displayed in.",
 | 
			
		||||
                                  "This function returns the native handle allowing to identify the toplevel window this plug-in's progress is displayed in.\n"
 | 
			
		||||
                                  "This handle can be of various types (integer, string, etc.) depending on the platform you are running on which is why it returns a GBytes. There are usually no reasons to call this directly.",
 | 
			
		||||
                                  NULL);
 | 
			
		||||
  pika_procedure_set_static_attribution (procedure,
 | 
			
		||||
                                         "Michael Natterer <mitch@gimp.org>",
 | 
			
		||||
                                         "Michael Natterer",
 | 
			
		||||
                                         "2004");
 | 
			
		||||
  pika_procedure_add_return_value (procedure,
 | 
			
		||||
                                   g_param_spec_int ("window",
 | 
			
		||||
                                                     "window",
 | 
			
		||||
                                                     "The progress bar's toplevel window",
 | 
			
		||||
                                                     G_MININT32, G_MAXINT32, 0,
 | 
			
		||||
                                                     PIKA_PARAM_READWRITE));
 | 
			
		||||
                                   g_param_spec_boxed ("handle",
 | 
			
		||||
                                                       "handle",
 | 
			
		||||
                                                       "The progress bar's toplevel window's handle",
 | 
			
		||||
                                                       G_TYPE_BYTES,
 | 
			
		||||
                                                       PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_pdb_register_procedure (pdb, procedure);
 | 
			
		||||
  g_object_unref (procedure);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -67,14 +67,14 @@ text_layer_new_invoker (PikaProcedure         *procedure,
 | 
			
		||||
  PikaValueArray *return_vals;
 | 
			
		||||
  PikaImage *image;
 | 
			
		||||
  const gchar *text;
 | 
			
		||||
  const gchar *fontname;
 | 
			
		||||
  PikaFont *font;
 | 
			
		||||
  gdouble size;
 | 
			
		||||
  PikaUnit unit;
 | 
			
		||||
  PikaTextLayer *layer = NULL;
 | 
			
		||||
 | 
			
		||||
  image = g_value_get_object (pika_value_array_index (args, 0));
 | 
			
		||||
  text = g_value_get_string (pika_value_array_index (args, 1));
 | 
			
		||||
  fontname = g_value_get_string (pika_value_array_index (args, 2));
 | 
			
		||||
  font = g_value_get_object (pika_value_array_index (args, 2));
 | 
			
		||||
  size = g_value_get_double (pika_value_array_index (args, 3));
 | 
			
		||||
  unit = g_value_get_int (pika_value_array_index (args, 4));
 | 
			
		||||
 | 
			
		||||
@ -87,7 +87,7 @@ text_layer_new_invoker (PikaProcedure         *procedure,
 | 
			
		||||
 | 
			
		||||
      pika_text = g_object_new (PIKA_TYPE_TEXT,
 | 
			
		||||
                                "text",           text,
 | 
			
		||||
                                "font",           fontname,
 | 
			
		||||
                                "font",           font,
 | 
			
		||||
                                "font-size",      size,
 | 
			
		||||
                                "font-size-unit", unit,
 | 
			
		||||
                                "color",          &color,
 | 
			
		||||
@ -259,26 +259,26 @@ text_layer_get_font_invoker (PikaProcedure         *procedure,
 | 
			
		||||
  gboolean success = TRUE;
 | 
			
		||||
  PikaValueArray *return_vals;
 | 
			
		||||
  PikaTextLayer *layer;
 | 
			
		||||
  gchar *font = NULL;
 | 
			
		||||
  PikaFont *font = NULL;
 | 
			
		||||
 | 
			
		||||
  layer = g_value_get_object (pika_value_array_index (args, 0));
 | 
			
		||||
 | 
			
		||||
  if (success)
 | 
			
		||||
    {
 | 
			
		||||
      PikaFont *font_obj;
 | 
			
		||||
 | 
			
		||||
      g_object_get (pika_text_layer_get_text (layer),
 | 
			
		||||
                    "font", &font_obj,
 | 
			
		||||
                    "font", &font,
 | 
			
		||||
                    NULL);
 | 
			
		||||
      font = g_strdup (pika_font_get_lookup_name (font_obj));
 | 
			
		||||
      g_object_unref (font_obj);
 | 
			
		||||
      /* The PikaText keeps a reference. Therefore unref before returning the
 | 
			
		||||
       * pointer so that we don't leak a reference.
 | 
			
		||||
       */
 | 
			
		||||
      g_object_unref (font);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return_vals = pika_procedure_get_return_values (procedure, success,
 | 
			
		||||
                                                  error ? *error : NULL);
 | 
			
		||||
 | 
			
		||||
  if (success)
 | 
			
		||||
    g_value_take_string (pika_value_array_index (return_vals, 1), font);
 | 
			
		||||
    g_value_set_object (pika_value_array_index (return_vals, 1), font);
 | 
			
		||||
 | 
			
		||||
  return return_vals;
 | 
			
		||||
}
 | 
			
		||||
@ -293,10 +293,10 @@ text_layer_set_font_invoker (PikaProcedure         *procedure,
 | 
			
		||||
{
 | 
			
		||||
  gboolean success = TRUE;
 | 
			
		||||
  PikaTextLayer *layer;
 | 
			
		||||
  const gchar *font;
 | 
			
		||||
  PikaFont *font;
 | 
			
		||||
 | 
			
		||||
  layer = g_value_get_object (pika_value_array_index (args, 0));
 | 
			
		||||
  font = g_value_get_string (pika_value_array_index (args, 1));
 | 
			
		||||
  font = g_value_get_object (pika_value_array_index (args, 1));
 | 
			
		||||
 | 
			
		||||
  if (success)
 | 
			
		||||
    {
 | 
			
		||||
@ -1028,12 +1028,11 @@ register_text_layer_procs (PikaPDB *pdb)
 | 
			
		||||
                                                       NULL,
 | 
			
		||||
                                                       PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               pika_param_spec_string ("fontname",
 | 
			
		||||
                                                       "fontname",
 | 
			
		||||
                                                       "The name of the font",
 | 
			
		||||
                                                       FALSE, FALSE, FALSE,
 | 
			
		||||
                                                       NULL,
 | 
			
		||||
                                                       PIKA_PARAM_READWRITE));
 | 
			
		||||
                               pika_param_spec_font ("font",
 | 
			
		||||
                                                     "font",
 | 
			
		||||
                                                     "The font to write the text with",
 | 
			
		||||
                                                     FALSE,
 | 
			
		||||
                                                     PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               g_param_spec_double ("size",
 | 
			
		||||
                                                    "size",
 | 
			
		||||
@ -1186,7 +1185,7 @@ register_text_layer_procs (PikaPDB *pdb)
 | 
			
		||||
                               "pika-text-layer-get-font");
 | 
			
		||||
  pika_procedure_set_static_help (procedure,
 | 
			
		||||
                                  "Get the font from a text layer as string.",
 | 
			
		||||
                                  "This procedure returns the name of the font from a text layer.",
 | 
			
		||||
                                  "This procedure returns the font from a text layer.",
 | 
			
		||||
                                  NULL);
 | 
			
		||||
  pika_procedure_set_static_attribution (procedure,
 | 
			
		||||
                                         "Marcus Heese <heese@cip.ifi.lmu.de>",
 | 
			
		||||
@ -1199,12 +1198,11 @@ register_text_layer_procs (PikaPDB *pdb)
 | 
			
		||||
                                                           FALSE,
 | 
			
		||||
                                                           PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_return_value (procedure,
 | 
			
		||||
                                   pika_param_spec_string ("font",
 | 
			
		||||
                                                           "font",
 | 
			
		||||
                                                           "The font which is used in the specified text layer.",
 | 
			
		||||
                                                           FALSE, FALSE, FALSE,
 | 
			
		||||
                                                           NULL,
 | 
			
		||||
                                                           PIKA_PARAM_READWRITE));
 | 
			
		||||
                                   pika_param_spec_font ("font",
 | 
			
		||||
                                                         "font",
 | 
			
		||||
                                                         "The font which is used in the specified text layer.",
 | 
			
		||||
                                                         FALSE,
 | 
			
		||||
                                                         PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_pdb_register_procedure (pdb, procedure);
 | 
			
		||||
  g_object_unref (procedure);
 | 
			
		||||
 | 
			
		||||
@ -1229,12 +1227,11 @@ register_text_layer_procs (PikaPDB *pdb)
 | 
			
		||||
                                                           FALSE,
 | 
			
		||||
                                                           PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               pika_param_spec_string ("font",
 | 
			
		||||
                                                       "font",
 | 
			
		||||
                                                       "The new font to use",
 | 
			
		||||
                                                       FALSE, FALSE, FALSE,
 | 
			
		||||
                                                       NULL,
 | 
			
		||||
                                                       PIKA_PARAM_READWRITE));
 | 
			
		||||
                               pika_param_spec_font ("font",
 | 
			
		||||
                                                     "font",
 | 
			
		||||
                                                     "The new font to use",
 | 
			
		||||
                                                     FALSE,
 | 
			
		||||
                                                     PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_pdb_register_procedure (pdb, procedure);
 | 
			
		||||
  g_object_unref (procedure);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -39,6 +39,7 @@
 | 
			
		||||
#include "core/pikaimage.h"
 | 
			
		||||
#include "core/pikalayer.h"
 | 
			
		||||
#include "core/pikaparamspecs.h"
 | 
			
		||||
#include "text/pikafont.h"
 | 
			
		||||
#include "text/pikatext-compat.h"
 | 
			
		||||
 | 
			
		||||
#include "pikapdb.h"
 | 
			
		||||
@ -48,12 +49,12 @@
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static PikaValueArray *
 | 
			
		||||
text_fontname_invoker (PikaProcedure         *procedure,
 | 
			
		||||
                       Pika                  *pika,
 | 
			
		||||
                       PikaContext           *context,
 | 
			
		||||
                       PikaProgress          *progress,
 | 
			
		||||
                       const PikaValueArray  *args,
 | 
			
		||||
                       GError               **error)
 | 
			
		||||
text_font_invoker (PikaProcedure         *procedure,
 | 
			
		||||
                   Pika                  *pika,
 | 
			
		||||
                   PikaContext           *context,
 | 
			
		||||
                   PikaProgress          *progress,
 | 
			
		||||
                   const PikaValueArray  *args,
 | 
			
		||||
                   GError               **error)
 | 
			
		||||
{
 | 
			
		||||
  gboolean success = TRUE;
 | 
			
		||||
  PikaValueArray *return_vals;
 | 
			
		||||
@ -65,7 +66,7 @@ text_fontname_invoker (PikaProcedure         *procedure,
 | 
			
		||||
  gint border;
 | 
			
		||||
  gboolean antialias;
 | 
			
		||||
  gdouble size;
 | 
			
		||||
  const gchar *fontname;
 | 
			
		||||
  PikaFont *font;
 | 
			
		||||
  PikaLayer *text_layer = NULL;
 | 
			
		||||
 | 
			
		||||
  image = g_value_get_object (pika_value_array_index (args, 0));
 | 
			
		||||
@ -76,7 +77,7 @@ text_fontname_invoker (PikaProcedure         *procedure,
 | 
			
		||||
  border = g_value_get_int (pika_value_array_index (args, 5));
 | 
			
		||||
  antialias = g_value_get_boolean (pika_value_array_index (args, 6));
 | 
			
		||||
  size = g_value_get_double (pika_value_array_index (args, 7));
 | 
			
		||||
  fontname = g_value_get_string (pika_value_array_index (args, 9));
 | 
			
		||||
  font = g_value_get_object (pika_value_array_index (args, 8));
 | 
			
		||||
 | 
			
		||||
  if (success)
 | 
			
		||||
    {
 | 
			
		||||
@ -87,15 +88,9 @@ text_fontname_invoker (PikaProcedure         *procedure,
 | 
			
		||||
        success = FALSE;
 | 
			
		||||
 | 
			
		||||
      if (success)
 | 
			
		||||
        {
 | 
			
		||||
          gchar *real_fontname = g_strdup_printf ("%s %d", fontname, (gint) size);
 | 
			
		||||
 | 
			
		||||
          text_layer = text_render (image, drawable, context,
 | 
			
		||||
                                    x, y, real_fontname, text,
 | 
			
		||||
                                    border, antialias);
 | 
			
		||||
 | 
			
		||||
          g_free (real_fontname);
 | 
			
		||||
        }
 | 
			
		||||
        text_layer = text_render (image, drawable, context,
 | 
			
		||||
                                  x, y, font, size, text,
 | 
			
		||||
                                  border, antialias);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return_vals = pika_procedure_get_return_values (procedure, success,
 | 
			
		||||
@ -108,18 +103,18 @@ text_fontname_invoker (PikaProcedure         *procedure,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static PikaValueArray *
 | 
			
		||||
text_get_extents_fontname_invoker (PikaProcedure         *procedure,
 | 
			
		||||
                                   Pika                  *pika,
 | 
			
		||||
                                   PikaContext           *context,
 | 
			
		||||
                                   PikaProgress          *progress,
 | 
			
		||||
                                   const PikaValueArray  *args,
 | 
			
		||||
                                   GError               **error)
 | 
			
		||||
text_get_extents_font_invoker (PikaProcedure         *procedure,
 | 
			
		||||
                               Pika                  *pika,
 | 
			
		||||
                               PikaContext           *context,
 | 
			
		||||
                               PikaProgress          *progress,
 | 
			
		||||
                               const PikaValueArray  *args,
 | 
			
		||||
                               GError               **error)
 | 
			
		||||
{
 | 
			
		||||
  gboolean success = TRUE;
 | 
			
		||||
  PikaValueArray *return_vals;
 | 
			
		||||
  const gchar *text;
 | 
			
		||||
  gdouble size;
 | 
			
		||||
  const gchar *fontname;
 | 
			
		||||
  PikaFont *font;
 | 
			
		||||
  gint width = 0;
 | 
			
		||||
  gint height = 0;
 | 
			
		||||
  gint ascent = 0;
 | 
			
		||||
@ -127,18 +122,14 @@ text_get_extents_fontname_invoker (PikaProcedure         *procedure,
 | 
			
		||||
 | 
			
		||||
  text = g_value_get_string (pika_value_array_index (args, 0));
 | 
			
		||||
  size = g_value_get_double (pika_value_array_index (args, 1));
 | 
			
		||||
  fontname = g_value_get_string (pika_value_array_index (args, 3));
 | 
			
		||||
  font = g_value_get_object (pika_value_array_index (args, 2));
 | 
			
		||||
 | 
			
		||||
  if (success)
 | 
			
		||||
    {
 | 
			
		||||
      gchar *real_fontname = g_strdup_printf ("%s %d", fontname, (gint) size);
 | 
			
		||||
 | 
			
		||||
      success = text_get_extents (pika,
 | 
			
		||||
                                  real_fontname, text,
 | 
			
		||||
                                  font, size, text,
 | 
			
		||||
                                  &width, &height,
 | 
			
		||||
                                  &ascent, &descent);
 | 
			
		||||
 | 
			
		||||
      g_free (real_fontname);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return_vals = pika_procedure_get_return_values (procedure, success,
 | 
			
		||||
@ -161,14 +152,15 @@ register_text_tool_procs (PikaPDB *pdb)
 | 
			
		||||
  PikaProcedure *procedure;
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
   * pika-text-fontname
 | 
			
		||||
   * pika-text-font
 | 
			
		||||
   */
 | 
			
		||||
  procedure = pika_procedure_new (text_fontname_invoker);
 | 
			
		||||
  procedure = pika_procedure_new (text_font_invoker);
 | 
			
		||||
  pika_object_set_static_name (PIKA_OBJECT (procedure),
 | 
			
		||||
                               "pika-text-fontname");
 | 
			
		||||
                               "pika-text-font");
 | 
			
		||||
  pika_procedure_set_static_help (procedure,
 | 
			
		||||
                                  "Add text at the specified location as a floating selection or a new layer.",
 | 
			
		||||
                                  "This tool requires a fontname matching an installed PangoFT2 font. You can specify the fontsize in units of pixels or points, and the appropriate metric is specified using the size_type argument. The x and y parameters together control the placement of the new text by specifying the upper left corner of the text bounding box. If the specified drawable parameter is valid, the text will be created as a floating selection attached to the drawable. If the drawable parameter is not valid (%NULL), the text will appear as a new layer. Finally, a border can be specified around the final rendered text. The border is measured in pixels. Parameter size-type is not used and is currently ignored. If you need to display a font in points, divide the size in points by 72.0 and multiply it by the image's vertical resolution.",
 | 
			
		||||
                                  "The x and y parameters together control the placement of the new text by specifying the upper left corner of the text bounding box. If the specified drawable parameter is valid, the text will be created as a floating selection attached to the drawable. If the drawable parameter is not valid (%NULL), the text will appear as a new layer. Finally, a border can be specified around the final rendered text. The border is measured in pixels.\n"
 | 
			
		||||
                                  "The size is always in pixels. If you need to display a font in points, divide the size in points by 72.0 and multiply it by the image's vertical resolution.",
 | 
			
		||||
                                  NULL);
 | 
			
		||||
  pika_procedure_set_static_attribution (procedure,
 | 
			
		||||
                                         "Martin Edlman & Sven Neumann",
 | 
			
		||||
@ -220,23 +212,15 @@ register_text_tool_procs (PikaPDB *pdb)
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               g_param_spec_double ("size",
 | 
			
		||||
                                                    "size",
 | 
			
		||||
                                                    "The size of text in either pixels or points",
 | 
			
		||||
                                                    "The size of text in pixels",
 | 
			
		||||
                                                    0, G_MAXDOUBLE, 0,
 | 
			
		||||
                                                    PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               g_param_spec_enum ("size-type",
 | 
			
		||||
                                                  "size type",
 | 
			
		||||
                                                  "The units of specified size",
 | 
			
		||||
                                                  PIKA_TYPE_SIZE_TYPE,
 | 
			
		||||
                                                  PIKA_PIXELS,
 | 
			
		||||
                                                  PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               pika_param_spec_string ("fontname",
 | 
			
		||||
                                                       "fontname",
 | 
			
		||||
                                                       "The name of the font",
 | 
			
		||||
                                                       FALSE, FALSE, FALSE,
 | 
			
		||||
                                                       NULL,
 | 
			
		||||
                                                       PIKA_PARAM_READWRITE));
 | 
			
		||||
                               pika_param_spec_font ("font",
 | 
			
		||||
                                                     "font",
 | 
			
		||||
                                                     "The font",
 | 
			
		||||
                                                     FALSE,
 | 
			
		||||
                                                     PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_return_value (procedure,
 | 
			
		||||
                                   pika_param_spec_layer ("text-layer",
 | 
			
		||||
                                                          "text layer",
 | 
			
		||||
@ -247,14 +231,16 @@ register_text_tool_procs (PikaPDB *pdb)
 | 
			
		||||
  g_object_unref (procedure);
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
   * pika-text-get-extents-fontname
 | 
			
		||||
   * pika-text-get-extents-font
 | 
			
		||||
   */
 | 
			
		||||
  procedure = pika_procedure_new (text_get_extents_fontname_invoker);
 | 
			
		||||
  procedure = pika_procedure_new (text_get_extents_font_invoker);
 | 
			
		||||
  pika_object_set_static_name (PIKA_OBJECT (procedure),
 | 
			
		||||
                               "pika-text-get-extents-fontname");
 | 
			
		||||
                               "pika-text-get-extents-font");
 | 
			
		||||
  pika_procedure_set_static_help (procedure,
 | 
			
		||||
                                  "Get extents of the bounding box for the specified text.",
 | 
			
		||||
                                  "This tool returns the width and height of a bounding box for the specified text string with the specified font information. Ascent and descent for the specified font are returned as well. Parameter size-type is not used and is currently ignored. If you need to display a font in points, divide the size in points by 72.0 and multiply it by the vertical resolution of the image you are taking into account.",
 | 
			
		||||
                                  "This tool returns the width and height of a bounding box for the specified text rendered with the specified font information. Ascent and descent of the glyph extents are returned as well.\n"
 | 
			
		||||
                                  "The ascent is the distance from the baseline to the highest point of the character. This is positive if the glyph ascends above the baseline. The descent is the distance from the baseline to the lowest point of the character. This is positive if the glyph descends below the baseline.\n"
 | 
			
		||||
                                  "The size is always in pixels. If you need to set a font in points, divide the size in points by 72.0 and multiply it by the vertical resolution of the image you are taking into account.",
 | 
			
		||||
                                  NULL);
 | 
			
		||||
  pika_procedure_set_static_attribution (procedure,
 | 
			
		||||
                                         "Martin Edlman & Sven Neumann",
 | 
			
		||||
@ -274,41 +260,33 @@ register_text_tool_procs (PikaPDB *pdb)
 | 
			
		||||
                                                    0, G_MAXDOUBLE, 0,
 | 
			
		||||
                                                    PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               g_param_spec_enum ("size-type",
 | 
			
		||||
                                                  "size type",
 | 
			
		||||
                                                  "The units of specified size",
 | 
			
		||||
                                                  PIKA_TYPE_SIZE_TYPE,
 | 
			
		||||
                                                  PIKA_PIXELS,
 | 
			
		||||
                                                  PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_argument (procedure,
 | 
			
		||||
                               pika_param_spec_string ("fontname",
 | 
			
		||||
                                                       "fontname",
 | 
			
		||||
                                                       "The name of the font",
 | 
			
		||||
                                                       FALSE, FALSE, FALSE,
 | 
			
		||||
                                                       NULL,
 | 
			
		||||
                                                       PIKA_PARAM_READWRITE));
 | 
			
		||||
                               pika_param_spec_font ("font",
 | 
			
		||||
                                                     "font",
 | 
			
		||||
                                                     "The name of the font",
 | 
			
		||||
                                                     FALSE,
 | 
			
		||||
                                                     PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_return_value (procedure,
 | 
			
		||||
                                   g_param_spec_int ("width",
 | 
			
		||||
                                                     "width",
 | 
			
		||||
                                                     "The width of the specified font",
 | 
			
		||||
                                                     "The width of the glyph extents",
 | 
			
		||||
                                                     G_MININT32, G_MAXINT32, 0,
 | 
			
		||||
                                                     PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_return_value (procedure,
 | 
			
		||||
                                   g_param_spec_int ("height",
 | 
			
		||||
                                                     "height",
 | 
			
		||||
                                                     "The height of the specified font",
 | 
			
		||||
                                                     "The height of the glyph extents",
 | 
			
		||||
                                                     G_MININT32, G_MAXINT32, 0,
 | 
			
		||||
                                                     PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_return_value (procedure,
 | 
			
		||||
                                   g_param_spec_int ("ascent",
 | 
			
		||||
                                                     "ascent",
 | 
			
		||||
                                                     "The ascent of the specified font",
 | 
			
		||||
                                                     "The ascent of the glyph extents",
 | 
			
		||||
                                                     G_MININT32, G_MAXINT32, 0,
 | 
			
		||||
                                                     PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_procedure_add_return_value (procedure,
 | 
			
		||||
                                   g_param_spec_int ("descent",
 | 
			
		||||
                                                     "descent",
 | 
			
		||||
                                                     "The descent of the specified font",
 | 
			
		||||
                                                     "The descent of the glyph extents",
 | 
			
		||||
                                                     G_MININT32, G_MAXINT32, 0,
 | 
			
		||||
                                                     PIKA_PARAM_READWRITE));
 | 
			
		||||
  pika_pdb_register_procedure (pdb, procedure);
 | 
			
		||||
 | 
			
		||||
@ -439,14 +439,18 @@ pika_update_about_dialog (PikaCoreConfig   *config,
 | 
			
		||||
                          const GParamSpec *pspec,
 | 
			
		||||
                          gpointer          user_data)
 | 
			
		||||
{
 | 
			
		||||
#ifndef PIKA_CONSOLE_COMPILATION
 | 
			
		||||
  Pika *pika = user_data;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  g_signal_handlers_disconnect_by_func (config,
 | 
			
		||||
                                        (GCallback) pika_update_about_dialog,
 | 
			
		||||
                                        NULL);
 | 
			
		||||
                                        user_data);
 | 
			
		||||
 | 
			
		||||
  if (config->last_known_release != NULL)
 | 
			
		||||
    {
 | 
			
		||||
#ifndef PIKA_CONSOLE_COMPILATION
 | 
			
		||||
      gtk_widget_show (about_dialog_create (config));
 | 
			
		||||
      gtk_widget_show (about_dialog_create (pika));
 | 
			
		||||
#else
 | 
			
		||||
      g_printerr (_("A new version of PIKA (%s) was released.\n"
 | 
			
		||||
                    "It is recommended to update."),
 | 
			
		||||
@ -643,7 +647,7 @@ pika_update_auto_check (PikaCoreConfig *config,
 | 
			
		||||
 | 
			
		||||
  g_signal_connect (config, "notify::last-known-release",
 | 
			
		||||
                    (GCallback) pika_update_about_dialog,
 | 
			
		||||
                    NULL);
 | 
			
		||||
                    pika);
 | 
			
		||||
 | 
			
		||||
  pika_update_check (config);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -237,7 +237,7 @@ pika_plug_in_progress_pulse (PikaPlugIn *plug_in)
 | 
			
		||||
    pika_progress_pulse (proc_frame->progress);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
guint32
 | 
			
		||||
GBytes *
 | 
			
		||||
pika_plug_in_progress_get_window_id (PikaPlugIn *plug_in)
 | 
			
		||||
{
 | 
			
		||||
  PikaPlugInProcFrame *proc_frame;
 | 
			
		||||
 | 
			
		||||
@ -38,7 +38,7 @@ void       pika_plug_in_progress_set_text      (PikaPlugIn          *plug_in,
 | 
			
		||||
void       pika_plug_in_progress_set_value     (PikaPlugIn          *plug_in,
 | 
			
		||||
                                                gdouble              percentage);
 | 
			
		||||
void       pika_plug_in_progress_pulse         (PikaPlugIn          *plug_in);
 | 
			
		||||
guint32    pika_plug_in_progress_get_window_id (PikaPlugIn          *plug_in);
 | 
			
		||||
GBytes   * pika_plug_in_progress_get_window_id (PikaPlugIn          *plug_in);
 | 
			
		||||
 | 
			
		||||
gboolean   pika_plug_in_progress_install       (PikaPlugIn          *plug_in,
 | 
			
		||||
                                                const gchar         *progress_callback);
 | 
			
		||||
 | 
			
		||||
@ -665,10 +665,11 @@ pika_plug_in_manager_add_from_file (PikaPlugInManager *manager,
 | 
			
		||||
  basename = g_path_get_basename (filename);
 | 
			
		||||
  g_free (filename);
 | 
			
		||||
 | 
			
		||||
  /* When we scan build dirs for plug-ins, there will be some
 | 
			
		||||
  /* When we scan build dirs for plug-ins, there might be some
 | 
			
		||||
   * executable files that are not plug-ins that we want to ignore,
 | 
			
		||||
   * for example plug-ins/common/mkgen.pl if
 | 
			
		||||
   * PIKA_TESTING_PLUGINDIRS=plug-ins/common
 | 
			
		||||
   * for example back with autotools, there used to be a file
 | 
			
		||||
   * plug-ins/common/mkgen.pl if PIKA_TESTING_PLUGINDIRS=plug-ins/common
 | 
			
		||||
   * Such files should be listed in PIKA_TESTING_PLUGINDIRS_BASENAME_IGNORES
 | 
			
		||||
   */
 | 
			
		||||
  if (pika_plug_in_manager_ignore_plugin_basename (basename))
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
@ -830,6 +830,56 @@ plug_in_proc_arg_deserialize (GScanner      *scanner,
 | 
			
		||||
        }
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case GP_PARAM_DEF_TYPE_CHOICE:
 | 
			
		||||
        {
 | 
			
		||||
          PikaChoice *choice;
 | 
			
		||||
          gint        n_choices;
 | 
			
		||||
 | 
			
		||||
          if (! pika_scanner_parse_string (scanner,
 | 
			
		||||
                                           ¶m_def.meta.m_choice.default_val) ||
 | 
			
		||||
              ! pika_scanner_parse_int (scanner, &n_choices))
 | 
			
		||||
            {
 | 
			
		||||
              token = G_TOKEN_INT;
 | 
			
		||||
              goto error;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          choice = pika_choice_new ();
 | 
			
		||||
          param_def.meta.m_choice.choice = choice;
 | 
			
		||||
 | 
			
		||||
          for (int i = 0; i < n_choices; i++)
 | 
			
		||||
            {
 | 
			
		||||
              gchar *nick  = NULL;
 | 
			
		||||
              gchar *label = NULL;
 | 
			
		||||
              gchar *help  = NULL;
 | 
			
		||||
              gint   id;
 | 
			
		||||
 | 
			
		||||
              if (! pika_scanner_parse_string (scanner, &nick))
 | 
			
		||||
                {
 | 
			
		||||
                  token = G_TOKEN_STRING;
 | 
			
		||||
                  goto error;
 | 
			
		||||
                }
 | 
			
		||||
              if (! pika_scanner_parse_int (scanner, &id))
 | 
			
		||||
                {
 | 
			
		||||
                  token = G_TOKEN_INT;
 | 
			
		||||
                  goto error;
 | 
			
		||||
                }
 | 
			
		||||
              if (! pika_scanner_parse_string (scanner, &label) ||
 | 
			
		||||
                  ! pika_scanner_parse_string (scanner, &help))
 | 
			
		||||
                {
 | 
			
		||||
                  token = G_TOKEN_STRING;
 | 
			
		||||
                  g_free (nick);
 | 
			
		||||
                  g_free (label);
 | 
			
		||||
                  g_free (help);
 | 
			
		||||
                  goto error;
 | 
			
		||||
                }
 | 
			
		||||
              pika_choice_add (choice, nick, id, label, help);
 | 
			
		||||
              g_free (nick);
 | 
			
		||||
              g_free (label);
 | 
			
		||||
              g_free (help);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case GP_PARAM_DEF_TYPE_BOOLEAN:
 | 
			
		||||
      if (! pika_scanner_parse_int (scanner,
 | 
			
		||||
                                    ¶m_def.meta.m_boolean.default_val))
 | 
			
		||||
@ -944,6 +994,11 @@ plug_in_proc_arg_deserialize (GScanner      *scanner,
 | 
			
		||||
    case GP_PARAM_DEF_TYPE_ID:
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case GP_PARAM_DEF_TYPE_CHOICE:
 | 
			
		||||
      g_clear_object (¶m_def.meta.m_choice.choice);
 | 
			
		||||
      g_free (param_def.meta.m_choice.default_val);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case GP_PARAM_DEF_TYPE_ID_ARRAY:
 | 
			
		||||
      g_free (param_def.meta.m_id_array.type_name);
 | 
			
		||||
      break;
 | 
			
		||||
@ -1038,6 +1093,31 @@ plug_in_rc_write_proc_arg (PikaConfigWriter *writer,
 | 
			
		||||
                                 param_def.meta.m_enum.default_val);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case GP_PARAM_DEF_TYPE_CHOICE:
 | 
			
		||||
        {
 | 
			
		||||
          GList *choices;
 | 
			
		||||
 | 
			
		||||
          choices = pika_choice_list_nicks (param_def.meta.m_choice.choice);
 | 
			
		||||
          pika_config_writer_string (writer, param_def.meta.m_choice.default_val);
 | 
			
		||||
          pika_config_writer_printf (writer, "%d", g_list_length (choices));
 | 
			
		||||
          for (GList *iter = choices; iter; iter = iter->next)
 | 
			
		||||
            {
 | 
			
		||||
              const gchar *nick = iter->data;
 | 
			
		||||
              const gchar *label;
 | 
			
		||||
              const gchar *help;
 | 
			
		||||
              gint         id;
 | 
			
		||||
 | 
			
		||||
              pika_choice_get_documentation (param_def.meta.m_choice.choice,
 | 
			
		||||
                                             nick, &label, &help);
 | 
			
		||||
              id = pika_choice_get_id (param_def.meta.m_choice.choice, nick);
 | 
			
		||||
              pika_config_writer_string (writer, nick);
 | 
			
		||||
              pika_config_writer_printf (writer, "%d", id);
 | 
			
		||||
              pika_config_writer_string (writer, label);
 | 
			
		||||
              pika_config_writer_string (writer, help);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case GP_PARAM_DEF_TYPE_BOOLEAN:
 | 
			
		||||
      pika_config_writer_printf (writer, "%d",
 | 
			
		||||
                                 param_def.meta.m_boolean.default_val);
 | 
			
		||||
 | 
			
		||||
@ -66,8 +66,7 @@ foreach test_name : app_tests
 | 
			
		||||
    env: [
 | 
			
		||||
      'PIKA_TESTING_ABS_TOP_SRCDIR='  + meson.project_source_root(),
 | 
			
		||||
      'PIKA_TESTING_ABS_TOP_BUILDDIR='+ meson.project_build_root(),
 | 
			
		||||
      'PIKA_TESTING_PLUGINDIRS=' +      meson.project_build_root()/'plug-ins'/'common',
 | 
			
		||||
      'PIKA_TESTING_PLUGINDIRS_BASENAME_IGNORES=mkgen.pl',
 | 
			
		||||
      'PIKA_TESTING_PLUGINDIRS='      + meson.project_build_root()/'plug-ins'/'common',
 | 
			
		||||
      'UI_TEST=yes',
 | 
			
		||||
    ],
 | 
			
		||||
    suite: 'app',
 | 
			
		||||
 | 
			
		||||
@ -406,13 +406,6 @@ pika_font_deserialize_create (GType     type,
 | 
			
		||||
 | 
			
		||||
      font = PIKA_FONT (pika_container_get_child_by_index (fonts_container, i));
 | 
			
		||||
 | 
			
		||||
      if (fonthash != NULL && font->hash != NULL && !g_strcmp0 (font->hash, fonthash))
 | 
			
		||||
        {
 | 
			
		||||
          most_similar_font_index = i;
 | 
			
		||||
          g_clear_pointer (&similar_fonts, g_list_free);
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      /* Some attrs are more identifying than others,
 | 
			
		||||
       * hence their higher importance in measuring similarity.
 | 
			
		||||
       */
 | 
			
		||||
 | 
			
		||||
@ -704,6 +704,7 @@ pika_font_factory_load_names (PikaContainer *container,
 | 
			
		||||
    {
 | 
			
		||||
      PangoFontDescription *pfd;
 | 
			
		||||
      GString              *xml;
 | 
			
		||||
      GString              *xml_bold_variant;
 | 
			
		||||
      gchar                *fontformat;
 | 
			
		||||
      gchar                *family           = NULL;
 | 
			
		||||
      gchar                *style            = NULL;
 | 
			
		||||
@ -796,26 +797,43 @@ pika_font_factory_load_names (PikaContainer *container,
 | 
			
		||||
 | 
			
		||||
      xml = g_string_new ("<?xml version=\"1.0\"?>\n<match>");
 | 
			
		||||
 | 
			
		||||
      /*We can't use faux bold (sometimes real bold) unless it is specified in fontconfig*/
 | 
			
		||||
      xml_bold_variant = g_string_new ("<?xml version=\"1.0\"?>\n<match>");
 | 
			
		||||
 | 
			
		||||
      g_string_append_printf (xml,
 | 
			
		||||
                              "<test name=\"family\"><string>%s</string></test>",
 | 
			
		||||
                              newname);
 | 
			
		||||
      g_string_append_printf (xml_bold_variant,
 | 
			
		||||
                              "<test name=\"family\"><string>%s</string></test>",
 | 
			
		||||
                              newname);
 | 
			
		||||
      g_string_append (xml_bold_variant,
 | 
			
		||||
                       "<test name=\"weight\" compare=\"eq\"><const>bold</const></test>");
 | 
			
		||||
 | 
			
		||||
      escaped_fullname = g_markup_escape_text (fullname, -1);
 | 
			
		||||
      g_string_append_printf (xml,
 | 
			
		||||
                              "<edit name=\"fullname\" mode=\"assign\" binding=\"strong\"><string>%s</string></edit>",
 | 
			
		||||
                              escaped_fullname);
 | 
			
		||||
      g_string_append_printf (xml_bold_variant,
 | 
			
		||||
                              "<edit name=\"fullname\" mode=\"prepend\" binding=\"strong\"><string>%s</string></edit>",
 | 
			
		||||
                              escaped_fullname);
 | 
			
		||||
      g_free (escaped_fullname);
 | 
			
		||||
 | 
			
		||||
      family = g_markup_escape_text (family, -1);
 | 
			
		||||
      g_string_append_printf (xml,
 | 
			
		||||
                              "<edit name=\"family\" mode=\"assign\" binding=\"strong\"><string>%s</string></edit>",
 | 
			
		||||
                              family);
 | 
			
		||||
      g_string_append_printf (xml_bold_variant,
 | 
			
		||||
                              "<edit name=\"family\" mode=\"assign\" binding=\"strong\"><string>%s</string></edit>",
 | 
			
		||||
                              family);
 | 
			
		||||
      g_free (family);
 | 
			
		||||
 | 
			
		||||
      escaped_file = g_markup_escape_text (file, -1);
 | 
			
		||||
      g_string_append_printf (xml,
 | 
			
		||||
                              "<edit name=\"file\" mode=\"assign\" binding=\"strong\"><string>%s</string></edit>",
 | 
			
		||||
                              escaped_file);
 | 
			
		||||
      g_string_append_printf (xml_bold_variant,
 | 
			
		||||
                              "<edit name=\"file\" mode=\"assign\" binding=\"strong\"><string>%s</string></edit>",
 | 
			
		||||
                              escaped_file);
 | 
			
		||||
      g_free (escaped_file);
 | 
			
		||||
 | 
			
		||||
      if (psname != NULL)
 | 
			
		||||
@ -824,6 +842,9 @@ pika_font_factory_load_names (PikaContainer *container,
 | 
			
		||||
          g_string_append_printf (xml,
 | 
			
		||||
                                  "<edit name=\"postscriptname\" mode=\"assign\" binding=\"strong\"><string>%s</string></edit>",
 | 
			
		||||
                                  psname);
 | 
			
		||||
          g_string_append_printf (xml_bold_variant,
 | 
			
		||||
                                  "<edit name=\"postscriptname\" mode=\"assign\" binding=\"strong\"><string>%s</string></edit>",
 | 
			
		||||
                                  psname);
 | 
			
		||||
          g_free (psname);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -833,36 +854,64 @@ pika_font_factory_load_names (PikaContainer *container,
 | 
			
		||||
          g_string_append_printf (xml,
 | 
			
		||||
                                  "<edit name=\"style\" mode=\"assign\" binding=\"strong\"><string>%s</string></edit>",
 | 
			
		||||
                                  style);
 | 
			
		||||
          g_string_append_printf (xml_bold_variant,
 | 
			
		||||
                                  "<edit name=\"style\" mode=\"assign\" binding=\"strong\"><string>%s</string></edit>",
 | 
			
		||||
                                  style);
 | 
			
		||||
          g_free (style);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      g_string_append (xml_bold_variant, "<edit name=\"weight\" mode=\"assign\" binding=\"strong\"><const>bold</const></edit>");
 | 
			
		||||
 | 
			
		||||
      if (weight != -1)
 | 
			
		||||
        g_string_append_printf (xml,
 | 
			
		||||
                                "<edit name=\"weight\" mode=\"assign\" binding=\"strong\"><int>%i</int></edit>",
 | 
			
		||||
                                "<edit name=\"weight\" mode=\"prepend\" binding=\"strong\"><int>%i</int></edit>",
 | 
			
		||||
                                weight);
 | 
			
		||||
 | 
			
		||||
      if (width != -1)
 | 
			
		||||
        g_string_append_printf (xml,
 | 
			
		||||
                                "<edit name=\"width\" mode=\"assign\" binding=\"strong\"><int>%i</int></edit>",
 | 
			
		||||
                                width);
 | 
			
		||||
        {
 | 
			
		||||
          g_string_append_printf (xml,
 | 
			
		||||
                                  "<edit name=\"width\" mode=\"assign\" binding=\"strong\"><int>%i</int></edit>",
 | 
			
		||||
                                  width);
 | 
			
		||||
          g_string_append_printf (xml_bold_variant,
 | 
			
		||||
                                  "<edit name=\"width\" mode=\"assign\" binding=\"strong\"><int>%i</int></edit>",
 | 
			
		||||
                                  width);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if (slant != -1)
 | 
			
		||||
        g_string_append_printf (xml,
 | 
			
		||||
                                "<edit name=\"slant\" mode=\"assign\" binding=\"strong\"><int>%i</int></edit>",
 | 
			
		||||
                                slant);
 | 
			
		||||
        {
 | 
			
		||||
          g_string_append_printf (xml,
 | 
			
		||||
                                  "<edit name=\"slant\" mode=\"prepend\" binding=\"strong\"><int>%i</int></edit>",
 | 
			
		||||
                                  slant);
 | 
			
		||||
          g_string_append_printf (xml_bold_variant,
 | 
			
		||||
                                  "<edit name=\"slant\" mode=\"prepend\" binding=\"strong\"><int>%i</int></edit>",
 | 
			
		||||
                                  slant);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if (fontversion != -1)
 | 
			
		||||
        g_string_append_printf (xml,
 | 
			
		||||
                                "<edit name=\"fontversion\" mode=\"assign\" binding=\"strong\"><int>%i</int></edit>",
 | 
			
		||||
                                fontversion);
 | 
			
		||||
        {
 | 
			
		||||
          g_string_append_printf (xml,
 | 
			
		||||
                                  "<edit name=\"fontversion\" mode=\"assign\" binding=\"strong\"><int>%i</int></edit>",
 | 
			
		||||
                                  fontversion);
 | 
			
		||||
          g_string_append_printf (xml_bold_variant,
 | 
			
		||||
                                  "<edit name=\"fontversion\" mode=\"assign\" binding=\"strong\"><int>%i</int></edit>",
 | 
			
		||||
                                  fontversion);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if (index != -1)
 | 
			
		||||
        g_string_append_printf (xml,
 | 
			
		||||
                                "<edit name=\"index\" mode=\"assign\" binding=\"strong\"><int>%i</int></edit>",
 | 
			
		||||
                                index);
 | 
			
		||||
        {
 | 
			
		||||
          g_string_append_printf (xml,
 | 
			
		||||
                                  "<edit name=\"index\" mode=\"assign\" binding=\"strong\"><int>%i</int></edit>",
 | 
			
		||||
                                  index);
 | 
			
		||||
          g_string_append_printf (xml_bold_variant,
 | 
			
		||||
                                  "<edit name=\"index\" mode=\"assign\" binding=\"strong\"><int>%i</int></edit>",
 | 
			
		||||
                                  index);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
      g_string_append (xml, "</match>\n");
 | 
			
		||||
      g_string_append (xml_bold_variant, "</match>\n");
 | 
			
		||||
 | 
			
		||||
      FcConfigParseAndLoadFromMemory (FcConfigGetCurrent (), (const FcChar8 *) xml_bold_variant->str, FcTrue);
 | 
			
		||||
      FcConfigParseAndLoadFromMemory (FcConfigGetCurrent (), (const FcChar8 *) xml->str, FcTrue);
 | 
			
		||||
 | 
			
		||||
      pfd = pango_font_description_from_string (newname);
 | 
			
		||||
@ -877,6 +926,7 @@ pika_font_factory_load_names (PikaContainer *container,
 | 
			
		||||
      pango_font_description_free (pfd);
 | 
			
		||||
      g_free (newname);
 | 
			
		||||
      g_string_free (xml, TRUE);
 | 
			
		||||
      g_string_free (xml_bold_variant, TRUE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (n_ignored > 0)
 | 
			
		||||
 | 
			
		||||
@ -42,6 +42,7 @@
 | 
			
		||||
#include "core/pikaimage-undo.h"
 | 
			
		||||
#include "core/pikalayer-floating-selection.h"
 | 
			
		||||
 | 
			
		||||
#include "pikafont.h"
 | 
			
		||||
#include "pikatext.h"
 | 
			
		||||
#include "pikatext-compat.h"
 | 
			
		||||
#include "pikatextlayer.h"
 | 
			
		||||
@ -55,24 +56,22 @@ text_render (PikaImage    *image,
 | 
			
		||||
             PikaContext  *context,
 | 
			
		||||
             gint          text_x,
 | 
			
		||||
             gint          text_y,
 | 
			
		||||
             const gchar  *fontname,
 | 
			
		||||
             PikaFont     *font,
 | 
			
		||||
             gdouble       font_size,
 | 
			
		||||
             const gchar  *text,
 | 
			
		||||
             gint          border,
 | 
			
		||||
             gboolean      antialias)
 | 
			
		||||
{
 | 
			
		||||
  PangoFontDescription *desc;
 | 
			
		||||
  PikaText             *gtext;
 | 
			
		||||
  PikaLayer            *layer;
 | 
			
		||||
  PikaRGB               color;
 | 
			
		||||
  gchar                *font;
 | 
			
		||||
  gdouble               size;
 | 
			
		||||
  PikaText  *gtext;
 | 
			
		||||
  PikaLayer *layer;
 | 
			
		||||
  PikaRGB    color;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (PIKA_IS_IMAGE (image), NULL);
 | 
			
		||||
  g_return_val_if_fail (drawable == NULL || PIKA_IS_DRAWABLE (drawable), NULL);
 | 
			
		||||
  g_return_val_if_fail (drawable == NULL ||
 | 
			
		||||
                        pika_item_is_attached (PIKA_ITEM (drawable)), NULL);
 | 
			
		||||
  g_return_val_if_fail (PIKA_IS_CONTEXT (context), NULL);
 | 
			
		||||
  g_return_val_if_fail (fontname != NULL, NULL);
 | 
			
		||||
  g_return_val_if_fail (PIKA_IS_FONT (font), NULL);
 | 
			
		||||
  g_return_val_if_fail (text != NULL, NULL);
 | 
			
		||||
 | 
			
		||||
  if (! pika_data_factory_data_wait (image->pika->font_factory))
 | 
			
		||||
@ -81,27 +80,17 @@ text_render (PikaImage    *image,
 | 
			
		||||
  if (border < 0)
 | 
			
		||||
    border = 0;
 | 
			
		||||
 | 
			
		||||
  desc = pango_font_description_from_string (fontname);
 | 
			
		||||
  size = PANGO_PIXELS (pango_font_description_get_size (desc));
 | 
			
		||||
 | 
			
		||||
  pango_font_description_unset_fields (desc, PANGO_FONT_MASK_SIZE);
 | 
			
		||||
  font = pango_font_description_to_string (desc);
 | 
			
		||||
 | 
			
		||||
  pango_font_description_free (desc);
 | 
			
		||||
 | 
			
		||||
  pika_context_get_foreground (context, &color);
 | 
			
		||||
 | 
			
		||||
  gtext = g_object_new (PIKA_TYPE_TEXT,
 | 
			
		||||
                        "text",      text,
 | 
			
		||||
                        "font",      font,
 | 
			
		||||
                        "font-size", size,
 | 
			
		||||
                        "font-size", font_size,
 | 
			
		||||
                        "antialias", antialias,
 | 
			
		||||
                        "border",    border,
 | 
			
		||||
                        "color",     &color,
 | 
			
		||||
                        NULL);
 | 
			
		||||
 | 
			
		||||
  g_free (font);
 | 
			
		||||
 | 
			
		||||
  layer = pika_text_layer_new (image, gtext);
 | 
			
		||||
 | 
			
		||||
  g_object_unref (gtext);
 | 
			
		||||
@ -142,7 +131,8 @@ text_render (PikaImage    *image,
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
text_get_extents (Pika        *pika,
 | 
			
		||||
                  const gchar *fontname,
 | 
			
		||||
                  PikaFont    *font,
 | 
			
		||||
                  gdouble      font_size,
 | 
			
		||||
                  const gchar *text,
 | 
			
		||||
                  gint        *width,
 | 
			
		||||
                  gint        *height,
 | 
			
		||||
@ -154,9 +144,10 @@ text_get_extents (Pika        *pika,
 | 
			
		||||
  PangoLayout          *layout;
 | 
			
		||||
  PangoFontMap         *fontmap;
 | 
			
		||||
  PangoRectangle        rect;
 | 
			
		||||
  gchar                *real_fontname;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (PIKA_IS_PIKA (pika), FALSE);
 | 
			
		||||
  g_return_val_if_fail (fontname != NULL, FALSE);
 | 
			
		||||
  g_return_val_if_fail (PIKA_IS_FONT (font), FALSE);
 | 
			
		||||
  g_return_val_if_fail (text != NULL, FALSE);
 | 
			
		||||
 | 
			
		||||
  if (! pika_data_factory_data_wait (pika->font_factory))
 | 
			
		||||
@ -175,9 +166,11 @@ text_get_extents (Pika        *pika,
 | 
			
		||||
  layout = pango_layout_new (context);
 | 
			
		||||
  g_object_unref (context);
 | 
			
		||||
 | 
			
		||||
  font_desc = pango_font_description_from_string (fontname);
 | 
			
		||||
  real_fontname = g_strdup_printf ("%s %d", pika_font_get_lookup_name (font), (gint) font_size);
 | 
			
		||||
  font_desc = pango_font_description_from_string (real_fontname);
 | 
			
		||||
  pango_layout_set_font_description (layout, font_desc);
 | 
			
		||||
  pango_font_description_free (font_desc);
 | 
			
		||||
  g_free (real_fontname);
 | 
			
		||||
 | 
			
		||||
  pango_layout_set_text (layout, text, -1);
 | 
			
		||||
 | 
			
		||||
@ -202,7 +195,7 @@ text_get_extents (Pika        *pika,
 | 
			
		||||
      if (ascent)
 | 
			
		||||
        *ascent = PANGO_ASCENT (rect);
 | 
			
		||||
      if (descent)
 | 
			
		||||
        *descent = - PANGO_DESCENT (rect);
 | 
			
		||||
        *descent = PANGO_DESCENT (rect);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_object_unref (layout);
 | 
			
		||||
 | 
			
		||||
@ -33,12 +33,14 @@ PikaLayer * text_render      (PikaImage    *image,
 | 
			
		||||
                              PikaContext  *context,
 | 
			
		||||
                              gint          text_x,
 | 
			
		||||
                              gint          text_y,
 | 
			
		||||
                              const gchar  *fontname,
 | 
			
		||||
                              PikaFont     *font,
 | 
			
		||||
                              gdouble       font_size,
 | 
			
		||||
                              const gchar  *text,
 | 
			
		||||
                              gint          border,
 | 
			
		||||
                              gboolean      antialias);
 | 
			
		||||
gboolean    text_get_extents (Pika         *pika,
 | 
			
		||||
                              const gchar  *fontname,
 | 
			
		||||
                              PikaFont     *font,
 | 
			
		||||
                              gdouble       font_size,
 | 
			
		||||
                              const gchar  *text,
 | 
			
		||||
                              gint         *width,
 | 
			
		||||
                              gint         *height,
 | 
			
		||||
 | 
			
		||||
@ -121,7 +121,7 @@ static void   pika_align_options_pivot_changed          (PikaPivotSelector *sele
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE_WITH_PRIVATE (PikaAlignOptions, pika_align_options, PIKA_TYPE_TOOL_OPTIONS)
 | 
			
		||||
 | 
			
		||||
#define parent_class pika_selection_options_parent_class
 | 
			
		||||
#define parent_class pika_align_options_parent_class
 | 
			
		||||
 | 
			
		||||
static guint align_options_signals[LAST_SIGNAL] = { 0 };
 | 
			
		||||
 | 
			
		||||
@ -205,6 +205,8 @@ pika_align_options_finalize (GObject *object)
 | 
			
		||||
  if (PIKA_CONTEXT (options)->pika)
 | 
			
		||||
    pika_align_options_image_changed (pika_get_user_context (PIKA_CONTEXT (options)->pika),
 | 
			
		||||
                                      NULL, options);
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (parent_class)->finalize (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@ -544,10 +546,10 @@ pika_align_options_gui (PikaToolOptions *tool_options)
 | 
			
		||||
    pika_align_options_button_new (options, PIKA_DISTRIBUTE_EVEN_VERTICAL_GAP, hbox,
 | 
			
		||||
                                   _("Distribute vertically with even vertical gaps"));
 | 
			
		||||
 | 
			
		||||
  g_signal_connect (pika_get_user_context (PIKA_CONTEXT (options)->pika),
 | 
			
		||||
                    "image-changed",
 | 
			
		||||
                    G_CALLBACK (pika_align_options_image_changed),
 | 
			
		||||
                    tool_options);
 | 
			
		||||
  g_signal_connect_object (pika_get_user_context (PIKA_CONTEXT (options)->pika),
 | 
			
		||||
                           "image-changed",
 | 
			
		||||
                           G_CALLBACK (pika_align_options_image_changed),
 | 
			
		||||
                           tool_options, 0);
 | 
			
		||||
  pika_align_options_image_changed (pika_get_user_context (PIKA_CONTEXT (options)->pika),
 | 
			
		||||
                                    pika_context_get_image (pika_get_user_context (PIKA_CONTEXT (options)->pika)),
 | 
			
		||||
                                    options);
 | 
			
		||||
 | 
			
		||||
@ -188,6 +188,11 @@ tool_manager_exit (Pika *pika)
 | 
			
		||||
                                        tool_manager_image_changed,
 | 
			
		||||
                                        tool_manager);
 | 
			
		||||
 | 
			
		||||
  if (tool_manager->image)
 | 
			
		||||
    g_signal_handlers_disconnect_by_func (tool_manager->image,
 | 
			
		||||
                                          tool_manager_selected_layers_changed,
 | 
			
		||||
                                          tool_manager);
 | 
			
		||||
 | 
			
		||||
  pika_container_remove_handler (pika->images,
 | 
			
		||||
                                 tool_manager->image_clean_handler_id);
 | 
			
		||||
  pika_container_remove_handler (pika->images,
 | 
			
		||||
 | 
			
		||||
@ -161,7 +161,9 @@ libappwidgets_sources = [
 | 
			
		||||
  'pikapatternselect.c',
 | 
			
		||||
  'pikapdbdialog.c',
 | 
			
		||||
  'pikapickablebutton.c',
 | 
			
		||||
  'pikapickablechooser.c',
 | 
			
		||||
  'pikapickablepopup.c',
 | 
			
		||||
  'pikapickableselect.c',
 | 
			
		||||
  'pikapivotselector.c',
 | 
			
		||||
  'pikapixbuf.c',
 | 
			
		||||
  'pikapluginview.c',
 | 
			
		||||
 | 
			
		||||
@ -366,6 +366,8 @@ pika_action_history_action_activated (PikaAction *action)
 | 
			
		||||
  GList                 *link;
 | 
			
		||||
  PikaActionHistoryItem *item;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (PIKA_IS_ACTION (action));
 | 
			
		||||
 | 
			
		||||
  /* Silently return when called at the wrong time, like when the
 | 
			
		||||
   * activated action was "quit" and the history is already gone.
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
@ -693,6 +693,39 @@ pika_action_use_default_accels (PikaAction *action)
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
pika_action_is_default_accel (PikaAction  *action,
 | 
			
		||||
                              const gchar *accel)
 | 
			
		||||
{
 | 
			
		||||
  gchar           **default_accels;
 | 
			
		||||
  guint             accelerator_key  = 0;
 | 
			
		||||
  GdkModifierType   accelerator_mods = 0;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (PIKA_IS_ACTION (action), TRUE);
 | 
			
		||||
  g_return_val_if_fail (accel != NULL, TRUE);
 | 
			
		||||
 | 
			
		||||
  gtk_accelerator_parse (accel, &accelerator_key, &accelerator_mods);
 | 
			
		||||
  g_return_val_if_fail (accelerator_key != 0 || accelerator_mods == 0, FALSE);
 | 
			
		||||
 | 
			
		||||
  default_accels = GET_PRIVATE (action)->default_accels;
 | 
			
		||||
 | 
			
		||||
  if (default_accels == NULL)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  for (gint i = 0; default_accels[i] != NULL; i++)
 | 
			
		||||
    {
 | 
			
		||||
      guint           default_key;
 | 
			
		||||
      GdkModifierType default_mods;
 | 
			
		||||
 | 
			
		||||
      gtk_accelerator_parse (default_accels[i], &default_key, &default_mods);
 | 
			
		||||
 | 
			
		||||
      if (default_key == accelerator_key && default_mods == accelerator_mods)
 | 
			
		||||
        return TRUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const gchar *
 | 
			
		||||
pika_action_get_menu_path (PikaAction *action)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
@ -119,6 +119,8 @@ const gchar    ** pika_action_get_default_accels  (PikaAction      *action);
 | 
			
		||||
const gchar    ** pika_action_get_accels          (PikaAction      *action);
 | 
			
		||||
gchar **          pika_action_get_display_accels  (PikaAction      *action);
 | 
			
		||||
gboolean          pika_action_use_default_accels  (PikaAction      *action);
 | 
			
		||||
gboolean          pika_action_is_default_accel    (PikaAction      *action,
 | 
			
		||||
                                                   const gchar     *accel);
 | 
			
		||||
 | 
			
		||||
const gchar     * pika_action_get_menu_path       (PikaAction      *action);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -394,7 +394,87 @@ pika_action_group_add_action_with_accel (PikaActionGroup    *group,
 | 
			
		||||
 | 
			
		||||
      if ((accelerators != NULL && accelerators[0] != NULL &&
 | 
			
		||||
           g_strcmp0 (accelerators[0], "") != 0))
 | 
			
		||||
        pika_action_set_default_accels (action, (const gchar **) accelerators);
 | 
			
		||||
        {
 | 
			
		||||
          guint       i = 0;
 | 
			
		||||
          GdkDisplay *display;
 | 
			
		||||
          GdkKeymap  *keymap;
 | 
			
		||||
          gchar      *accel_strs[] = { NULL, NULL, NULL, NULL};
 | 
			
		||||
 | 
			
		||||
          display = gdk_display_get_default ();
 | 
			
		||||
          keymap = gdk_keymap_get_for_display (display);
 | 
			
		||||
 | 
			
		||||
          while (accelerators[i] != NULL)
 | 
			
		||||
            {
 | 
			
		||||
              /**
 | 
			
		||||
               * Shifted numeric key accelerators ("<shift>0" .. "<shift>9") do
 | 
			
		||||
               * not work with GTK3 so the following code converts these
 | 
			
		||||
               * accelerators to the shifted character (or the un-shifted
 | 
			
		||||
               * character in the case of an azerty keyboard for example) that
 | 
			
		||||
               * relates to the selected numeric character. This takes into
 | 
			
		||||
               * account the keyboard layout that is being used when PIKA starts.
 | 
			
		||||
               * This means that the appropriate characters will be shown for the
 | 
			
		||||
               * shortcuts in the menus and keyboard preferences.
 | 
			
		||||
               **/
 | 
			
		||||
              guint           accelerator_key;
 | 
			
		||||
              GdkModifierType accelerator_modifier;
 | 
			
		||||
              gboolean        accelerator_string_set;
 | 
			
		||||
 | 
			
		||||
              accelerator_string_set = FALSE;
 | 
			
		||||
 | 
			
		||||
              gtk_accelerator_parse (accelerators[i],
 | 
			
		||||
                                     &accelerator_key,
 | 
			
		||||
                                     &accelerator_modifier);
 | 
			
		||||
 | 
			
		||||
              if ((accelerator_key >= '0') &&
 | 
			
		||||
                  (accelerator_key <= '9') &&
 | 
			
		||||
                  (accelerator_modifier == GDK_SHIFT_MASK))
 | 
			
		||||
                {
 | 
			
		||||
                  gboolean      result;
 | 
			
		||||
                  gint          count;
 | 
			
		||||
                  GdkKeymapKey  key;
 | 
			
		||||
                  GdkKeymapKey *keys = NULL;
 | 
			
		||||
                  guint         non_number_keyval;
 | 
			
		||||
 | 
			
		||||
                  result = gdk_keymap_get_entries_for_keyval (keymap,
 | 
			
		||||
                                                              accelerator_key,
 | 
			
		||||
                                                              &keys,
 | 
			
		||||
                                                              &count);
 | 
			
		||||
                  if (result && (count > 0))
 | 
			
		||||
                    {
 | 
			
		||||
                      key.keycode = keys[0].keycode;
 | 
			
		||||
                      key.group   = 0;
 | 
			
		||||
                      key.level   = 1;
 | 
			
		||||
 | 
			
		||||
                      non_number_keyval = gdk_keymap_lookup_key (keymap, &key);
 | 
			
		||||
 | 
			
		||||
                      if (non_number_keyval == accelerator_key)
 | 
			
		||||
                        {
 | 
			
		||||
                          /**
 | 
			
		||||
                           * the number shifted is the number - assume keyboard
 | 
			
		||||
                           * such as azerty where the numbers are on the shifted
 | 
			
		||||
                           * key and the other characters are obtained without
 | 
			
		||||
                           * the shift
 | 
			
		||||
                           **/
 | 
			
		||||
                          key.level = 0;
 | 
			
		||||
                          non_number_keyval = gdk_keymap_lookup_key (keymap, &key);
 | 
			
		||||
                        }
 | 
			
		||||
                      accel_strs[i] = g_strdup (gdk_keyval_name (non_number_keyval));
 | 
			
		||||
                      accelerator_string_set = TRUE;
 | 
			
		||||
                    }
 | 
			
		||||
                  g_free (keys);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
              if (! accelerator_string_set)
 | 
			
		||||
                accel_strs[i] = g_strdup (accelerators[i]);
 | 
			
		||||
 | 
			
		||||
              i++;
 | 
			
		||||
            }
 | 
			
		||||
          pika_action_set_default_accels (action, (const gchar **) accel_strs);
 | 
			
		||||
 | 
			
		||||
          /* free up to 3 accelerator strings (4th entry is always NULL) */
 | 
			
		||||
          for (guint i = 0; i < 3; i++)
 | 
			
		||||
            g_free (accel_strs[i]);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      pika_action_set_group (action, group);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -282,7 +282,7 @@ pika_brush_select_run_callback (PikaPdbDialog  *dialog,
 | 
			
		||||
                                        dialog->caller_context,
 | 
			
		||||
                                        NULL, error,
 | 
			
		||||
                                        dialog->callback_name,
 | 
			
		||||
                                        G_TYPE_STRING,         pika_object_get_name (object),
 | 
			
		||||
                                        PIKA_TYPE_RESOURCE,    object,
 | 
			
		||||
                                        G_TYPE_DOUBLE,         pika_context_get_opacity (dialog->context) * 100.0,
 | 
			
		||||
                                        G_TYPE_INT,            PIKA_BRUSH_SELECT (dialog)->spacing,
 | 
			
		||||
                                        PIKA_TYPE_LAYER_MODE,  pika_context_get_paint_mode (dialog->context),
 | 
			
		||||
 | 
			
		||||
@ -538,7 +538,7 @@ pika_color_history_color_changed (GtkWidget *widget,
 | 
			
		||||
 | 
			
		||||
  pika_color_area_get_color (PIKA_COLOR_AREA (widget), &color);
 | 
			
		||||
 | 
			
		||||
  pika_palette_set_entry_color (palette, GPOINTER_TO_INT (data), &color);
 | 
			
		||||
  pika_palette_set_entry_color (palette, GPOINTER_TO_INT (data), &color, FALSE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
 | 
			
		||||
@ -47,29 +47,33 @@
 | 
			
		||||
#include "pika-intl.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void pika_colormap_editor_docked_iface_init (PikaDockedInterface  *face);
 | 
			
		||||
static void       pika_colormap_editor_docked_iface_init  (PikaDockedInterface   *face);
 | 
			
		||||
 | 
			
		||||
static void   pika_colormap_editor_constructed     (GObject              *object);
 | 
			
		||||
static void   pika_colormap_editor_dispose         (GObject              *object);
 | 
			
		||||
static void       pika_colormap_editor_constructed        (GObject               *object);
 | 
			
		||||
static void       pika_colormap_editor_dispose            (GObject               *object);
 | 
			
		||||
 | 
			
		||||
static void   pika_colormap_editor_unmap           (GtkWidget            *widget);
 | 
			
		||||
static void       pika_colormap_editor_unmap              (GtkWidget             *widget);
 | 
			
		||||
 | 
			
		||||
static void   pika_colormap_editor_set_context     (PikaDocked           *docked,
 | 
			
		||||
                                                    PikaContext          *context);
 | 
			
		||||
static void       pika_colormap_editor_set_context        (PikaDocked            *docked,
 | 
			
		||||
                                                           PikaContext           *context);
 | 
			
		||||
 | 
			
		||||
static void   pika_colormap_editor_color_update    (PikaColorDialog      *dialog,
 | 
			
		||||
                                                    const PikaRGB        *color,
 | 
			
		||||
                                                    PikaColorDialogState  state,
 | 
			
		||||
                                                    PikaColormapEditor   *editor);
 | 
			
		||||
static void       pika_colormap_editor_color_update       (PikaColorDialog       *dialog,
 | 
			
		||||
                                                          const PikaRGB          *color,
 | 
			
		||||
                                                          PikaColorDialogState    state,
 | 
			
		||||
                                                          PikaColormapEditor     *editor);
 | 
			
		||||
 | 
			
		||||
static gboolean   pika_colormap_editor_entry_button_press (GtkWidget             *widget,
 | 
			
		||||
                                                           GdkEvent              *event,
 | 
			
		||||
                                                           gpointer               user_data);
 | 
			
		||||
static gboolean   pika_colormap_editor_entry_popup        (GtkWidget             *widget,
 | 
			
		||||
                                                           gpointer               user_data);
 | 
			
		||||
static void       pika_colormap_editor_color_clicked      (PikaColormapEditor    *editor,
 | 
			
		||||
                                                           PikaPaletteEntry      *entry,
 | 
			
		||||
                                                           GdkModifierType        state);
 | 
			
		||||
static void       pika_colormap_editor_notify_index       (PikaColormapSelection *selection,
 | 
			
		||||
                                                           const GParamSpec      *pspec,
 | 
			
		||||
                                                           PikaColormapEditor    *editor);
 | 
			
		||||
 | 
			
		||||
static gboolean   pika_colormap_editor_entry_button_press (GtkWidget     *widget,
 | 
			
		||||
                                                           GdkEvent      *event,
 | 
			
		||||
                                                           gpointer       user_data);
 | 
			
		||||
static gboolean   pika_colormap_editor_entry_popup     (GtkWidget            *widget,
 | 
			
		||||
                                                        gpointer              user_data);
 | 
			
		||||
static void   pika_colormap_editor_color_clicked   (PikaColormapEditor   *editor,
 | 
			
		||||
                                                    PikaPaletteEntry     *entry,
 | 
			
		||||
                                                    GdkModifierType       state);
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE_WITH_CODE (PikaColormapEditor, pika_colormap_editor,
 | 
			
		||||
                         PIKA_TYPE_IMAGE_EDITOR,
 | 
			
		||||
@ -127,6 +131,9 @@ pika_colormap_editor_constructed (GObject *object)
 | 
			
		||||
  pika_editor_add_action_button (PIKA_EDITOR (editor), "colormap",
 | 
			
		||||
                                 "colormap-edit-color",
 | 
			
		||||
                                 NULL);
 | 
			
		||||
  pika_editor_add_action_button (PIKA_EDITOR (editor), "colormap",
 | 
			
		||||
                                 "colormap-delete-color",
 | 
			
		||||
                                 NULL);
 | 
			
		||||
 | 
			
		||||
  pika_editor_add_action_button (PIKA_EDITOR (editor), "colormap",
 | 
			
		||||
                                 "colormap-add-color-from-fg",
 | 
			
		||||
@ -197,6 +204,9 @@ pika_colormap_editor_set_context (PikaDocked  *docked,
 | 
			
		||||
      g_signal_connect (editor->selection, "popup-menu",
 | 
			
		||||
                        G_CALLBACK (pika_colormap_editor_entry_popup),
 | 
			
		||||
                        editor);
 | 
			
		||||
      g_signal_connect (editor->selection, "notify::index",
 | 
			
		||||
                        G_CALLBACK (pika_colormap_editor_notify_index),
 | 
			
		||||
                        editor);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -281,6 +291,43 @@ pika_colormap_editor_edit_color (PikaColormapEditor *editor)
 | 
			
		||||
  gtk_window_present (GTK_WINDOW (editor->color_dialog));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
pika_colormap_editor_delete_color (PikaColormapEditor *editor)
 | 
			
		||||
{
 | 
			
		||||
  PikaColormapSelection *selection;
 | 
			
		||||
  PikaImage             *image;
 | 
			
		||||
  gint                   index;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (PIKA_IS_COLORMAP_EDITOR (editor));
 | 
			
		||||
  g_return_if_fail (pika_colormap_editor_is_color_deletable (editor));
 | 
			
		||||
 | 
			
		||||
  image     = PIKA_IMAGE_EDITOR (editor)->image;
 | 
			
		||||
  selection = PIKA_COLORMAP_SELECTION (editor->selection);
 | 
			
		||||
  index     = pika_colormap_selection_get_index (selection, NULL);
 | 
			
		||||
 | 
			
		||||
  pika_image_delete_colormap_entry (image, index, TRUE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
pika_colormap_editor_is_color_deletable (PikaColormapEditor *editor)
 | 
			
		||||
{
 | 
			
		||||
  PikaColormapSelection *selection;
 | 
			
		||||
  PikaImage             *image;
 | 
			
		||||
  gint                   index;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (PIKA_IS_COLORMAP_EDITOR (editor), FALSE);
 | 
			
		||||
 | 
			
		||||
  image     = PIKA_IMAGE_EDITOR (editor)->image;
 | 
			
		||||
  selection = PIKA_COLORMAP_SELECTION (editor->selection);
 | 
			
		||||
  index     = pika_colormap_selection_get_index (selection, NULL);
 | 
			
		||||
 | 
			
		||||
  if (index == -1)
 | 
			
		||||
    /* No colormap. */
 | 
			
		||||
    return FALSE;
 | 
			
		||||
  else
 | 
			
		||||
    return ! pika_image_colormap_is_index_used (image, index);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gint
 | 
			
		||||
pika_colormap_editor_get_index (PikaColormapEditor *editor,
 | 
			
		||||
                                const PikaRGB      *search)
 | 
			
		||||
@ -411,3 +458,16 @@ pika_colormap_editor_color_clicked (PikaColormapEditor *editor,
 | 
			
		||||
  else
 | 
			
		||||
    pika_context_set_foreground (image_editor->context, &entry->color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
pika_colormap_editor_notify_index (PikaColormapSelection *selection,
 | 
			
		||||
                                   const GParamSpec      *pspec,
 | 
			
		||||
                                   PikaColormapEditor    *editor)
 | 
			
		||||
{
 | 
			
		||||
  g_return_if_fail (PIKA_IS_COLORMAP_EDITOR (editor));
 | 
			
		||||
 | 
			
		||||
  pika_editor_set_action_sensitive (PIKA_EDITOR (editor), "colormap",
 | 
			
		||||
                                    "colormap-delete-color",
 | 
			
		||||
                                    pika_colormap_editor_is_color_deletable (editor),
 | 
			
		||||
                                    _("The color is used in this indexed image"));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -50,19 +50,21 @@ struct _PikaColormapEditorClass
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
GType       pika_colormap_editor_get_type   (void) G_GNUC_CONST;
 | 
			
		||||
GType       pika_colormap_editor_get_type           (void) G_GNUC_CONST;
 | 
			
		||||
 | 
			
		||||
GtkWidget * pika_colormap_editor_new        (PikaMenuFactory    *menu_factory);
 | 
			
		||||
GtkWidget * pika_colormap_editor_new                (PikaMenuFactory    *menu_factory);
 | 
			
		||||
 | 
			
		||||
void        pika_colormap_editor_edit_color (PikaColormapEditor *editor);
 | 
			
		||||
void        pika_colormap_editor_edit_color         (PikaColormapEditor *editor);
 | 
			
		||||
void        pika_colormap_editor_delete_color       (PikaColormapEditor *editor);
 | 
			
		||||
gboolean    pika_colormap_editor_is_color_deletable (PikaColormapEditor *editor);
 | 
			
		||||
 | 
			
		||||
gint        pika_colormap_editor_get_index  (PikaColormapEditor *editor,
 | 
			
		||||
                                             const PikaRGB      *search);
 | 
			
		||||
gboolean    pika_colormap_editor_set_index  (PikaColormapEditor *editor,
 | 
			
		||||
                                             gint                index,
 | 
			
		||||
                                             PikaRGB            *color);
 | 
			
		||||
gint        pika_colormap_editor_get_index          (PikaColormapEditor *editor,
 | 
			
		||||
                                                     const PikaRGB      *search);
 | 
			
		||||
gboolean    pika_colormap_editor_set_index          (PikaColormapEditor *editor,
 | 
			
		||||
                                                     gint                index,
 | 
			
		||||
                                                     PikaRGB            *color);
 | 
			
		||||
 | 
			
		||||
gint        pika_colormap_editor_max_index  (PikaColormapEditor *editor);
 | 
			
		||||
gint        pika_colormap_editor_max_index          (PikaColormapEditor *editor);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif /* __PIKA_COLORMAP_EDITOR_H__ */
 | 
			
		||||
 | 
			
		||||
@ -57,7 +57,8 @@
 | 
			
		||||
enum
 | 
			
		||||
{
 | 
			
		||||
  PROP_0,
 | 
			
		||||
  PROP_CONTEXT
 | 
			
		||||
  PROP_CONTEXT,
 | 
			
		||||
  PROP_INDEX
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum
 | 
			
		||||
@ -169,6 +170,10 @@ pika_colormap_selection_class_init (PikaColormapSelectionClass* klass)
 | 
			
		||||
                                                        PIKA_TYPE_CONTEXT,
 | 
			
		||||
                                                        PIKA_PARAM_READWRITE |
 | 
			
		||||
                                                        G_PARAM_CONSTRUCT));
 | 
			
		||||
  g_object_class_install_property (object_class, PROP_INDEX,
 | 
			
		||||
                                   g_param_spec_int ("index", NULL, NULL,
 | 
			
		||||
                                                     0, G_MAXINT, 0,
 | 
			
		||||
                                                     PIKA_PARAM_READABLE));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@ -285,6 +290,9 @@ pika_colormap_selection_get_property (GObject    *object,
 | 
			
		||||
    case PROP_CONTEXT:
 | 
			
		||||
      g_value_set_object (value, selection->context);
 | 
			
		||||
      break;
 | 
			
		||||
    case PROP_INDEX:
 | 
			
		||||
      g_value_set_int (value, selection->col_index);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 | 
			
		||||
@ -433,6 +441,7 @@ pika_colormap_selection_set_index (PikaColormapSelection *selection,
 | 
			
		||||
 | 
			
		||||
      selection->col_index = index;
 | 
			
		||||
 | 
			
		||||
      g_object_notify (G_OBJECT (selection), "index");
 | 
			
		||||
      pika_palette_view_select_entry (PIKA_PALETTE_VIEW (selection->view),
 | 
			
		||||
                                      pika_palette_get_entry (palette, index));
 | 
			
		||||
 | 
			
		||||
@ -789,6 +798,8 @@ pika_colormap_selection_set_palette (PikaColormapSelection *selection)
 | 
			
		||||
    {
 | 
			
		||||
      if (selection->active_palette)
 | 
			
		||||
        {
 | 
			
		||||
          pika_colormap_selection_set_index (selection, 0, NULL);
 | 
			
		||||
 | 
			
		||||
          g_signal_handlers_disconnect_by_func (selection->active_palette,
 | 
			
		||||
                                                G_CALLBACK (gtk_widget_queue_draw),
 | 
			
		||||
                                                selection);
 | 
			
		||||
 | 
			
		||||
@ -899,6 +899,7 @@ pika_container_tree_view_select_items (PikaContainerView *view,
 | 
			
		||||
  GList                 *path;
 | 
			
		||||
  gboolean               free_paths      = FALSE;
 | 
			
		||||
  gboolean               scroll_to_first = TRUE;
 | 
			
		||||
  GtkTreePath           *focused_path    = NULL;
 | 
			
		||||
 | 
			
		||||
  /* If @paths is not set, compute it ourselves. */
 | 
			
		||||
  if (g_list_length (items) != g_list_length (paths))
 | 
			
		||||
@ -926,6 +927,95 @@ pika_container_tree_view_select_items (PikaContainerView *view,
 | 
			
		||||
                                   pika_container_tree_view_selection_changed,
 | 
			
		||||
                                   tree_view);
 | 
			
		||||
  gtk_tree_selection_unselect_all (tree_view->priv->selection);
 | 
			
		||||
  gtk_tree_view_get_cursor (tree_view->view, &focused_path, NULL);
 | 
			
		||||
  if (focused_path != NULL)
 | 
			
		||||
    {
 | 
			
		||||
      GtkTreePath *closer_up   = NULL;
 | 
			
		||||
      GtkTreePath *closer_down = NULL;
 | 
			
		||||
 | 
			
		||||
      for (path = paths; path; path = path->next)
 | 
			
		||||
        {
 | 
			
		||||
          if (gtk_tree_path_compare (path->data, focused_path) == 0)
 | 
			
		||||
            {
 | 
			
		||||
              break;
 | 
			
		||||
            }
 | 
			
		||||
          else if (gtk_tree_path_compare (path->data, focused_path) == -1)
 | 
			
		||||
            {
 | 
			
		||||
              if (closer_up == NULL || gtk_tree_path_compare (path->data, closer_up) == 1)
 | 
			
		||||
                closer_up = path->data;
 | 
			
		||||
            }
 | 
			
		||||
          else
 | 
			
		||||
            {
 | 
			
		||||
              if (closer_down == NULL || gtk_tree_path_compare (path->data, closer_down) == -1)
 | 
			
		||||
                closer_down = path->data;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if (path == NULL)
 | 
			
		||||
        {
 | 
			
		||||
          /* The current cursor is not part of the selection. This may happen in
 | 
			
		||||
           * particular with a ctrl-click interaction which would deselect the
 | 
			
		||||
           * item the cursor is now on.
 | 
			
		||||
           */
 | 
			
		||||
          g_clear_pointer (&focused_path, gtk_tree_path_free);
 | 
			
		||||
 | 
			
		||||
          if (closer_up != NULL || closer_down != NULL)
 | 
			
		||||
            {
 | 
			
		||||
              GtkTreePath *first = NULL;
 | 
			
		||||
              GtkTreePath *last  = NULL;
 | 
			
		||||
 | 
			
		||||
              if (gtk_tree_view_get_visible_range (tree_view->view, &first, &last))
 | 
			
		||||
                {
 | 
			
		||||
                  if (closer_up != NULL                             &&
 | 
			
		||||
                      gtk_tree_path_compare (closer_up, first) >= 0 &&
 | 
			
		||||
                      gtk_tree_path_compare (closer_up, last) <= 0)
 | 
			
		||||
                    focused_path = gtk_tree_path_copy (closer_up);
 | 
			
		||||
                  else if (closer_down != NULL                             &&
 | 
			
		||||
                           gtk_tree_path_compare (closer_down, first) >= 0 &&
 | 
			
		||||
                           gtk_tree_path_compare (closer_down, last) <= 0)
 | 
			
		||||
                    focused_path = gtk_tree_path_copy (closer_down);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
              if (focused_path == NULL)
 | 
			
		||||
                {
 | 
			
		||||
                  if (closer_up != NULL)
 | 
			
		||||
                    focused_path = gtk_tree_path_copy (closer_up);
 | 
			
		||||
                  else
 | 
			
		||||
                    focused_path = gtk_tree_path_copy (closer_down);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
              gtk_tree_path_free (first);
 | 
			
		||||
              gtk_tree_path_free (last);
 | 
			
		||||
            }
 | 
			
		||||
          else if (paths != NULL)
 | 
			
		||||
            {
 | 
			
		||||
              focused_path = gtk_tree_path_copy (paths->data);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  else if (paths != NULL)
 | 
			
		||||
    {
 | 
			
		||||
      focused_path = gtk_tree_path_copy (paths->data);
 | 
			
		||||
    }
 | 
			
		||||
  /* Setting a cursor will reset the selection, so we must do it first. We don't
 | 
			
		||||
   * want to change the cursor (which is likely the last clicked item), yet we
 | 
			
		||||
   * also want to make sure that the cursor cannot end up out of the selected
 | 
			
		||||
   * items, leading to discrepancy between pointer and keyboard navigation. This
 | 
			
		||||
   * is why we set the cursor with this priority:
 | 
			
		||||
   * 1. unchanged if it stays within selection;
 | 
			
		||||
   * 2. closer item above the current cursor, if visible;
 | 
			
		||||
   * 3. closer item below the current cursor, if visible;
 | 
			
		||||
   * 4. closer item above the current cursor (even though invisible, which will
 | 
			
		||||
   *    make the view scroll up);
 | 
			
		||||
   * 5. closer item below the current cursor if there are no items above (view
 | 
			
		||||
   *    will scroll down);
 | 
			
		||||
   * 6. top selected item if there was no current cursor;
 | 
			
		||||
   * 7. nothing if no selected items.
 | 
			
		||||
   */
 | 
			
		||||
  if (focused_path != NULL)
 | 
			
		||||
    gtk_tree_view_set_cursor (tree_view->view, focused_path, NULL, FALSE);
 | 
			
		||||
  gtk_tree_path_free (focused_path);
 | 
			
		||||
 | 
			
		||||
  for (item = items, path = paths; item && path; item = item->next, path = path->next)
 | 
			
		||||
    {
 | 
			
		||||
      GtkTreePath *parent_path;
 | 
			
		||||
@ -1267,12 +1357,10 @@ pika_container_tree_view_button (GtkWidget             *widget,
 | 
			
		||||
  PikaContainerView *container_view = PIKA_CONTAINER_VIEW (tree_view);
 | 
			
		||||
  GtkTreeViewColumn *column;
 | 
			
		||||
  GtkTreePath       *path;
 | 
			
		||||
  gboolean           handled        = TRUE;
 | 
			
		||||
 | 
			
		||||
  tree_view->priv->dnd_renderer = NULL;
 | 
			
		||||
 | 
			
		||||
  if (bevent->type != GDK_BUTTON_RELEASE && ! gtk_widget_has_focus (widget))
 | 
			
		||||
    gtk_widget_grab_focus (widget);
 | 
			
		||||
 | 
			
		||||
  if (gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (widget),
 | 
			
		||||
                                     bevent->x, bevent->y,
 | 
			
		||||
                                     &path, &column, NULL, NULL))
 | 
			
		||||
@ -1283,10 +1371,10 @@ pika_container_tree_view_button (GtkWidget             *widget,
 | 
			
		||||
      GtkCellRenderer          *edit_cell    = NULL;
 | 
			
		||||
      GdkRectangle              column_area;
 | 
			
		||||
      GtkTreeIter               iter;
 | 
			
		||||
      gboolean                  handled = TRUE;
 | 
			
		||||
      gboolean                  multisel_mode;
 | 
			
		||||
      GdkModifierType           modifiers = (bevent->state & pika_get_all_modifiers_mask ());
 | 
			
		||||
 | 
			
		||||
      handled       = TRUE;
 | 
			
		||||
      multisel_mode = (gtk_tree_selection_get_mode (tree_view->priv->selection)
 | 
			
		||||
                       == GTK_SELECTION_MULTIPLE);
 | 
			
		||||
 | 
			
		||||
@ -1301,6 +1389,19 @@ pika_container_tree_view_button (GtkWidget             *widget,
 | 
			
		||||
          multisel_mode = FALSE;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      /* We need to grab focus after a button click, in order to make keyboard
 | 
			
		||||
       * navigation possible. For multi-selection though, actual selection will
 | 
			
		||||
       * happen in pika_container_tree_view_selection_changed() but the widget
 | 
			
		||||
       * must already be focused or the handler won't run.
 | 
			
		||||
       * Whereas for single selection, grab must happen after we changed the
 | 
			
		||||
       * selection (which will happen in this function) otherwise we end up
 | 
			
		||||
       * first scrolling to the current selection. So we have a separate
 | 
			
		||||
       * gtk_widget_grab_focus() at the end of the function.
 | 
			
		||||
       * See also commit 3e101922 and MR !1128.
 | 
			
		||||
       */
 | 
			
		||||
      if (multisel_mode && bevent->type == GDK_BUTTON_PRESS && ! gtk_widget_has_focus (widget))
 | 
			
		||||
        gtk_widget_grab_focus (widget);
 | 
			
		||||
 | 
			
		||||
      gtk_tree_model_get_iter (tree_view->model, &iter, path);
 | 
			
		||||
 | 
			
		||||
      renderer = pika_container_tree_store_get_renderer (PIKA_CONTAINER_TREE_STORE (tree_view->model), &iter);
 | 
			
		||||
@ -1607,7 +1708,7 @@ pika_container_tree_view_button (GtkWidget             *widget,
 | 
			
		||||
      gtk_tree_path_free (path);
 | 
			
		||||
      g_object_unref (renderer);
 | 
			
		||||
 | 
			
		||||
      return multisel_mode ? handled : (bevent->type == GDK_BUTTON_RELEASE ? FALSE : TRUE);
 | 
			
		||||
      handled = (multisel_mode ? handled : (bevent->type == GDK_BUTTON_RELEASE ? FALSE : TRUE));
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
@ -1616,8 +1717,13 @@ pika_container_tree_view_button (GtkWidget             *widget,
 | 
			
		||||
          pika_editor_popup_menu_at_pointer (PIKA_EDITOR (tree_view), (GdkEvent *) bevent);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      return TRUE;
 | 
			
		||||
      handled = TRUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (handled && bevent->type == GDK_BUTTON_PRESS && ! gtk_widget_has_focus (widget))
 | 
			
		||||
    gtk_widget_grab_focus (widget);
 | 
			
		||||
 | 
			
		||||
  return handled;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* We want to zoom on each 1/4 scroll events to roughly match zooming
 | 
			
		||||
 | 
			
		||||
@ -1195,9 +1195,7 @@ pika_container_view_remove (PikaContainerView *view,
 | 
			
		||||
 | 
			
		||||
  if (insert_data)
 | 
			
		||||
    {
 | 
			
		||||
      PIKA_CONTAINER_VIEW_GET_IFACE (view)->remove_item (view,
 | 
			
		||||
                                                             viewable,
 | 
			
		||||
                                                             insert_data);
 | 
			
		||||
      PIKA_CONTAINER_VIEW_GET_IFACE (view)->remove_item (view, viewable, insert_data);
 | 
			
		||||
 | 
			
		||||
      g_hash_table_remove (private->item_hash, viewable);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -226,7 +226,7 @@ pika_data_factory_view_constructed (GObject *object)
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (parent_class)->constructed (object);
 | 
			
		||||
 | 
			
		||||
  pika_container_editor_set_selection_mode (editor, GTK_SELECTION_MULTIPLE);
 | 
			
		||||
  pika_container_editor_set_selection_mode (editor, GTK_SELECTION_SINGLE);
 | 
			
		||||
 | 
			
		||||
  if (PIKA_IS_CONTAINER_TREE_VIEW (editor->view))
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
@ -778,6 +778,31 @@ pika_editor_add_action_button (PikaEditor  *editor,
 | 
			
		||||
  return button;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
pika_editor_set_action_sensitive (PikaEditor  *editor,
 | 
			
		||||
                                  const gchar *group_name,
 | 
			
		||||
                                  const gchar *action_name,
 | 
			
		||||
                                  gboolean     sensitive,
 | 
			
		||||
                                  const gchar *reason)
 | 
			
		||||
{
 | 
			
		||||
  PikaActionGroup *group;
 | 
			
		||||
  PikaAction      *action;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (PIKA_IS_EDITOR (editor));
 | 
			
		||||
  g_return_if_fail (action_name != NULL);
 | 
			
		||||
  g_return_if_fail (editor->priv->ui_manager != NULL);
 | 
			
		||||
 | 
			
		||||
  group = pika_ui_manager_get_action_group (editor->priv->ui_manager,
 | 
			
		||||
                                            group_name);
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (group != NULL);
 | 
			
		||||
 | 
			
		||||
  action = pika_action_group_get_action (group, action_name);
 | 
			
		||||
  g_return_if_fail (action != NULL);
 | 
			
		||||
 | 
			
		||||
  pika_action_set_sensitive (action, sensitive, reason);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
pika_editor_set_show_name (PikaEditor *editor,
 | 
			
		||||
                           gboolean    show)
 | 
			
		||||
 | 
			
		||||
@ -89,6 +89,11 @@ GtkWidget * pika_editor_add_action_button (PikaEditor           *editor,
 | 
			
		||||
                                           const gchar          *group_name,
 | 
			
		||||
                                           const gchar          *action_name,
 | 
			
		||||
                                           ...) G_GNUC_NULL_TERMINATED;
 | 
			
		||||
void     pika_editor_set_action_sensitive (PikaEditor          *editor,
 | 
			
		||||
                                           const gchar         *group_name,
 | 
			
		||||
                                           const gchar         *action_name,
 | 
			
		||||
                                           gboolean             sensitive,
 | 
			
		||||
                                           const gchar         *reason);
 | 
			
		||||
 | 
			
		||||
void        pika_editor_set_show_name       (PikaEditor         *editor,
 | 
			
		||||
                                             gboolean            show);
 | 
			
		||||
 | 
			
		||||
@ -90,6 +90,8 @@ static gboolean pika_file_dialog_delete_event            (GtkWidget           *w
 | 
			
		||||
                                                          GdkEventAny         *event);
 | 
			
		||||
static void     pika_file_dialog_response                (GtkDialog           *dialog,
 | 
			
		||||
                                                          gint                 response_id);
 | 
			
		||||
static void     pika_file_dialog_map                     (PikaFileDialog      *dialog,
 | 
			
		||||
                                                          gpointer             data);
 | 
			
		||||
static GFile  * pika_file_dialog_real_get_default_folder (PikaFileDialog      *dialog);
 | 
			
		||||
static void     pika_file_dialog_real_save_state         (PikaFileDialog      *dialog,
 | 
			
		||||
                                                          const gchar         *state_name);
 | 
			
		||||
@ -108,7 +110,7 @@ static void     pika_file_dialog_progress_set_value      (PikaProgress        *p
 | 
			
		||||
                                                          gdouble              percentage);
 | 
			
		||||
static gdouble  pika_file_dialog_progress_get_value      (PikaProgress        *progress);
 | 
			
		||||
static void     pika_file_dialog_progress_pulse          (PikaProgress        *progress);
 | 
			
		||||
static guint32  pika_file_dialog_progress_get_window_id  (PikaProgress        *progress);
 | 
			
		||||
static GBytes * pika_file_dialog_progress_get_window_id  (PikaProgress        *progress);
 | 
			
		||||
 | 
			
		||||
static void     pika_file_dialog_add_user_dir            (PikaFileDialog      *dialog,
 | 
			
		||||
                                                          GUserDirectory       directory);
 | 
			
		||||
@ -229,6 +231,11 @@ pika_file_dialog_class_init (PikaFileDialogClass *klass)
 | 
			
		||||
static void
 | 
			
		||||
pika_file_dialog_init (PikaFileDialog *dialog)
 | 
			
		||||
{
 | 
			
		||||
#ifdef G_OS_WIN32
 | 
			
		||||
  g_signal_connect (dialog, "map",
 | 
			
		||||
                    G_CALLBACK (pika_file_dialog_map),
 | 
			
		||||
                    NULL);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@ -372,6 +379,8 @@ pika_file_dialog_constructed (GObject *object)
 | 
			
		||||
  dialog->progress = pika_progress_box_new ();
 | 
			
		||||
  gtk_box_pack_end (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
 | 
			
		||||
                    dialog->progress, FALSE, FALSE, 0);
 | 
			
		||||
 | 
			
		||||
  pika_widget_set_native_handle (GTK_WIDGET (dialog), &dialog->window_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@ -422,6 +431,15 @@ pika_file_dialog_response (GtkDialog *dialog,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
pika_file_dialog_map (PikaFileDialog *dialog,
 | 
			
		||||
                      gpointer        data)
 | 
			
		||||
{
 | 
			
		||||
#ifdef G_OS_WIN32
 | 
			
		||||
  pika_window_set_title_bar_theme (dialog->pika, GTK_WIDGET (dialog), FALSE);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GFile *
 | 
			
		||||
pika_file_dialog_real_get_default_folder (PikaFileDialog *dialog)
 | 
			
		||||
{
 | 
			
		||||
@ -579,12 +597,12 @@ pika_file_dialog_progress_pulse (PikaProgress *progress)
 | 
			
		||||
    pika_progress_pulse (PIKA_PROGRESS (dialog->progress));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static guint32
 | 
			
		||||
static GBytes *
 | 
			
		||||
pika_file_dialog_progress_get_window_id (PikaProgress *progress)
 | 
			
		||||
{
 | 
			
		||||
  PikaFileDialog *dialog = PIKA_FILE_DIALOG (progress);
 | 
			
		||||
 | 
			
		||||
  return pika_window_get_native_id (GTK_WINDOW (dialog));
 | 
			
		||||
  return dialog->window_handle;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user