mirror of https://github.com/GNOME/gimp.git
TODO.xml new files. TODO.xml is a first start on a roadmap towards
2000-12-27 Sven Neumann <sven@gimp.org> * TODO.xml * docs/make-todo: new files. TODO.xml is a first start on a roadmap towards gimp-1.4. All new features and major changes need to be defined here to be accepted into the gimp-1.3 branch.
This commit is contained in:
parent
7f29801363
commit
c6ea8d673f
|
@ -1,3 +1,10 @@
|
|||
2000-12-27 Sven Neumann <sven@gimp.org>
|
||||
|
||||
* TODO.xml
|
||||
* docs/make-todo: new files. TODO.xml is a first start on a roadmap
|
||||
towards gimp-1.4. All new features and major changes need to be
|
||||
defined here to be accepted into the gimp-1.3 branch.
|
||||
|
||||
2000-12-27 Michael Natterer <mitch@gimp.org>
|
||||
|
||||
* app/gimpimage.c: gimp_image_merge_layers(): apply the layer mask
|
||||
|
|
|
@ -0,0 +1,158 @@
|
|||
<!-- Stuff that is scheduled to be done. Ideas do not go here, put
|
||||
them into the old TODO file for now. -->
|
||||
|
||||
<!-- The following comment is not yet valid, since we have not yet
|
||||
set up the website and updated the commit scripts. Please check
|
||||
for parse errors anyway.
|
||||
|
||||
This is used to generate the online TODO list for GIMP using
|
||||
the script docs/make-todo. Whenever a change to this file is
|
||||
committed to CVS, the file is run through make-todo and the online
|
||||
version updated. If you modify this file, you should check for
|
||||
parse errors by running:
|
||||
|
||||
$ docs/make-todo TODO.xml > /dev/null
|
||||
|
||||
before committing, or you may screw up the online version -->
|
||||
|
||||
<todo logourl="wilber.png">
|
||||
<title>GIMP TODO List</title>
|
||||
|
||||
<section>
|
||||
<title>Objectification</title>
|
||||
|
||||
<entry size="small" difficulty="easy" status="0%" target="1.4">
|
||||
<title>Generic GimpObject</title>
|
||||
<description>
|
||||
<p>
|
||||
Directly derived from GObject, should probably have a name
|
||||
argument.
|
||||
</p>
|
||||
</description>
|
||||
<contact>
|
||||
GIMP Developer List <gimp-developer@xcf.berkeley.edu>
|
||||
</contact>
|
||||
</entry>
|
||||
|
||||
<entry size="medium" difficulty="medium" status="0%" target="1.4">
|
||||
<title>Cleanup existing internal objects</title>
|
||||
<description>
|
||||
<p>
|
||||
GimpDrawable, Layer, GimpImage, GDisplay need to be redone as
|
||||
proper GimpObjects. Write new objects (with proper names) and
|
||||
port all stuff to the new objects incrementally.
|
||||
</p>
|
||||
</description>
|
||||
<contact>
|
||||
GIMP Developer List <gimp-developer@xcf.berkeley.edu>
|
||||
</contact>
|
||||
</entry>
|
||||
|
||||
<entry size="small" difficulty="medium" status="0%" target="1.4">
|
||||
<title>Generic data structures</title>
|
||||
<description>
|
||||
<p>
|
||||
Brushes, Patterns, Gradients should be derived from a GimpData
|
||||
object.
|
||||
</p>
|
||||
</description>
|
||||
<contact>
|
||||
GIMP Developer List <gimp-developer@xcf.berkeley.edu>
|
||||
</contact>
|
||||
</entry>
|
||||
|
||||
<entry size="medium" difficulty="medium" status="0%" target="1.4">
|
||||
<title>Generic object container(s)</title>
|
||||
<description>
|
||||
<p>
|
||||
A GimpContainer that holds GimpObject objects. Comparable to
|
||||
the GCimContainer, but no serialization for now. Should probably
|
||||
dispatch "changed" (or other) signals from its children.
|
||||
</p>
|
||||
<p>
|
||||
This container will be used for lists of brushes, patterns,
|
||||
layers, channels, paths, ...
|
||||
</p>
|
||||
</description>
|
||||
<contact>
|
||||
GIMP Developer List <gimp-developer@xcf.berkeley.edu>
|
||||
</contact>
|
||||
</entry>
|
||||
|
||||
<entry size="medium" difficulty="medium" status="0%" target="1.4">
|
||||
<title>Abstract GimpBrush object and derived brush types</title>
|
||||
<description>
|
||||
<p>
|
||||
The GimpBrush object we have now is not a generic BrushProvider.
|
||||
We need an abstract object to derive the different kinds of brushes
|
||||
from (BrushPipes, parametric brushes, ...). It has to provide
|
||||
methods for the PaintCore to transparently select and use the brush
|
||||
data.
|
||||
</p>
|
||||
</description>
|
||||
<contact>
|
||||
GIMP Developer List <gimp-developer@xcf.berkeley.edu>
|
||||
</contact>
|
||||
</entry>
|
||||
|
||||
</section> <!-- Objectification -->
|
||||
|
||||
<section>
|
||||
<title>User Interface</title>
|
||||
|
||||
<entry size="medium" difficulty="medium" status="0%" target="1.4">
|
||||
<title>Abstract Container Views</title>
|
||||
<description>
|
||||
<p>
|
||||
Views on data stored in a GimpContainer. The objects need to provide
|
||||
hooks that this view can use to show data like patterns, brushes,
|
||||
etc. in different views (list, grid, ...)
|
||||
</p>
|
||||
</description>
|
||||
<contact>
|
||||
GIMP Developer List <gimp-developer@xcf.berkeley.edu>
|
||||
</contact>
|
||||
</entry>
|
||||
|
||||
<entry size="big" difficulty="advanced" status="0%" target="1.4">
|
||||
<title>Effect Preview Widget</title>
|
||||
<description>
|
||||
<p>
|
||||
A generic preview widget with functions like scrolling and zooming
|
||||
useable by effect filters. Should have adaptive supersampling,
|
||||
progressive display (if possible) and other neat stuff.
|
||||
</p>
|
||||
</description>
|
||||
<contact>
|
||||
GIMP Developer List <gimp-developer@xcf.berkeley.edu>
|
||||
</contact>
|
||||
</entry>
|
||||
|
||||
</section> <!-- User Interface -->
|
||||
|
||||
<section>
|
||||
<title>Internationalization</title>
|
||||
|
||||
<entry size="small" difficulty="medium" status="0%" target="1.4">
|
||||
<title>Context-sensitive translations</title>
|
||||
<description>
|
||||
<p>
|
||||
The same english string used in different contexts may need to
|
||||
be translated differently in other languages. Think of a way to
|
||||
implement this using gettext or come up with something better.
|
||||
</p>
|
||||
<p>
|
||||
There is a patch with a possible solution on ftp.gimp.org,
|
||||
but actually we'd like something cleaner if possible.
|
||||
</p>
|
||||
</description>
|
||||
<url>ftp://ftp.gimp.org/pub/gimp/patches/gimp-chyla-20001207-0.patch</url>
|
||||
<contact>
|
||||
GIMP Developer List <gimp-developer@xcf.berkeley.edu>
|
||||
</contact>
|
||||
</entry>
|
||||
|
||||
</section> <!-- Internationalization -->
|
||||
|
||||
</todo>
|
||||
|
|
@ -0,0 +1,372 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
# Shamelessly stolen from the GTK+ source.
|
||||
# Modified for The GIMP.
|
||||
|
||||
|
||||
import xmllib;
|
||||
import sys;
|
||||
import string
|
||||
import re
|
||||
|
||||
def html_subst(s):
|
||||
if s.group(1) != None:
|
||||
return s.group(0)
|
||||
elif s.group(2) != None:
|
||||
return '<a href="' + s.group(0) + '">' + s.group(0) + '</a>'
|
||||
elif s.group(3) != None:
|
||||
return '<a href="mailto:' + s.group(0) + '">' + s.group(0) + '</a>'
|
||||
|
||||
def htmlify(str):
|
||||
return re.sub ("(<[^>]*>)|([ht|f]tp://[~.:/\w-]+)|([\w._!-]+@[\w_-]+).[\w._-]+", html_subst, str)
|
||||
|
||||
def bug_subst(s):
|
||||
if s.group(1) != None:
|
||||
return s.group(0)
|
||||
else:
|
||||
n = s.group(2)
|
||||
return '<a href="http://bugs.gnome.org/db/%s/%s.html">#%s</a>' % (n[0:2], n, n)
|
||||
|
||||
def bugify(str):
|
||||
str = re.sub ("(<[^>]*>)|#(\d+)", bug_subst, str)
|
||||
return htmlify(str)
|
||||
|
||||
def make_id(str):
|
||||
return re.sub ("[^a-z]","-", string.lower(str))
|
||||
|
||||
class ParseError (Exception):
|
||||
pass
|
||||
|
||||
class Entry:
|
||||
def __init__(self):
|
||||
self.description = None
|
||||
self.title = None
|
||||
self.url = None
|
||||
self.contact = None
|
||||
self.bugs = None
|
||||
|
||||
def set_size(self, size):
|
||||
size = string.lower(size)
|
||||
if size == "small":
|
||||
self.size = "Small"
|
||||
elif size == "medium":
|
||||
self.size = "Medium"
|
||||
elif size == "big":
|
||||
self.size = "Big"
|
||||
else:
|
||||
raise ParseError, 'size must be "small", "medium", or "big"'
|
||||
|
||||
def set_difficulty(self, difficulty):
|
||||
difficulty = string.lower(difficulty)
|
||||
if difficulty == "easy":
|
||||
self.difficulty = "Easy"
|
||||
elif difficulty == "medium":
|
||||
self.difficulty = "Medium"
|
||||
elif difficulty == "advanced":
|
||||
self.difficulty = "Advanced"
|
||||
else:
|
||||
raise ParseError, 'difficulty must be "easy", "medium", or "advanced"'
|
||||
|
||||
def output(self):
|
||||
if self.size == "Big":
|
||||
bgcolor = "#88bb88"
|
||||
elif self.size == "Medium":
|
||||
bgcolor = "#b4d4b4"
|
||||
else:
|
||||
bgcolor = "#d0e0d0"
|
||||
|
||||
print '''<table cellspacing="0" cellpadding="2" width="97%%" border="0" bgcolor="#000000">
|
||||
<tbody><tr><td colspan=2>
|
||||
<table cellspacing="0" cellpadding="5" width="100%%" border="0" bgcolor="#ffffff">
|
||||
<tbody>
|
||||
<tr bgcolor="%s">
|
||||
<td align="left" colspan="4"><font size="+1">%s</font></font></td>
|
||||
</tr>
|
||||
<tr bgcolor="%s">
|
||||
<td align="left" width="20%%"><b>Size</b>: %s</td>
|
||||
<td align="left" width="20%%"><b>Difficulty</b>: %s</td>
|
||||
<td align="center" width="20%%"><b>Status</b>: %s</td>
|
||||
<td align="right" width="20%%"><b>Target Version</b>: %s</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan=4>
|
||||
%s
|
||||
<table cellspacing="0" cellpadding="0">
|
||||
<tbody>''' % (bgcolor, self.title, bgcolor, self.size, self.difficulty, self.status, self.target, htmlify(self.description))
|
||||
|
||||
if self.url != None:
|
||||
print '''<tr><td width="0"><b>More Info</b>:</td>
|
||||
<td>%s</td>
|
||||
</tr>''' % htmlify (self.url)
|
||||
|
||||
if self.bugs != None:
|
||||
print '''<tr><td width="0"><b>Bug Reports</b>:</td>
|
||||
<td>%s</td>
|
||||
</tr>''' % bugify (self.bugs)
|
||||
|
||||
if self.contact != None:
|
||||
print '''<tr><td width="0"><b>Contact</b>:</td>
|
||||
<td>%s</td>
|
||||
</tr>''' % htmlify (self.contact)
|
||||
|
||||
print '''</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
</td></tr></tbody></table>
|
||||
'''
|
||||
|
||||
class Section:
|
||||
def __init__(self):
|
||||
self.title = None
|
||||
self.entries = []
|
||||
|
||||
def output(self):
|
||||
|
||||
print '<h2><a name="%s">%s</a></h2>' % (make_id(self.title), self.title)
|
||||
|
||||
first = 1
|
||||
for entry in self.entries:
|
||||
if not first:
|
||||
print "<br>"
|
||||
first = 0
|
||||
entry.output()
|
||||
|
||||
class TodoParser (xmllib.XMLParser):
|
||||
def __init__(self):
|
||||
xmllib.XMLParser.__init__(self)
|
||||
|
||||
self.in_todo = 0
|
||||
self.in_data = 0
|
||||
self.data = ""
|
||||
self.section = None
|
||||
self.entry = None
|
||||
self.logourl = None
|
||||
self.title = None
|
||||
self.sections = []
|
||||
|
||||
self.entitydefs = {}
|
||||
|
||||
def start_todo(self,attributes):
|
||||
if self.in_todo:
|
||||
raise ParseError, "<todo> tags may not be nested"
|
||||
if attributes.has_key ("logourl"):
|
||||
self.logourl = attributes["logourl"]
|
||||
self.in_todo = 1
|
||||
|
||||
def end_todo(self):
|
||||
self.in_todo = 0
|
||||
|
||||
def start_section(self,attributes):
|
||||
if self.section:
|
||||
raise ParseError, "<section> tags may not be nested"
|
||||
|
||||
self.section = Section()
|
||||
|
||||
def end_section(self):
|
||||
if self.section.title == None:
|
||||
raise ParseError, "<section> requires <title>"
|
||||
|
||||
self.sections.append(self.section)
|
||||
self.section = None
|
||||
|
||||
def start_title(self,attributes):
|
||||
if not self.in_todo:
|
||||
raise ParseError, "<title> tag must be in <todo>, <section> or <entry>"
|
||||
if self.in_data:
|
||||
raise ParseError, "Unexpected <title> tag in content"
|
||||
self.in_data = 1
|
||||
|
||||
def end_title(self):
|
||||
self.in_data = 0
|
||||
if self.entry:
|
||||
self.entry.title = self.data
|
||||
elif self.section:
|
||||
self.section.title = self.data
|
||||
else:
|
||||
self.title = self.data
|
||||
self.data = ""
|
||||
|
||||
def start_description(self,attributes):
|
||||
if not self.entry:
|
||||
raise ParseError, "<description> tag must be in <entry>"
|
||||
if self.in_data:
|
||||
raise ParseError, "Unexpected <description> tag in content"
|
||||
self.in_data = 1
|
||||
|
||||
def end_description(self):
|
||||
self.in_data = 0
|
||||
self.entry.description = self.data
|
||||
self.data = ""
|
||||
|
||||
def start_url(self,attributes):
|
||||
if not self.entry:
|
||||
raise ParseError, "<url> tag must be in <entry>"
|
||||
if self.in_data:
|
||||
raise ParseError, "Unexpected <url> tag in content"
|
||||
self.in_data = 1
|
||||
|
||||
def end_url(self):
|
||||
self.in_data = 0
|
||||
self.entry.url = self.data
|
||||
self.data = ""
|
||||
|
||||
def start_contact(self,attributes):
|
||||
if not self.entry:
|
||||
raise ParseError, "<contact> tag must be in <entry>"
|
||||
if self.in_data:
|
||||
raise ParseError, "Unexpected <contact> tag in content"
|
||||
self.in_data = 1
|
||||
|
||||
def end_contact(self):
|
||||
self.in_data = 0
|
||||
self.entry.contact = self.data
|
||||
self.data = ""
|
||||
|
||||
def start_bugs(self,attributes):
|
||||
if not self.entry:
|
||||
raise ParseError, "<bugs> tag must be in <bugs>"
|
||||
if self.in_data:
|
||||
raise ParseError, "Unexpected <bugs> tag in content"
|
||||
self.in_data = 1
|
||||
|
||||
def end_bugs(self):
|
||||
self.in_data = 0
|
||||
self.entry.bugs = self.data
|
||||
self.data = ""
|
||||
|
||||
def start_entry(self,attributes):
|
||||
if not self.section:
|
||||
raise ParseError, "<entry> tag must be in <section>"
|
||||
if self.entry:
|
||||
raise ParseError, "<entry> tags may not be nested"
|
||||
|
||||
self.entry = Entry()
|
||||
|
||||
if not attributes.has_key("size"):
|
||||
raise ParseError, '"size" attribute required for entry'
|
||||
self.entry.set_size(attributes["size"])
|
||||
|
||||
if not attributes.has_key("difficulty"):
|
||||
raise ParseError, '"difficulty" attribute required for entry'
|
||||
self.entry.set_difficulty(attributes["difficulty"])
|
||||
|
||||
if not attributes.has_key("status"):
|
||||
raise ParseError, '"status" attribute (completion percentage) required for entry'
|
||||
self.entry.status=attributes["status"]
|
||||
|
||||
if not attributes.has_key("target"):
|
||||
raise ParseError, '"target" attribute (target version) required for entry'
|
||||
self.entry.target=attributes["target"]
|
||||
|
||||
def end_entry(self):
|
||||
if self.entry.title == None:
|
||||
raise ParseError, "<entry> requires <title>"
|
||||
|
||||
if self.entry.description == None:
|
||||
raise ParseError, "<entry> requires <description>"
|
||||
|
||||
self.section.entries.append(self.entry)
|
||||
self.entry = None
|
||||
|
||||
def handle_data(self,data):
|
||||
if self.in_data:
|
||||
self.data = self.data + data
|
||||
|
||||
def unknown_starttag(self,tag,attributes):
|
||||
if not self.in_data:
|
||||
raise ParseError, "Unexpected start tag: " + tag
|
||||
else:
|
||||
self.data = self.data + "<" + tag
|
||||
for (key,val) in attributes.items():
|
||||
self.data = self.data + ' %s="%s"' % (key,val)
|
||||
self.data = self.data + ">"
|
||||
|
||||
def unknown_endtag(self,tag):
|
||||
if not self.in_data:
|
||||
raise ParseError, "Unexpected end tag: " + tag
|
||||
else:
|
||||
self.data = self.data + "</%s>" % tag
|
||||
|
||||
def syntax_error(self, err):
|
||||
if re.match("reference to unknown entity", err):
|
||||
pass
|
||||
else:
|
||||
xmllib.XMLParser.syntax_error (self, err)
|
||||
|
||||
def unknown_entityref(self,ref):
|
||||
if not self.in_data:
|
||||
raise ParseError, "Unknown entity &" + ref + ";"
|
||||
else:
|
||||
self.data = self.data + "&" + ref + ";"
|
||||
|
||||
file = open(sys.argv[1])
|
||||
parser = TodoParser()
|
||||
|
||||
lineno = 1
|
||||
while 1:
|
||||
line = file.readline()
|
||||
if line == "":
|
||||
break
|
||||
|
||||
try:
|
||||
parser.feed(line)
|
||||
except ParseError, err:
|
||||
sys.stderr.write("Parse error at line " + `lineno` + ": " + err.__str__() + "\n")
|
||||
sys.exit(1)
|
||||
except RuntimeError, err:
|
||||
sys.stderr.write(err.__str__() + "\n")
|
||||
sys.exit(1)
|
||||
|
||||
lineno = lineno + 1
|
||||
|
||||
parser.close()
|
||||
if parser.title == None:
|
||||
sys.stderr.write ("<todo> Document must have a <title>\n")
|
||||
sys.exit (1)
|
||||
|
||||
print '''<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>%s</title>
|
||||
</head>
|
||||
<body bgcolor="#ffffff">
|
||||
<table width="100%%" cellspacing="0" cellpadding="0" border="0">
|
||||
<tbody>
|
||||
<tr valign="top">
|
||||
<td>
|
||||
<h1>%s</h1>''' % (parser.title, parser.title)
|
||||
|
||||
|
||||
for section in parser.sections:
|
||||
ntasks = len(section.entries)
|
||||
id = make_id (section.title)
|
||||
if ntasks == 1:
|
||||
print '<a href="#%s">%s</a> (1 item)<br>' % (id,section.title)
|
||||
else:
|
||||
print '<a href="#%s">%s</a> (%d items)<br>' % (id,section.title,ntasks)
|
||||
|
||||
print '''
|
||||
</td>'''
|
||||
if parser.logourl != None:
|
||||
print ''' <td align="right">
|
||||
<img src="%s" alt="Logo"></img>
|
||||
</td>''' % parser.logourl
|
||||
print '''
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
'''
|
||||
|
||||
first = 1
|
||||
for section in parser.sections:
|
||||
if not first:
|
||||
print "<br><br>"
|
||||
first = 0
|
||||
section.output()
|
||||
|
||||
print '''</body>
|
||||
</html>'''
|
||||
|
||||
|
Loading…
Reference in New Issue