RSS/Atom feed Twitter
Site is read-only, email is disabled

template python plugin

This discussion is connected to the gimp-developer-list.gnome.org mailing list which is provided by the GIMP developers and not related to gimpusers.com.

This is a read-only list on gimpusers.com so this discussion thread is read-only, too.

6 of 6 messages available
Toggle history

Please log in to manage your subscriptions.

template python plugin Greg MacDonald 29 Sep 02:15
  template python plugin Sven Neumann 29 Sep 11:03
   template python plugin Greg MacDonald 29 Sep 12:04
  template python plugin Sven Neumann 29 Sep 12:37
   template python plugin Greg MacDonald 01 Oct 05:59
    template python plugin Sven Neumann 01 Oct 08:37
Greg MacDonald
2008-09-29 02:15:03 UTC (over 16 years ago)

template python plugin

Hi Everyone,

I've been fiddling around with writing gimp-python plugins and ended up creating a template for myself. It took me a day to put together so I was thinking I might post it. It demonstrates a few things like logging exceptions to a file for gui debugging (print statements and exceptions don't seem to display in gui mode for some reason) and running a plugin from the console which I've found useful for quick debug iterations. And it also shows how to use a file chooser dialog to prompt the user for a file. Hope you like it.

-Greg

#!/usr/bin/env python

# 9/14/2008 - Greg MacDonald

# This is an example gimp python plugin template. It demonstrates how to # create two different types of plugins; an image plugin, and a toolbox # plugin. The toolbox plugin only takes a run_mode parameter, while # the image plugin takes a run_mode parameter as well as an image and # drawable paramter.
#
# The example also shows how to use logging. This is useful for "printf" # debugging when running in interactive mode as print statements don't seem to # output to the console. They do however in batch mode. #
# Batch mode is also demonstrated with a mechanism to run a command in batch # mode if this file is run from the command line: "python gimp_plugin_template.py". #
# If an exception occurs during plugin execution, a stack trace is sent to the log.

try: import gimp
except:
if __name__ == '__main__':
import os
cmd = 'gimp-2.4 --console-messages --verbose --no-data --batch-interpreter python-fu-eval --no-interface --batch "pdb.toolbox_go(RUN_NONINTERACTIVE)" --batch "pdb.gimp_quit(0)"' os.sys.exit(os.system(cmd))
else:
raise

import gimpplugin
from gimpenums import *
pdb = gimp.pdb

import logging
FORMAT = '%(lineno)d:%(levelname)s %(asctime)s : %(message)s' # Other logging format options:
# %(name)s Name of the logger (logging channel). # %(levelno)s Numeric logging level for the message (DEBUG, INFO, WARNING, ERROR, CRITICAL). # %(levelname)s Text logging level for the message ('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'). # %(pathname)s Full pathname of the source file where the logging call was issued (if available). # %(filename)s Filename portion of pathname. # %(module)s Module (name portion of filename). # %(funcName)s Name of function containing the logging call. # %(lineno)d Source line number where the logging call was issued (if available). # %(created)f Time when the LogRecord was created (as returned by time.time()). # %(relativeCreated)d Time in milliseconds when the LogRecord was created, relative to the time the logging module was loaded. # %(asctime)s Human-readable time when the LogRecord was created. By default this is of the form ``2003-07-08 16:49:45,896'' (the numbers after the comma are millisecond portion of the time). # %(msecs)d Millisecond portion of the time when the LogRecord was created. # %(thread)d Thread ID (if available). # %(threadName)s Thread name (if available). # %(process)d Process ID (if available). # %(message)s The logged message, computed as msg % args.

logging.basicConfig(filename=r'c:\gimp_plugin.log', level=logging.INFO, format=FORMAT)

import gtk

class MyPlugin(gimpplugin.plugin): def __init__(self):
self.log = logging.getLogger('MyPlugin')
def start(self):
self.log.info('start')
gimp.main(self.init, self.quit, self.query, self._run)
def init(self):
self.log.info('init')

def quit(self):
self.log.info('quit')

def query(self):
self.log.info('query')

authorname = "My Name"
copyrightname = "My Name"
date = "2008"

menupath = "/My _Plugin/_Go" toolbox_go_description = "An example of a toolbox plugin." toolbox_go_help = "An example of a toolbox plugin." toolbox_go_params = [(PDB_INT32, "run_mode", "Run mode")] gimp.install_procedure("toolbox_go", toolbox_go_description, toolbox_go_help, authorname, copyrightname, date, menupath, "*",
PLUGIN, toolbox_go_params, [])

menupath = "/My _Plugin/_Go" image_go_description = "An example of an image plugin." image_go_help = "An example of an image plugin." image_go_params = [(PDB_INT32, "run_mode", "Run mode"), (PDB_IMAGE, "image", "Input image"), (PDB_DRAWABLE, "drawable", "Input drawable")] gimp.install_procedure("image_go", image_go_description, image_go_help, authorname, copyrightname, date, menupath, "*",
PLUGIN, image_go_params, [])

