mirror of
https://gitlab.gnome.org/GNOME/gimp.git
synced 2025-10-06 01:12:40 +02:00
app, libgimp, pdb: new gimp_palette_set_colormap() PDB procedure.
This commit is contained in:
@@ -175,6 +175,7 @@ gimp_data_class_init (GimpDataClass *klass)
|
||||
g_object_class_install_property (object_class, PROP_IMAGE,
|
||||
g_param_spec_object ("image", NULL, NULL,
|
||||
GIMP_TYPE_IMAGE,
|
||||
G_PARAM_EXPLICIT_NOTIFY |
|
||||
GIMP_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_WRITABLE,
|
||||
@@ -992,6 +993,8 @@ gimp_data_set_image (GimpData *data,
|
||||
|
||||
private->writable = writable ? TRUE : FALSE;
|
||||
private->deletable = deletable ? TRUE : FALSE;
|
||||
|
||||
g_object_notify (G_OBJECT (data), "image");
|
||||
}
|
||||
|
||||
GimpImage *
|
||||
|
@@ -88,7 +88,7 @@ gimp_image_colormap_init (GimpImage *image)
|
||||
palette_id = g_strdup_printf ("gimp-indexed-image-palette-%d",
|
||||
gimp_image_get_id (image));
|
||||
|
||||
private->palette = GIMP_PALETTE (gimp_palette_new (NULL, palette_name));
|
||||
private->palette = GIMP_PALETTE (gimp_palette_new (NULL, palette_name));
|
||||
|
||||
gimp_image_colormap_update_formats (image);
|
||||
|
||||
@@ -254,8 +254,6 @@ _gimp_image_get_colormap (GimpImage *image,
|
||||
gint *n_colors)
|
||||
{
|
||||
GimpImagePrivate *private;
|
||||
const Babl *space;
|
||||
const Babl *format;
|
||||
|
||||
g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
|
||||
|
||||
@@ -264,10 +262,9 @@ _gimp_image_get_colormap (GimpImage *image,
|
||||
if (private->palette == NULL)
|
||||
return NULL;
|
||||
|
||||
space = gimp_image_get_layer_space (image);
|
||||
format = gimp_babl_format (GIMP_RGB, private->precision, FALSE, space);
|
||||
g_return_val_if_fail (private->palette->format != NULL, NULL);
|
||||
|
||||
return gimp_palette_get_colormap (private->palette, format, n_colors);
|
||||
return gimp_palette_get_colormap (private->palette, private->palette->format, n_colors);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -277,12 +274,8 @@ _gimp_image_set_colormap (GimpImage *image,
|
||||
gboolean push_undo)
|
||||
{
|
||||
GimpImagePrivate *private;
|
||||
GimpPaletteEntry *entry;
|
||||
const Babl *space;
|
||||
const Babl *format;
|
||||
GeglColor *color;
|
||||
gint bpp;
|
||||
gint i;
|
||||
|
||||
g_return_if_fail (GIMP_IS_IMAGE (image));
|
||||
g_return_if_fail (colormap != NULL || n_colors == 0);
|
||||
@@ -290,31 +283,14 @@ _gimp_image_set_colormap (GimpImage *image,
|
||||
|
||||
private = GIMP_IMAGE_GET_PRIVATE (image);
|
||||
|
||||
if (push_undo)
|
||||
gimp_image_undo_push_image_colormap (image, C_("undo-type", "Set Colormap"));
|
||||
|
||||
if (!private->palette)
|
||||
if (private->palette == NULL)
|
||||
gimp_image_colormap_init (image);
|
||||
|
||||
gimp_data_freeze (GIMP_DATA (private->palette));
|
||||
|
||||
while ((entry = gimp_palette_get_entry (private->palette, 0)))
|
||||
gimp_palette_delete_entry (private->palette, entry);
|
||||
|
||||
space = gimp_image_get_layer_space (image);
|
||||
format = gimp_babl_format (GIMP_RGB, private->precision, FALSE, space);
|
||||
bpp = babl_format_get_bytes_per_pixel (format);
|
||||
|
||||
color = gegl_color_new (NULL);
|
||||
for (i = 0; i < n_colors; i++)
|
||||
{
|
||||
gegl_color_set_pixel (color, format, &colormap[i * bpp]);
|
||||
gimp_image_colormap_set_palette_entry (image, color, i);
|
||||
}
|
||||
g_object_unref (color);
|
||||
|
||||
gimp_palette_set_colormap (private->palette, format, colormap, n_colors, push_undo);
|
||||
gimp_image_colormap_changed (image, -1);
|
||||
gimp_data_thaw (GIMP_DATA (private->palette));
|
||||
}
|
||||
|
||||
void
|
||||
|
@@ -28,6 +28,8 @@
|
||||
|
||||
#include "core-types.h"
|
||||
|
||||
#include "gegl/gimp-babl.h"
|
||||
|
||||
#include "gimp-memsize.h"
|
||||
#include "gimpimage.h"
|
||||
#include "gimpimage-undo-push.h"
|
||||
@@ -51,41 +53,47 @@ enum
|
||||
|
||||
/* local function prototypes */
|
||||
|
||||
static void gimp_palette_tagged_iface_init (GimpTaggedInterface *iface);
|
||||
static void gimp_palette_tagged_iface_init (GimpTaggedInterface *iface);
|
||||
|
||||
static void gimp_palette_finalize (GObject *object);
|
||||
static void gimp_palette_finalize (GObject *object);
|
||||
|
||||
static gint64 gimp_palette_get_memsize (GimpObject *object,
|
||||
gint64 *gui_size);
|
||||
static gint64 gimp_palette_get_memsize (GimpObject *object,
|
||||
gint64 *gui_size);
|
||||
|
||||
static void gimp_palette_get_preview_size (GimpViewable *viewable,
|
||||
gint size,
|
||||
gboolean popup,
|
||||
gboolean dot_for_dot,
|
||||
gint *width,
|
||||
gint *height);
|
||||
static gboolean gimp_palette_get_popup_size (GimpViewable *viewable,
|
||||
gint width,
|
||||
gint height,
|
||||
gboolean dot_for_dot,
|
||||
gint *popup_width,
|
||||
gint *popup_height);
|
||||
static GimpTempBuf * gimp_palette_get_new_preview (GimpViewable *viewable,
|
||||
GimpContext *context,
|
||||
gint width,
|
||||
gint height);
|
||||
static gchar * gimp_palette_get_description (GimpViewable *viewable,
|
||||
gchar **tooltip);
|
||||
static const gchar * gimp_palette_get_extension (GimpData *data);
|
||||
static void gimp_palette_copy (GimpData *data,
|
||||
GimpData *src_data);
|
||||
static void gimp_palette_real_entry_changed (GimpPalette *palette,
|
||||
gint index);
|
||||
static void gimp_palette_get_preview_size (GimpViewable *viewable,
|
||||
gint size,
|
||||
gboolean popup,
|
||||
gboolean dot_for_dot,
|
||||
gint *width,
|
||||
gint *height);
|
||||
static gboolean gimp_palette_get_popup_size (GimpViewable *viewable,
|
||||
gint width,
|
||||
gint height,
|
||||
gboolean dot_for_dot,
|
||||
gint *popup_width,
|
||||
gint *popup_height);
|
||||
static GimpTempBuf * gimp_palette_get_new_preview (GimpViewable *viewable,
|
||||
GimpContext *context,
|
||||
gint width,
|
||||
gint height);
|
||||
static gchar * gimp_palette_get_description (GimpViewable *viewable,
|
||||
gchar **tooltip);
|
||||
static const gchar * gimp_palette_get_extension (GimpData *data);
|
||||
static void gimp_palette_copy (GimpData *data,
|
||||
GimpData *src_data);
|
||||
static void gimp_palette_real_entry_changed (GimpPalette *palette,
|
||||
gint index);
|
||||
|
||||
static void gimp_palette_entry_free (GimpPaletteEntry *entry);
|
||||
static gint64 gimp_palette_entry_get_memsize (GimpPaletteEntry *entry,
|
||||
gint64 *gui_size);
|
||||
static gchar * gimp_palette_get_checksum (GimpTagged *tagged);
|
||||
static void gimp_palette_entry_free (GimpPaletteEntry *entry);
|
||||
static gint64 gimp_palette_entry_get_memsize (GimpPaletteEntry *entry,
|
||||
gint64 *gui_size);
|
||||
static gchar * gimp_palette_get_checksum (GimpTagged *tagged);
|
||||
|
||||
static void gimp_palette_image_space_updated (GimpImage *image,
|
||||
GimpPalette *palette);
|
||||
static void gimp_palette_notify_image (GimpPalette *palette,
|
||||
const GParamSpec *unused,
|
||||
gpointer unused_user_data);
|
||||
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GimpPalette, gimp_palette, GIMP_TYPE_DATA,
|
||||
@@ -141,6 +149,12 @@ gimp_palette_init (GimpPalette *palette)
|
||||
palette->colors = NULL;
|
||||
palette->n_colors = 0;
|
||||
palette->n_columns = 0;
|
||||
palette->image = NULL;
|
||||
palette->format = NULL;
|
||||
|
||||
g_signal_connect (palette, "notify::image",
|
||||
G_CALLBACK (gimp_palette_notify_image),
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -155,6 +169,8 @@ gimp_palette_finalize (GObject *object)
|
||||
palette->colors = NULL;
|
||||
}
|
||||
|
||||
g_clear_weak_pointer (&palette->image);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
@@ -401,6 +417,58 @@ gimp_palette_get_checksum (GimpTagged *tagged)
|
||||
return checksum_string;
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_palette_image_space_updated (GimpImage *image,
|
||||
GimpPalette *palette)
|
||||
{
|
||||
const Babl *space;
|
||||
const Babl *format;
|
||||
|
||||
space = gimp_image_get_layer_space (image);
|
||||
format = gimp_babl_format (GIMP_RGB, gimp_image_get_precision (image), FALSE, space);
|
||||
gimp_palette_restrict_format (palette, format);
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_palette_notify_image (GimpPalette *palette,
|
||||
const GParamSpec *unused,
|
||||
gpointer unused_user_data)
|
||||
{
|
||||
GimpImage *image = gimp_data_get_image (GIMP_DATA (palette));
|
||||
|
||||
if (palette->image == image)
|
||||
return;
|
||||
|
||||
if (palette->image)
|
||||
g_signal_handlers_disconnect_by_func (palette->image,
|
||||
G_CALLBACK (gimp_palette_image_space_updated),
|
||||
palette);
|
||||
|
||||
g_set_weak_pointer (&palette->image, image);
|
||||
|
||||
if (image)
|
||||
{
|
||||
/* Note: I only connect to "precision-changed", and not
|
||||
* "profile-changed" changes which is handled in
|
||||
* gimp_image_convert_profile_colormap() with additional bpc
|
||||
* argument.
|
||||
* In current implementation of indexed images,
|
||||
* "precision-changed" should not happen because it is always
|
||||
* 8-bit non-linear.
|
||||
*/
|
||||
g_signal_connect_object (image,
|
||||
"precision-changed",
|
||||
G_CALLBACK (gimp_palette_image_space_updated),
|
||||
palette, 0);
|
||||
|
||||
gimp_palette_image_space_updated (image, palette);
|
||||
}
|
||||
else
|
||||
{
|
||||
gimp_palette_restrict_format (palette, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* public functions */
|
||||
|
||||
@@ -799,6 +867,53 @@ gimp_palette_get_colormap (GimpPalette *palette,
|
||||
return colormap;
|
||||
}
|
||||
|
||||
void
|
||||
gimp_palette_set_colormap (GimpPalette *palette,
|
||||
const Babl *format,
|
||||
const guchar *colormap,
|
||||
gint n_colors,
|
||||
gboolean push_undo_if_image)
|
||||
{
|
||||
GimpPaletteEntry *entry;
|
||||
GeglColor *color;
|
||||
gchar name[64];
|
||||
gint bpp;
|
||||
gint i;
|
||||
|
||||
g_return_if_fail (GIMP_IS_PALETTE (palette));
|
||||
g_return_if_fail (format != NULL);
|
||||
g_return_if_fail (n_colors > 0);
|
||||
|
||||
if (push_undo_if_image && gimp_data_get_image (GIMP_DATA (palette)))
|
||||
gimp_image_undo_push_image_colormap (gimp_data_get_image (GIMP_DATA (palette)),
|
||||
C_("undo-type", "Set Colormap"));
|
||||
|
||||
if (gimp_data_get_image (GIMP_DATA (palette)))
|
||||
n_colors = MIN (n_colors, 256);
|
||||
|
||||
gimp_data_freeze (GIMP_DATA (palette));
|
||||
|
||||
while ((entry = gimp_palette_get_entry (palette, 0)))
|
||||
gimp_palette_delete_entry (palette, entry);
|
||||
|
||||
bpp = babl_format_get_bytes_per_pixel (format);
|
||||
|
||||
color = gegl_color_new (NULL);
|
||||
for (i = 0; i < n_colors; i++)
|
||||
{
|
||||
gegl_color_set_pixel (color, format, &colormap[i * bpp]);
|
||||
g_snprintf (name, sizeof (name), "#%d", i);
|
||||
gimp_palette_add_entry (palette, i, name, color);
|
||||
}
|
||||
g_object_unref (color);
|
||||
|
||||
gimp_data_thaw (GIMP_DATA (palette));
|
||||
|
||||
if (! gimp_data_is_frozen (GIMP_DATA (palette)))
|
||||
for (gint i = 0; i < n_colors; i++)
|
||||
g_signal_emit (palette, signals[ENTRY_CHANGED], 0, i);
|
||||
}
|
||||
|
||||
|
||||
/* private functions */
|
||||
|
||||
|
@@ -43,6 +43,13 @@ struct _GimpPalette
|
||||
{
|
||||
GimpData parent_instance;
|
||||
|
||||
/* When set to an image, we store the image we connect to, so that we
|
||||
* can correctly disconnect if parent GimpData's image changes (so the
|
||||
* GimpPalette and GimpData's images may be unsynced for a tiny span of
|
||||
* time).
|
||||
*/
|
||||
GimpImage *image;
|
||||
|
||||
/* Palette colors can be restricted to a given format. If NULL, then the
|
||||
* palette can be a mix of color models and color spaces.
|
||||
*/
|
||||
@@ -114,6 +121,11 @@ GimpPaletteEntry * gimp_palette_find_entry (GimpPalette *palette,
|
||||
guchar * gimp_palette_get_colormap (GimpPalette *palette,
|
||||
const Babl *format,
|
||||
gint *n_colors);
|
||||
void gimp_palette_set_colormap (GimpPalette *palette,
|
||||
const Babl *format,
|
||||
const guchar *colormap,
|
||||
gint n_colors,
|
||||
gboolean push_undo_if_image);
|
||||
|
||||
|
||||
#endif /* __GIMP_PALETTE_H__ */
|
||||
|
@@ -30,7 +30,7 @@
|
||||
#include "internal-procs.h"
|
||||
|
||||
|
||||
/* 779 procedures registered total */
|
||||
/* 780 procedures registered total */
|
||||
|
||||
void
|
||||
internal_procs_init (GimpPDB *pdb)
|
||||
|
@@ -492,6 +492,49 @@ palette_get_colormap_invoker (GimpProcedure *procedure,
|
||||
return return_vals;
|
||||
}
|
||||
|
||||
static GimpValueArray *
|
||||
palette_set_colormap_invoker (GimpProcedure *procedure,
|
||||
Gimp *gimp,
|
||||
GimpContext *context,
|
||||
GimpProgress *progress,
|
||||
const GimpValueArray *args,
|
||||
GError **error)
|
||||
{
|
||||
gboolean success = TRUE;
|
||||
GimpPalette *palette;
|
||||
const Babl *format;
|
||||
GBytes *colormap;
|
||||
|
||||
palette = g_value_get_object (gimp_value_array_index (args, 0));
|
||||
format = g_value_get_boxed (gimp_value_array_index (args, 1));
|
||||
colormap = g_value_get_boxed (gimp_value_array_index (args, 2));
|
||||
|
||||
if (success)
|
||||
{
|
||||
gint bpp;
|
||||
|
||||
bpp = babl_format_get_bytes_per_pixel (format);
|
||||
|
||||
if (g_bytes_get_size (colormap) % bpp == 0)
|
||||
{
|
||||
const guchar *data;
|
||||
gsize n_bytes;
|
||||
gint n_colors;
|
||||
|
||||
data = g_bytes_get_data (colormap, &n_bytes),
|
||||
n_colors = n_bytes / bpp;
|
||||
gimp_palette_set_colormap (palette, format, (guchar *) data, n_colors, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
success = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return gimp_procedure_get_return_values (procedure, success,
|
||||
error ? *error : NULL);
|
||||
}
|
||||
|
||||
void
|
||||
register_palette_procs (GimpPDB *pdb)
|
||||
{
|
||||
@@ -961,4 +1004,42 @@ register_palette_procs (GimpPDB *pdb)
|
||||
GIMP_PARAM_READWRITE));
|
||||
gimp_pdb_register_procedure (pdb, procedure);
|
||||
g_object_unref (procedure);
|
||||
|
||||
/*
|
||||
* gimp-palette-set-colormap
|
||||
*/
|
||||
procedure = gimp_procedure_new (palette_set_colormap_invoker);
|
||||
gimp_object_set_static_name (GIMP_OBJECT (procedure),
|
||||
"gimp-palette-set-colormap");
|
||||
gimp_procedure_set_static_help (procedure,
|
||||
"Sets the entries in the image's colormap.",
|
||||
"This procedure sets the entries in the specified palette in one go. The number of entries depens on the size of @colormap and the bytes-per-pixel size of @format.\n"
|
||||
"The procedure will fail if the size of @colormap is not an exact multiple of the number of bytes per pixel of @format.",
|
||||
NULL);
|
||||
gimp_procedure_set_static_attribution (procedure,
|
||||
"Jehan",
|
||||
"Jehan",
|
||||
"2024");
|
||||
gimp_procedure_add_argument (procedure,
|
||||
gimp_param_spec_palette ("palette",
|
||||
"palette",
|
||||
"The palette",
|
||||
FALSE,
|
||||
NULL,
|
||||
FALSE,
|
||||
GIMP_PARAM_READWRITE));
|
||||
gimp_procedure_add_argument (procedure,
|
||||
g_param_spec_boxed ("format",
|
||||
"format",
|
||||
"The desired color format",
|
||||
GIMP_TYPE_BABL_FORMAT,
|
||||
GIMP_PARAM_READWRITE));
|
||||
gimp_procedure_add_argument (procedure,
|
||||
g_param_spec_boxed ("colormap",
|
||||
"colormap",
|
||||
"The new colormap values",
|
||||
G_TYPE_BYTES,
|
||||
GIMP_PARAM_READWRITE));
|
||||
gimp_pdb_register_procedure (pdb, procedure);
|
||||
g_object_unref (procedure);
|
||||
}
|
||||
|
@@ -674,6 +674,7 @@ EXPORTS
|
||||
gimp_palette_get_columns
|
||||
gimp_palette_get_type
|
||||
gimp_palette_new
|
||||
gimp_palette_set_colormap
|
||||
gimp_palette_set_columns
|
||||
gimp_palettes_close_popup
|
||||
gimp_palettes_get_list
|
||||
|
@@ -578,3 +578,48 @@ gimp_palette_get_colormap (GimpPalette *palette,
|
||||
|
||||
return colormap;
|
||||
}
|
||||
|
||||
/**
|
||||
* gimp_palette_set_colormap:
|
||||
* @palette: The palette.
|
||||
* @format: The desired color format.
|
||||
* @colormap: The new colormap values.
|
||||
*
|
||||
* Sets the entries in the image's colormap.
|
||||
*
|
||||
* This procedure sets the entries in the specified palette in one go.
|
||||
* The number of entries depens on the size of @colormap and the
|
||||
* bytes-per-pixel size of @format.
|
||||
* The procedure will fail if the size of @colormap is not an exact
|
||||
* multiple of the number of bytes per pixel of @format.
|
||||
*
|
||||
* Returns: TRUE on success.
|
||||
*
|
||||
* Since: 3.0
|
||||
**/
|
||||
gboolean
|
||||
gimp_palette_set_colormap (GimpPalette *palette,
|
||||
const Babl *format,
|
||||
GBytes *colormap)
|
||||
{
|
||||
GimpValueArray *args;
|
||||
GimpValueArray *return_vals;
|
||||
gboolean success = TRUE;
|
||||
|
||||
args = gimp_value_array_new_from_types (NULL,
|
||||
GIMP_TYPE_PALETTE, palette,
|
||||
GIMP_TYPE_BABL_FORMAT, format,
|
||||
G_TYPE_BYTES, colormap,
|
||||
G_TYPE_NONE);
|
||||
|
||||
return_vals = _gimp_pdb_run_procedure_array (gimp_get_pdb (),
|
||||
"gimp-palette-set-colormap",
|
||||
args);
|
||||
gimp_value_array_unref (args);
|
||||
|
||||
success = GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS;
|
||||
|
||||
gimp_value_array_unref (return_vals);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
@@ -59,6 +59,9 @@ gboolean gimp_palette_entry_set_name (GimpPalette *palette,
|
||||
GBytes* gimp_palette_get_colormap (GimpPalette *palette,
|
||||
const Babl *format,
|
||||
gint *num_colors);
|
||||
gboolean gimp_palette_set_colormap (GimpPalette *palette,
|
||||
const Babl *format,
|
||||
GBytes *colormap);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
@@ -475,6 +475,55 @@ CODE
|
||||
);
|
||||
}
|
||||
|
||||
sub palette_set_colormap {
|
||||
$blurb = "Sets the entries in the image's colormap.";
|
||||
|
||||
$help = <<'HELP';
|
||||
This procedure sets the entries in the specified palette in one go. The number
|
||||
of entries depens on the size of @colormap and the bytes-per-pixel size of @format.
|
||||
|
||||
The procedure will fail if the size of @colormap is not an exact
|
||||
multiple of the number of bytes per pixel of @format.
|
||||
HELP
|
||||
|
||||
&jehan_pdb_misc('2024', '3.0');
|
||||
|
||||
@inargs = (
|
||||
{ name => 'palette', type => 'palette',
|
||||
desc => 'The palette' },
|
||||
{ name => 'format', type => 'format',
|
||||
desc => 'The desired color format' },
|
||||
{ name => 'colormap', type => 'bytes',
|
||||
desc => 'The new colormap values' }
|
||||
);
|
||||
|
||||
%invoke = (
|
||||
headers => [ qw("core/gimpimage-colormap.h") ],
|
||||
code => <<'CODE'
|
||||
{
|
||||
gint bpp;
|
||||
|
||||
bpp = babl_format_get_bytes_per_pixel (format);
|
||||
|
||||
if (g_bytes_get_size (colormap) % bpp == 0)
|
||||
{
|
||||
const guchar *data;
|
||||
gsize n_bytes;
|
||||
gint n_colors;
|
||||
|
||||
data = g_bytes_get_data (colormap, &n_bytes),
|
||||
n_colors = n_bytes / bpp;
|
||||
gimp_palette_set_colormap (palette, format, (guchar *) data, n_colors, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
success = FALSE;
|
||||
}
|
||||
}
|
||||
CODE
|
||||
);
|
||||
}
|
||||
|
||||
@headers = qw(<string.h>
|
||||
"core/gimp.h"
|
||||
"core/gimpcontext.h"
|
||||
@@ -491,7 +540,7 @@ CODE
|
||||
palette_add_entry palette_delete_entry
|
||||
palette_entry_get_color palette_entry_set_color
|
||||
palette_entry_get_name palette_entry_set_name
|
||||
palette_get_colormap);
|
||||
palette_get_colormap palette_set_colormap);
|
||||
|
||||
%exports = (app => [@procs], lib => [@procs]);
|
||||
|
||||
|
Reference in New Issue
Block a user