Edgewall Software

Extension Point : IPreferencePanelProvider


The IPreferencePanelProvider allows adding panels to Trac's preferences dialog.


Trac provides a user preferences system. Plugins can participate in this system by implementing the IPreferencePanelProvider. This allows a unified web UI where all preferences are configured in the same place, the preferences dialog.

When a user browses to the preferences dialog, all implementations are called to provide any implemented panels, which are shown as tabs. When the user activates a tab the respective implementation is called to render the page corresponding to that tab.

Since Trac 1.1.3 implementations can also provide child panels that show up as a section in the parent panel. A modular ecosystem of thematically related plugins can use child panels to populate a shared preferences page.


Implementing the interface follows the standard guidelines found in TracDev/ComponentArchitecture and of course TracDev/PluginDevelopment.

The implementation has to render a panel by returning a template file name and a data dictionary to be used by that template. (See ITemplateProvider and IRequestHandler)

The panel template should <xi:include href="prefs.html" /> to provide the consistent common UI to all preference panels. Including this will also add a "Save changes" button if the template contains no forms of its own. Note that the IPreferencePanelProvider still has to implement any actual save functionality!

Saving preferences is usually handled by storing the value with an appropriate unique key in the session. With the default "Save changes" button this means checking for req.method == 'POST' (and possibly req.args['action']=='save' if there are other POST usages?)


The following example provides a simple scratchpad text area in the preferences. Any entered text is stored in the session. In a real preference panel, the saved preference value should of course be read from the session by some other (part of the) component to configure some of its functionality.

from trac.core import *
from trac.prefs import IPreferencePanelProvider

class ScratchpadPreferencePanel(Component):


    # IPreferencePanelProvider methods

    def get_preference_panels(self, req):
        yield ('scratchpad', _('Scratchpad'))

    def render_preference_panel(self, req, panel):
        if req.method == 'POST':
            new_content = req.args.get('scratchpad_textarea')
            if new_content:
                req.session['scratchpad'] = new_content
                add_notice(req, _('Your Scratchpad text has been saved.'))
            req.redirect(req.href.prefs(panel or None))

        return 'prefs_scratchpad.html', {
            'scratchpad_text': req.session.get('scratchpad', 'your text')

The accompanying prefs_scratchpad.html:

<!DOCTYPE html
    PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
<html xmlns="http://www.w3.org/1999/xhtml"
  <xi:include href="prefs.html" />
    <p><label>A Scratchpad text field:
      <textarea rows="10" cols="40" name="scratchpad_textarea">

Available Implementations

Additional Information and References

API History

Last modified 6 years ago Last modified on Feb 10, 2016, 10:41:50 AM
Note: See TracWiki for help on using the wiki.