def __del__(self):
logging.shutdown()

def toolbox_go(self, run_mode):
try:
# RUN_WITH_LAST_VALS
self.log.info('toolbox_go') self.log_interaction_mode(run_mode)
if run_mode != RUN_INTERACTIVE: return

# Example file chooser.
chooser = gtk.FileChooserDialog(title='Choose a file.',action=gtk.FILE_CHOOSER_ACTION_OPEN, buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK)) chooser.set_current_folder('.')
# Repeat this block for additional file filter. filter = gtk.FileFilter() filter.set_name("All Files") filter.add_pattern("*.*") chooser.add_filter(filter)
response = chooser.run()
if response == gtk.RESPONSE_OK: path = chooser.get_filename() self.log.info('Chose File: %s', path) elif response == gtk.RESPONSE_CANCEL: self.log.info('User cancelled choosing a file.') return

chooser.destroy()
except:
import traceback
self.log.error("%s", traceback.format_exc()) raise

def log_interaction_mode(self, run_mode): if run_mode == RUN_INTERACTIVE: self.log.debug('run_mode=INTERACTIVE') elif run_mode == RUN_NONINTERACTIVE: self.log.debug('run_mode=RUN_NONINTERACTIVE') elif run_mode == RUN_WITH_LAST_VALS: self.log.debug('run_mode=RUN_WITH_LAST_VALS') else:
self.log.error('run_mode=UNKNOWN')
def image_go(self, run_mode, image, drawable): try:
self.log.info('image_go') self.log_interaction_mode(run_mode)
# Do something here.

except:
import traceback
self.log.error("%s", traceback.format_exc()) raise

if __name__ == '__main__':
MyPlugin().start()

Sven Neumann
2008-09-29 11:03:48 UTC (over 16 years ago)

template python plugin

Hi,

On Sun, 2008-09-28 at 17:15 -0700, Greg MacDonald wrote:

I've been fiddling around with writing gimp-python plugins and ended up creating a template for myself. It took me a day to put together so I was thinking I might post it.

This is interesting. Is there a particular reason that your plug-in template is not using gimpfu, the convenience layer that the Python binding offers for making it easier to write simple plug-ins?

Sven

Greg MacDonald
2008-09-29 12:04:57 UTC (over 16 years ago)

template python plugin

Hi Sven,

No reason really. But now that you bring it up, I wonder if gimpfu might be more useful to people. If I had needed to setup a gui, I probably would've stuck with gimpfu for it's auto gui generation features. I think I may have gone with gimpplugin too because it just felt familiar to me; reminded me of other sorts of plugins I've written.

Would you like me to switch it over?

-Greg

On Mon, Sep 29, 2008 at 2:03 AM, Sven Neumann wrote:

Hi,

On Sun, 2008-09-28 at 17:15 -0700, Greg MacDonald wrote:

I've been fiddling around with writing gimp-python plugins and ended up creating a template for myself. It took me a day to put together so I was thinking I might post it.

This is interesting. Is there a particular reason that your plug-in template is not using gimpfu, the convenience layer that the Python binding offers for making it easier to write simple plug-ins?

Sven

Sven Neumann
2008-09-29 12:37:36 UTC (over 16 years ago)

template python plugin

Hi,

I would very much welcome if you could change the call to gimp.install_procedure() to not pass the full menu path. The procedure is supposed to be passed the menu label only. There's a seperate procedure to register the menu entry: gimp.menu_register().

Sven

Greg MacDonald
2008-10-01 05:59:59 UTC (over 16 years ago)

template python plugin

Revised version attached.

On Mon, Sep 29, 2008 at 3:37 AM, Sven Neumann wrote:

Hi,

I would very much welcome if you could change the call to gimp.install_procedure() to not pass the full menu path. The procedure is supposed to be passed the menu label only. There's a seperate procedure to register the menu entry: gimp.menu_register().

Sven

#!/usr/bin/env python

# 9/14/2008 - Greg MacDonald

# This is an example gimp python plugin template. It demonstrates how to # create two different types of plugins; an image plugin, and a toolbox # plugin. The toolbox plugin only takes a run_mode parameter, while # the image plugin takes a run_mode parameter as well as an image and # drawable paramter.
#
# The example also shows how to use logging. This is useful for "printf" # debugging when running in interactive mode as print statements don't seem to # output to the console. They do however in batch mode. #
# Batch mode is also demonstrated with a mechanism to run a command in batch # mode if this file is run from the command line: "python gimp_plugin_template.py". #
# If an exception occurs during plugin execution, a stack trace is sent to the log.

try: import gimp
except:
if __name__ == '__main__':
import os
cmd = 'gimp-2.4 --console-messages --verbose --no-data --batch-interpreter python-fu-eval --no-interface --batch "pdb.toolbox_go(RUN_NONINTERACTIVE)" --batch "pdb.gimp_quit(0)"' os.sys.exit(os.system(cmd))
else:
raise

