Mini Kabibi Habibi
#!/usr/bin/env python2
# Gimp-Python - allows the writing of Gimp plugins in Python.
# Copyright (C) 1997 James Henstridge <james@daa.com.au>
#
# 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/>.
from gimpfu import *
t = gettext.translation('gimp20-python', gimp.locale_directory, fallback=True)
_ = t.ugettext
PROC_NAME = 'python-fu-console'
RESPONSE_BROWSE, RESPONSE_CLEAR, RESPONSE_SAVE = range(3)
def do_console():
import pygtk
pygtk.require('2.0')
import sys, gobject, gtk, gimpenums, gimpshelf, gimpui, pyconsole
gimpui.gimp_ui_init ()
namespace = {'__builtins__': __builtins__,
'__name__': '__main__', '__doc__': None,
'gimp': gimp, 'pdb': gimp.pdb,
'shelf': gimpshelf.shelf}
for s in gimpenums.__dict__.keys():
if s[0] != '_':
namespace[s] = getattr(gimpenums, s)
class GimpConsole(pyconsole.Console):
def __init__(self, quit_func=None):
banner = ('GIMP %s Python Console\nPython %s\n' %
(gimp.pdb.gimp_version(), sys.version))
pyconsole.Console.__init__(self,
locals=namespace, banner=banner,
quit_func=quit_func)
def _commit(self):
pyconsole.Console._commit(self)
gimp.displays_flush()
class ConsoleDialog(gimpui.Dialog):
def __init__(self):
gimpui.Dialog.__init__(self, title=_("Python Console"),
role=PROC_NAME, help_id=PROC_NAME,
buttons=(gtk.STOCK_SAVE, RESPONSE_SAVE,
gtk.STOCK_CLEAR, RESPONSE_CLEAR,
_("_Browse..."), RESPONSE_BROWSE,
gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE))
self.set_name (PROC_NAME)
self.set_alternative_button_order((gtk.RESPONSE_CLOSE,
RESPONSE_BROWSE,
RESPONSE_CLEAR,
RESPONSE_SAVE))
self.cons = GimpConsole(quit_func=lambda: gtk.main_quit())
self.style_set (None, None)
self.connect('response', self.response)
self.connect('style-set', self.style_set)
self.browse_dlg = None
self.save_dlg = None
vbox = gtk.VBox(False, 12)
vbox.set_border_width(12)
self.vbox.pack_start(vbox)
scrl_win = gtk.ScrolledWindow()
scrl_win.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS)
vbox.pack_start(scrl_win)
scrl_win.add(self.cons)
width, height = self.cons.get_default_size()
sb_width, sb_height = scrl_win.get_vscrollbar().size_request()
# Account for scrollbar width and border width to ensure
# the text view gets a width of 80 characters. We don't care
# so much whether the height will be exactly 40 characters.
self.set_default_size(width + sb_width + 2 * 12, height)
def style_set(self, old_style, user_data):
style = self.get_style ()
self.cons.stdout_tag.set_property ("foreground", style.text[gtk.STATE_NORMAL])
self.cons.stderr_tag.set_property ("foreground", style.text[gtk.STATE_INSENSITIVE])
def response(self, dialog, response_id):
if response_id == RESPONSE_BROWSE:
self.browse()
elif response_id == RESPONSE_CLEAR:
self.cons.banner = None
self.cons.clear()
elif response_id == RESPONSE_SAVE:
self.save_dialog()
else:
gtk.main_quit()
self.cons.grab_focus()
def browse_response(self, dlg, response_id):
if response_id != gtk.RESPONSE_APPLY:
dlg.hide()
return
proc_name = dlg.get_selected()
if not proc_name:
return
proc = pdb[proc_name]
cmd = ''
if len(proc.return_vals) > 0:
cmd = ', '.join([x[1].replace('-', '_')
for x in proc.return_vals]) + ' = '
cmd = cmd + 'pdb.%s' % proc.proc_name.replace('-', '_')
if len(proc.params) > 0 and proc.params[0][1] == 'run-mode':
params = proc.params[1:]
else:
params = proc.params
cmd = cmd + '(%s)' % ', '.join([x[1].replace('-', '_')
for x in params])
buffer = self.cons.buffer
lines = buffer.get_line_count()
iter = buffer.get_iter_at_line_offset(lines - 1, 4)
buffer.delete(iter, buffer.get_end_iter())
buffer.place_cursor(buffer.get_end_iter())
buffer.insert_at_cursor(cmd)
def browse(self):
if not self.browse_dlg:
dlg = gimpui.ProcBrowserDialog(_("Python Procedure Browser"),
role=PROC_NAME,
buttons=(gtk.STOCK_APPLY,
gtk.RESPONSE_APPLY,
gtk.STOCK_CLOSE,
gtk.RESPONSE_CLOSE))
dlg.set_default_response(gtk.RESPONSE_APPLY)
dlg.set_alternative_button_order((gtk.RESPONSE_CLOSE,
gtk.RESPONSE_APPLY))
dlg.connect('response', self.browse_response)
dlg.connect('row-activated',
lambda dlg: dlg.response(gtk.RESPONSE_APPLY))
self.browse_dlg = dlg
self.browse_dlg.present()
def save_response(self, dlg, response_id):
if response_id == gtk.RESPONSE_DELETE_EVENT:
self.save_dlg = None
return
elif response_id == gtk.RESPONSE_OK:
filename = dlg.get_filename()
try:
logfile = open(filename, 'w')
except IOError, e:
gimp.message(_("Could not open '%s' for writing: %s") %
(filename, e.strerror))
return
buffer = self.cons.buffer
start = buffer.get_start_iter()
end = buffer.get_end_iter()
log = buffer.get_text(start, end, False)
try:
logfile.write(log)
logfile.close()
except IOError, e:
gimp.message(_("Could not write to '%s': %s") %
(filename, e.strerror))
return
dlg.hide()
def save_dialog(self):
if not self.save_dlg:
dlg = gtk.FileChooserDialog(_("Save Python-Fu Console Output"),
parent=self,
action=gtk.FILE_CHOOSER_ACTION_SAVE,
buttons=(gtk.STOCK_CANCEL,
gtk.RESPONSE_CANCEL,
gtk.STOCK_SAVE,
gtk.RESPONSE_OK))
dlg.set_default_response(gtk.RESPONSE_OK)
dlg.set_alternative_button_order((gtk.RESPONSE_OK,
gtk.RESPONSE_CANCEL))
dlg.connect('response', self.save_response)
self.save_dlg = dlg
self.save_dlg.present()
def run(self):
self.show_all()
gtk.main()
ConsoleDialog().run()
register(
PROC_NAME,
N_("Interactive GIMP Python interpreter"),
"Type in commands and see results",
"James Henstridge",
"James Henstridge",
"1997-1999",
N_("_Console"),
"",
[],
[],
do_console,
menu="<Image>/Filters/Languages/Python-Fu",
domain=("gimp20-python", gimp.locale_directory))
main()