def _add_actions(self, uimanager): """ Set up menu items. Here we override parent function that adds menu items. If we did not override, all the items would be placed directly in Tools, not in Edit. """ def get_actions(obj): import inspect return inspect.getmembers(obj.__class__, lambda m: isinstance(m, ActionMethod)) actions = get_actions(self) if actions: self._uimanager = uimanager action_group = get_gtk_actiongroup(self) uimanager.insert_action_group(action_group, 0) xml = ''' <ui> <menubar name='menubar'> <menu action='edit_menu'> <menuitem action='copy_rich'/> </menu> </menubar> </ui> ''' self._uimanager.add_ui_from_string(xml)
def __init__(self, plugin, window): '''Constructor @param plugin: the plugin object to which this extension belongs @param window: the C{gtk.Window} being extended ''' ObjectExtension.__init__(self, plugin, window) self.window = window if hasattr(window, 'ui') and hasattr( window.ui, 'uistate') and window.ui.uistate: # XXX self.uistate = window.ui.uistate[plugin.config_key] else: self.uistate = None if hasattr(self, 'uimanager_xml'): actiongroup = get_gtk_actiongroup(self) if hasattr(self, 'uimanager_menu_labels'): actiongroup.add_actions( sorted((k, None, v) for k, v in self.uimanager_menu_labels.items())) self.window.uimanager.insert_action_group(actiongroup, 0) self._uimanager_id = self.window.uimanager.add_ui_from_string( self.uimanager_xml) self.connectto(window, 'destroy')
def _add_actions(self, uimanager): actions = get_actions(self) if actions: self._uimanager = uimanager actiongroup = get_gtk_actiongroup(self) uimanager.insert_action_group(actiongroup, 0) self._uimanager_ids = [] for name, action in actions: xml = self._uimanager_xml(action, actiongroup, 'tools') if xml is not None: self._uimanager_ids.append( uimanager.add_ui_from_string(xml))
def populate_menu_with_actions(self, scope, menu): assert scope == PAGE_ACTIONS uimanager = Gtk.UIManager() group = get_gtk_actiongroup(self) uimanager.insert_action_group(group, 0) xml = _get_xml_for_menu(scope + '_popup') uimanager.add_ui_from_string(xml) tmp_menu = uimanager.get_widget('/' + scope + '_popup') assert isinstance(tmp_menu, Gtk.Menu) for item in tmp_menu.get_children(): item.reparent(menu)
def __init__(self, plugin, window): ObjectExtension.__init__(self, plugin, window) self.window = window if hasattr(window, 'ui') and hasattr(window.ui, 'uistate') and window.ui.uistate: # XXX self.uistate = window.ui.uistate[plugin.config_key] else: self.uistate = None if hasattr(self, 'uimanager_xml'): # XXX TODO move uimanager to window actiongroup = get_gtk_actiongroup(self) self.window.ui.uimanager.insert_action_group(actiongroup, 0) self._uimanager_id = self.window.ui.uimanager.add_ui_from_string(self.uimanager_xml) self.connectto(window, 'destroy')
def __init__(self, widget, notebook, page, navigation): '''Constructor @param widget: owning gtk widget or C{None}, only used to determine parent window for dialogs @param notebook: L{Notebook} object for actions to act on @param page: L{Page} object that reflects the _default_ page for actions to act on. @param navigation: a L{NavigationModel} ''' self.widget = widget self.notebook = notebook self.page = page self.navigation = navigation self.notebook.properties.connect('changed', self.on_notebook_properties_changed) group = get_gtk_actiongroup(self) action = self.actiongroup.get_action('show_debug_log') action.set_sensitive(zim.debug_log_file is not None)
def __init__(self, notebook, page=None, fullscreen=False, geometry=None): '''Constructor @param notebook: the L{Notebook} to show in this window @param page: a C{Path} object to open @param fullscreen: if C{True} the window is shown fullscreen, if C{None} the previous state is restored @param geometry: the window geometry as string in format "C{WxH+X+Y}", if C{None} the previous state is restored ''' Window.__init__(self) self.notebook = notebook self.page = None # will be set later by open_page self.navigation = NavigationModel(self) self.hideonclose = False self.preferences = ConfigManager.preferences['GtkInterface'] self.preferences.define( toggle_on_ctrlspace=Boolean(False), remove_links_on_delete=Boolean(True), always_use_last_cursor_pos=Boolean(True), ) self.preferences.connect('changed', self.do_preferences_changed) self.maximized = False self.isfullscreen = False self.connect_after('window-state-event', self.__class__.on_window_state_event) # Hidden setting to force the gtk bell off. Otherwise it # can bell every time you reach the begin or end of the text # buffer. Especially specific gtk version on windows. # See bug lp:546920 self.preferences.setdefault('gtk_bell', False) if not self.preferences['gtk_bell']: Gtk.rc_parse_string('gtk-error-bell = 0') self._block_toggle_panes = False self._sidepane_autoclose = False self._switch_focus_accelgroup = None # Catching this signal prevents the window to actually be destroyed # when the user tries to close it. The action for close should either # hide or destroy the window. def do_delete_event(*a): logger.debug('Action: close (delete-event)') self.close() return True # Do not destroy - let close() handle it self.connect('delete-event', do_delete_event) # setup uistate self.uistate = notebook.state['MainWindow'] self.uistate.setdefault('windowpos', None, check=value_is_coord) self.uistate.setdefault('windowsize', (600, 450), check=value_is_coord) self.uistate.setdefault('windowmaximized', False) self.uistate.setdefault('active_tabs', None, tuple) self.uistate.setdefault('show_toolbar', True) self.uistate.setdefault('show_statusbar', True) self.uistate.setdefault('readonly', False) self.history = History(notebook, notebook.state) # init uimanager self.uimanager = Gtk.UIManager() self.uimanager.add_ui_from_string(''' <ui> <menubar name="menubar"> </menubar> <toolbar name="toolbar"> </toolbar> </ui> ''') # setup menubar and toolbar self.add_accel_group(self.uimanager.get_accel_group()) self.menubar = self.uimanager.get_widget('/menubar') self.toolbar = self.uimanager.get_widget('/toolbar') self.toolbar.connect('popup-context-menu', self.do_toolbar_popup) self.add_bar(self.menubar) self.add_bar(self.toolbar) self.pageview = PageView(self.notebook, self.navigation) self.connect_object('readonly-changed', PageView.set_readonly, self.pageview) self.pageview.connect_after('textstyle-changed', self.on_textview_textstyle_changed) self.pageview.textview.connect_after('toggle-overwrite', self.on_textview_toggle_overwrite) self.pageview.textview.connect('link-enter', self.on_link_enter) self.pageview.textview.connect('link-leave', self.on_link_leave) self.add(self.pageview) # create statusbar self.statusbar = Gtk.Statusbar() self.statusbar.push(0, '<page>') self.add_bar(self.statusbar, start=False) self.statusbar.set_property('margin', 0) self.statusbar.set_property('spacing', 0) def statusbar_element(string, size): frame = Gtk.Frame() frame.set_shadow_type(Gtk.ShadowType.NONE) self.statusbar.pack_end(frame, False, True, 0) label = Gtk.Label(label=string) label.set_size_request(size, 10) label.set_alignment(0.1, 0.5) frame.add(label) return label # specify statusbar elements right-to-left self.statusbar_insert_label = statusbar_element('INS', 60) self.statusbar_style_label = statusbar_element('<style>', 110) # and build the widget for backlinks self.statusbar_backlinks_button = \ BackLinksMenuButton(self.notebook, self.open_page, status_bar_style=True) frame = Gtk.Frame() frame.set_shadow_type(Gtk.ShadowType.NONE) self.statusbar.pack_end(Gtk.Separator(), False, True, 0) self.statusbar.pack_end(frame, False, True, 0) self.statusbar.pack_end(Gtk.Separator(), False, True, 0) frame.add(self.statusbar_backlinks_button) self.move_bottom_minimized_tabs_to_statusbar(self.statusbar) self.do_preferences_changed() self._geometry_set = False self._set_fullscreen = False if geometry: try: self.parse_geometry(geometry) self._geometry_set = True except: logger.exception('Parsing geometry string failed:') elif fullscreen: self._set_fullscreen = True # Init mouse settings self.preferences.setdefault('mouse_nav_button_back', 8) self.preferences.setdefault('mouse_nav_button_forw', 9) # Finish uimanager self._uiactions = UIActions(self, self.notebook, self.page, self.navigation) group = get_gtk_actiongroup(self._uiactions) self.uimanager.insert_action_group(group, 0) group = get_gtk_actiongroup(self.pageview) self.uimanager.insert_action_group(group, 0) group = get_gtk_actiongroup(self) # don't use mnemonics on macOS to allow alt-<letter> shortcuts global MENU_ACTIONS if sys.platform == "darwin": MENU_ACTIONS = tuple( (t[0], t[1], t[2].replace('_', '')) for t in MENU_ACTIONS) group.add_actions(MENU_ACTIONS) self.uimanager.insert_action_group(group, 0) group.get_action('open_page_back').set_sensitive(False) group.get_action('open_page_forward').set_sensitive(False) fname = 'menubar.xml' self.uimanager.add_ui_from_string(data_file(fname).read()) self.pageview.emit( 'ui-init') # Needs to trigger after default menus are build # Do this last, else menu items show up in wrong place self._customtools = CustomToolManagerUI(self.uimanager, self.pageview) self._insertedobjects = InsertedObjectUI(self.uimanager, self.pageview) # XXX: would like to do this in PageView itself, but need access to uimanager # Setup notebook signals notebook.connect('page-info-changed', self.do_page_info_changed) def move_away(o, path): # Try several options to get awaay actions = [ self.open_page_back, self.open_page_parent, self.open_page_home ] while (path == self.page or self.page.ischild(path)) and actions: action = actions.pop(0) action() notebook.connect('deleted-page', move_away) # after action def follow(o, path, newpath): if path == self.page: self.open_page(newpath) elif self.page.ischild(path): newpath = newpath + self.page.relname(path) self.open_page(newpath) else: pass notebook.connect('moved-page', follow) # after action # init page page = page or self.history.get_current() if page: page = notebook.get_page(page) self.open_page(page) else: self.open_page_home() self.pageview.grab_focus()
def __init__(self, notebook, page, navigation, editable=True): Window.__init__(self) self.navigation = navigation self.notebook = notebook headerbar = Gtk.HeaderBar() headerbar.set_show_close_button(True) action = self.toggle_editable button = action.create_icon_button() headerbar.pack_end(button) self.set_titlebar(headerbar) self.set_title(page.name) #if ui.notebook.icon: # try: # self.set_icon_from_file(ui.notebook.icon) # except GObject.GError: # logger.exception('Could not load icon %s', ui.notebook.icon) self.notebook = notebook self.page = notebook.get_page(page) self.uistate = notebook.state['PageWindow'] self.uistate.setdefault('windowsize', (500, 400), check=value_is_coord) w, h = self.uistate['windowsize'] self.set_default_size(w, h) self.pageview = PageView(notebook, navigation) self.connect_object('readonly-changed', PageView.set_readonly, self.pageview) self.pageview.set_page(self.page) self.add(self.pageview) # Need UIManager to make accelerators work self.uimanager = Gtk.UIManager() self.add_accel_group(self.uimanager.get_accel_group()) group = get_gtk_actiongroup(self.pageview) self.uimanager.insert_action_group(group, 0) fname = 'pagewindow_ui.xml' self.uimanager.add_ui_from_string(data_file(fname).read()) # Close window when page is moved or deleted def on_notebook_change(o, path, *a): if path == self.page: logger.debug('Close PageWindow for %s (page is gone)', self.page) self._save_uistate() self.destroy() notebook.connect('deleted-page', on_notebook_change) notebook.connect('moved-page', on_notebook_change) # setup state if self.notebook.readonly: self.toggle_editable(False) self.toggle_editable.set_sensitive(False) else: self.toggle_editable(editable) # on close window def do_delete_event(*a): logger.debug('Close PageWindow for %s', self.page) self._save_uistate() self.connect('delete-event', do_delete_event)
def on_notebook_properties_changed(self, propeties): group = get_gtk_actiongroup(self) action = self.actiongroup.get_action('open_document_root') action.set_sensitive(self.notebook.document_root is not None)
def _add_actions(self, uimanager): """ Set up menu items. Here we override parent function that adds menu items. If we did not override, all the items would be placed directly in Tools, not in Tools / Google Tasks. """ def get_actions(obj): import inspect return inspect.getmembers(obj.__class__, lambda m: isinstance(m, ActionMethod)) actions = get_actions(self) if actions: self._uimanager = uimanager action_group = get_gtk_actiongroup(self) uimanager.insert_action_group(action_group, 0) # Set up menu items. Here we change parent function behaviour. permissions = [] if GoogleCalendarApi.service_obtainable(): permissions.append("<menuitem action='permission_readonly'/>") if GoogleCalendarApi.service_obtainable(write_access=True): permissions.append("<menuitem action='permission_write'/>") if permissions: permissions = ["<separator/>"] + permissions lists = [] for title in self.controller.cache.lists: # Apostrophe suppressed; I was not able to reliably slash it, getting a strange error: # gi.repository.GLib.GError: g-markup-error-quark: Error on line 12 char 82: # Odd character “l”, expected a “=” after attribute name “s” of element “menuitem” (2) el = "change_list_{}".format(title.replace(r"'", r"")) lists.append(f"<menuitem action='{el}'/>") action_group.add_actions(( (el, None, _(f'_{title}'), None, None, self.controller.change_task_list_closure(title)),)) xml = ''' <ui> <menubar name='menubar'> <menu action='tools_menu'> <menu action='googletasks_menu'> <menuitem action='import_tasks'/> <menuitem action='sync_status'/> <menuitem action='send_as_task'/> <menuitem action='add_new_task'/> <menuitem action='import_history'/> ''' + "\n".join(permissions) + ''' <menu action='choose_task_list'> ''' + "\n".join(lists) + ''' <separator/> <menuitem action='refresh_task_lists'/> </menu> </menu> </menu> </menubar> </ui> ''' # Add menu actions seen in XML action_group.add_actions((('googletasks_menu', None, _('_Google tasks')),)) action_group.add_actions((('choose_task_list', None, _('_Choose task list')),)) self._uimanager.add_ui_from_string(xml)
def __init__(self, notebook, page, anchor, navigation, editable=True): Window.__init__(self) self._block_toggle_panes = False self._sidepane_autoclose = False self.navigation = navigation self.notebook = notebook self.page = notebook.get_page(page) self._headerbar = Gtk.HeaderBar() self._headerbar.set_show_close_button(True) self.set_titlebar(self._headerbar) self._init_fullscreen_headerbar() self._populate_headerbars() if self.notebook.readonly or self.page.readonly: title = page.name + ' [' + _( 'readonly') + ']' # T: page status for title bar else: title = page.name self.set_title(title) #if ui.notebook.icon: # try: # self.set_icon_from_file(ui.notebook.icon) # except (GObject.GError, GLib.Error): # logger.exception('Could not load icon %s', ui.notebook.icon) self.uistate = notebook.state['PageWindow'] self.uistate.setdefault('windowsize', (500, 400), check=value_is_coord) w, h = self.uistate['windowsize'] self.set_default_size(w, h) self.pageview = PageView(notebook, navigation) self.connect_object('readonly-changed', PageView.set_readonly, self.pageview) self.pageview.set_page(self.page) self.add(self.pageview) # Need UIManager & menubar to make accelerators and plugin actions work self.uimanager = Gtk.UIManager() self.add_accel_group(self.uimanager.get_accel_group()) group = get_gtk_actiongroup(self) group.add_actions(MENU_ACTIONS) self.uimanager.insert_action_group(group, 0) group = get_gtk_actiongroup(self.pageview) self.uimanager.insert_action_group(group, 0) self._uiactions = UIActions(self, self.notebook, self.page, self.navigation) group = get_gtk_actiongroup(self._uiactions) self.uimanager.insert_action_group(group, 0) fname = 'pagewindow_ui.xml' self.uimanager.add_ui_from_string(data_file(fname).read()) self.menubar = self.uimanager.get_widget('/menubar') self.add_bar(self.menubar, position=TOP) # Close window when page is moved or deleted def on_notebook_change(o, path, *a): if path == self.page or self.page.ischild(path): logger.debug('Close PageWindow for %s (page is gone)', self.page) self.save_uistate() self.destroy() notebook.connect('deleted-page', on_notebook_change) notebook.connect('moved-page', on_notebook_change) # setup state self.setup_toggle_editable_state(editable) # on close window def do_delete_event(*a): logger.debug('Close PageWindow for %s', self.page) self.save_uistate() self.connect('delete-event', do_delete_event) PluginManager.register_new_extendable(self.pageview) initialize_actiongroup(self, 'win') if anchor: self.pageview.navigate_to_anchor(anchor) self.pageview.grab_focus()
def __init__(self, notebook, page=None, fullscreen=False, geometry=None): '''Constructor @param notebook: the L{Notebook} to show in this window @param page: a C{Path} object to open @param fullscreen: if C{True} the window is shown fullscreen, if C{None} the previous state is restored @param geometry: the window geometry as string in format "C{WxH+X+Y}", if C{None} the previous state is restored ''' Window.__init__(self) self.notebook = notebook self.page = None # will be set later by open_page self.navigation = NavigationModel(self) self.hideonclose = False self.preferences = ConfigManager.preferences['GtkInterface'] self.preferences.define( toggle_on_ctrlspace=Boolean(False), always_use_last_cursor_pos=Boolean(True), ) self.preferences.connect('changed', self.do_preferences_changed) self.maximized = False self.isfullscreen = False self._init_fullscreen_headerbar() self.connect_after('window-state-event', self.__class__.on_window_state_event) # Hidden setting to force the gtk bell off. Otherwise it # can bell every time you reach the begin or end of the text # buffer. Especially specific gtk version on windows. # See bug lp:546920 self.preferences.setdefault('gtk_bell', False) if not self.preferences['gtk_bell']: Gtk.rc_parse_string('gtk-error-bell = 0') self._block_toggle_panes = False self._sidepane_autoclose = False self._switch_focus_accelgroup = None # Catching this signal prevents the window to actually be destroyed # when the user tries to close it. The action for close should either # hide or destroy the window. def do_delete_event(*a): logger.debug('Action: close (delete-event)') self.close() return True # Do not destroy - let close() handle it self.connect('delete-event', do_delete_event) # setup uistate self.uistate = notebook.state['MainWindow'] self.uistate.setdefault('windowpos', None, check=value_is_coord) self.uistate.setdefault('windowsize', (600, 450), check=value_is_coord) self.uistate.setdefault('windowmaximized', False) self.uistate.setdefault('active_tabs', None, tuple) self.uistate.setdefault('readonly', False) self.history = History(notebook, notebook.state) # init uimanager self.uimanager = Gtk.UIManager() self.uimanager.add_ui_from_string(''' <ui> <menubar name="menubar"> </menubar> </ui> ''') # setup menubar self.add_accel_group(self.uimanager.get_accel_group()) self.menubar = self.uimanager.get_widget('/menubar') self.add_bar(self.menubar, position=TOP) self.pageview = NotebookView(self.notebook, self.navigation) self.connect_object('readonly-changed', NotebookView.set_readonly, self.pageview) self.add(self.pageview) self.do_preferences_changed() self._geometry_set = False self._set_fullscreen = False if geometry: try: self.parse_geometry(geometry) self._geometry_set = True except: logger.exception('Parsing geometry string failed:') elif fullscreen: self._set_fullscreen = True # Init mouse settings self.preferences.setdefault('mouse_nav_button_back', 8) self.preferences.setdefault('mouse_nav_button_forw', 9) # Finish uimanager self._uiactions = UIActions(self, self.notebook, self.page, self.navigation) self.__zim_extension_objects__.append( self._uiactions) # HACK to make actions discoverable group = get_gtk_actiongroup(self._uiactions) self.uimanager.insert_action_group(group, 0) group = get_gtk_actiongroup(self.pageview) self.uimanager.insert_action_group(group, 0) group = get_gtk_actiongroup(self) group.add_actions(MENU_ACTIONS) self.uimanager.insert_action_group(group, 0) self.open_page_back.set_sensitive(False) self.open_page_forward.set_sensitive(False) fname = 'menubar.xml' self.uimanager.add_ui_from_string(data_file(fname).read()) # header Bar self._headerbar = Gtk.HeaderBar() self._headerbar.set_show_close_button(True) self.set_titlebar(self._headerbar) self._populate_headerbars() # Do this last, else menu items show up in wrong place self._customtools = CustomToolManagerUI(self.uimanager, self.pageview) self._insertedobjects = InsertedObjectUI(self.uimanager, self.pageview) # XXX: would like to do this in PageView itself, but need access to uimanager # Setup notebook signals notebook.connect('page-info-changed', self.do_page_info_changed) def move_away(o, path): # Try several options to get awaay actions = [ self.open_page_back, self.open_page_parent, self.open_page_home ] while (path == self.page or self.page.ischild(path)) and actions: action = actions.pop(0) action() notebook.connect('deleted-page', move_away) # after action def follow(o, path, newpath): if path == self.page: self.open_page(newpath) elif self.page.ischild(path): newpath = newpath + self.page.relname(path) self.open_page(newpath) else: pass notebook.connect('moved-page', follow) # after action # init page page = page or self.history.get_current() if page: page = notebook.get_page(page) self.open_page(page) else: self.open_page_home() PluginManager.register_new_extendable(self.pageview) initialize_actiongroup(self, 'win') self.pageview.grab_focus()