Browse Source

Merge pull request #252 from hbrunn/8.0-web_favicon

[ADD] web_favicon
pull/347/head
Pedro M. Baeza 9 years ago
parent
commit
9ca4448c5b
  1. 80
      web_favicon/README.rst
  2. 5
      web_favicon/__init__.py
  3. 23
      web_favicon/__openerp__.py
  4. 4
      web_favicon/controllers/__init__.py
  5. 29
      web_favicon/controllers/web_favicon.py
  6. 4
      web_favicon/models/__init__.py
  7. 17
      web_favicon/models/res_company.py
  8. BIN
      web_favicon/static/description/icon.png
  9. BIN
      web_favicon/static/src/img/android-chrome-144x144.png
  10. BIN
      web_favicon/static/src/img/android-chrome-192x192.png
  11. BIN
      web_favicon/static/src/img/android-chrome-36x36.png
  12. BIN
      web_favicon/static/src/img/android-chrome-48x48.png
  13. BIN
      web_favicon/static/src/img/android-chrome-72x72.png
  14. BIN
      web_favicon/static/src/img/android-chrome-96x96.png
  15. BIN
      web_favicon/static/src/img/apple-touch-icon-114x114.png
  16. BIN
      web_favicon/static/src/img/apple-touch-icon-120x120.png
  17. BIN
      web_favicon/static/src/img/apple-touch-icon-144x144.png
  18. BIN
      web_favicon/static/src/img/apple-touch-icon-152x152.png
  19. BIN
      web_favicon/static/src/img/apple-touch-icon-180x180.png
  20. BIN
      web_favicon/static/src/img/apple-touch-icon-57x57.png
  21. BIN
      web_favicon/static/src/img/apple-touch-icon-60x60.png
  22. BIN
      web_favicon/static/src/img/apple-touch-icon-72x72.png
  23. BIN
      web_favicon/static/src/img/apple-touch-icon-76x76.png
  24. BIN
      web_favicon/static/src/img/apple-touch-icon-precomposed.png
  25. BIN
      web_favicon/static/src/img/apple-touch-icon.png
  26. 12
      web_favicon/static/src/img/browserconfig.xml
  27. BIN
      web_favicon/static/src/img/favicon-16x16.png
  28. BIN
      web_favicon/static/src/img/favicon-32x32.png
  29. BIN
      web_favicon/static/src/img/favicon-96x96.png
  30. BIN
      web_favicon/static/src/img/favicon.ico
  31. 41
      web_favicon/static/src/img/manifest.json
  32. BIN
      web_favicon/static/src/img/master_original_favicon.png
  33. 56
      web_favicon/static/src/img/master_original_favicon.svg
  34. BIN
      web_favicon/static/src/img/mstile-144x144.png
  35. BIN
      web_favicon/static/src/img/mstile-150x150.png
  36. BIN
      web_favicon/static/src/img/mstile-310x150.png
  37. BIN
      web_favicon/static/src/img/mstile-310x310.png
  38. BIN
      web_favicon/static/src/img/mstile-70x70.png
  39. 24
      web_favicon/static/src/img/website_favicon_sample.html
  40. 4
      web_favicon/tests/__init__.py
  41. 48
      web_favicon/tests/test_web_favicon.py
  42. 17
      web_favicon/views/res_company.xml
  43. 10
      web_favicon/views/templates.xml

80
web_favicon/README.rst

