diff --git a/CHANGELOG b/CHANGELOG index 2455698f1f..27d5dfb6a5 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +* Add window manager for: + - replace current window + - prevent simmilar window * Merge and review toolbars in form and board * Drop support of Python 2.5 * Use the same design for Many2Many than One2Many diff --git a/tryton/gui/main.py b/tryton/gui/main.py index d182dc5c9f..ae91b24d6e 100644 --- a/tryton/gui/main.py +++ b/tryton/gui/main.py @@ -1106,7 +1106,14 @@ class Main(object): gtk.gdk.WINDOW_STATE_MAXIMIZED) return False - def win_add(self, page): + def win_add(self, page, hide_current=False, allow_similar=True): + if not allow_similar: + for other_page in self.pages: + if page == other_page: + page_num = self.notebook.page_num(other_page.widget) + other_page.widget.props.visible = True + self.notebook.set_current_page(page_num) + return if page.model == 'ir.ui.menu' and not self.pane.get_child1(): screen = page.screen screen.screen_container.alternate_view = True @@ -1119,6 +1126,11 @@ class Main(object): self.sig_win_menu() previous_page_id = self.notebook.get_current_page() previous_widget = self.notebook.get_nth_page(previous_page_id) + if previous_widget and hide_current: + previous_widget.props.visible = False + page_id = previous_page_id + 1 + else: + page_id = -1 self.previous_pages[page] = previous_widget self.pages.append(page) hbox = gtk.HBox(spacing=3) @@ -1165,10 +1177,10 @@ class Main(object): hbox.set_size_request(120, -1) label_menu = gtk.Label(page.name) label_menu.set_alignment(0.0, 0.5) - self.notebook.append_page_menu(page.widget, hbox, label_menu) + self.notebook.insert_page_menu(page.widget, hbox, label_menu, page_id) if hasattr(self.notebook, 'set_tab_reorderable'): self.notebook.set_tab_reorderable(page.widget, True) - self.notebook.set_current_page(-1) + self.notebook.set_current_page(page_id) def _sig_remove_book(self, widget, page_widget): for page in self.pages: @@ -1213,6 +1225,9 @@ class Main(object): page.destroy() del page + current_widget = self.notebook.get_nth_page(next_page_id) + if current_widget: + current_widget.props.visible = True self.notebook.set_current_page(next_page_id) if not self.pages and self.menu_screen: self.menu_screen.current_view.set_cursor() diff --git a/tryton/gui/window/board.py b/tryton/gui/window/board.py index 862cdceaf6..038dfff433 100644 --- a/tryton/gui/window/board.py +++ b/tryton/gui/window/board.py @@ -53,6 +53,9 @@ class Board(SignalEvent, TabContent): self.board = ViewBoard(view['arch'], window, context=context) self.model = model + self.view_id = view_id + self.context = context + self.auto_refresh = auto_refresh if not name: self.name = self.board.name else: @@ -73,5 +76,16 @@ class Board(SignalEvent, TabContent): def sig_close(self): return True + def __eq__(self, value): + if not value: + return False + if not isinstance(value, Board): + return False + return (self.model == value.model + and self.view_id == value.view_id + and self.context == value.context + and self.name == value.name + and self.auto_refresh == value.auto_refresh) + def sig_win_close(self, widget): Main.get_main().sig_win_close(widget) diff --git a/tryton/gui/window/form.py b/tryton/gui/window/form.py index 603354aa31..e86bba6976 100644 --- a/tryton/gui/window/form.py +++ b/tryton/gui/window/form.py @@ -10,6 +10,7 @@ from tryton.gui.window.view_form.screen import Screen from tryton.action import Action from tryton.config import CONFIG from tryton.gui import Main +from tryton.gui.window import Window from tryton.gui.window.win_search import WinSearch from tryton.gui.window.preference import Preference from tryton.gui.window.win_export import WinExport @@ -108,8 +109,12 @@ class Form(SignalEvent, TabContent): self.model = model self.window = window + self.res_id = res_id self.domain = domain + self.mode = mode self.context = context + self.auto_refresh = auto_refresh + self.view_ids = view_ids self.screen = Screen(self.model, self.window, mode=mode, context=self.context, view_ids=view_ids, domain=domain, @@ -163,6 +168,23 @@ class Form(SignalEvent, TabContent): def widget_get(self): return self.screen.widget + def __eq__(self, value): + if not value: + return False + if not isinstance(value, Form): + return False + return (self.model == value.model + and self.window == value.window + and self.res_id == value.res_id + and self.domain == value.domain + and self.mode == value.mode + and self.view_ids == value.view_ids + and self.context == value.context + and self.name == value.name + and self.screen.limit == value.screen.limit + and self.auto_refresh == value.auto_refresh + and self.screen.search_value == value.screen.search_value) + def sig_goto(self, widget=None): if not self.modified_save(): return @@ -585,7 +607,14 @@ class Form(SignalEvent, TabContent): return menu def _popup_menu_selected(self, menuitem, togglebutton, action, keyword): - self._action(action, keyword) + event = gtk.get_current_event() + if event.button == 1: + hide = not bool(event.state + & (gtk.gdk.CONTROL_MASK | gtk.gdk.MOD1_MASK)) + else: + hide = False + with Window(hide_current=hide): + self._action(action, keyword) togglebutton.props.active = False def _popup_menu_hide(self, menuitem, togglebutton): diff --git a/tryton/gui/window/view_form/screen/screen.py b/tryton/gui/window/view_form/screen/screen.py index c23fbb5e08..08e75a920e 100644 --- a/tryton/gui/window/view_form/screen/screen.py +++ b/tryton/gui/window/view_form/screen/screen.py @@ -46,7 +46,7 @@ class Screen(SignalEvent): self.model_name = model_name self.context = context self.views = [] - self.view_ids = view_ids + self.view_ids = view_ids[:] self.parent = None self.parent_name = None self.exclude_field = exclude_field @@ -69,8 +69,8 @@ class Screen(SignalEvent): if mode: self.view_to_load = mode[1:] view_id = False - if view_ids: - view_id = view_ids.pop(0) + if self.view_ids: + view_id = self.view_ids.pop(0) view = self.add_view_id(view_id, mode[0]) self.screen_container.set(view.widget) self.display() diff --git a/tryton/gui/window/view_form/view/list.py b/tryton/gui/window/view_form/view/list.py index 07b4c5fabd..9e4617c63a 100644 --- a/tryton/gui/window/view_form/view/list.py +++ b/tryton/gui/window/view_form/view/list.py @@ -15,6 +15,7 @@ from tryton.config import CONFIG from tryton.common.cellrendererbutton import CellRendererButton from tryton.common.cellrenderertoggle import CellRendererToggle from tryton.pyson import PYSONEncoder +from tryton.gui.window import Window from tryton.exceptions import TrytonServerError import os @@ -566,6 +567,11 @@ class ViewList(ParserView): item.show() menu.append(item) menu.popup(None, None, None, event.button, event.time) + elif event.button == 2: + event.button = 1 + event.state |= gtk.gdk.MOD1_MASK + treeview.emit('button-press-event', event) + return True return False def click_and_relate(self, action, value, path): @@ -648,11 +654,17 @@ class ViewList(ParserView): def __sig_switch(self, treeview, path, column): if column._type == 'button': return - if not self.screen.row_activate(): - if treeview.row_expanded(path): - treeview.collapse_row(path) - else: - treeview.expand_row(path, False) + allow_similar = False + event = gtk.get_current_event() + if (event.state & gtk.gdk.MOD1_MASK + or event.state & gtk.gdk.SHIFT_MASK): + allow_similar = True + with Window(allow_similar=allow_similar): + if not self.screen.row_activate(): + if treeview.row_expanded(path): + treeview.collapse_row(path) + else: + treeview.expand_row(path, False) def __select_changed(self, tree_sel): previous_record = self.screen.current_record diff --git a/tryton/gui/window/window.py b/tryton/gui/window/window.py index f95863b576..07f0f22ae7 100644 --- a/tryton/gui/window/window.py +++ b/tryton/gui/window/window.py @@ -6,6 +6,20 @@ from preference import * class Window(object): + hide_current = False + allow_similar = True + + def __init__(self, hide_current=False, allow_similar=True): + Window.hide_current = hide_current + Window.allow_similar = allow_similar + + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + Window.hide_current = False + Window.allow_similar = True + @staticmethod def create(view_ids, model, res_id=False, domain=None, window=None, context=None, mode=None, name=False, limit=None, @@ -25,7 +39,8 @@ class Window(object): win = Board(model, window, view_ids and view_ids[0] or None, context=context, name=name, auto_refresh=auto_refresh) win.icon = icon - Main.get_main().win_add(win) + Main.get_main().win_add(win, hide_current=Window.hide_current, + allow_similar=Window.allow_similar) @staticmethod def create_wizard(action, datas, parent, state='init', direct_print=False, @@ -35,6 +50,6 @@ class Window(object): from wizard import Wizard win = Wizard(parent, name=name) win.icon = icon - Main.get_main().win_add(win) + Main.get_main().win_add(win, Window.hide_current) win.run(action, datas, state=state, direct_print=direct_print, email_print=email_print, email=email, context=context)