import gimpplugin
from gimpenums import *
pdb = gimp.pdb

import logging
FORMAT = '%(lineno)d:%(levelname)s %(asctime)s : %(message)s' # Other logging format options:
# %(name)s Name of the logger (logging channel). # %(levelno)s Numeric logging level for the message (DEBUG, INFO, WARNING, ERROR, CRITICAL). # %(levelname)s Text logging level for the message ('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'). # %(pathname)s Full pathname of the source file where the logging call was issued (if available). # %(filename)s Filename portion of pathname. # %(module)s Module (name portion of filename). # %(funcName)s Name of function containing the logging call. # %(lineno)d Source line number where the logging call was issued (if available). # %(created)f Time when the LogRecord was created (as returned by time.time()). # %(relativeCreated)d Time in milliseconds when the LogRecord was created, relative to the time the logging module was loaded. # %(asctime)s Human-readable time when the LogRecord was created. By default this is of the form ``2003-07-08 16:49:45,896'' (the numbers after the comma are millisecond portion of the time). # %(msecs)d Millisecond portion of the time when the LogRecord was created. # %(thread)d Thread ID (if available). # %(threadName)s Thread name (if available). # %(process)d Process ID (if available). # %(message)s The logged message, computed as msg % args.

logging.basicConfig(filename=r'c:\gimp_plugin.log', level=logging.INFO, format=FORMAT)

import gtk

class MyPlugin(gimpplugin.plugin): def __init__(self):
self.log = logging.getLogger('MyPlugin')
def start(self):
self.log.info('start')
gimp.main(self.init, self.quit, self.query, self._run)
def init(self):
self.log.info('init')

def quit(self):
self.log.info('quit')

def query(self):
self.log.info('query')

authorname = "My Name"
copyrightname = "My Name"
date = "2008"

menulabel = "_Go"
toolbox_go_description = "An example of a toolbox plugin." toolbox_go_help = "An example of a toolbox plugin." toolbox_go_params = [(PDB_INT32, "run_mode", "Run mode")] gimp.install_procedure("toolbox_go", toolbox_go_description, toolbox_go_help, authorname, copyrightname, date, menulabel, "*",
PLUGIN, toolbox_go_params, [])

menupath = "/My _Plugin/"
gimp.menu_register("toolbox_go", menupath)
menulabel = "_Go"
image_go_description = "An example of an image plugin." image_go_help = "An example of an image plugin." image_go_params = [(PDB_INT32, "run_mode", "Run mode"), (PDB_IMAGE, "image", "Input image"), (PDB_DRAWABLE, "drawable", "Input drawable")] gimp.install_procedure("image_go", image_go_description, image_go_help, authorname, copyrightname, date, menulabel, "*",
PLUGIN, image_go_params, [])

menupath = "/My _Plugin/"
gimp.menu_register("image_go", menupath)
def __del__(self):
logging.shutdown()

def toolbox_go(self, run_mode):
try:
# RUN_WITH_LAST_VALS
self.log.info('toolbox_go') self.log_interaction_mode(run_mode)
if run_mode != RUN_INTERACTIVE: return

# Example file chooser.
chooser = gtk.FileChooserDialog(title='Choose a file.',action=gtk.FILE_CHOOSER_ACTION_OPEN, buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK)) chooser.set_current_folder('.')
# Repeat this block for additional file filter. filter = gtk.FileFilter() filter.set_name("All Files") filter.add_pattern("*.*") chooser.add_filter(filter)
response = chooser.run()
if response == gtk.RESPONSE_OK: path = chooser.get_filename() self.log.info('Chose File: %s', path) elif response == gtk.RESPONSE_CANCEL: self.log.info('User cancelled choosing a file.') return

chooser.destroy()
except:
import traceback
self.log.error("%s", traceback.format_exc()) raise

def log_interaction_mode(self, run_mode): if run_mode == RUN_INTERACTIVE: self.log.debug('run_mode=INTERACTIVE') elif run_mode == RUN_NONINTERACTIVE: self.log.debug('run_mode=RUN_NONINTERACTIVE') elif run_mode == RUN_WITH_LAST_VALS: self.log.debug('run_mode=RUN_WITH_LAST_VALS') else:
self.log.error('run_mode=UNKNOWN')
def image_go(self, run_mode, image, drawable): try:
self.log.info('image_go') self.log_interaction_mode(run_mode)
# Do something here.

except:
import traceback
self.log.error("%s", traceback.format_exc()) raise

if __name__ == '__main__':
MyPlugin().start()

Sven Neumann
2008-10-01 08:37:00 UTC (over 16 years ago)

template python plugin

Hi,

On Tue, 2008-09-30 at 20:59 -0700, Greg MacDonald wrote:

Revised version attached.

Another question: why does your plug-in register image and drawable input parameters? It doesn't seem to use these at all.

Sven