@ -0,0 +1,80 @@
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
==============================
Custom shortcut icon (favicon)
==============================
This module was written to allow you to customize your Odoo instance's shortcut
icon (aka favicon). This is useful for branding purposes, but also for
integrators who have many different Odoo instances running and need to see at a
glance which browser tab does what.
More info about favicon: https://en.wikipedia.org/wiki/Favicon
Configuration
=============
Upload your favicon (16x16, 32x32, 64x64 or "as big as possible") on the
company form. The file format would be ico, gif or png with 16x16, 32x32 or
64x64 pixels and 16 colors. Highers resolutions or colors support depends on
the used browser, but most modern browsers do.
Note that most browsers cache favicons basically forever, so if you want your
icon to show up, you'll most probably have to delete you browser cache.
You have a sample SVG that can be used as template for generating your icon
in /static/src/img/master_original_favicon.svg. You can also search for some
favicon generators across the web.
Usage
=====
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
:alt: Try me on Runbot
:target: https://runbot.odoo-community.org/runbot/162/8.0
Known issues / Roadmap
======================
* Allow to upload some big icon (preferrably SVG or the like) and generate
all the icons from it
* Generate icons suitable for mobile devices and web apps (see /static/src/img/
folder inside the module for a sample of the possible current formats.
* Put the icon definition at system level, not at company level. It doesn't
make sense (as the icon is cached) to have a different icon per company.
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/web/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed feedback
`here <https://github.com/OCA/web/issues/new?body=module:%20
web_favicon%0Aversion:%20
8.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Credits
=======
Contributors
------------
* Holger Brunn <hbrunn@therp.nl>
* Pedro M. Baeza <pedro.baeza@gmail.com>
Maintainer
----------
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org
This module is maintained by the OCA.
OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
To contribute to this module, please visit https://odoo-community.org.

5
web_favicon/__init__.py

@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from . import models
from . import controllers

23
web_favicon/__openerp__.py

@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
# © 2015 Therp BV <http://therp.nl>
# © 2016 Pedro M. Baeza
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
"name": "Custom shortcut icon",
"version": "8.0.1.0.0",
"author": "Therp BV, "
"Tecnativa, "
"Odoo Community Association (OCA)",
"license": "AGPL-3",
"category": "Website",
"summary": "Allows to set a custom shortcut icon (aka favicon)",
"depends": [
'web',
],
"data": [
"views/res_company.xml",
'views/templates.xml',
],
"installable": True,
}

4
web_favicon/controllers/__init__.py

@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from . import web_favicon

29
web_favicon/controllers/web_favicon.py

@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
# © 2015 Therp BV <http://therp.nl>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import StringIO
import base64
from openerp import http
from openerp.tools.misc import file_open
class WebFavicon(http.Controller):
@http.route('/web_favicon/favicon', type='http', auth="none")
def icon(self):
request = http.request
if 'uid' in request.env.context:
user = request.env['res.users'].browse(request.env.context['uid'])
company = user.sudo(user.id).company_id
else:
company = request.env['res.company'].search([], limit=1)
favicon = company.favicon_backend
favicon_mimetype = company.favicon_backend_mimetype
if not favicon:
favicon = file_open('web/static/src/img/favicon.ico')
favicon_mimetype = 'image/x-icon'
else:
favicon = StringIO.StringIO(base64.b64decode(favicon))
return request.make_response(
favicon.read(), [('Content-Type', favicon_mimetype)])

4
web_favicon/models/__init__.py

@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from . import res_company

17
web_favicon/models/res_company.py

@ -0,0 +1,17 @@
# -*- coding: utf-8 -*-
# © 2015 Therp BV <http://therp.nl>
# © 2016 Pedro M. Baeza
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import models, fields
class ResCompany(models.Model):
_inherit = 'res.company'
favicon_backend = fields.Binary()
favicon_backend_mimetype = fields.Selection(
selection=[('image/x-icon', 'image/x-icon'),
('image/gif', 'image/gif'),
('image/png', 'image/png')],
help='Set the mimetype of your file.')

BIN
web_favicon/static/description/icon.png

After

Width: 128  |  Height: 128  |  Size: 3.3 KiB

BIN
web_favicon/static/src/img/android-chrome-144x144.png

After

Width: 144  |  Height: 144  |  Size: 1.6 KiB

BIN
web_favicon/static/src/img/android-chrome-192x192.png

After

Width: 192  |  Height: 192  |  Size: 2.3 KiB

BIN
web_favicon/static/src/img/android-chrome-36x36.png

After

Width: 36  |  Height: 36  |  Size: 582 B

BIN
web_favicon/static/src/img/android-chrome-48x48.png

After

Width: 48  |  Height: 48  |  Size: 693 B

BIN
web_favicon/static/src/img/android-chrome-72x72.png

After

Width: 72  |  Height: 72  |  Size: 949 B

BIN
web_favicon/static/src/img/android-chrome-96x96.png

After

Width: 96  |  Height: 96  |  Size: 1.2 KiB

BIN
web_favicon/static/src/img/apple-touch-icon-114x114.png

After

Width: 114  |  Height: 114  |  Size: 1.2 KiB

BIN
web_favicon/static/src/img/apple-touch-icon-120x120.png

After

Width: 120  |  Height: 120  |  Size: 1.2 KiB

BIN
web_favicon/static/src/img/apple-touch-icon-144x144.png

After

Width: 144  |  Height: 144  |  Size: 1.5 KiB

BIN
web_favicon/static/src/img/apple-touch-icon-152x152.png

After

Width: 152  |  Height: 152  |  Size: 1.5 KiB

BIN
web_favicon/static/src/img/apple-touch-icon-180x180.png

After

Width: 180  |  Height: 180  |  Size: 1.8 KiB

BIN
web_favicon/static/src/img/apple-touch-icon-57x57.png

After

Width: 57  |  Height: 57  |  Size: 677 B

BIN
web_favicon/static/src/img/apple-touch-icon-60x60.png

After

Width: 60  |  Height: 60  |  Size: 736 B

BIN
web_favicon/static/src/img/apple-touch-icon-72x72.png

After

Width: 72  |  Height: 72  |  Size: 869 B

BIN
web_favicon/static/src/img/apple-touch-icon-76x76.png

After

Width: 76  |  Height: 76  |  Size: 855 B

BIN
web_favicon/static/src/img/apple-touch-icon-precomposed.png

After

Width: 180  |  Height: 180  |  Size: 2.3 KiB

BIN
web_favicon/static/src/img/apple-touch-icon.png

After

Width: 180  |  Height: 180  |  Size: 1.8 KiB

12
web_favicon/static/src/img/browserconfig.xml

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square70x70logo src="/mstile-70x70.png"/>
<square150x150logo src="/mstile-150x150.png"/>
<square310x310logo src="/mstile-310x310.png"/>
<wide310x150logo src="/mstile-310x150.png"/>
<TileColor>#da532c</TileColor>
</tile>
</msapplication>
</browserconfig>

BIN
web_favicon/static/src/img/favicon-16x16.png

After

Width: 16  |  Height: 16  |  Size: 390 B

BIN
web_favicon/static/src/img/favicon-32x32.png

After

Width: 32  |  Height: 32  |  Size: 533 B

BIN
web_favicon/static/src/img/favicon-96x96.png

After

Width: 96  |  Height: 96  |  Size: 1.2 KiB

BIN
web_favicon/static/src/img/favicon.ico

41
web_favicon/static/src/img/manifest.json

@ -0,0 +1,41 @@
{
"name": "Odoo",
"icons": [
{
"src": "\/android-chrome-36x36.png",
"sizes": "36x36",
"type": "image\/png",
"density": "0.75"
},
{
"src": "\/android-chrome-48x48.png",
"sizes": "48x48",
"type": "image\/png",
"density": "1.0"
},
{
"src": "\/android-chrome-72x72.png",
"sizes": "72x72",
"type": "image\/png",
"density": "1.5"
},
{
"src": "\/android-chrome-96x96.png",
"sizes": "96x96",
"type": "image\/png",
"density": "2.0"
},
{
"src": "\/android-chrome-144x144.png",
"sizes": "144x144",
"type": "image\/png",
"density": "3.0"
},
{
"src": "\/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image\/png",
"density": "4.0"
}
]
}

BIN
web_favicon/static/src/img/master_original_favicon.png

After

Width: 260  |  Height: 260  |  Size: 7.1 KiB

56
web_favicon/static/src/img/master_original_favicon.svg

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
id="svg2"
version="1.1"
inkscape:version="0.48.4 r9939"
width="260"
height="260"
xml:space="preserve"
sodipodi:docname="master_original_favicon.svg"
inkscape:export-filename="master_original_favicon.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"><metadata
id="metadata8"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs6" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1861"
inkscape:window-height="1176"
id="namedview4"
showgrid="false"
inkscape:zoom="2.6264843"
inkscape:cx="139.55902"
inkscape:cy="63.525562"
inkscape:window-x="59"
inkscape:window-y="24"
inkscape:window-maximized="1"
inkscape:current-layer="g10"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0" /><g
id="g10"
inkscape:groupmode="layer"
inkscape:label="ink_ext_XXXXXX"
transform="matrix(1.25,0,0,-1.25,0,260)"><path
inkscape:connector-curvature="0"
id="path14"
style="fill:#a2478a;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 104.00014,165.45424 c -8.313043,0 -16.263246,-1.57861 -23.850744,-4.72609 -7.594015,-3.15718 -14.181554,-7.52151 -19.768717,-13.10966 -5.587026,-5.58537 -10.031894,-12.10596 -13.321854,-19.55278 -3.297028,-7.45376 -4.942836,-15.61837 -4.942836,-24.4966 0,-8.312905 1.645808,-16.26269 4.942836,-23.850746 3.28996,-7.594012 7.734828,-14.256255 13.321854,-19.984093 5.587163,-5.733797 12.174702,-10.246299 19.768717,-13.536809 7.587498,-3.297027 15.537701,-4.941729 23.850744,-4.941729 8.30583,0 16.2577,1.644702 23.85171,4.941729 7.5875,3.29051 14.18128,7.803012 19.76942,13.536809 5.58675,5.727838 10.02454,12.390081 13.32171,19.984093 3.29023,7.588056 4.94089,15.537841 4.94089,23.850746 -0.85928,16.90258 -6.87567,31.15898 -18.04779,42.76184 -11.17419,11.60314 -25.6454,17.97571 -43.40561,19.12329 l -0.43033,0 z M 104.43047,208 c 14.03437,0 27.28859,-2.79405 39.75226,-8.38083 12.46244,-5.58534 23.4211,-13.10687 32.87602,-22.5618 9.45355,-9.45492 16.97508,-20.48705 22.56183,-33.09085 C 205.20733,131.3558 208,117.89258 208,103.56911 208,89.239815 205.27385,75.85019 199.83679,63.387487 194.39,50.925336 187.01124,39.966662 177.70323,30.511325 168.38966,21.056678 157.431,13.602838 144.82719,8.1646355 132.21703,2.726419 118.61203,0 104.00014,0 89.671258,0 76.208041,2.5780813 63.603558,7.7347705 50.993109,12.892 39.96777,20.123798 30.512431,29.437215 21.058202,38.744259 13.605015,49.702934 8.1651761,62.313379 2.7204595,74.917448 0,88.668665 0,103.56911 c 0,14.32347 2.6462976,27.71892 7.9502436,40.1826 5.2990814,12.46381 12.6781754,23.34765 22.1335154,32.66119 9.453538,9.30801 20.553026,16.76025 33.305391,22.347 12.744188,5.58675 26.429298,8.66218 41.04132,9.2401" /></g></svg>

BIN
web_favicon/static/src/img/mstile-144x144.png

After

Width: 144  |  Height: 144  |  Size: 1.8 KiB

BIN
web_favicon/static/src/img/mstile-150x150.png

After

Width: 270  |  Height: 270  |  Size: 1.6 KiB

BIN
web_favicon/static/src/img/mstile-310x150.png

After

Width: 558  |  Height: 270  |  Size: 1.5 KiB

BIN
web_favicon/static/src/img/mstile-310x310.png

After

Width: 558  |  Height: 558  |  Size: 3.2 KiB

BIN
web_favicon/static/src/img/mstile-70x70.png

After

Width: 128  |  Height: 128  |  Size: 1.2 KiB

24
web_favicon/static/src/img/website_favicon_sample.html

@ -0,0 +1,24 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en-US">
<head profile="http://www.w3.org/2005/10/profile">
<link rel="shortcut icon" href="/website_favicon/static/src/img/favicon.ico" type="image/x-icon"/>
<link rel="apple-touch-icon" sizes="57x57" href="/website_favicon/static/src/img/apple-touch-icon-57x57.png"/>
<link rel="apple-touch-icon" sizes="60x60" href="/website_favicon/static/src/img/apple-touch-icon-60x60.png"/>
<link rel="apple-touch-icon" sizes="72x72" href="/website_favicon/static/src/img/apple-touch-icon-72x72.png"/>
<link rel="apple-touch-icon" sizes="76x76" href="/website_favicon/static/src/img/apple-touch-icon-76x76.png"/>
<link rel="apple-touch-icon" sizes="114x114" href="/website_favicon/static/src/img/apple-touch-icon-114x114.png"/>
<link rel="apple-touch-icon" sizes="120x120" href="/website_favicon/static/src/img/apple-touch-icon-120x120.png"/>
<link rel="apple-touch-icon" sizes="144x144" href="/website_favicon/static/src/img/apple-touch-icon-144x144.png"/>
<link rel="apple-touch-icon" sizes="152x152" href="/website_favicon/static/src/img/apple-touch-icon-152x152.png"/>
<link rel="apple-touch-icon" sizes="180x180" href="/website_favicon/static/src/img/apple-touch-icon-180x180.png"/>
<link rel="icon" type="image/png" href="/website_favicon/static/src/img/favicon-32x32.png" sizes="32x32"/>
<link rel="icon" type="image/png" href="/website_favicon/static/src/img/android-chrome-192x192.png" sizes="192x192"/>
<link rel="icon" type="image/png" href="/website_favicon/static/src/img/favicon-96x96.png" sizes="96x96"/>
<link rel="icon" type="image/png" href="/website_favicon/static/src/img/favicon-16x16.png" sizes="16x16"/>
<link rel="manifest" href="/manifest.json"/>
<meta name="msapplication-TileColor" content="#da532c"/>
<meta name="msapplication-TileImage" content="/mstile-144x144.png"/>
<meta name="theme-color" content="#ffffff"/>
</head>
<body/>
</html>

4
web_favicon/tests/__init__.py

@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from . import test_web_favicon

48
web_favicon/tests/test_web_favicon.py

@ -0,0 +1,48 @@
# -*- coding: utf-8 -*-
# © 2015 Therp BV <http://therp.nl>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import base64
from openerp.tests.common import TransactionCase
from openerp.tools.misc import file_open
from openerp import http
class FakeRequest(object):
def __init__(self, env):
self.env = env
def make_response(self, data, headers):
return FakeResponse(data, headers)
class FakeResponse(object):
def __init__(self, data, headers):
self.data = data
self.headers = dict(headers)
class TestWebFavicon(TransactionCase):
def test_web_favicon(self):
original_request = http.request
http.request = FakeRequest(self.env)
from openerp.addons.web_favicon.controllers.web_favicon import\
WebFavicon
company = self.env['res.company'].search([], limit=1)
# default icon
company.write({
'favicon_backend': False,
'favicon_backend_mimetype': False,
})
data = WebFavicon().icon()
self.assertEqual(data.headers['Content-Type'], 'image/x-icon')
# our own icon
company.write({
'favicon_backend': base64.b64encode(file_open(
'web_favicon/static/description/icon.png').read()),
'favicon_backend_mimetype': 'image/png',
})
data = WebFavicon().icon()
self.assertEqual(data.headers['Content-Type'],
company.favicon_backend_mimetype)
http.request = original_request

17
web_favicon/views/res_company.xml

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<openerp>
<data>
<record id="view_company_form" model="ir.ui.view">
<field name="model">res.company</field>
<field name="inherit_id" ref="base.view_company_form" />
<field name="arch" type="xml">
<page string="Configuration" position="inside">
<group string="Favicon" name="favicon">
<field name="favicon_backend" widget="image" />
<field name="favicon_backend_mimetype" attrs="{'required': [('favicon_backend', '!=', False)]}" />
</group>
</page>
</field>
</record>
</data>
</openerp>

10
web_favicon/views/templates.xml

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<openerp>
<data>
<template id="layout" inherit_id="web.layout">
<xpath expr="//link[@rel='shortcut icon']" position="replace">
<link rel="icon" href="/web_favicon/favicon" />
</xpath>
</template>
</data>
</openerp>
Loading…
Cancel
Save