mirror of https://github.com/GNOME/gimp.git
168 lines
6.7 KiB
Python
Executable File
168 lines
6.7 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
# 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/>.
|
|
|
|
import gi
|
|
gi.require_version('Gimp', '3.0')
|
|
from gi.repository import Gimp
|
|
gi.require_version('GimpUi', '3.0')
|
|
from gi.repository import GimpUi
|
|
gi.require_version('Gegl', '0.4')
|
|
from gi.repository import Gegl
|
|
from gi.repository import GObject
|
|
from gi.repository import GLib
|
|
from gi.repository import Gio
|
|
|
|
import os
|
|
import sys
|
|
|
|
def N_(message): return message
|
|
def _(message): return GLib.dgettext(None, message)
|
|
|
|
class Goat (Gimp.PlugIn):
|
|
## GimpPlugIn virtual methods ##
|
|
def do_query_procedures(self):
|
|
return [ "plug-in-goat-exercise-python" ]
|
|
|
|
def do_create_procedure(self, name):
|
|
procedure = Gimp.ImageProcedure.new(self, name,
|
|
Gimp.PDBProcType.PLUGIN,
|
|
self.run, None)
|
|
|
|
procedure.set_image_types("*")
|
|
procedure.set_sensitivity_mask (Gimp.ProcedureSensitivityMask.DRAWABLE)
|
|
|
|
procedure.set_menu_label(_("Plug-In Example in _Python 3"))
|
|
procedure.set_icon_name(GimpUi.ICON_GEGL)
|
|
procedure.add_menu_path('<Image>/Filters/Development/Plug-In Examples/')
|
|
|
|
procedure.set_documentation(_("Plug-in example in Python 3"),
|
|
_("Plug-in example in Python 3"),
|
|
name)
|
|
procedure.set_attribution("Jehan", "Jehan", "2019")
|
|
|
|
return procedure
|
|
|
|
def run(self, procedure, run_mode, image, n_drawables, drawables, config, run_data):
|
|
if n_drawables != 1:
|
|
msg = _("Procedure '{}' only works with one drawable.").format(procedure.get_name())
|
|
error = GLib.Error.new_literal(Gimp.PlugIn.error_quark(), msg, 0)
|
|
return procedure.new_return_values(Gimp.PDBStatusType.CALLING_ERROR, error)
|
|
else:
|
|
drawable = drawables[0]
|
|
|
|
if run_mode == Gimp.RunMode.INTERACTIVE:
|
|
gi.require_version('Gtk', '3.0')
|
|
from gi.repository import Gtk
|
|
gi.require_version('Gdk', '3.0')
|
|
from gi.repository import Gdk
|
|
|
|
GimpUi.init("goat-exercise-py3.py")
|
|
|
|
dialog = GimpUi.Dialog(use_header_bar=True,
|
|
title=_("Plug-In Example in Python 3"),
|
|
role="goat-exercise-Python3")
|
|
|
|
dialog.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL)
|
|
dialog.add_button(_("_Source"), Gtk.ResponseType.APPLY)
|
|
dialog.add_button(_("_OK"), Gtk.ResponseType.OK)
|
|
|
|
geometry = Gdk.Geometry()
|
|
geometry.min_aspect = 0.5
|
|
geometry.max_aspect = 1.0
|
|
dialog.set_geometry_hints(None, geometry, Gdk.WindowHints.ASPECT)
|
|
|
|
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=2)
|
|
dialog.get_content_area().add(box)
|
|
box.show()
|
|
|
|
# XXX We use printf-style string for sharing the localized
|
|
# string. You may just use recommended Python format() or
|
|
# any style you like in your plug-ins.
|
|
head_text=_("This plug-in is an exercise in '%s' to "
|
|
"demo plug-in creation.\nCheck out the last "
|
|
"version of the source code online by clicking "
|
|
"the \"Source\" button.") % ("Python 3")
|
|
label = Gtk.Label(label=head_text)
|
|
box.pack_start(label, False, False, 1)
|
|
label.show()
|
|
|
|
contents = None
|
|
# Get the file contents Python-style instead of using
|
|
# GLib.file_get_contents() which returns bytes result, and
|
|
# when converting to string, get newlines as text contents.
|
|
# Rather than wasting time to figure this out, use Python
|
|
# core API!
|
|
with open(os.path.realpath(__file__), 'r') as f:
|
|
contents = f.read()
|
|
|
|
if contents is not None:
|
|
scrolled = Gtk.ScrolledWindow()
|
|
scrolled.set_vexpand (True)
|
|
box.pack_start(scrolled, True, True, 1)
|
|
scrolled.show()
|
|
|
|
view = Gtk.TextView()
|
|
view.set_wrap_mode(Gtk.WrapMode.WORD)
|
|
view.set_editable(False)
|
|
buffer = view.get_buffer()
|
|
buffer.set_text(contents, -1)
|
|
scrolled.add(view)
|
|
view.show()
|
|
|
|
while (True):
|
|
response = dialog.run()
|
|
if response == Gtk.ResponseType.OK:
|
|
dialog.destroy()
|
|
break
|
|
elif response == Gtk.ResponseType.APPLY:
|
|
url = "https://gitlab.gnome.org/GNOME/gimp/-/blob/master/extensions/goat-exercises/goat-exercise-py3.py"
|
|
Gio.app_info_launch_default_for_uri(url, None)
|
|
continue
|
|
else:
|
|
dialog.destroy()
|
|
return procedure.new_return_values(Gimp.PDBStatusType.CANCEL,
|
|
GLib.Error())
|
|
|
|
intersect, x, y, width, height = drawable.mask_intersect()
|
|
if intersect:
|
|
Gegl.init(None)
|
|
|
|
buffer = drawable.get_buffer()
|
|
shadow_buffer = drawable.get_shadow_buffer()
|
|
|
|
graph = Gegl.Node()
|
|
input = graph.create_child("gegl:buffer-source")
|
|
input.set_property("buffer", buffer)
|
|
invert = graph.create_child("gegl:invert")
|
|
output = graph.create_child("gegl:write-buffer")
|
|
output.set_property("buffer", shadow_buffer)
|
|
input.link(invert)
|
|
invert.link(output)
|
|
output.process()
|
|
|
|
# This is extremely important in bindings, since we don't
|
|
# unref buffers. If we don't explicitly flush a buffer, we
|
|
# may left hanging forever. This step is usually done
|
|
# during an unref().
|
|
shadow_buffer.flush()
|
|
|
|
drawable.merge_shadow(True)
|
|
drawable.update(x, y, width, height)
|
|
Gimp.displays_flush()
|
|
|
|
return procedure.new_return_values(Gimp.PDBStatusType.SUCCESS, GLib.Error())
|
|
|
|
Gimp.main(Goat.__gtype__, sys.argv)
|