Add Note
issue4669 review9171002
This commit is contained in:
1 parent
9f16e1d1bc
commit
29c5ee48c6
9 files changed
+123
-4
No files matched your search
@@ -1,3 +1,4 @@
|
||||
* Add Note
|
||||
* Manage view_ids on tree view
|
||||
* Use Apple key for copy/past of list
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ from tryton.gui.window.view_form.screen import Screen
|
||||
from tryton.action import Action
|
||||
from tryton.gui.window import Window
|
||||
from tryton.gui.window.attachment import Attachment
|
||||
from tryton.gui.window.note import Note
|
||||
|
||||
_ = gettext.gettext
|
||||
|
||||
@@ -55,6 +56,9 @@ def populate(menu, model, record, title='', field=None):
|
||||
def attachment(menuitem):
|
||||
Attachment(load(record), None)
|
||||
|
||||
def note(menuitem):
|
||||
Note(load(record), None)
|
||||
|
||||
def edit(menuitem):
|
||||
with Window(hide_current=True, allow_similar=True):
|
||||
Window.create(field.attrs.get('view_ids'), model, id_(record),
|
||||
@@ -82,6 +86,10 @@ def populate(menu, model, record, title='', field=None):
|
||||
attachment_item.set_label(_('Attachments...'))
|
||||
action_menu.append(attachment_item)
|
||||
attachment_item.connect('activate', attachment)
|
||||
note_item = gtk.ImageMenuItem('tryton-note')
|
||||
note_item.set_label(_('Notes...'))
|
||||
action_menu.append(note_item)
|
||||
note_item.connect('activate', note)
|
||||
|
||||
def set_toolbar(toolbar):
|
||||
try:
|
||||
|
||||
@@ -21,10 +21,11 @@ class Attachment(WinForm):
|
||||
('resource', '=', self.resource),
|
||||
], mode=['tree', 'form'], context=context,
|
||||
exclude_field='resource')
|
||||
screen.search_filter()
|
||||
screen.parent = record
|
||||
super(Attachment, self).__init__(screen, self.callback,
|
||||
view_type='tree')
|
||||
screen.search_filter()
|
||||
# Set parent after to be allowed to call search_filter
|
||||
screen.parent = record
|
||||
|
||||
def destroy(self):
|
||||
self.prev_view.save_width_height()
|
||||
|
||||
@@ -11,6 +11,7 @@ from tryton.gui.window import Window
|
||||
from tryton.gui.window.win_export import WinExport
|
||||
from tryton.gui.window.win_import import WinImport
|
||||
from tryton.gui.window.attachment import Attachment
|
||||
from tryton.gui.window.note import Note
|
||||
from tryton.gui.window.revision import Revision
|
||||
from tryton.signal_event import SignalEvent
|
||||
from tryton.common import message, sur, sur_3b, timezoned_date
|
||||
@@ -44,6 +45,8 @@ class Form(SignalEvent, TabContent):
|
||||
(None,) * 5,
|
||||
('attach', 'tryton-attachment', _('Attachment(0)'),
|
||||
_('Add an attachment to the record'), 'sig_attach'),
|
||||
('note', 'tryton-note', _('Note(0)'),
|
||||
_('Add a note to the record'), 'sig_note'),
|
||||
]
|
||||
menu_def = [
|
||||
(_('_New'), 'tryton-new', 'sig_new', '<tryton>/Form/New'),
|
||||
@@ -69,6 +72,7 @@ class Form(SignalEvent, TabContent):
|
||||
(None,) * 4,
|
||||
(_('A_ttachments...'), 'tryton-attachment', 'sig_attach',
|
||||
'<tryton>/Form/Attachments'),
|
||||
(_('_Notes...'), 'tryton-note', 'sig_note', '<tryton>/Form/Notes'),
|
||||
(_('_Actions...'), 'tryton-executable', 'sig_action',
|
||||
'<tryton>/Form/Actions'),
|
||||
(_('_Relate...'), 'tryton-go-jump', 'sig_relate',
|
||||
@@ -143,6 +147,7 @@ class Form(SignalEvent, TabContent):
|
||||
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)
|
||||
|
||||
if res_id not in (None, False):
|
||||
if isinstance(res_id, (int, long)):
|
||||
@@ -211,6 +216,35 @@ class Form(SignalEvent, TabContent):
|
||||
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))
|
||||
|
||||
def update_unread_note(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)
|
||||
|
||||
def _unread_note(self, widget, signal_data):
|
||||
label = _('Note(%d)') % signal_data
|
||||
self.buttons['note'].set_label(label)
|
||||
if signal_data:
|
||||
self.buttons['note'].set_stock_id('tryton-note-hi')
|
||||
else:
|
||||
self.buttons['note'].set_stock_id('tryton-note')
|
||||
record = self.screen.current_record
|
||||
if not record or record.id < 0:
|
||||
sensitive = False
|
||||
else:
|
||||
sensitive = True
|
||||
self.buttons['note'].props.sensitive = sensitive
|
||||
|
||||
def sig_switch(self, widget=None):
|
||||
if not self.modified_save():
|
||||
return
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
|
||||
from tryton.gui.window.view_form.screen import Screen
|
||||
from tryton.gui.window.win_form import WinForm
|
||||
|
||||
|
||||
class Note(WinForm):
|
||||
"Note window"
|
||||
|
||||
def __init__(self, record, callback=None):
|
||||
self.resource = '%s,%s' % (record.model_name, record.id)
|
||||
self.note_callback = callback
|
||||
context = record.context_get()
|
||||
context['resource'] = self.resource
|
||||
screen = Screen('ir.note', domain=[
|
||||
('resource', '=', self.resource),
|
||||
], mode=['tree', 'form'], context=context,
|
||||
exclude_field='resource')
|
||||
super(Note, self).__init__(screen, self.callback, view_type='tree')
|
||||
screen.search_filter()
|
||||
# Set parent after to be allowed to call search_filter
|
||||
screen.parent = record
|
||||
|
||||
def destroy(self):
|
||||
self.prev_view.save_width_height()
|
||||
super(Note, self).destroy()
|
||||
|
||||
def callback(self, result):
|
||||
if result:
|
||||
resource = self.screen.group.fields['resource']
|
||||
unread = self.screen.group.fields['unread']
|
||||
for record in self.screen.group:
|
||||
if record.loaded:
|
||||
resource.set_client(record, self.resource)
|
||||
if 'unread' not in record.modified_fields:
|
||||
unread.set_client(record, False)
|
||||
self.screen.group.save()
|
||||
if self.note_callback:
|
||||
self.note_callback()
|
||||
@@ -31,6 +31,7 @@ class Record(SignalEvent):
|
||||
self.modified_fields = {}
|
||||
self._timestamp = None
|
||||
self.attachment_count = -1
|
||||
self.unread_note = -1
|
||||
self.next = {} # Used in Group list
|
||||
self.value = {}
|
||||
self.autocompletion = {}
|
||||
@@ -616,6 +617,21 @@ class Record(SignalEvent):
|
||||
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.context_get())
|
||||
except RPCException:
|
||||
return 0
|
||||
return self.unread_note
|
||||
|
||||
def destroy(self):
|
||||
for v in self.value.itervalues():
|
||||
if hasattr(v, 'destroy'):
|
||||
|
||||
@@ -324,8 +324,13 @@ class Screen(SignalEvent):
|
||||
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
|
||||
gobject.timeout_add(1000, self.update_attachment, record)
|
||||
gobject.timeout_add(1000, self.update_note, record)
|
||||
return True
|
||||
|
||||
current_record = property(__get_current_record, __set_current_record)
|
||||
@@ -338,6 +343,14 @@ class Screen(SignalEvent):
|
||||
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)
|
||||
return False
|
||||
|
||||
def destroy(self):
|
||||
self.group.destroy()
|
||||
for view in self.views:
|
||||
|
||||
@@ -289,7 +289,9 @@ class ViewTree(View):
|
||||
self.parse(xml)
|
||||
|
||||
self.treeview.set_property('rules-hint', True)
|
||||
self.treeview.set_fixed_height_mode(True)
|
||||
self.treeview.set_fixed_height_mode(
|
||||
all(c.get_sizing() == gtk.TREE_VIEW_COLUMN_FIXED
|
||||
for c in self.treeview.get_columns()))
|
||||
self.treeview.connect('button-press-event', self.__button_press)
|
||||
self.treeview.connect('key-press-event', self.on_keypress)
|
||||
self.treeview.connect_after('row-activated', self.__sig_switch)
|
||||
@@ -520,7 +522,8 @@ class ViewTree(View):
|
||||
expand = attributes.get('expand', False)
|
||||
column.set_expand(expand)
|
||||
column.set_resizable(True)
|
||||
column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
|
||||
if field and field.attrs['type'] != 'text':
|
||||
column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
|
||||
|
||||
def get_column_widget(self, column):
|
||||
'Return the widget of the column'
|
||||
|
||||
@@ -178,6 +178,7 @@ class GenericText(Cell):
|
||||
if not isinstance(self.renderer, CellRendererBinary):
|
||||
self.renderer.connect_after('editing-started', send_keys,
|
||||
view.treeview)
|
||||
self.renderer.set_property('yalign', 0)
|
||||
self.view = view
|
||||
|
||||
@property
|
||||
@@ -833,6 +834,7 @@ class ProgressBar(object):
|
||||
orientation = self.orientations.get(self.attrs.get('orientation',
|
||||
'left_to_right'), gtk.PROGRESS_LEFT_TO_RIGHT)
|
||||
self.renderer.set_property('orientation', orientation)
|
||||
self.renderer.set_property('yalign', 0)
|
||||
|
||||
@realized
|
||||
@CellCache.cache
|
||||
@@ -872,6 +874,7 @@ class Button(object):
|
||||
self.view = view
|
||||
|
||||
self.renderer.connect('clicked', self.button_clicked)
|
||||
self.renderer.set_property('yalign', 0)
|
||||
|
||||
@realized
|
||||
@CellCache.cache
|
||||
|
||||
Reference in new issue
Block a user