details:   https://code.tryton.org/tryton/commit/234f0a089153
branch:    default
user:      Cédric Krier <[email protected]>
date:      Tue May 12 15:40:54 2026 +0200
description:
        Add filters attribute for binary and image widgets

        Closes #14822
diffstat:

 sao/CHANGELOG                                              |   1 +
 sao/src/view/form.js                                       |  10 ++++--
 tryton/CHANGELOG                                           |   1 +
 tryton/tryton/gui/window/view_form/view/form_gtk/binary.py |  18 +++++++++--
 tryton/tryton/gui/window/view_form/view/form_gtk/image.py  |  12 +-------
 tryton/tryton/gui/window/view_form/view/list_gtk/widget.py |  20 +++++++++++++-
 trytond/CHANGELOG                                          |   1 +
 trytond/doc/topics/views/index.rst                         |   8 +++++
 trytond/trytond/ir/ui/form.rnc                             |   1 +
 trytond/trytond/ir/ui/tree.rnc                             |   1 +
 10 files changed, 54 insertions(+), 19 deletions(-)

diffs (194 lines):

diff -r 99660f995c4a -r 234f0a089153 sao/CHANGELOG
--- a/sao/CHANGELOG     Fri Apr 10 11:29:50 2026 +0200
+++ b/sao/CHANGELOG     Tue May 12 15:40:54 2026 +0200
@@ -1,3 +1,4 @@
+* Support filters attribute for binary and image widgets
 * Use search window to delete/remove records from xxx2Many widgets
 
 Version 8.0.0 - 2026-04-20
diff -r 99660f995c4a -r 234f0a089153 sao/src/view/form.js
--- a/sao/src/view/form.js      Fri Apr 10 11:29:50 2026 +0200
+++ b/sao/src/view/form.js      Tue May 12 15:40:54 2026 +0200
@@ -4521,6 +4521,10 @@
                 this, view, attributes);
             this.filename = attributes.filename || null;
         },
