如何在 odoo 9 的自定义模块内的树视图中添加图像或图标?

How can I add images or icons in a tree view inside a custom module in odoo 9?

我想在 odoo 9 中的自定义模块的树视图中的按钮内放置一个图像。

我在 my_module.xml 中有 2 个按钮:

<?xml version="1.0"?>
<openerp>
    <data>
        <record id="view_my_module_tree" model="ir.ui.view">
            <field name="name">my.module.tree</field>
            <field name="model">my.module</field>
            <field name="type">tree</field>
            <field name="arch" type="xml">
                <tree string="my_module_tree" create="false" delete="false">
                    <button name="button_form" icon="cat" type="object"/>
                    <button name="button_form" icon="dog" type="object"/>                   
                </tree>
            </field>
        </record>  
    </data>
</openerp>

如果图标 'cat.png' 和 dog.png' 位于 'addons/web/static/src/img/icons/' 内,则有效。但是我想把这个图标放在我的自定义模块中。

我已经创建了 'my_module/static/src/img/icons/' 层次结构并将两个图像都放入其中,但是其中 none 出现在按钮中。

我做错了什么? 我需要在 openerp.py 文件中添加一些东西吗?

编辑:我试过了

<button name="button_form" type="object" icon="/my_module/static/src/img/icons/cat.png"/> 

但是没有用。如果我在浏览器 DevTools 中看到,我可以检查 html 代码:

<img src="http://localhost:8069/web/static/src/img/icons//my_module/static/src/img/icons/cat.png.png">

