changeset 65aff6f1a7e9 in tryton:default
details: https://hg.tryton.org/tryton?cmd=changeset;node=65aff6f1a7e9
description:
Improve note button
* Add resources method to ModelStorage
* Support badge on icon
* Display unread and total of notes
* Add two extra colors for icon
issue8122
review70561002
diffstat:
CHANGELOG | 3 +
tryton/common/common.py | 31 +++++++--
tryton/config.py | 2 +-
tryton/gui/window/form.py | 91 ++++++++++++----------------
tryton/gui/window/view_form/model/record.py | 36 ++--------
tryton/gui/window/view_form/screen/screen.py | 33 ++-------
6 files changed, 82 insertions(+), 114 deletions(-)
diffs (325 lines):
diff -r 71de92ba03b6 -r 65aff6f1a7e9 CHANGELOG
--- a/CHANGELOG Fri Mar 22 11:57:42 2019 +0100
+++ b/CHANGELOG Fri Mar 22 12:16:36 2019 +0100
@@ -1,3 +1,6 @@
+* Display unread and total of notes
+* Support badge on icon
+* Use resources method
* Replace Arrow by Image
* Remove Fast Tabbing option
* Remove usage of focus_chain
diff -r 71de92ba03b6 -r 65aff6f1a7e9 tryton/common/common.py
--- a/tryton/common/common.py Fri Mar 22 11:57:42 2019 +0100
+++ b/tryton/common/common.py Fri Mar 22 12:16:36 2019 +0100
@@ -111,10 +111,12 @@
cls._tryton_icons.remove((icon['id'], icon['name']))
del cls._name2id[icon['name']]
+ colors = CONFIG['icon.colors'].split(',')
+
@classmethod
- def get_pixbuf(cls, iconname, size=16, color=None):
+ def get_pixbuf(cls, iconname, size=16, color=None, badge=None):
cls.register_icon(iconname)
- if iconname not in cls._pixbufs[size]:
+ if iconname not in cls._pixbufs[(size, badge)]:
if iconname in cls._icons:
data = cls._icons[iconname]
elif iconname in cls._local_icons:
@@ -124,12 +126,24 @@
else:
logger.error("Unknown icon %s" % iconname)
return
- if color is None:
- color = CONFIG['icon.color']
+ if not color:
+ color = cls.colors[0]
try:
ET.register_namespace('', 'http://www.w3.org/2000/svg')
root = ET.fromstring(data)
root.attrib['fill'] = color
+ if badge:
+ if not isinstance(badge, str):
+ try:
+ badge = cls.colors[badge]
+ except IndexError:
+ badge = color
+ ET.SubElement(root, 'circle', {
+ 'cx': '20',
+ 'cy': '4',
+ 'r': '4',
+ 'fill': badge,
+ })
data = ET.tostring(root)
except ET.ParseError:
pass
@@ -141,12 +155,13 @@
Gtk.IconSize.DND: 12,
Gtk.IconSize.DIALOG: 48,
}.get(size, size)
- cls._pixbufs[size][iconname] = data2pixbuf(data, width, height)
- return cls._pixbufs[size][iconname]
+ pixbuf = data2pixbuf(data, width, height)
+ cls._pixbufs[(size, badge)][iconname] = pixbuf
+ return cls._pixbufs[(size, badge)][iconname]
@classmethod
- def get_image(cls, iconname, size=16, color=None):
- pixbuf = cls.get_pixbuf(iconname, size, color)
+ def get_image(cls, iconname, size=16, color=None, badge=None):
+ pixbuf = cls.get_pixbuf(iconname, size, color, badge)
image = Gtk.Image()
image.set_from_pixbuf(pixbuf)
return image
diff -r 71de92ba03b6 -r 65aff6f1a7e9 tryton/config.py
--- a/tryton/config.py Fri Mar 22 11:57:42 2019 +0100
+++ b/tryton/config.py Fri Mar 22 12:16:36 2019 +0100
@@ -55,7 +55,7 @@
'client.limit': 1000,
'client.check_version': True,
'client.bus_timeout': 10 * 60,
- 'icon.color': '#3465a4',
+ 'icon.colors': '#3465a4,#555753,#cc0000',
'image.max_size': 10 ** 6,
'bug.url': 'https://bugs.tryton.org/',
'download.url': 'https://downloads.tryton.org/',
diff -r 71de92ba03b6 -r 65aff6f1a7e9 tryton/gui/window/form.py
--- a/tryton/gui/window/form.py Fri Mar 22 11:57:42 2019 +0100
+++ b/tryton/gui/window/form.py Fri Mar 22 12:16:36 2019 +0100
@@ -53,9 +53,9 @@
self.screen.signal_connect(self, 'record-modified',
lambda *a: GLib.idle_add(self._record_modified, *a))
self.screen.signal_connect(self, 'record-saved', self._record_saved)
- self.screen.signal_connect(self, 'attachment-count',
- self._attachment_count)
- self.screen.signal_connect(self, 'unread-note', self._unread_note)
+ self.screen.signal_connect(
+ self, 'resources',
+ lambda screen, resources: self.update_resources(resources))
if res_id not in (None, False):
if isinstance(res_id, int):
@@ -105,7 +105,7 @@
def sig_attach(self, widget=None):
def window(widget):
return Attachment(
- record, lambda: self.update_attachment_count(reload=True))
+ record, lambda: self.refresh_resources(reload=True))
def add_file(widget):
filenames = common.file_selection(_("Select"), multi=True)
@@ -139,61 +139,48 @@
menu.connect('deactivate', self._popup_menu_hide, button)
self.action_popup(button)
- def update_attachment_count(self, reload=False):
- record = self.screen.current_record
- if record:
- attachment_count = record.get_attachment_count(reload=reload)
- else:
- attachment_count = 0
- self._attachment_count(None, attachment_count)
-
- def _attachment_count(self, widget, signal_data):
- label = _('Attachment(%d)') % signal_data
- self.buttons['attach'].set_label(label)
- if signal_data:
- # FIXME
- icon = 'tryton-attach'
- else:
- icon = 'tryton-attach'
- image = common.IconFactory.get_image(icon, Gtk.IconSize.LARGE_TOOLBAR)
- image.show()
- self.buttons['attach'].set_icon_widget(image)
- record = self.screen.current_record
- self.buttons['attach'].props.sensitive = bool(
- record.id >= 0 if record else False)
-
def sig_note(self, widget=None):
record = self.screen.current_record
if not record or record.id < 0:
return
Note(record,
- lambda: self.update_unread_note(reload=True))
+ lambda: self.refresh_resources(reload=True))
- def update_unread_note(self, reload=False):
+ def refresh_resources(self, reload=False):
record = self.screen.current_record
- if record:
- unread = record.get_unread_note(reload=reload)
- else:
- unread = 0
- self._unread_note(None, unread)
+ self.update_resources(
+ record.get_resources(reload=reload) if record else None)
+
+ def update_resources(self, resources):
+ if not resources:
+ resources = {}
+ record = self.screen.current_record
+ sensitive = record.id >= 0 if record else False
- def _unread_note(self, widget, signal_data):
- label = _('Note(%d)') % signal_data
- self.buttons['note'].set_label(label)
- if signal_data:
- # FIXME
- icon = 'tryton-note'
+ def update(name, label, icon, badge):
+ button = self.buttons[name]
+ button.set_label(label)
+ image = common.IconFactory.get_image(
+ icon, Gtk.IconSize.LARGE_TOOLBAR, badge=badge)
+ image.show()
+ button.set_icon_widget(image)
+ button.props.sensitive = sensitive
+
+ attachment_count = resources.get('attachment_count', 0)
+ badge = 1 if attachment_count else None
+ label = _("Attachment (%s)") % attachment_count
+ update('attach', label, 'tryton-attach', badge)
+
+ note_count = resources.get('note_count', 0)
+ note_unread = resources.get('note_unread', 0)
+ if note_unread:
+ badge = 2
+ elif note_count:
+ badge = 1
else:
- icon = 'tryton-note'
- image = common.IconFactory.get_image(icon, Gtk.IconSize.LARGE_TOOLBAR)
- image.show()
- self.buttons['note'].set_icon_widget(image)
- record = self.screen.current_record
- if not record or record.id < 0:
- sensitive = False
- else:
- sensitive = True
- self.buttons['note'].props.sensitive = sensitive
+ badge = None
+ label = _("Note (%d/%d)") % (note_unread, note_count)
+ update('note', label, 'tryton-note', badge)
def sig_switch(self, widget=None):
if not self.modified_save():
@@ -498,7 +485,7 @@
def _record_saved(self, screen, signal_data):
self.activate_save()
- self.update_attachment_count()
+ self.refresh_resources()
def modified_save(self):
self.screen.save_tree_state()
@@ -711,7 +698,7 @@
if not record or record.id < 0:
return
win_attach = Attachment(record,
- lambda: self.update_attachment_count(reload=True))
+ lambda: self.refresh_resources(reload=True))
if info == 0:
if selection.get_uris():
for uri in selection.get_uris():
diff -r 71de92ba03b6 -r 65aff6f1a7e9 tryton/gui/window/view_form/model/record.py
--- a/tryton/gui/window/view_form/model/record.py Fri Mar 22 11:57:42
2019 +0100
+++ b/tryton/gui/window/view_form/model/record.py Fri Mar 22 12:16:36
2019 +0100
@@ -28,8 +28,7 @@
self.state_attrs = {}
self.modified_fields = {}
self._timestamp = None
- self.attachment_count = -1
- self.unread_note = -1
+ self.resources = None
self.button_clicks = {}
self.next = {} # Used in Group list
self.value = {}
@@ -602,34 +601,15 @@
if context:
value.context = self.expr_eval(context)
- def get_attachment_count(self, reload=False):
- if self.id < 0:
- return 0
- if self.attachment_count < 0 or reload:
+ def get_resources(self, reload=False):
+ if self.id >= 0 and (not self.resources or reload):
try:
- self.attachment_count = RPCExecute('model', 'ir.attachment',
- 'search_count', [
- ('resource', '=',
- '%s,%s' % (self.model_name, self.id)),
- ], context=self.get_context())
+ self.resources = RPCExecute(
+ 'model', self.model_name, 'resources', self.id,
+ context=self.get_context())
except RPCException:
- return 0
- return self.attachment_count
-
- def get_unread_note(self, reload=False):
- if self.id < 0:
- return 0
- if self.unread_note < 0 or reload:
- try:
- self.unread_note = RPCExecute('model', 'ir.note',
- 'search_count', [
- ('resource', '=',
- '%s,%s' % (self.model_name, self.id)),
- ('unread', '=', True),
- ], context=self.get_context())
- except RPCException:
- return 0
- return self.unread_note
+ pass
+ return self.resources
def get_button_clicks(self, name):
if self.id < 0:
diff -r 71de92ba03b6 -r 65aff6f1a7e9
tryton/gui/window/view_form/screen/screen.py
--- a/tryton/gui/window/view_form/screen/screen.py Fri Mar 22 11:57:42
2019 +0100
+++ b/tryton/gui/window/view_form/screen/screen.py Fri Mar 22 12:16:36
2019 +0100
@@ -436,35 +436,18 @@
pos = 0
self.signal('record-message', (pos, len(self.group) + self.offset,
self.search_count, record and record.id))
- attachment_count = 0
- if record and record.attachment_count > 0:
- attachment_count = record.attachment_count
- self.signal('attachment-count', attachment_count)
- unread_note = 0
- if record and record.unread_note > 0:
- unread_note = record.unread_note
- self.signal('unread-note', unread_note)
- # update attachment-count after 1 second
- GLib.timeout_add(1000, self.update_attachment, record)
- GLib.timeout_add(1000, self.update_note, record)
+ self.signal('resources', record.resources if record else None)
+ # update resources after 1 second
+ GLib.timeout_add(1000, self._update_resources, record)
return True
current_record = property(__get_current_record, __set_current_record)
- def update_attachment(self, record):
- if record != self.current_record:
- return False
- if record and self.signal_connected('attachment-count'):
- attachment_count = record.get_attachment_count()
- self.signal('attachment-count', attachment_count)
- return False
-
- def update_note(self, record):
- if record != self.current_record:
- return False
- if record and self.signal_connected('unread-note'):
- unread_note = record.get_unread_note()
- self.signal('unread-note', unread_note)
+ def _update_resources(self, record):
+ if (record
+ and record == self.current_record
+ and self.signal_connected('resources')):
+ self.signal('resources', record.get_resources())
return False
def destroy(self):