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
This commit is contained in:
Cédric Krier committed 2019-03-22 12:16:36 +01:00
1 parent 8a179f313b
commit aaf9e9e75c
6 files changed
+81 -113

No files matched your search

+3
View File
@@ -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
+23 -8
View File
@@ -111,10 +111,12 @@ class IconFactory:
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 @@ class IconFactory:
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 @@ class IconFactory:
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
+1 -1
View File
@@ -55,7 +55,7 @@ class ConfigManager(object):
'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/',
+38 -51
View File
@@ -53,9 +53,9 @@ class Form(SignalEvent, TabContent):
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 @@ class Form(SignalEvent, TabContent):
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 @@ class Form(SignalEvent, TabContent):
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 _unread_note(self, widget, signal_data):
label = _('Note(%d)') % signal_data
self.buttons['note'].set_label(label)
if signal_data:
# FIXME
icon = 'tryton-note'
else:
icon = 'tryton-note'
image = common.IconFactory.get_image(icon, Gtk.IconSize.LARGE_TOOLBAR)
image.show()
self.buttons['note'].set_icon_widget(image)
def update_resources(self, resources):
if not resources:
resources = {}
record = self.screen.current_record
if not record or record.id < 0:
sensitive = False
sensitive = record.id >= 0 if record else False
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:
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 @@ class Form(SignalEvent, TabContent):
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 @@ class Form(SignalEvent, TabContent):
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():
+8 -28
View File
@@ -28,8 +28,7 @@ class Record(SignalEvent):
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 @@ class Record(SignalEvent):
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:
+8 -25
View File
@@ -436,35 +436,18 @@ class Screen(SignalEvent):
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):