+        default_filters: '',
+        get filters() {
+            return this.attributes.filters || this.default_filters;
+        },
         toolbar: function(class_) {
             var group = jQuery('<div/>', {
                 'class': class_,
@@ -4539,6 +4543,7 @@
             this.input_select = jQuery('<input/>', {
                 'type': 'file',
             }).change(this.select.bind(this));
+            this.input_select.attr('accept', this.filters);
             this.but_select = jQuery('<div/>', {
                 'class': 'btn btn-default input-file',
                 'type': 'button',
@@ -4856,9 +4861,6 @@
                     break;
             }
             var group = this.toolbar('btn-group');
-            this.input_select.attr(
-                'accept',
-                'image/png,image/jpeg,image/gif,.png,.jpg,.gif,.tif,.xpm');
             if (!attributes.readonly) {
                 jQuery('<div/>', {
                     'class': 'text-center caption',
@@ -4866,6 +4868,8 @@
             }
             this._readonly = false;
         },
+        default_filters: (
+            'image/png,image/jpeg,image/gif,.png,.jpg,.gif,.tif,.xpm'),
         set_readonly: function(readonly) {
             Sao.View.Form.Image._super.set_readonly.call(this, readonly);
             var record = this.record;
diff -r 99660f995c4a -r 234f0a089153 tryton/CHANGELOG
--- a/tryton/CHANGELOG  Fri Apr 10 11:29:50 2026 +0200
+++ b/tryton/CHANGELOG  Tue May 12 15:40:54 2026 +0200
@@ -1,3 +1,4 @@
+* Support filters attribute for binary and image widgets
 * Use search window to delete/remove records from xxx2Many widgets
 
 Version 8.0.0 - 2026-04-20
diff -r 99660f995c4a -r 234f0a089153 
tryton/tryton/gui/window/view_form/view/form_gtk/binary.py
--- a/tryton/tryton/gui/window/view_form/view/form_gtk/binary.py        Fri Apr 
10 11:29:50 2026 +0200
+++ b/tryton/tryton/gui/window/view_form/view/form_gtk/binary.py        Tue May 
12 15:40:54 2026 +0200
@@ -64,12 +64,22 @@
     def filename_field(self):
         return self.record.group.fields.get(self.filename)
 
+    default_filters = None
+
     @property
     def filters(self):
-        filter_all = Gtk.FileFilter()
-        filter_all.set_name(_('All files'))
-        filter_all.add_pattern("*")
-        return [filter_all]
+        file_filter = Gtk.FileFilter()
+        if filters := self.attrs.get('filters', self.default_filters):
+            file_filter.set_name(_("All Supported Types"))
+            for type in filters.split(','):
+                if type.startswith('.'):
+                    file_filter.add_pattern(type)
+                else:
+                    file_filter.add_mime_type(type)
+        else:
+            file_filter.set_name(_("All files"))
+            file_filter.add_pattern("*")
+        return [file_filter]
 
     @property
     def preview(self):
diff -r 99660f995c4a -r 234f0a089153 
tryton/tryton/gui/window/view_form/view/form_gtk/image.py
--- a/tryton/tryton/gui/window/view_form/view/form_gtk/image.py Fri Apr 10 
11:29:50 2026 +0200
+++ b/tryton/tryton/gui/window/view_form/view/form_gtk/image.py Tue May 12 
15:40:54 2026 +0200
@@ -47,17 +47,7 @@
 
         self._readonly = False
 
-    @property
-    def filters(self):
-        filters = super().filters
-        filter_image = Gtk.FileFilter()
-        filter_image.set_name(_('Images'))
-        for mime in ("image/png", "image/jpeg", "image/gif"):
-            filter_image.add_mime_type(mime)
-        for pat in ("*.png", "*.jpg", "*.gif", "*.tif", "*.xpm"):
-            filter_image.add_pattern(pat)
-        filters.insert(0, filter_image)
-        return filters
+    default_filters = 'image/png,image/jpeg,image/gif,.png,.jpg,.gif,.tif,.xpm'
 
     def _readonly_set(self, value):
         self._readonly = value
diff -r 99660f995c4a -r 234f0a089153 
tryton/tryton/gui/window/view_form/view/list_gtk/widget.py
--- a/tryton/tryton/gui/window/view_form/view/list_gtk/widget.py        Fri Apr 
10 11:29:50 2026 +0200
+++ b/tryton/tryton/gui/window/view_form/view/list_gtk/widget.py        Tue May 
12 15:40:54 2026 +0200
@@ -699,6 +699,24 @@
 
 
 class _BinarySelect(_BinaryIcon):
+
+    default_filters = None
+
+    @property
+    def filters(self):
+        file_filter = Gtk.FileFilter()
+        if filters := self.attrs.get('filters', self.default_filters):
+            file_filter.set_name(_("All Supported Types"))
+            for type in filters.split(','):
+                if type.startswith('.'):
+                    file_filter.add_pattern(type)
+                else:
+                    file_filter.add_mime_type(type)
+        else:
+            file_filter.set_name(_("All files"))
+            file_filter.add_pattern("*")
+        return [file_filter]
+
     def clicked(self, renderer, path):
         record, field = self._get_record_field_from_path(path)
         if hasattr(field, 'get_size'):
@@ -715,7 +733,7 @@
             field.set_client(record, None)
         else:
             def _select():
-                filename = file_selection(_('Open...'))
+                filename = file_selection(_("Select"), filters=self.filters)
                 if filename:
                     with open(filename, 'rb') as fp:
                         field.set_client(record, fp.read())
diff -r 99660f995c4a -r 234f0a089153 trytond/CHANGELOG
--- a/trytond/CHANGELOG Fri Apr 10 11:29:50 2026 +0200
+++ b/trytond/CHANGELOG Tue May 12 15:40:54 2026 +0200
@@ -1,3 +1,4 @@
+* Add filters attribute for binary and image widgets
 * Move last_user and last_modification to ResourceAccessMixin
 * Add check deliverability option to validate email tool
 * Add support for AGE to SQLite backend
diff -r 99660f995c4a -r 234f0a089153 trytond/doc/topics/views/index.rst
--- a/trytond/doc/topics/views/index.rst        Fri Apr 10 11:29:50 2026 +0200
+++ b/trytond/doc/topics/views/index.rst        Tue May 12 15:40:54 2026 +0200
@@ -365,6 +365,14 @@
    ``rounded`` or ``circle``.
    The default value is ``square``.
 
+``filters``
+   A comma separated list of mime type and file extension (starting with a
+   period ``.``) to restrict the files being shown for selection of binary and
+   image widgets.
+   The default value for binary widget is no filter.
+   The default value for image widget is:
+   ``image/png,image/jpeg,image/gif,.png,.jpg,.gif,.tif,.xpm``.
+
 ``visible``
    When set to ``1`` for :class:`~trytond.model.fields.One2Many` and
    :class:`~trytond.model.fields.Many2Many` the client may try to read the
diff -r 99660f995c4a -r 234f0a089153 trytond/trytond/ir/ui/form.rnc
--- a/trytond/trytond/ir/ui/form.rnc    Fri Apr 10 11:29:50 2026 +0200
+++ b/trytond/trytond/ir/ui/form.rnc    Tue May 12 15:40:54 2026 +0200
@@ -122,6 +122,7 @@
 attlist.field &= attribute symbol { text }?
 attlist.field &= [a:defaultValue = "1"] attribute grouping { "0" | "1" }?
 attlist.field &= [a:defaultValue = "square"] attribute border { "square" | 
"circle" | "rounded" }?
+attlist.field &= attribute filters { text }?
 attlist.field &= [a:defaultValue = "0"] attribute visible { "0" | "1" }?
 image = element image { attlist.image, empty }
 attlist.image &= attribute name { text }
diff -r 99660f995c4a -r 234f0a089153 trytond/trytond/ir/ui/tree.rnc
--- a/trytond/trytond/ir/ui/tree.rnc    Fri Apr 10 11:29:50 2026 +0200
+++ b/trytond/trytond/ir/ui/tree.rnc    Tue May 12 15:40:54 2026 +0200
@@ -75,6 +75,7 @@
 attlist.field &= attribute view_ids { text }?
 attlist.field &= attribute symbol { text }?
 attlist.field &= [a:defaultValue = "1"] attribute grouping { "0" | "1" }?
+attlist.field &= attribute filters { text }?
 prefix = element prefix { attlist.affix, empty }
 suffix = element suffix { attlist.affix, empty }
 attlist.affix &= attribute string { text }?

Reply via email to