Commit 905a0e46 authored by Manish Singh's avatar Manish Singh Committed by Manish Singh

clone methods can't be marked as constructors.

2006-10-20  Manish Singh  <yosh@gimp.org>

        * plug-ins/pygimp/gimpui.defs: clone methods can't be marked as
        constructors.

        * plug-ins/pygimp/Makefile.am
        * plug-ins/pygimp/procbrowser.c: Remove one-off GimpProcBrowserDialog
        wrapper. Nobody but the console should've been using it anyway.

        * plug-ins/pygimp/gimpui.override: overrides for GimpEnumLabel,
        GimpIntComboBox, and GimpProcBrowserDialog constructors, as well
        as gimp_browser_add_search_types.

        * plug-ins/pygimp/plug-ins/pyconsole.py: New console widget,
        taken from GGAP (http://ggap.sourceforge.net)

        * plug-ins/pygimp/plug-ins/gtkcons.py: removed.

        * plug-ins/gimpcons.py: use new console widget, and the
        GimpProcBrowserDialog binding directly. Still a little rough in
        places.

        * plug-ins/pygimp/plug-ins/pdbbrowse.py: removed, it's redundant.

        * plug-ins/pygimp/plug-ins/Makefile.am: reflect above changes.
parent 590c4d0b
2006-10-20 Manish Singh <yosh@gimp.org>
* plug-ins/pygimp/gimpui.defs: clone methods can't be marked as
constructors.
* plug-ins/pygimp/Makefile.am
* plug-ins/pygimp/procbrowser.c: Remove one-off GimpProcBrowserDialog
wrapper. Nobody but the console should've been using it anyway.
* plug-ins/pygimp/gimpui.override: overrides for GimpEnumLabel,
GimpIntComboBox, and GimpProcBrowserDialog constructors, as well
as gimp_browser_add_search_types.
* plug-ins/pygimp/plug-ins/pyconsole.py: New console widget,
taken from GGAP (http://ggap.sourceforge.net)
* plug-ins/pygimp/plug-ins/gtkcons.py: removed.
* plug-ins/gimpcons.py: use new console widget, and the
GimpProcBrowserDialog binding directly. Still a little rough in
places.
* plug-ins/pygimp/plug-ins/pdbbrowse.py: removed, it's redundant.
* plug-ins/pygimp/plug-ins/Makefile.am: reflect above changes.
2006-10-20 Kevin Cozens <kcozens@cvs.gnome.org>
* plug-ins/script-fu/scheme-wrapper.c: Moved the MIN and MAX entries
......
......@@ -27,7 +27,7 @@ pygimpbase = python
pygimpdir = $(gimpplugindir)/$(pygimpbase)
pygimp_LTLIBRARIES = gimp.la _gimpenums.la gimpcolor.la _gimpui.la \
gimpthumb.la gimpprocbrowser.la
gimpthumb.la
gimp_la_SOURCES = \
gimpmodule.c \
......@@ -113,25 +113,6 @@ gimpthumb_la_LIBADD = \
$(GDK_PIXBUF_LIBS) \
$(PYLINK_LIBS)
gimpprocbrowser_la_SOURCES = \
procbrowser.c
gimpprocbrowser_la_LDFLAGS = -module -avoid-version $(no_undefined) \
-export-symbols-regex initgimpprocbrowser
gimpprocbrowser_la_LIBADD = \
$(libgimpui) \
$(libgimpwidgets) \
$(libgimpconfig) \
$(libgimpmath) \
$(libgimp) \
$(libgimpcolor) \
$(libgimpbase) \
$(GTK_LIBS) \
$(PYLINK_LIBS) \
$(RT_LIBS) \
$(INTLLIBS)
pygimp_PYTHON = \
gimpenums.py \
gimpfu.py \
......
......@@ -715,7 +715,6 @@
(define-method clone
(of-object "GimpColorDisplay")
(c-name "gimp_color_display_clone")
(is-constructor-of "GimpColorDisplay")
(return-type "GimpColorDisplay*")
)
......@@ -798,7 +797,6 @@
(define-method clone
(of-object "GimpColorDisplayStack")
(c-name "gimp_color_display_stack_clone")
(is-constructor-of "GimpColorDisplayStack")
(return-type "GimpColorDisplayStack*")
)
......
......@@ -708,3 +708,264 @@ _wrap_gimp_color_scale_new(PyGObject *self, PyObject *args, PyObject *kwargs)
}
%%
new-constructor GIMP_TYPE_COLOR_SCALE
%%
override gimp_enum_label_new kwargs
static int
_wrap_gimp_enum_label_new(PyGObject *self, PyObject *args, PyObject *kwargs)
{
PyObject *py_enum_type = NULL;
gint value;
GType enum_type;
GimpEnumLabel *label;
static char *kwlist[] = { "enum_type", "value", NULL };
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"Oi:gimpui.GimpEnumLabel.__init__",
kwlist,
&py_enum_type, &value))
return -1;
if ((enum_type = pyg_type_from_object(py_enum_type)) == 0)
return -1;
if (pygobject_construct(self, NULL))
return -1;
label = GIMP_ENUM_LABEL(self->obj);
label->enum_class = g_type_class_ref(enum_type);
gimp_enum_label_set_value (label, value);
return 0;
}
%%
new-constructor GIMP_TYPE_ENUM_LABEL
%%
override gimp_int_combo_box_new kwargs
static int
_wrap_gimp_int_combo_box_new(PyGObject *self, PyObject *args, PyObject *kwargs)
{
PyObject *py_items = NULL;
int len, i;
static char *kwlist[] = { "items", NULL };
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"|O:gimpui.IntComboBox.__init__",
kwlist,
&py_items))
return -1;
if (py_items == NULL || py_items == Py_None)
len = 0;
else if (PyTuple_Check(py_items))
len = PyTuple_Size(py_items);
else {
PyErr_SetString(PyExc_TypeError,
"items must be a tuple containing label/value pairs "
"or None");
return -1;
}
if (len % 2) {
PyErr_SetString(PyExc_RuntimeError,
"items tuple must contain label/value pairs");
return -1;
}
if (pygobject_construct(self, NULL))
return -1;
for (i = 0; i < len; i += 2) {
PyObject *label = PyTuple_GetItem(py_items, i);
PyObject *value = PyTuple_GetItem(py_items, i + 1);
if (!PyString_Check(label)) {
gtk_object_destroy(GTK_OBJECT(self->obj));
self->obj = NULL;
PyErr_SetString(PyExc_RuntimeError,
"first member of each label/value pair "
"must be a string");
return -1;
}
if (!PyInt_Check(value)) {
gtk_object_destroy(GTK_OBJECT(self->obj));
self->obj = NULL;
PyErr_SetString(PyExc_RuntimeError,
"second member of each label/value pair "
"must be a number");
return -1;
}
gimp_int_combo_box_append(GIMP_INT_COMBO_BOX(self->obj),
PyString_AsString(label),
PyInt_AsLong(value),
-1);
}
return 0;
}
%%
new-constructor GIMP_TYPE_INT_COMBO_BOX
%%
override gimp_browser_add_search_types kwargs
static PyObject *
_wrap_gimp_browser_add_search_types(PyGObject *self, PyObject *args, PyObject *kwargs)
{
PyObject *py_types = NULL;
int len, i;
static char *kwlist[] = { "search_types", NULL };
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"O:GimpBrowser.add_search_types",
kwlist,
&py_types))
return NULL;
if (PyTuple_Check(py_types))
len = PyTuple_Size(py_types);
else {
PyErr_SetString(PyExc_TypeError,
"search_types must be a tuple containing label/id "
"pairs");
return NULL;
}
if (len % 2) {
PyErr_SetString(PyExc_RuntimeError,
"search_types tuple must contain label/id pairs");
return NULL;
}
for (i = 0; i < len; i += 2) {
PyObject *label = PyTuple_GetItem(py_types, i);
PyObject *id = PyTuple_GetItem(py_types, i + 1);
if (!PyString_Check(label)) {
PyErr_SetString(PyExc_RuntimeError,
"first member of each label/id pair "
"must be a string");
return NULL;
}
if (!PyInt_Check(id)) {
PyErr_SetString(PyExc_RuntimeError,
"second member of each label/id pair "
"must be a number");
return NULL;
}
gimp_browser_add_search_types(GIMP_BROWSER(self->obj),
PyString_AsString(label),
PyInt_AsLong(id),
NULL);
}
Py_INCREF(Py_None);
return Py_None;
}
%%
override gimp_proc_browser_dialog_new kwargs
static int
_wrap_gimp_proc_browser_dialog_new(PyGObject *self, PyObject *args, PyObject *kwargs)
{
gchar *title, *role;
PyObject *py_buttons = Py_None;
PyObject *help_func = NULL;
gchar *help_id = NULL;
int len, i;
GimpHelpFunc func;
static char *kwlist[] = { "title", "role", "help_func", "help_id",
"buttons", NULL };
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"zz|OzO:gimpui.GimpProcBrowserDialog.__init__",
kwlist,
&title, &role, &help_func, &help_id,
&py_buttons))
return -1;
if (help_func) {
if (help_func != Py_None) {
if (!PyCallable_Check(help_func)) {
PyErr_SetString(PyExc_TypeError, "help_func must be callable");
return -1;
}
func = pygimp_help_func_marshal;
g_object_set_data(self->obj, "pygimp-dialog-help-data", self);
Py_INCREF(help_func);
g_object_set_data_full(self->obj, "pygimp-dialog-help-func",
help_func, pygimp_help_func_destroy);
} else {
func = gimp_standard_help_func;
}
} else {
func = gimp_standard_help_func;
}
if (py_buttons == Py_None)
len = 0;
else if (PyTuple_Check(py_buttons))
len = PyTuple_Size(py_buttons);
else {
PyErr_SetString(PyExc_TypeError, "buttons must be a tuple containing text/response pairs or None");
return -1;
}
if (len % 2) {
PyErr_SetString(PyExc_RuntimeError,
"buttons tuple must contain text/response id pairs");
return -1;
}
pygobject_construct(self,
"title", title,
"role", role,
"help-func", func,
"help-id", help_id,
NULL);
if (!self->obj) {
PyErr_SetString(PyExc_RuntimeError,
"could not create GimpProcBrowserDialog object");
return -1;
}
for (i = 0; i < len; i += 2) {
PyObject *text = PyTuple_GetItem(py_buttons, i);
PyObject *id = PyTuple_GetItem(py_buttons, i + 1);
if (!PyString_Check(text) && !PyUnicode_Check(text)) {
gtk_object_destroy(GTK_OBJECT(self->obj));
self->obj = NULL;
PyErr_SetString(PyExc_RuntimeError,
"first member of each text/response id pair "
"must be a string");
return -1;
}
if (!PyInt_Check(id)) {
gtk_object_destroy(GTK_OBJECT(self->obj));
self->obj = NULL;
PyErr_SetString(PyExc_RuntimeError,
"second member of each text/response id pair "
"must be a number");
return -1;
}
gimp_dialog_add_button(GIMP_DIALOG(self->obj), PyString_AsString(text),
PyInt_AsLong(id));
}
g_signal_emit_by_name(GIMP_PROC_BROWSER_DIALOG(self->obj)->browser,
"search", "", 0, self->obj);
return 0;
}
%%
new-constructor GIMP_TYPE_PROC_BROWSER_DIALOG
......@@ -8,7 +8,6 @@ scripts = \
palette-offset.py \
palette-sort.py \
palette-to-gradient.py \
pdbbrowse.py \
py-slice.py \
shadow_bevel.py
......@@ -24,6 +23,6 @@ else
pluginexec_SCRIPTS = $(scripts)
endif
pluginexec_DATA = gtkcons.py
pluginexec_DATA = pyconsole.py
EXTRA_DIST = $(pluginexec_DATA) $(pluginexec_SCRIPTS) $(test_scripts)
......@@ -21,13 +21,15 @@ from gimpfu import *
gettext.install("gimp20-python", gimp.locale_directory, unicode=1)
PROC_NAME = 'python-fu-console'
RESPONSE_BROWSE, RESPONSE_CLEAR, RESPONSE_SAVE = range(3)
def console():
import pygtk
pygtk.require('2.0')
import gobject, gtk, gimpenums, gimpshelf
gtk.rc_parse(gimp.gtkrc())
import sys, gobject, gtk, gimpenums, gimpshelf, gimpui
namespace = {'__builtins__': __builtins__,
'__name__': '__main__', '__doc__': None,
......@@ -38,54 +40,121 @@ def console():
if s[0] != '_':
namespace[s] = getattr(gimpenums, s)
def bye(*args):
gtk.main_quit()
def response(dialog, response_id, cons):
if response_id == RESPONSE_BROWSE:
browse(cons)
elif response_id == RESPONSE_CLEAR:
cons.banner = None
cons.clear()
elif response_id == RESPONSE_SAVE:
save_dialog(dialog, cons)
else:
gtk.main_quit()
dialog = gimpui.Dialog(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))
dialog.set_alternative_button_order((gtk.RESPONSE_CLOSE, RESPONSE_BROWSE,
RESPONSE_CLEAR, RESPONSE_SAVE))
banner = 'Gimp %s Python Console\nPython %s\n' % (gimp.pdb.gimp_version(),
sys.version)
dialog = gtk.Dialog(title=_("Python Console"),
buttons=(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE))
dialog.set_has_separator(False)
dialog.connect("response", bye)
import pyconsole
cons = pyconsole.Console(locals=namespace, banner=banner)
import gtkcons
cons = gtkcons.Console(namespace=namespace, quit_cb=bye, closer=False)
dialog.connect("response", response, cons)
def on_apply(proc):
def browse_response(dlg, response_id, cons):
if response_id != gtk.RESPONSE_APPLY:
dlg.destroy()
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] for x in proc.return_vals]) + ' = '
cmd = ', '.join([x[1].replace('-', '_') for x in proc.return_vals]) + ' = '
if '-' in proc.proc_name:
cmd = cmd + "pdb['%s']" % proc.proc_name
else:
cmd = cmd + "pdb.%s" % proc.proc_name
cmd = cmd + "pdb.%s" % proc.proc_name.replace('-', '_')
if len(proc.params) > 0 and proc.params[0][1] == 'run_mode':
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] for x in params])
cmd = cmd + "(%s)" % ', '.join([x[1].replace('-', '_') for x in params])
cons.line.set_text(cmd)
cons.buffer.insert_at_cursor(cmd)
def browse(button, cons):
import gimpprocbrowser
gimpprocbrowser.dialog_new(on_apply)
def browse(cons):
dlg = gimpui.ProcBrowserDialog(_("Python Procedure Browser"), 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))
button = gtk.Button(_("_Browse..."))
button.connect("clicked", browse, cons)
dlg.connect("response", browse_response, cons)
dlg.connect("row-activated",
lambda dlg: dlg.response(gtk.RESPONSE_APPLY))
cons.inputbox.pack_end(button, fill=False, expand=False, padding=2)
button.show()
dlg.show()
dialog.vbox.pack_start(cons)
cons.show()
def save_dialog(parent, cons):
dlg = gtk.FileChooserDialog(title=_("Save Python-Fu Console Output"),
parent=parent,
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))
dialog.set_default_size(500, 500)
dialog.show()
def save_response(dlg, response_id, cons):
if response_id == gtk.RESPONSE_OK:
filename = dlg.get_filename()
cons.init()
try:
logfile = open(filename, 'w')
except IOError, e:
gimp.message(_("Could not open '%s' for writing: %s") %
(filename, e.strerror))
return
start = cons.buffer.get_start_iter()
end = cons.buffer.get_end_iter()
log = cons.buffer.get_text(start, end, False)
logfile.write(log)
logfile.close()
dlg.destroy()
dlg.connect("response", save_response, cons)
dlg.present()
vbox = gtk.VBox(False, 12)
vbox.set_border_width(12)
dialog.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(cons)
dialog.set_default_size(500, 500)
dialog.show_all()
# flush the displays every half second
def timeout():
......@@ -96,7 +165,7 @@ def console():
gtk.main()
register(
"python-fu-console",
PROC_NAME,
N_("Interactive Gimp-Python interpreter"),
"Type in commands and see results",
"James Henstridge",
......
</
#!/usr/bin/env python
# Interactive Python-GTK Console
# Copyright (C),
# 1998 James Henstridge
# 2004 John Finlay
#
# 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 2 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, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# This module implements an interactive python session in a GTK window. To
# start the session, use the gtk_console command. Its specification is:
# gtk_console(namespace, title, copyright)
# where namespace is a dictionary representing the namespace of the session,
# title is the title on the window and
# copyright is any additional copyright info to print.
#
# As well as the starting attributes in namespace, the session will also
# have access to the list __history__, which is the command history.
import sys, string, traceback
import pygtk
pygtk.require('2.0')
import gtk, pango
from gimp import locale_directory
import gettext
t = gettext.translation('gimp20-python', locale_directory, fallback=True)
_ = t.ugettext
stdout = sys.stdout
if not hasattr(sys, 'ps1'): sys.ps1 = '>>> '
if not hasattr(sys, 'ps2'): sys.ps2 = '... '
# some functions to help recognise breaks between commands
def remQuotStr(s):
'''Returns s with any quoted strings removed (leaving quote marks)'''
r = ''
inq = 0
qt = ''
prev = '_'
while len(s):
s0, s = s[0], s[1:]
if inq and (s0 != qt or prev == '\\'):
prev = s0
continue
prev = s0
if s0 in '\'"':
if inq:
inq = 0
else:
inq = 1
qt = s0
r = r + s0
return r
def bracketsBalanced(s):
'''Returns true iff the brackets in s are balanced'''
s = filter(lambda x: x in '()[]{}', s)
stack = []
brackets = {'(':')', '[':']', '{':'}'}
while len(s) != 0:
if s[0] in ")]}":
if len(stack) != 0 and brackets[stack[-1]] == s[0]:
del stack[-1]
else:
return 0
else:
stack.append(s[0])
s = s[1:]
return len(stack) == 0
class gtkoutfile:
'''A fake output file object. It sends output to a GTK TextView widget,
and if asked for a file number, returns one set on instance creation'''
def __init__(self, w, fn, font):
self.__fn = fn
self.__w = w
self.__b = w.get_buffer()
self.__ins = self.__b.get_mark('insert')
self.__font = font
def close(self): pass
flush = close
def fileno(self): return self.__fn
def isatty(self): return 0
def read(self, a): return ''
def readline(self): return ''
def readlines(self): return []
def write(self, s):
#stdout.write(str(self.__w.get_point()) + '\n')
iter = self.__b.get_iter_at_mark(self.__ins)
self.__b.insert_with_tags(iter, s, self.__font)
self.__w.scroll_to_mark(self.__ins, 0.0)
self.__w.queue_draw()
def writelines(self, l):
iter = self.__b.get_iter_at_mark(self.__ins)
for s in l:
self.__b.insert_with_tags(iter, s, self.__font)
self.__w.scroll_to_mark(self.__ins, 0.0)
self.__w.queue_draw()
def seek(self, a): raise IOError, (29, 'Illegal seek')
def tell(self): raise IOError, (29, 'Illegal seek')
truncate = tell
class Console(gtk.VBox):
def __init__(self, namespace={}, copyright='', greetings=(), quit_cb=None,
closer=True):
gtk.VBox.__init__(self, spacing=2)
self.set_border_width(2)
self.copyright = copyright
self.greetings = greetings
#self.set_size_request(475, 300)
self.quit_cb = quit_cb
self.inp = gtk.HBox()
self.pack_start(self.inp)
self.inp.show()
self.scrolledwin = gtk.ScrolledWindow()
self.scrolledwin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS)
self.scrolledwin.show()
self.inp.pack_start(self.scrolledwin, padding=2)
self.text = gtk.TextView()
self.text.set_editable(False)
self.text.set_wrap_mode(gtk.WRAP_WORD)
self.text.set_size_request(480, 400)
self.scrolledwin.add(self.text)
self.text.show()
self.buffer = self.text.get_buffer()
#create the tags we will use
self.normal = self.buffer.create_tag('Normal')
self.title = self.buffer.create_tag('Title',
weight=pango.WEIGHT_BOLD)
self.subtitle = self.buffer.create_tag('Subtitle',
scale=pango.SCALE_SMALL)
self.emphasis = self.buffer.create_tag('Emphasis',
style=pango.STYLE_OBLIQUE)
self.error = self.buffer.create_tag('Error',
foreground='red')
self.command = self.buffer.create_tag('Command')
self.inputbox = gtk.HBox(spacing=2)
self.pack_end(self.inputbox, expand=False)
self.inputbox.show()
self.prompt = gtk.Label(sys.ps1)
self.prompt.set_padding(xpad=2, ypad=0)
self.prompt.set_size_request(30, -1)
self.inputbox.pack_start(self.prompt, fill=False, expand=False)
self.prompt.show()
if closer:
self.closer = gtk.Button(gtk.CLOSE)
self.closer.connect("clicked", self.quit)
self.inputbox.pack_end(self.closer, fill=False, expand=False)
self.closer.show()
self.line = gtk.Entry()
self.line.set_size_request(400,-1)
self.line.connect("key_press_event", self.key_function)
self.inputbox.pack_start(self.line, padding=2)
self.line.show()
# now let the text box be resized
self.text.set_size_request(0, 0)
self.line.set_size_request(0, -1)
self.namespace = namespace
self.cmd = ''
self.cmd2 = ''
# set up hooks for standard output.
self.stdout = gtkoutfile(self.text, sys.stdout.fileno(),
self.normal)
self.stderr = gtkoutfile(self.text, sys.stderr.fileno(),
self.error)