ほげにっき

hogedigoの日記

ScrumもどきPlugin開発記その3

これまでのあらすじ


今回はTracScrumHalfのメインページを作成して、ナビゲーションメニューに追加する。

↓こんなかんじ↓

メインページの中身はとりあえずテキトーで。


例によってTiming and Estimating Pluginを参考にする。

Component追加

src/scrumhalf/scrumhalf.py
import re
from genshi.builder import tag
from trac.core import *
from trac.web import IRequestHandler
from trac.web.chrome import INavigationContributor, ITemplateProvider, \
                                add_stylesheet

class ScrumHalf(Component):
    implements(INavigationContributor, IRequestHandler, ITemplateProvider)
    
    def __init__(self):
        pass

    # INavigationContributor methods
    def get_active_navigation_item(self, req):
        return 'scrumhalf'
    
    def get_navigation_items(self, req):
        yield ('mainnav', 'scrumhalf',
               tag.a('scrumhalf', href=req.href.scrumhalf()))
    
    # IRequestHandler methods
    def match_request(self, req):
        return re.match(r'/scrumhalf(?:_trac)?(?:/.*)?$', req.path_info)

    def process_request(self, req):
        add_stylesheet(req, 'static/css/scrumhalf.css')
        return 'scrumhalf.html', {}, None
    
    # ITemplateProvider methods
    def get_templates_dirs(self):
        from pkg_resources import resource_filename
        return [resource_filename(__name__, 'templates')]

    def get_htdocs_dirs(self):
        from pkg_resources import resource_filename
        return [('static', resource_filename(__name__, 'htdocs'))]

今回実装した拡張ポイントは以下の3つ。

INavigationContributor ナビゲーションメニューを拡張
IRequestHandler HTTPリクエストを処理するハンドラ
ITemplateProvider 独自テンプレートと静的コンテンツの使用


以下に各拡張ポイント実装を(分かる範囲で)説明する。

INavigationContributorメソッド実装
    # INavigationContributor methods
    def get_active_navigation_item(self, req):
        return 'scrumhalf'
    
    def get_navigation_items(self, req):
        yield ('mainnav', 'scrumhalf',
               tag.a('scrumhalf', href=req.href.scrumhalf()))
get_active_navigation_item IRequestHandlerがHTTPリクエストを処理すると呼び出される。非選択ハイライト表示する、ナビゲーション項目名を返す。
get_navigation_items 追加するナビゲーション項目を返す。それぞれの項目は(category, name, text)のタプルで返す。

このget_navigation_itemsがジェネレータ関数てやつね。つまりナビゲーション項目を複数追加する場合はyieldを複数記述する・・・と。

IRequestHandler実装
    # IRequestHandler methods
    def match_request(self, req):
        return re.match(r'/scrumhalf(?:_trac)?(?:/.*)?$', req.path_info)

    def process_request(self, req):
        add_stylesheet(req, 'static/css/scrumhalf.css')
        return 'scrumhalf.html', {}, None
match_request リクエストを処理するかどうかを判定する。
process_request リクエストを処理する。

process_requestは、Genshiテンプレート使用の場合(template_name, data, content_type)のタプルを返す。ClearSilverの場合は(template_name, content_type)。
dataは置換するデータのdictionary(今回はナシ)。content_typeは、Noneの場合"text/html"。
add_stylesheetでスタイルシートを追加出来る。

ITemplateProvider実装
    # ITemplateProvider methods
    def get_templates_dirs(self):
        from pkg_resources import resource_filename
        return [resource_filename(__name__, 'templates')]

    def get_htdocs_dirs(self):
        from pkg_resources import resource_filename
        return [('static', resource_filename(__name__, 'htdocs'))]
get_templates_dirs テンプレートを置くディレクトリパスのlist
get_htdocs_dirs 静的ファイルを置くディレクトリ。(prefix, abspath)タプルのlist。prefixはアクセスするURLプレフィクス。abspathはディレクトリのローカルファイルシステム絶対パス

テンプレート追加

とりあえず超簡単なテンプレートを。

src/scrumhalf/templates/scrumhalf.html
<!DOCTYPE html
    PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:py="http://genshi.edgewall.org/"
      xmlns:xi="http://www.w3.org/2001/XInclude">
  <xi:include href="layout.html" />
  <head>
    <title>Helloworld</title>
  </head>

  <body>
    <div id="ctxtnav" class="nav"></div>

    <div id="content" class="scrumhalf">
      <h1>Scrum Half!!!</h1>
      <img src="${href.chrome('static/images/chart.png')}"/>
    </div>
  </body>
</html>

静的ファイル追加

src/scrumhalf/htdocs/css/scrumhalf.css
div.scrumhalf h1 {
        color: red;
}
src/scrumhalf/htdocs/images/chart.png

てきとーな画像。

__init__.py追記

__init__.py
# TracScrumHalf module
from initenv import *
from scrumhalf import *

実行!

Tracdを再起動して、WebAdminからComponentを有効にする。

ナビゲーションメニューから[scrumhalf]をクリック。

おお。でけた。なんかズレとるけど。(^_^;
※画像はダミーです

最終的なフォルダ構成

src
│  setup.py
│
└─scrumhalf
    │  initenv.py
    │  scrumhalf.py
    │  __init__.py
    │
    ├─htdocs
    │  ├─css
    │  │      scrumhalf.css
    │  │
    │  └─images
    │          chart.png
    │
    └─templates
            scrumhalf.html


まだまだ分からんことだらけだが・・・少しずつ作ってくよ。