First drop of aptitude for Maemo
[aptitude] / aptitude-hackers-guide.txt
1                        APTITUDE HACKERS GUIDE (for 0.2.0)
2
3   This intends to be a high-level overview of the internals of Aptitude,
4 and useful as a jumping-off point for people looking to modify it.  It covers
5 the overall structure and some specific stuff, and was inspired by the
6 Freeciv Hackers Guide.  (I'm sure there are other documents like this out
7 there, but that's the one I've read)  Previously, this covered each and every
8 source file.  This is no longer the case; it doesn't `scale' ;-)  Instead, I
9 just present a broad overview of the various subsystems.
10
11   Aptitude is written in C++, with extremely heavy use of some language
12 features: in particular, templating and inheritence.  The 0.2.x series also
13 is heavily based around the libsigc++ library and heavily uses callbacks and
14 signal/slot style programming.
15
16   The source tree is divided into three parts: the "generic" routines: various
17 utility routines and routines for interfacing with the apt libraries;
18 the "vscreen" library, containing the UI widget library; and the toplevel
19 directory, which contains aptitude itself.
20
21                                 VSCREEN
22
23   The vscreen library is the core of aptitude's user interface.  It is
24 a widget set based on libsigc++ using Curses.  It supports what is
25 needed in aptitude; some things (like a multiline text entry widget or
26 a dropdown menu) are not yet available because I haven't needed them
27 yet.  However, within the feature set that it has, it should be fully
28 functional.
29
30   The "testvscreen" program tests the minimal functionality of most of
31 the widgets in the vscreen library.  It is also probably useful as a
32 programming example, as a simple program utilizing the library.
33
34   vscreen/vscreen.h contains functions to manipulate the vscreen main
35 loop and other global state.  They include:
36   vscreen_update() -- queues a request to repaint the screen.  (note
37    that vscreen takes a brute-force approach to redrawing and counts on
38    Curses to optimize things)
39      Multiple requests to paint the screen will be merged into a
40    single request.  Calling vscreen_update() is (should be) very
41    efficient; don't be afraid to do it if you aren't sure whether it's
42    necessary.
43   vscreen_tryupdate() -- handles any pending vscreen_update() requests
44   vscreen_mainloop() -- enters the main loop, in which the program
45    waits for and handles events.
46   vscreen_exitmain() -- exits the currently running main loop.  (note
47    that main loops are allowed to nest)
48   vscreen_poll()
49   vscreen_addtimeout() -- installs a new timeout which will be called
50    in no less than the given amount of time.  The timeout should be
51    provided as a libsigc++-style slot.
52
53   Other public routines exist as well; they should be described in vscreen.h.  
54
55
56   There are several low-level pieces of glue that aptitude uses.
57 These are mostly inherited from previous versions of the program,
58 although modifications have been made:
59
60   curses++.* contain a C++ class wrapper around Curses windows.
61 Although this was initially merely a bunch of syntactic sugar, there
62 are now very good reasons to use it: it turned out that the underlying
63 Curses windows have to be destroyed in a "children before parents"
64 fashion, or memory leaks occur.  Therefore, the wrapper class now
65 refcounts each WINDOW * that it allocates.  This is done (supposedly)
66 entirely transparently and with any luck you won't have to mess with
67 that.
68
69   config/colors.* contian some routines to handle symbolic allocation
70 of colors.  There are a few things that need to be fixed here:
71 in particular, attributes like A_BOLD should be configured here as
72 well.  The interface is straightforward.
73
74   config/keybindings.* contain routines to parse, store, compare, and
75 print keybindings.  Again, the interface is straightforward.
76
77   vscreen/vscreen_widget.* contains the base class for all widgets in
78 the vscreen widget system.  Note that it is a *relatively* heavy
79 class; the expectation is that a fairly small (say, less than
80 100-1000) number will be allocated.  Allocating one widget for each
81 package in the package cache is a questionable idea.  (although who
82 knows, it might work)
83
84   Widgets should generally not be explicitly deleted; instead, call
85 their "destroy" method.  This will place the widget onto a queue to be
86 deleted, generally by the main program loop.  This allows the widget
87 to clean itself up gracefully, and also makes things like destroying a
88 widget currently in use on the stack (relatively) safe.
89
90   Widgets have quite a bit of state.  Each widget has an "owner",
91 which is the container into which the widget has been placed.  The
92 cwindow assigned to the widget will be contained within the cwindow
93 assigned to its owner; the location and size is determined by the
94 "geom" member variable.  It stores an X location, a Y location, a
95 width and a height, where X and Y are relative to the origin of the
96 owner.
97   Widgets also can have a default background attribute; before
98 entering a custom paint routine, the background and current colors
99 will be set to this value, and the widget will be cleared (so it only
100 contains blanks of that color)
101
102   The size_request() method specifies the desired minimum size of
103 the widget (see README.layout).  Override it to calculate the correct
104 value.
105   The focus_me() method should return true if the widget should
106 receive keystrokes, and false otherwise.  Widgets which have multiple
107 children, for instance, may use this to determine where to forward
108 keystroke events.
109
110   To draw a widget in a non-standard way, override its paint()
111 method.
112
113   To alter the behavior of a widget on keystrokes, there are two
114 options.  You can override handle_char, or you can connect a "key
115 signal" to the widget.
116   Overriding handle_char is pretty simple: just check whether the key
117 is a key that you want to handle (see the way the stock widgets do it
118 if you aren't sure).  If your widget handled the keystroke, return
119 true, otherwise return false.  Be sure to call the superclass's
120 handle_char() method if your class does not need the keystroke (for
121 one thing, key signals may not work if you don't!)
122   Key signals are signals that are triggered when a keyboard
123 event is sent.  They may be activated before or after the widget has
124 finished processing keystrokes, and work pretty much like normal
125 signals.  The intent behind key signals is to cut down on unneccessary
126 subclassing by allowing the user of the widget to slightly modify its
127 behavior.  Key signals are also, of course, more dynamic than
128 inheritance (ie, you can add and delete them on the fly)  In general,
129 you should override dispatch_char() when creating a new widgettype,
130 and use key signals if they are fine by themselves.  See the usage of
131 these two in the source for more guidance, and use your judgement.
132   The connect_key, connect_key_post, disconnect_key, and
133 disconnect_key_post routines manage key signals.
134
135 focussed() and unfocussed() are actually signals, but they should be
136   called when the widget gains or loses focus.  (for instance, some
137   widgets might use this to determine when to show or hide a "cursor")
138
139   The following signals are emitted by widgets:
140 shown(), hidden() -- emitted when the widget is shown or hidden (it is
141   already visible or invisible at that point)
142
143 destroyed() -- emitted when the widget is destroyed (it no longer has
144   a valid owner, but some signals may be connected)
145
146 do_layout() -- sent when a widget's layout has been altered.  It is
147   not entirely clear to me why this is not a virtual method.
148   Presumably it made sense at the time, but it doesn't now.
149
150   The following stock vscreen widgets are available:
151 vs_bin -- abstract class for a container holding a single widget
152
153 vs_button -- a standard pushbutton
154
155 vs_center -- a widget that centers its contents within itself; should
156             be replaced by a generic 'layout' widget
157
158 vs_container -- abstract class for a widget that holds other widgets
159
160 vs_editline -- a line-editing widget
161
162 vs_file_pager -- displays the contents of a file.  Subclass of vs_pager.
163
164 vs_frame -- a widget that draws a frame around its contents
165
166 vs_label -- a widget that displays static (possibly multi-line) text
167
168 vs_menubar -- a widget to generate a menubar
169
170 vs_menu -- a single menu.  Currently very reliant on the menubar, and
171           not very graceful about small terminals.
172
173 vs_minibuf_win -- a holdover from the old vscreen, which can display
174                    a message in a "header" line, various widgets in
175                    the "status" line, and a "main" widget in the
176                    middle.
177
178                    DEPRECATED.
179
180 vs_pager -- displays long amounts of text with scrolling.
181
182 vs_passthrough -- an abstract container with a notion of "the
183                  currently focusssed child".  Keyboard events are
184                  passed through to this child, as are some other
185                  things.  For instance, vs_table is one of these.
186
187 vs_radiogroup -- controls a set of togglebuttons so that only a single
188                 one can be selected at once.
189
190 vs_scrollbar -- a vertical or horizontal scrollbar.
191
192 vs_stacked -- displays several stacked (possibly overlapping)
193              widgets.
194
195 vs_statuschoice -- displays a single-line question; eg: "Continue? [yn]".
196                   Useful in status lines.
197
198 vs_table -- arranges several widgets in a "table".  Widgets can be
199            added and removed, and the table will dynamically update.
200            The algorithm could probably use some work; see
201            README.layout for a description of it.  (it was basically
202            lifted from GTK)
203
204 vs_togglebutton -- a button that can either be on or off.  (eg, a
205                   checkbutton)
206
207   In addition, some common interface dialogs are available in vs_util.h:
208 popup messages, yes/no choices, string inputs, and a popup file pager.
209
210   Generic utility code and useful APT routines are stored in generic/
211 Important files in here include:
212
213  -> undo.* contains a generic undo system.
214
215  -> Getting the package changelogs from cgi.debian.org is done in
216   pkg_changelog.*  -- a pretty simple extension of the Acquire system.
217   Right now this is totally broken because the changelogs on debian.org
218   have been broken by package pools.
219
220  -> aptcache.* contains replacements for the APT pkgCacheFile and pkgDepCache
221 classes.  The reason for this is that I wanted/needed to add extra persistent
222 information for each class, and this seemed like the logical way to do it.
223
224   Previous versions of this file suggested that the aptitudeDepCache
225 would eventually be used to handle persistent selection of a
226 particular version.  With pins available, I think that that is no
227 longer necessary (and in fact not especially desirable)
228
229     This file also handles the generation of undo information about
230 apt actions.
231
232  -> matchers.* defines the generalized package matching system.  This is
233 currently used to sort for a particular package and to limit the display.  It
234 works by compiling a pattern (using an incredibly hairy and somewhat quirky
235 parser which should probably be sanitized a little) into an internal tree of
236 operators which can then be (relatively) efficiently applied to packages.
237
238  -> config_signal.* wraps the apt configuration class.  It allows
239 slots to be connected to 'signals' which are generated when a
240 configuration option changes.  Quite useful.  (IMO :) )
241
242   aptitude-specific code is stored in the top of the source tree (src/)
243
244   Important classes include:
245
246  -> apt_trees are a parent for all the various trees which display information
247 about packages.  The following behaviors are handled here: handling undo
248 information when the screen is quit, preventing undos from touching actions
249 performed before the screen was entered, displaying APT errors in the status
250 line, performing install runs, updating the package lists, and restoring the
251 current display state after an install run or a package-list update occurs.
252
253  -> The most important interface element is the pkg_tree class.  This
254 class displays a hierarchy of all the packages (sort of, see below)
255 and allows you to mark them for installation or removal. pkg_trees
256 work by creating hierarchies of pkg_subtrees and pkg_items, but are
257 very flexible in how they create this hierarchy.  In fact, actually
258 creating the hierarchy is the job of a 'grouping policy' -- a class
259 that knows how to sort out packages into several groups and add them
260 to a tree.  Grouping policies can be nested for greater
261 configurability, as diagrammed (poorly :) ) below.  (this shows the
262 flow of data through the system from the package cache to the final
263 tree structure)
264
265 PACKAGES ===> LIMIT ===> GROUP POLICY 1 ===> (GROUP POLICIES 2..N) ==> TREE
266
267   Packages come from the package cache (on the left) and are filtered through
268 the tree's display limit, followed by any number of grouping policies.  Each
269 grouping policy will take action on a package based on the rules for that
270 policy: it may discard the package altogether, it may insert it into a tree, or
271 it may pass it onto the next grouping policy.  These policies are produced by
272 "grouping policy factories". Grouping policy factories are classes which, as
273 the name suggests, have a method which produces a grouping policy when called.
274 They are essentially closures hacked into C++.
275   Grouping policies should never be created directly.  The reason for this is
276 that a grouping policy may create multiple subtrees, and each subtree will
277 require a separate grouping policy (because each policy can potentially track
278 state about stuff inserted into it, we can't just use a single policy for
279 each link in the chain)  Policy factories are used as the exclusive interface
280 for allocating policy objects; in fact, the policy classes themselves are
281 generally not even included in the .h files.
282   Policies are named as pkg_grouppolicy_foo with corresponding factory
283 pkg_grouppolicy_foo_factory.
284
285   One policy is particularly special: the end policy.  This terminates a policy
286 chain; instead of passing its arguments on to another link, it inserts the
287 item into the tree.  In the diagram above, GROUP POLICY N would be an end
288 policy.
289   There are several other policies which act like the end policy, in that
290 they terminate a policy chain: in particular, the dep policy and the
291 ver policy.  These cause packages added to them to be directly inserted to
292 the tree, but with subtrees tacked on (see pkg_item_with_subtree.h).  In
293 particular, the dep policy adds a package's dependencies as subitems of the
294 package itself, and the ver policy adds its available versions as subitems.
295 There is no description policy (which would add the description as a subtree).
296 It is left as an exercise to the reader. (hint. ;-) )
297
298   The bulk of the grouping policy stuff is in pkg_grouppolicy.*
299
300   The work of parsing group-policies is done by load_grouppolicy.
301
302  -> Information about the packages is displayed by several specialized screens:
303 pkg_ver_screen, pkg_dep_screen, pkg_description_screen, and pkg_info_screen.
304
305  -> Downloading is done by download_list and download_bar.
306 download_bar was written for changelogs, but can be used for other
307 things.  Its major correctable deficiency is that it does not allow a
308 download to be cancelled.
309
310   The code to pull all this together and actually download/install packages
311 is in download.* .
312
313  -> Columnification.  This is split into two parts:
314   * Parsing, storing, and using of column configuration files.  This is mainly
315    in vscreen/config/column_definition.*, and used in pkg_columnizer.* .  Think
316    of the column_generator class and its descendents as closures and it will
317    (hopefully) be clearer.  If not, just think of it as a fancy function :)
318    Basically, column_parser_func tells what integer ID a particular column name
319    maps to, while column_generator maps from an ID (and some other information,
320    stored in an instance of the class) to a string value.  The ID is used to
321    avoid parsing too often.
322   * Generation of columns.  See vscreen/columnify.* .  The columnify function
323    returns a formatted string.
324
325   -> Sorting is handled by 'sort policies'.  These are similar to
326 group policies, but in order to reduce typing they are generated by a
327 macro function that adds the redundant cruft (the sort policies
328 themselves are only created by factory routines, which would add some
329 unnecessary typing for each class)
330
331      Note: there are way too many dynamic_casts and virtual methods in
332 the sort system.  Bonus cookie points to anyone who manages to
333 streamline it without making it any nastier than it is.
334
335  -- Daniel Burrows <Daniel_Burrows@brown.edu>