From c6ea8d673f56f37e10caea4002a0c687d511c4b4 Mon Sep 17 00:00:00 2001 From: Sven Neumann Date: Wed, 27 Dec 2000 18:55:02 +0000 Subject: [PATCH] TODO.xml new files. TODO.xml is a first start on a roadmap towards 2000-12-27 Sven Neumann * 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. --- ChangeLog | 7 + TODO.xml | 158 +++++++++++++++++++++ docs/make-todo | 372 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 537 insertions(+) create mode 100644 TODO.xml create mode 100755 docs/make-todo diff --git a/ChangeLog b/ChangeLog index 153bf641b0..b4eda8f4f7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2000-12-27 Sven Neumann + + * 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 * app/gimpimage.c: gimp_image_merge_layers(): apply the layer mask diff --git a/TODO.xml b/TODO.xml new file mode 100644 index 0000000000..370ffbeb4a --- /dev/null +++ b/TODO.xml @@ -0,0 +1,158 @@ + + + + + + GIMP TODO List + +
+ Objectification + + + Generic GimpObject + +

+ Directly derived from GObject, should probably have a name + argument. +

+
+ + GIMP Developer List <gimp-developer@xcf.berkeley.edu> + +
+ + + Cleanup existing internal objects + +

+ 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. +

+
+ + GIMP Developer List <gimp-developer@xcf.berkeley.edu> + +
+ + + Generic data structures + +

+ Brushes, Patterns, Gradients should be derived from a GimpData + object. +

+
+ + GIMP Developer List <gimp-developer@xcf.berkeley.edu> + +
+ + + Generic object container(s) + +

+ 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. +

+

+ This container will be used for lists of brushes, patterns, + layers, channels, paths, ... +

+
+ + GIMP Developer List <gimp-developer@xcf.berkeley.edu> + +
+ + + Abstract GimpBrush object and derived brush types + +

+ 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. +

+
+ + GIMP Developer List <gimp-developer@xcf.berkeley.edu> + +
+ +
+ +
+ User Interface + + + Abstract Container Views + +

+ 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, ...) +

+
+ + GIMP Developer List <gimp-developer@xcf.berkeley.edu> + +
+ + + Effect Preview Widget + +

+ 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. +

+
+ + GIMP Developer List <gimp-developer@xcf.berkeley.edu> + +
+ +
+ +
+ Internationalization + + + Context-sensitive translations + +

+ 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. +

+

+ There is a patch with a possible solution on ftp.gimp.org, + but actually we'd like something cleaner if possible. +

+
+ ftp://ftp.gimp.org/pub/gimp/patches/gimp-chyla-20001207-0.patch + + GIMP Developer List <gimp-developer@xcf.berkeley.edu> + +
+ +
+ +
+ diff --git a/docs/make-todo b/docs/make-todo new file mode 100755 index 0000000000..7f7f9766d7 --- /dev/null +++ b/docs/make-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 '' + s.group(0) + '' + elif s.group(3) != None: + return '' + s.group(0) + '' + +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 '#%s' % (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 ''' +
+ + + + + + + + + + + + + + +
%s
Size: %sDifficulty: %sStatus: %sTarget Version: %s
+ %s + + ''' % (bgcolor, self.title, bgcolor, self.size, self.difficulty, self.status, self.target, htmlify(self.description)) + + if self.url != None: + print ''' + + ''' % htmlify (self.url) + + if self.bugs != None: + print ''' + + ''' % bugify (self.bugs) + + if self.contact != None: + print ''' + + ''' % htmlify (self.contact) + + print ''' +
More Info:%s
Bug Reports:%s
Contact:%s
+
+
+''' + +class Section: + def __init__(self): + self.title = None + self.entries = [] + + def output(self): + + print '

%s

' % (make_id(self.title), self.title) + + first = 1 + for entry in self.entries: + if not first: + print "
" + 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, " 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, "
tags may not be nested" + + self.section = Section() + + def end_section(self): + if self.section.title == None: + raise ParseError, "
requires " + + 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 + + + + + + ''' +if parser.logourl != None: + print ''' ''' % parser.logourl +print ''' + + +
+

%s

''' % (parser.title, parser.title) + + +for section in parser.sections: + ntasks = len(section.entries) + id = make_id (section.title) + if ntasks == 1: + print '%s (1 item)
' % (id,section.title) + else: + print '%s (%d items)
' % (id,section.title,ntasks) + +print ''' +
+ Logo +
+''' + +first = 1 +for section in parser.sections: + if not first: + print "

" + first = 0 + section.output() + +print ''' +''' + +