这对 WidgetButton 的源代码有意义(它附加到 '/web/static/src/img/icons/' 你的图像路径,然后在末尾添加 '.png' 但是当然,这并没有解决问题。

据我所知,您必须直接在图标上使用 link,因为 odoo 已经在生成的 img 标签前面附加了您的 url,这将是 localhost:8069 假设您 运行 在本地主机上,端口为 8069

<button name="print_report" context="{'open_purchase': True}" string="Print" type="object" icon="/my_module/static/src/img/icons/images.png" class="oe_highlight"/>

这是我机器的屏幕截图,带有 adobe pdf 图标

如果您阅读 source code 就会清楚为什么它不起作用。该文件还定义了 odoo 中不同视图的所有可用核心模板,因此您可以在不了解特定标签如何工作的任何时候返回并参考它。

var WidgetButton = common.FormWidget.extend({
    template: 'WidgetButton',
    init: function(field_manager, node) {
        node.attrs.type = node.attrs['data-button-type'];
        this._super(field_manager, node);
        this.force_disabled = false;
        this.string = (this.node.attrs.string || '').replace(/_/g, '');
        if (JSON.parse(this.node.attrs.default_focus || "0")) {
            // TODO fme: provide enter key binding to widgets
            this.view.default_focus_button = this;
        }
        if (this.node.attrs.icon) {
            // if the icon isn't a font-awesome one, find it in the icons folder
            this.fa_icon = this.node.attrs.icon.indexOf('fa-') === 0;
            if (!this.fa_icon && (! /\//.test(this.node.attrs.icon))) {
                this.node.attrs.icon = '/web/static/src/img/icons/' + this.node.attrs.icon + '.png';
            }
        }
},

if 语句测试图标是否是超赞字体图标,如果它不是超赞字体图标并且不包含任何斜杠('(! /\//.test' 测试),那么它将使用您提供的路径否则它将使用路径 '/web/static/src/img/icons/' + this.node.attrs.icon + '.png' 并将 .png 附加到路径的末尾,这意味着该文件夹中只有 .png 文件可以用作图标

在文件底部,您可以看到新小部件 WidgetButton 在视图中作为 button 标记注册的位置。

core.form_tag_registry.add('button', WidgetButton);

如果您对按钮的实现方式以及它们的属性如何解析以生成 html 感兴趣,您还可以阅读源代码 here

从第 1446 行到第 1457 行

1446<t t-name="WidgetButton">
1447     <button type="button" t-att-class="widget.is_stat_button ? 'oe_stat_button btn btn-default' : 'oe_button oe_form_button ' + (widget.node.att     rs.class ? widget.node.attrs.class : '')"
1448         t-att-style="widget.node.attrs.style"
1449         t-att-tabindex="widget.node.attrs.tabindex"
1450         t-att-autofocus="widget.node.attrs.autofocus"
1451         t-att-accesskey="widget.node.attrs.accesskey">
1452         <img t-if="!widget.is_stat_button and widget.node.attrs.icon " t-att-src="_s + widget.node.attrs.icon" width="16" height="16"/>
1453         <div t-if="widget.is_stat_button and widget.icon_class" t-att-class="widget.icon_class"></div>
1454         <span t-if="widget.string and !widget.is_stat_button"><t t-esc="widget.string"/></span>
1455         <div t-if="widget.string and widget.is_stat_button"><t t-esc="widget.string"/></div>
1456     </button>
1457 </t>

第 1452 行告诉我们,如果小部件不是统计按钮(用于计数)并且它的图标 属性 也被设置,那么将生成一个 <img> 标签,其 src 是 '_s' + 图标的值。

'_s' 稍后被评估为您当前的 url 具有适当的端口,具体取决于您来自 运行 Odoo 的位置,创建新会话时,来自源位于此处 qweb 的代码有一个名为 default_dict 的字典,用于存储一些参数

所以 ._s 设置为 origin 这是你最初启动 odoo 服务器时的 url

/**
     * Setup a session
     */
    session_bind: function(origin) {
        var self = this;
        this.setup(origin);
        qweb.default_dict._s = this.origin;
        this.uid = null;
        this.username = null;
        this.user_context= {};
        this.db = null;
        this.module_loaded = {};
        _(this.module_list).each(function (mod) {
            self.module_loaded[mod] = true;
        });
        this.active_id = null;
        return this.session_init();
    },
/**

编辑: 对于阅读本文的任何人,此解决方案不适用于列表视图(Odoo 的树视图)中的图标。我已经向 Odoo 8 提交了 PR 来解决这个问题。 (希望它能被合并并转发到 Odoo 9)

最后,解决方案。

这是一个odoo错误。窗体视图和列表视图按钮中的自定义按钮图标之间存在不一致。

更多信息在这里: https://github.com/odoo/odoo/pull/13983

在他们解决问题之前,有 3 种解决方案可用:

解决方案 1:低级黑客

改变这个:

<button name="button_form" icon="cat" type="object"/>

为此:

<button name="button_form" icon="../../../../../my_module/static/src/img/icons/cat" type="object"/>

方案二:odoo官方图标文件夹中的图标

将图标放入文件夹/web/static/src/img/icons

解决方案 3:手动修复错误

编辑文件:addons/web/static/src/xml/base.xml

改变这个:

<button t-name="ListView.row.button" type="button"
    t-att-title="widget.string" t-att-disabled="disabled || undefined"
    t-att-class="disabled ? 'oe_list_button_disabled' : ''"
    ><img t-attf-src="#{prefix}/web/static/src/img/icons/#{widget.icon}.png"
    t-att-alt="widget.string"/></button>

为此:

<button t-name="ListView.row.button" type="button"
    t-att-title="widget.string" t-att-disabled="disabled || undefined"
    t-att-class="disabled ? 'oe_list_button_disabled' : ''"
    ><t t-if="!widget.icon.indexOf('fa-') == 0"><t t-if="!/\//.test(widget.icon)"><img t-attf-src="#{prefix}/web/static/src/img/icons/#{widget.icon}.png" /></t></t>
    <t t-if="/\//.test(widget.icon)"><img t-attf-src="#{widget.icon}" /></t>
    <i t-if="widget.icon.indexOf('fa-') == 0" t-attf-class="fa #{widget.icon}" t-att-title="widget.string"/></button>