def register(self, name, bindings, callback, args=[], kwargs={}): """ Registers an action for a predefined keybinding name. @param name: Action name, defined in L{BINDING_INFO}. @param bindings: List of keybinding strings, as understood by L{gtk.accelerator_parse}. Only used if no bindings were loaded for this action. @param callback: Function callback @param args: List of arguments to pass to the callback @param kwargs: List of keyword arguments to pass to the callback. """ global BINDING_INFO assert name in BINDING_INFO, "'%s' isn't a valid keyboard action." % name # Load stored keybindings, or fall back to passed arguments keycodes = self._action_to_bindings[name] if keycodes == []: keycodes = [gtk.accelerator_parse(binding) for binding in bindings ] for keycode in keycodes: if keycode in self._binding_to_action.keys(): if self._binding_to_action[keycode] != name: log.warning(_('Keybinding for "%(action)s" overrides hotkey for another action.'), {"action": name}) log.warning('Binding %s overrides %r' % (keycode, self._binding_to_action[keycode])) else: self._binding_to_action[keycode] = name self._action_to_bindings[name].append(keycode) # Add gtk accelerator for labels in menu if len(self._action_to_bindings[name]) > 0: key, mod = self._action_to_bindings[name][0] gtk.accel_map_change_entry('<Actions>/mcomix-main/%s' % name, key, mod, True) self._action_to_callback[name] = (callback, args, kwargs)
def on_accel_edited(renderer, path, accel_key, accel_mods, hardware_keycode): iter = self.treestore.get_iter(path) col = column + 3 # accel cells start from 3 position old_accel = self.treestore.get(iter, col)[0] new_accel = gtk.accelerator_name(accel_key, accel_mods) self.treestore.set_value(iter, col, new_accel) action_name = self.treestore.get_value(iter, 1) affected_action = self.keymanager.edit_accel( action_name, new_accel, old_accel) # Find affected row and cell if affected_action == action_name: for idx in range(0, self.accel_column_num): if idx != column and self.treestore.get( iter, idx + 3)[0] == new_accel: self.treestore.set_value(iter, idx + 3, "") elif affected_action is not None: titer = self.action_treeiter_map[affected_action] for idx in range(0, self.accel_column_num): if self.treestore.get(titer, idx + 3)[0] == new_accel: self.treestore.set_value(titer, idx + 3, "") # updating gtk accelerator for label in menu if self.keymanager.get_bindings_for_action(action_name)[0] == ( accel_key, accel_mods): gtk.accel_map_change_entry( '<Actions>/mcomix-main/%s' % action_name, accel_key, accel_mods, True)
def _response(dlg, response): d.hide() if response == gtk.RESPONSE_ACCEPT: newaccel = e.get_text() action.set_accel(newaccel) actwrap.reset_markup() key, mod = gtk.accelerator_parse(newaccel) gtk.accel_map_change_entry(action.accel_path, key, mod, True) d.destroy()
def on_accel_cleared(self, renderer, path, *args): iter = self.actions.get_iter(path) name = self.actions.get_value(iter, 0) path = shortcuts.get_path_by_name(name) accel_map_change_entry(path, 0, 0, True) shortcuts.names_by_key.clear() self.actions.set_value(iter, 1, None) self.actions.set_value(iter, 4, WEIGHT_BOLD)
def on_accel_edited(self, renderer, path, accel_key, accel_mods, hardware_keycode): iter = self.actions.get_iter(path) accel = accelerator_name(accel_key, accel_mods) name = self.actions.get_value(iter, 0) path = shortcuts.get_path_by_name(name) accel_map_change_entry(path, accel_key, accel_mods, True) shortcuts.names_by_key.clear() self.actions.set_value(iter, 1, accel) self.actions.set_value(iter, 4, self.get_weight(path, accel_key, accel_mods))
def on_ok_click(self, event): self._get_dialog_widgets_values() self._set_options_from_widgets_values() # Reconfigure accel keys on menu for index, action in enumerate(self.action_list): accel_value = gtk.accelerator_parse(self.options[index]) accel_path = self.action_path + action gtk.accel_map_change_entry(accel_path, accel_value[0], accel_value[1], False) self._set_config_file() self.dialog.destroy()
def apply_changes_to_accel(self, iter): """ Recursively saves accelerators from tree to gtk.AccelMap. """ if not iter: return if self.__model[iter][2]: path = self.__model[iter][2] (key, mods) = self.__my_accel_map[path] gtk.accel_map_change_entry(path, key, mods, False) if self.__model.iter_has_child(iter): self.apply_changes_to_accel(self.__model.iter_children(iter)) self.apply_changes_to_accel(self.__model.iter_next(iter))
def on_accel_edited(self, renderer, path, accel_key, accel_mods, hardware_keycode): model = self.shortcuts_model iter_ = model.get_iter(path) action = model.get_value(iter_, 5) if not action: return if accel_key == gtk.keysyms.Delete and not accel_mods: accel_key = accel_mods = 0 model.set_value(iter_, 1, accel_key) model.set_value(iter_, 2, accel_mods) gtk.accel_map_change_entry(action.get_accel_path(), accel_key, accel_mods, True)
def _is_valid_accel(self, keyval, mod): accel_path = self.action_path + self.action_list[self.accel_index] old_accel = gtk.accel_map_lookup_entry(accel_path) if not gtk.accel_map_change_entry(accel_path, keyval, mod, False): msgdlg = gtk.MessageDialog(self.dialog, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, _('Shortcut %s is already in use') % gtk.accelerator_name(keyval, mod)) msgdlg.run() msgdlg.destroy() return False else: gtk.accel_map_change_entry(accel_path, old_accel[0], old_accel[1], True) return True
def register_gtk_accelerator(self, groupname, action, accel_string, accel_name): # menu item and shortcut try: import gtk except ImportError: return actiongroup = gtk.ActionGroup(groupname) accel_path = "<pycam>/%s" % accel_name action.set_accel_path(accel_path) # it is a bit pointless, but we allow an empty accel_string anyway ... if accel_string: key, mod = gtk.accelerator_parse(accel_string) gtk.accel_map_change_entry(accel_path, key, mod, True) actiongroup.add_action(action) self.core.get("gtk-uimanager").insert_action_group(actiongroup, pos=-1)
def add_action_with_accel(self, action, accel): # print "add_action_with_accel" _keyval = None _mods = None _name = action.get_name() _path = "/".join(['<Actions>', self.name, _name]) if accel is None: # print "accel is None" _sid = action.get_property('stock-id') if _sid != '': # print "sid = '%s'" % _sid _data = gtk.stock_lookup(_sid) if _data is not None and _data[3] != 0: # print "data: " + str(_data) _mods = _data[2] _keyval = _data[3] else: _k, _m = gtk.accelerator_parse(accel) if gtk.accelerator_valid(_k, _m): _keyval = _k _mods = _m if _keyval is not None: # print "calling gtk.accel_map_change_entry()" # print "Path: " + _path # print "Key: " + str(_keyval) # print "Mods: " + str(_mods) if not gtk.accel_map_change_entry(_path, _keyval, _mods, True): print "Failed to change accel_map for '%s'" % _path action.set_accel_path(_path) self.add_action(action)
def on_accel_cleared(renderer, path, *args): iter = self.treestore.get_iter(path) col = column + 3 accel = self.treestore.get(iter, col)[0] action_name = self.treestore.get_value(iter, 1) if accel != "": self.keymanager.clear_accel(action_name, accel) # updating gtk accelerator for label in menu if len(self.keymanager.get_bindings_for_action(action_name)) == 0: gtk.accel_map_change_entry('<Actions>/mcomix-main/%s' % action_name, 0, 0, True) else: key, mods = self.keymanager.get_bindings_for_action(action_name)[0] gtk.accel_map_change_entry('<Actions>/mcomix-main/%s' % action_name, key, mods, True) self.treestore.set_value(iter, col, "")
def add_ui_actions(self, ui_string, actions, name='Actions', action_type='normal', filename=None, instance=None): if instance is None: instance = self ag = self._get_action_group(name) to_add = [entry[0] for entry in actions] for action in ag.list_actions(): if action.get_name() in to_add: ag.remove_action(action) if action_type == 'normal': ag.add_actions(actions) elif action_type == 'toggle': ag.add_toggle_actions(actions) elif action_type == 'radio': ag.add_radio_actions(actions) else: raise ValueError(action_type) if filename is not None: ui_string = environ.get_resource_string('stoq', 'uixml', filename) ui_id = self.uimanager.add_ui_from_string(ui_string) self.action_permissions.update(self.common_action_permissions) pm = PermissionManager.get_permission_manager() for action in ag.list_actions(): action_name = action.get_name() setattr(instance, action_name, action) # Check permissions key, required = instance.action_permissions.get( action_name, (None, pm.PERM_ALL)) if not pm.get(key) & required: action.set_visible(False) # Disable keyboard shortcut path = action.get_accel_path() gtk.accel_map_change_entry(path, 0, 0, True) return ui_id
def add_ui_actions(self, ui_string, actions, name='Actions', action_type='normal', filename=None, instance=None): if instance is None: instance = self ag = self._get_action_group(name) to_add = [entry[0] for entry in actions] for action in ag.list_actions(): if action.get_name() in to_add: ag.remove_action(action) if action_type == 'normal': ag.add_actions(actions) elif action_type == 'toggle': ag.add_toggle_actions(actions) elif action_type == 'radio': ag.add_radio_actions(actions) else: raise ValueError(action_type) if filename is not None: ui_string = environ.get_resource_string('stoq', 'uixml', filename) ui_id = self.uimanager.add_ui_from_string(ui_string) self.action_permissions.update(self.common_action_permissions) pm = PermissionManager.get_permission_manager() for action in ag.list_actions(): action_name = action.get_name() setattr(instance, action_name, action) # Check permissions key, required = instance.action_permissions.get(action_name, (None, pm.PERM_ALL)) if not pm.get(key) & required: action.set_visible(False) # Disable keyboard shortcut path = action.get_accel_path() gtk.accel_map_change_entry(path, 0, 0, True) return ui_id
def _setup_accel(widget, name, shortcut=None): """Setup accelerators for a menu item. This method sets an accel path for the widget and optionally connects a shortcut to that accel path. """ # The GTK docs say that we should set the path using this form: # <Window-Name>/Menu/Submenu/MenuItem # ...but this is hard to do because we don't yet know what window/menu # this menu item is going to be added to. gtk.Action and gtk.ActionGroup # don't follow the above suggestion, so we don't need to either. path = "<MiroActions>/MenuBar/%s" % name widget.set_accel_path(path) if shortcut is not None: accel_string = keymap.get_accel_string(shortcut) key, mods = gtk.accelerator_parse(accel_string) if gtk.accel_map_lookup_entry(path) is None: gtk.accel_map_add_entry(path, key, mods) else: gtk.accel_map_change_entry(path, key, mods, True)
def on_accel_cleared(renderer, path, *args): iter = self.treestore.get_iter(path) col = column + 3 accel = self.treestore.get(iter, col)[0] action_name = self.treestore.get_value(iter, 1) if accel != "": self.keymanager.clear_accel(action_name, accel) # updating gtk accelerator for label in menu if len(self.keymanager.get_bindings_for_action( action_name)) == 0: gtk.accel_map_change_entry( '<Actions>/mcomix-main/%s' % action_name, 0, 0, True) else: key, mods = self.keymanager.get_bindings_for_action( action_name)[0] gtk.accel_map_change_entry( '<Actions>/mcomix-main/%s' % action_name, key, mods, True) self.treestore.set_value(iter, col, "")
def _insert_directory(self, directory, path): manager = self._window.get_ui_manager() for item in directory.subdirs: action_name = 'ExternalToolDirectory%X' % id(item) action = gtk.Action(action_name, item.name.replace('_', '__'), None, None) self._action_group.add_action(action) manager.add_ui(self._merge_id, path, action_name, action_name, gtk.UI_MANAGER_MENU, False) self._insert_directory(item, path + '/' + action_name) for item in directory.tools: action_name = 'ExternalToolTool%X' % id(item) action = gtk.Action(action_name, item.name.replace('_', '__'), item.comment, None) handler = action.connect("activate", capture_menu_action, self._window, item) action.set_data(self.ACTION_ITEM_DATA_KEY, item) action.set_data(self.ACTION_HANDLER_DATA_KEY, handler) # Make sure to replace accel accelpath = '<Actions>/ExternalToolsPluginToolActions/%s' % ( action_name, ) if item.shortcut: key, mod = gtk.accelerator_parse(item.shortcut) gtk.accel_map_change_entry(accelpath, key, mod, True) self._signals.append(gtk.accel_map_get().connect( 'changed::%s' % (accelpath, ), self.on_accelmap_changed, item)) self._action_group.add_action_with_accel(action, item.shortcut) manager.add_ui(self._merge_id, path, action_name, action_name, gtk.UI_MANAGER_MENUITEM, False)
def on_accel_edited(renderer, path, accel_key, accel_mods, hardware_keycode): iter = self.treestore.get_iter(path) col = column + 3 # accel cells start from 3 position old_accel = self.treestore.get(iter, col)[0] new_accel = gtk.accelerator_name(accel_key, accel_mods) self.treestore.set_value(iter, col, new_accel) action_name = self.treestore.get_value(iter, 1) affected_action = self.keymanager.edit_accel(action_name, new_accel, old_accel) # Find affected row and cell if affected_action == action_name: for idx in range(0, self.accel_column_num): if idx != column and self.treestore.get(iter, idx + 3)[0] == new_accel: self.treestore.set_value(iter, idx + 3, "") elif affected_action is not None: titer = self.action_treeiter_map[affected_action] for idx in range(0, self.accel_column_num): if self.treestore.get(titer, idx + 3)[0] == new_accel: self.treestore.set_value(titer, idx + 3, "") # updating gtk accelerator for label in menu if self.keymanager.get_bindings_for_action(action_name)[0] == (accel_key, accel_mods): gtk.accel_map_change_entry('<Actions>/mcomix-main/%s' % action_name, accel_key, accel_mods, True)
def _insert_directory(self, directory, path): manager = self._window.get_ui_manager() for item in directory.subdirs: action_name = 'RunExternalToolDirectory%X' % id(item) action = gtk.Action(action_name, item.name.replace('_', '__'), None, None) self._action_group.add_action(action) manager.add_ui(self._merge_id, path, action_name, action_name, gtk.UI_MANAGER_MENU, False) self._insert_directory(item, path + '/' + action_name) for item in directory.tools: action_name = 'RunExternalToolTool%X' % id(item) action = gtk.Action(action_name, item.name.replace('_', '__'), item.comment, None) handler = action.connect("activate", capture_menu_action, self._window, item) action.set_data(self.ACTION_ITEM_DATA_KEY, item) action.set_data(self.ACTION_HANDLER_DATA_KEY, handler) # Make sure to replace accel accelpath = '<Actions>/RunExternalToolsPluginToolActions/%s' % (action_name, ) if item.shortcut: key, mod = gtk.accelerator_parse(item.shortcut) gtk.accel_map_change_entry(accelpath, key, mod, True) self._signals.append(gtk.accel_map_get().connect('changed::%s' % (accelpath,), self.on_accelmap_changed, item)) self._action_group.add_action_with_accel(action, item.shortcut) manager.add_ui(self._merge_id, path, action_name, action_name, gtk.UI_MANAGER_MENUITEM, False)
def __init__(self, window): gtk.UIManager.__init__(self) self._window = window self._tooltipstatus = status.TooltipStatusHelper( self, window.statusbar) # ---------------------------------------------------------------- # Create actions for the menus. # ---------------------------------------------------------------- self._actiongroup = gtk.ActionGroup('mcomix-main') self._actiongroup.add_actions([ ('copy_page', gtk.STOCK_COPY, _('_Copy'), None, _('Copies the current page to clipboard.'), window.clipboard.copy_page), ('delete', gtk.STOCK_DELETE, _('_Delete'), None, _('Deletes the current file or archive from disk.'), window.delete), ('next_page', gtk.STOCK_GO_FORWARD, _('_Next page'), None, _('Next page'), window.next_page), ('previous_page', gtk.STOCK_GO_BACK, _('_Previous page'), None, _('Previous page'), window.previous_page), ('first_page', gtk.STOCK_GOTO_FIRST, _('_First page'), None, _('First page'), window.first_page), ('last_page', gtk.STOCK_GOTO_LAST, _('_Last page'), None, _('Last page'), window.last_page), ('go_to', gtk.STOCK_JUMP_TO, _('_Go to page...'), None, _('Go to page...'), window.page_select), ('refresh_archive', gtk.STOCK_REFRESH, _('Re_fresh'), None, _('Reloads the currently opened files or archive.'), window.filehandler.refresh_file), ('next_archive', gtk.STOCK_MEDIA_NEXT, _('Next _archive'), None, _('Next archive'), window.filehandler._open_next_archive), ('previous_archive', gtk.STOCK_MEDIA_PREVIOUS, _('Previous a_rchive'), None, _('Previous archive'), window.filehandler._open_previous_archive), ('next_directory', gtk.STOCK_REDO, _('Next directory'), None, _('Next directory'), window.filehandler.open_next_directory), ('previous_directory', gtk.STOCK_UNDO, _('Previous directory'), None, _('Previous directory'), window.filehandler.open_previous_directory), ('zoom_in', gtk.STOCK_ZOOM_IN, _('Zoom _In'), None, None, window.manual_zoom_in), ('zoom_out', gtk.STOCK_ZOOM_OUT, _('Zoom _Out'), None, None, window.manual_zoom_out), ('zoom_original', gtk.STOCK_ZOOM_100, _('_Normal Size'), None, None, window.manual_zoom_original), ('minimize', gtk.STOCK_LEAVE_FULLSCREEN, _('Mi_nimize'), None, None, window.minimize), ('close', gtk.STOCK_CLOSE, _('_Close'), None, _('Closes all opened files.'), window.filehandler.close_file), ('quit', gtk.STOCK_QUIT, _('_Quit'), None, None, window.close_program), ('save_and_quit', gtk.STOCK_QUIT, _('_Save and quit'), None, _('Quits and restores the currently opened file next time the program starts.' ), window.save_and_terminate_program), ('rotate_90', 'mcomix-rotate-90', _('_Rotate 90 degrees CW'), None, None, window.rotate_90), ('rotate_180', 'mcomix-rotate-180', _('Rotate 180 de_grees'), None, None, window.rotate_180), ('rotate_270', 'mcomix-rotate-270', _('Rotat_e 90 degrees CCW'), None, None, window.rotate_270), ('flip_horiz', 'mcomix-flip-horizontal', _('Fli_p horizontally'), None, None, window.flip_horizontally), ('flip_vert', 'mcomix-flip-vertical', _('Flip _vertically'), None, None, window.flip_vertically), ('extract_page', gtk.STOCK_SAVE_AS, _('Save _As'), None, None, window.extract_page), ('menu_zoom', 'mcomix-zoom', _('_Zoom')), ('menu_recent', gtk.STOCK_DND_MULTIPLE, _('_Recent')), ('menu_bookmarks_popup', 'comix-add-bookmark', _('_Bookmarks')), ('menu_bookmarks', None, _('_Bookmarks')), ('menu_toolbars', None, _('T_oolbars')), ('menu_edit', None, _('_Edit')), ('menu_open_with', gtk.STOCK_OPEN, _('Open _with'), ''), ('menu_open_with_popup', gtk.STOCK_OPEN, _('Open _with'), ''), ('menu_file', None, _('_File')), ('menu_view', None, _('_View')), ('menu_view_popup', 'comix-image', _('_View')), ('menu_go', None, _('_Go')), ('menu_go_popup', gtk.STOCK_GO_FORWARD, _('_Go')), ('menu_tools', None, _('_Tools')), ('menu_help', None, _('_Help')), ('menu_transform', 'mcomix-transform', _('_Transform image')), ('menu_autorotate', None, _('_Auto-rotate image')), ('menu_autorotate_width', None, _('...when width exceeds height')), ('menu_autorotate_height', None, _('...when height exceeds width')), ('expander', None, None, None, None, None) ]) self._actiongroup.add_toggle_actions([ ('fullscreen', gtk.STOCK_FULLSCREEN, _('_Fullscreen'), None, _('Fullscreen mode'), window.change_fullscreen), ('double_page', 'mcomix-double-page', _('_Double page mode'), None, _('Double page mode'), window.change_double_page), ('toolbar', None, _('_Toolbar'), None, None, window.change_toolbar_visibility), ('menubar', None, _('_Menubar'), None, None, window.change_menubar_visibility), ('statusbar', None, _('St_atusbar'), None, None, window.change_statusbar_visibility), ('scrollbar', None, _('S_crollbars'), None, None, window.change_scrollbar_visibility), ('thumbnails', None, _('Th_umbnails'), None, None, window.change_thumbnails_visibility), ('hide_all', None, _('H_ide all'), None, None, window.change_hide_all), ('manga_mode', 'mcomix-manga', _('_Manga mode'), None, _('Manga mode'), window.change_manga_mode), ('invert_scroll', gtk.STOCK_UNDO, _('Invert smart scroll'), None, _('Invert smart scrolling direction.'), window.change_invert_scroll), ('keep_transformation', None, _('_Keep transformation'), None, _('Keeps the currently selected transformation for the next pages.' ), window.change_keep_transformation), ('slideshow', gtk.STOCK_MEDIA_PLAY, _('Start _slideshow'), None, _('Start slideshow'), window.slideshow.toggle), ('lens', 'mcomix-lens', _('Magnifying _lens'), None, _('Magnifying lens'), window.lens.toggle), ('stretch', None, _('Stretch small images'), None, _('Stretch images to fit to the screen, depending on zoom mode.'), window.change_stretch) ]) # Note: Don't change the default value for the radio buttons unless # also fixing the code for setting the correct one on start-up in main.py. self._actiongroup.add_radio_actions( [('best_fit_mode', 'mcomix-fitbest', _('_Best fit mode'), None, _('Best fit mode'), constants.ZOOM_MODE_BEST), ('fit_width_mode', 'mcomix-fitwidth', _('Fit _width mode'), None, _('Fit width mode'), constants.ZOOM_MODE_WIDTH), ('fit_height_mode', 'mcomix-fitheight', _('Fit _height mode'), None, _('Fit height mode'), constants.ZOOM_MODE_HEIGHT), ('fit_size_mode', 'mcomix-fitsize', _('Fit _size mode'), None, _('Fit to size mode'), constants.ZOOM_MODE_SIZE), ('fit_manual_mode', 'mcomix-fitmanual', _('M_anual zoom mode'), None, _('Manual zoom mode'), constants.ZOOM_MODE_MANUAL)], 3, window.change_zoom_mode) # Automatically rotate image if width>height or height>width self._actiongroup.add_radio_actions([ ('no_autorotation', None, _('Never'), None, None, constants.AUTOROTATE_NEVER), ('rotate_90_width', 'mcomix-rotate-90', _('_Rotate 90 degrees CW'), None, None, constants.AUTOROTATE_WIDTH_90), ('rotate_270_width', 'mcomix-rotate-270', _('Rotat_e 90 degrees CCW'), None, None, constants.AUTOROTATE_WIDTH_270), ('rotate_90_height', 'mcomix-rotate-90', _('_Rotate 90 degrees CW'), None, None, constants.AUTOROTATE_HEIGHT_90), ('rotate_270_height', 'mcomix-rotate-270', _('Rotat_e 90 degrees CCW'), None, None, constants.AUTOROTATE_HEIGHT_270) ], prefs['auto rotate depending on size'], window.change_autorotation) self._actiongroup.add_actions( [('about', gtk.STOCK_ABOUT, _('_About'), None, None, dialog_handler.open_dialog)], (window, 'about-dialog')) self._actiongroup.add_actions( [('comments', 'mcomix-comments', _('Co_mments...'), None, None, dialog_handler.open_dialog)], (window, 'comments-dialog')) self._actiongroup.add_actions( [('properties', gtk.STOCK_PROPERTIES, _('Proper_ties'), None, None, dialog_handler.open_dialog)], (window, 'properties-dialog')) self._actiongroup.add_actions( [('preferences', gtk.STOCK_PREFERENCES, _('Pr_eferences'), None, None, preferences_dialog.open_dialog)], (window)) # Some actions added separately since they need extra arguments. self._actiongroup.add_actions( [('edit_archive', gtk.STOCK_EDIT, _('_Edit archive...'), None, _('Opens the archive editor.'), edit_dialog.open_dialog), ('open', gtk.STOCK_OPEN, _('_Open...'), None, None, file_chooser_main_dialog.open_main_filechooser_dialog), ('enhance_image', 'mcomix-enhance-image', _('En_hance image...'), None, None, enhance_dialog.open_dialog)], window) self._actiongroup.add_actions( [('library', 'mcomix-library', _('_Library...'), None, None, library_main_dialog.open_dialog)], window) # fix some gtk magic: removing unreqired accelerators gtk.accel_map_change_entry('<Actions>/mcomix-main/%s' % 'close', 0, 0, True) ui_description = """ <ui> <toolbar name="Tool"> <toolitem action="previous_archive" /> <toolitem action="first_page" /> <toolitem action="previous_page" /> <toolitem action="go_to" /> <toolitem action="next_page" /> <toolitem action="last_page" /> <toolitem action="next_archive" /> <separator /> <toolitem action="slideshow" /> <toolitem action="expander" /> <toolitem action="best_fit_mode" /> <toolitem action="fit_width_mode" /> <toolitem action="fit_height_mode" /> <toolitem action="fit_size_mode" /> <toolitem action="fit_manual_mode" /> <separator /> <toolitem action="double_page" /> <toolitem action="manga_mode" /> <separator /> <toolitem action="lens" /> </toolbar> <menubar name="Menu"> <menu action="menu_file"> <menuitem action="open" /> <menu action="menu_recent" /> <menuitem action="library" /> <separator /> <menuitem action="extract_page" /> <menuitem action="refresh_archive" /> <menuitem action="properties" /> <separator /> <menu action="menu_open_with"></menu> <separator /> <menuitem action="delete" /> <separator /> <menuitem action="minimize" /> <menuitem action="close" /> <menuitem action="save_and_quit" /> <menuitem action="quit" /> </menu> <menu action="menu_edit"> <menuitem action="copy_page" /> <separator /> <menuitem action="edit_archive" /> <menuitem action="comments" /> <separator /> <menuitem action="preferences" /> </menu> <menu action="menu_view"> <menuitem action="fullscreen" /> <menuitem action="double_page" /> <menuitem action="manga_mode" /> <separator /> <menuitem action="best_fit_mode" /> <menuitem action="fit_width_mode" /> <menuitem action="fit_height_mode" /> <menuitem action="fit_size_mode" /> <menuitem action="fit_manual_mode" /> <separator /> <menuitem action="slideshow" /> <separator /> <menuitem action="stretch" /> <menuitem action="invert_scroll" /> <menuitem action="lens" /> <menu action="menu_zoom"> <menuitem action="zoom_in" /> <menuitem action="zoom_out" /> <menuitem action="zoom_original" /> </menu> <separator /> <menu action="menu_toolbars"> <menuitem action="menubar" /> <menuitem action="toolbar" /> <menuitem action="statusbar" /> <menuitem action="scrollbar" /> <menuitem action="thumbnails" /> <separator /> <menuitem action="hide_all" /> </menu> </menu> <menu action="menu_go"> <menuitem action="next_page" /> <menuitem action="previous_page" /> <menuitem action="go_to" /> <menuitem action="first_page" /> <menuitem action="last_page" /> <separator /> <menuitem action="next_archive" /> <menuitem action="previous_archive" /> <separator /> <menuitem action="next_directory" /> <menuitem action="previous_directory" /> </menu> <menu action="menu_bookmarks"> </menu> <menu action="menu_tools"> <menuitem action="enhance_image" /> <menu action="menu_transform"> <menuitem action="rotate_90" /> <menuitem action="rotate_270" /> <menuitem action="rotate_180" /> <separator /> <menu action="menu_autorotate"> <menuitem action="no_autorotation" /> <separator /> <menuitem action="menu_autorotate_height" /> <separator /> <menuitem action="rotate_90_height" /> <menuitem action="rotate_270_height" /> <separator /> <menuitem action="menu_autorotate_width" /> <separator /> <menuitem action="rotate_90_width" /> <menuitem action="rotate_270_width" /> </menu> <separator /> <menuitem action="flip_horiz" /> <menuitem action="flip_vert" /> <separator /> <menuitem action="keep_transformation" /> </menu> </menu> <menu action="menu_help"> <menuitem action="about" /> </menu> </menubar> <popup name="Popup"> <menu action="menu_go_popup"> <menuitem action="next_page" /> <menuitem action="previous_page" /> <menuitem action="go_to" /> <menuitem action="first_page" /> <menuitem action="last_page" /> <separator /> <menuitem action="next_archive" /> <menuitem action="previous_archive" /> <separator /> <menuitem action="next_directory" /> <menuitem action="previous_directory" /> </menu> <menu action="menu_view_popup"> <menuitem action="fullscreen" /> <menuitem action="double_page" /> <menuitem action="manga_mode" /> <separator /> <menuitem action="best_fit_mode" /> <menuitem action="fit_width_mode" /> <menuitem action="fit_height_mode" /> <menuitem action="fit_size_mode" /> <menuitem action="fit_manual_mode" /> <separator /> <menuitem action="slideshow" /> <separator /> <menuitem action="enhance_image" /> <separator /> <menuitem action="stretch" /> <menuitem action="invert_scroll" /> <menuitem action="lens" /> <menu action="menu_zoom"> <menuitem action="zoom_in" /> <menuitem action="zoom_out" /> <menuitem action="zoom_original" /> </menu> <separator /> <menu action="menu_toolbars"> <menuitem action="menubar" /> <menuitem action="toolbar" /> <menuitem action="statusbar" /> <menuitem action="scrollbar" /> <menuitem action="thumbnails" /> <separator /> <menuitem action="hide_all" /> </menu> </menu> <menu action="menu_bookmarks_popup"> </menu> <separator /> <menuitem action="open" /> <menu action="menu_recent" /> <menuitem action="library" /> <separator /> <menu action="menu_open_with_popup"></menu> <separator /> <menuitem action="preferences" /> <separator /> <menuitem action="close" /> <menuitem action="quit" /> </popup> </ui> """ self.add_ui_from_string(ui_description) self.insert_action_group(self._actiongroup, 0) self.bookmarks = bookmark_menu.BookmarksMenu(self, window) self.get_widget('/Menu/menu_bookmarks').set_submenu(self.bookmarks) self.get_widget('/Menu/menu_bookmarks').show() self.bookmarks_popup = bookmark_menu.BookmarksMenu(self, window) self.get_widget('/Popup/menu_bookmarks_popup').set_submenu( self.bookmarks_popup) self.get_widget('/Popup/menu_bookmarks_popup').show() self.recent = recent.RecentFilesMenu(self, window) self.get_widget('/Menu/menu_file/menu_recent').set_submenu(self.recent) self.get_widget('/Menu/menu_file/menu_recent').show() self.recentPopup = recent.RecentFilesMenu(self, window) self.get_widget('/Popup/menu_recent').set_submenu(self.recentPopup) self.get_widget('/Popup/menu_recent').show() openwith = openwith_menu.OpenWithMenu(self, window) self.get_widget('/Menu/menu_file/menu_open_with').set_submenu(openwith) self.get_widget('/Menu/menu_file/menu_open_with').show() openwith = openwith_menu.OpenWithMenu(self, window) self.get_widget('/Popup/menu_open_with_popup').set_submenu(openwith) self.get_widget('/Popup/menu_open_with_popup').show() window.add_accel_group(self.get_accel_group()) # Is there no built-in way to do this? self.get_widget('/Tool/expander').set_expand(True) self.get_widget('/Tool/expander').set_sensitive(False)
def _set_action_keypress(self, name, accel_string): keyval, modmask = gtk.accelerator_parse(accel_string) gtk.accel_map_change_entry(self._create_accel_path(name), keyval, modmask, True)
def set_accel_keymap(self): if self.__keyval: gtk.accel_map_change_entry(self.accel_path, self.__keyval, self.__modmask, True)
def __init__(self, window): super(MainUI, self).__init__() self._window = window self._tooltipstatus = status.TooltipStatusHelper(self, window.statusbar) def _action_lambda(fn, *args): return lambda *_: fn(*args) # ---------------------------------------------------------------- # Create actions for the menus. # ---------------------------------------------------------------- self._actiongroup = gtk.ActionGroup('mcomix-main') self._actiongroup.add_actions([ ('copy_page', gtk.STOCK_COPY, _('_Copy'), None, _('Copies the current page to clipboard.'), window.clipboard.copy_page), ('delete', gtk.STOCK_DELETE, _('_Delete'), None, _('Deletes the current file or archive from disk.'), window.delete), ('next_page', gtk.STOCK_GO_FORWARD, _('_Next page'), None, _('Next page'), _action_lambda(window.flip_page, +1)), ('previous_page', gtk.STOCK_GO_BACK, _('_Previous page'), None, _('Previous page'), _action_lambda(window.flip_page, -1)), ('first_page', gtk.STOCK_GOTO_FIRST, _('_First page'), None, _('First page'), _action_lambda(window.first_page)), ('last_page', gtk.STOCK_GOTO_LAST, _('_Last page'), None, _('Last page'), _action_lambda(window.last_page)), ('go_to', gtk.STOCK_JUMP_TO, _('_Go to page...'), None, _('Go to page...'), window.page_select), ('refresh_archive', gtk.STOCK_REFRESH, _('Re_fresh'), None, _('Reloads the currently opened files or archive.'), window.filehandler.refresh_file), ('next_archive', gtk.STOCK_MEDIA_NEXT, _('Next _archive'), None, _('Next archive'), window.filehandler._open_next_archive), ('previous_archive', gtk.STOCK_MEDIA_PREVIOUS, _('Previous a_rchive'), None, _('Previous archive'), window.filehandler._open_previous_archive), ('next_directory', gtk.STOCK_REDO, _('Next directory'), None, _('Next directory'), window.filehandler.open_next_directory), ('previous_directory', gtk.STOCK_UNDO, _('Previous directory'), None, _('Previous directory'), window.filehandler.open_previous_directory), ('zoom_in', gtk.STOCK_ZOOM_IN, _('Zoom _In'), None, None, window.manual_zoom_in), ('zoom_out', gtk.STOCK_ZOOM_OUT, _('Zoom _Out'), None, None, window.manual_zoom_out), ('zoom_original', gtk.STOCK_ZOOM_100, _('_Normal Size'), None, None, window.manual_zoom_original), ('minimize', gtk.STOCK_LEAVE_FULLSCREEN, _('Mi_nimize'), None, None, window.minimize), ('close', gtk.STOCK_CLOSE, _('_Close'), None, _('Closes all opened files.'), _action_lambda(window.filehandler.close_file)), ('quit', gtk.STOCK_QUIT, _('_Quit'), None, None, window.close_program), ('save_and_quit', gtk.STOCK_QUIT, _('_Save and quit'), None, _('Quits and restores the currently opened file next time the program starts.'), window.save_and_terminate_program), ('rotate_90', 'mcomix-rotate-90', _('_Rotate 90 degrees CW'), None, None, window.rotate_90), ('rotate_180','mcomix-rotate-180', _('Rotate 180 de_grees'), None, None, window.rotate_180), ('rotate_270', 'mcomix-rotate-270', _('Rotat_e 90 degrees CCW'), None, None, window.rotate_270), ('flip_horiz', 'mcomix-flip-horizontal', _('Fli_p horizontally'), None, None, window.flip_horizontally), ('flip_vert', 'mcomix-flip-vertical', _('Flip _vertically'), None, None, window.flip_vertically), ('extract_page', gtk.STOCK_SAVE_AS, _('Save _As'), None, None, window.extract_page), ('menu_zoom', 'mcomix-zoom', _('_Zoom')), ('menu_recent', gtk.STOCK_DND_MULTIPLE, _('_Recent')), ('menu_bookmarks_popup', 'comix-add-bookmark', _('_Bookmarks')), ('menu_bookmarks', None, _('_Bookmarks')), ('menu_toolbars', None, _('T_oolbars')), ('menu_edit', None, _('_Edit')), ('menu_open_with', gtk.STOCK_OPEN, _('Open _with'), ''), ('menu_open_with_popup', gtk.STOCK_OPEN, _('Open _with'), ''), ('menu_file', None, _('_File')), ('menu_view', None, _('_View')), ('menu_view_popup', 'comix-image', _('_View')), ('menu_go', None, _('_Go')), ('menu_go_popup', gtk.STOCK_GO_FORWARD, _('_Go')), ('menu_tools', None, _('_Tools')), ('menu_help', None, _('_Help')), ('menu_transform', 'mcomix-transform', _('_Transform image')), ('menu_autorotate', None, _('_Auto-rotate image')), ('menu_autorotate_width', None, _('...when width exceeds height')), ('menu_autorotate_height', None, _('...when height exceeds width')), ('expander', None, None, None, None, None)]) self._actiongroup.add_toggle_actions([ ('fullscreen', gtk.STOCK_FULLSCREEN, _('_Fullscreen'), None, _('Fullscreen mode'), window.change_fullscreen), ('double_page', 'mcomix-double-page', _('_Double page mode'), None, _('Double page mode'), window.change_double_page), ('toolbar', None, _('_Toolbar'), None, None, window.change_toolbar_visibility), ('menubar', None, _('_Menubar'), None, None, window.change_menubar_visibility), ('statusbar', None, _('St_atusbar'), None, None, window.change_statusbar_visibility), ('scrollbar', None, _('S_crollbars'), None, None, window.change_scrollbar_visibility), ('thumbnails', None, _('Th_umbnails'), None, None, window.change_thumbnails_visibility), ('hide_all', None, _('H_ide all'), None, None, window.change_hide_all), ('manga_mode', 'mcomix-manga', _('_Manga mode'), None, _('Manga mode'), window.change_manga_mode), ('invert_scroll', gtk.STOCK_UNDO, _('Invert smart scroll'), None, _('Invert smart scrolling direction.'), window.change_invert_scroll), ('keep_transformation', None, _('_Keep transformation'), None, _('Keeps the currently selected transformation for the next pages.'), window.change_keep_transformation), ('slideshow', gtk.STOCK_MEDIA_PLAY, _('Start _slideshow'), None, _('Start slideshow'), window.slideshow.toggle), ('lens', 'mcomix-lens', _('Magnifying _lens'), None, _('Magnifying lens'), window.lens.toggle), ('stretch', None, _('Stretch small images'), None, _('Stretch images to fit to the screen, depending on zoom mode.'), window.change_stretch)]) # Note: Don't change the default value for the radio buttons unless # also fixing the code for setting the correct one on start-up in main.py. self._actiongroup.add_radio_actions([ ('best_fit_mode', 'mcomix-fitbest', _('_Best fit mode'), None, _('Best fit mode'), constants.ZOOM_MODE_BEST), ('fit_width_mode', 'mcomix-fitwidth', _('Fit _width mode'), None, _('Fit width mode'), constants.ZOOM_MODE_WIDTH), ('fit_height_mode', 'mcomix-fitheight', _('Fit _height mode'), None, _('Fit height mode'), constants.ZOOM_MODE_HEIGHT), ('fit_size_mode', 'mcomix-fitsize', _('Fit _size mode'), None, _('Fit to size mode'), constants.ZOOM_MODE_SIZE), ('fit_manual_mode', 'mcomix-fitmanual', _('M_anual zoom mode'), None, _('Manual zoom mode'), constants.ZOOM_MODE_MANUAL)], 3, window.change_zoom_mode) # Automatically rotate image if width>height or height>width self._actiongroup.add_radio_actions([ ('no_autorotation', None, _('Never'), None, None, constants.AUTOROTATE_NEVER), ('rotate_90_width', 'mcomix-rotate-90', _('_Rotate 90 degrees CW'), None, None, constants.AUTOROTATE_WIDTH_90), ('rotate_270_width', 'mcomix-rotate-270', _('Rotat_e 90 degrees CCW'), None, None, constants.AUTOROTATE_WIDTH_270), ('rotate_90_height', 'mcomix-rotate-90', _('_Rotate 90 degrees CW'), None, None, constants.AUTOROTATE_HEIGHT_90), ('rotate_270_height', 'mcomix-rotate-270', _('Rotat_e 90 degrees CCW'), None, None, constants.AUTOROTATE_HEIGHT_270)], prefs['auto rotate depending on size'], window.change_autorotation) self._actiongroup.add_actions([ ('about', gtk.STOCK_ABOUT, _('_About'), None, None, dialog_handler.open_dialog)], (window, 'about-dialog')) self._actiongroup.add_actions([ ('comments', 'mcomix-comments', _('Co_mments...'), None, None, dialog_handler.open_dialog)], (window, 'comments-dialog')) self._actiongroup.add_actions([ ('properties', gtk.STOCK_PROPERTIES, _('Proper_ties'), None, None, dialog_handler.open_dialog)], (window,'properties-dialog')) self._actiongroup.add_actions([ ('preferences', gtk.STOCK_PREFERENCES, _('Pr_eferences'), None, None, preferences_dialog.open_dialog)], (window)) # Some actions added separately since they need extra arguments. self._actiongroup.add_actions([ ('edit_archive', gtk.STOCK_EDIT, _('_Edit archive...'), None, _('Opens the archive editor.'), edit_dialog.open_dialog), ('open', gtk.STOCK_OPEN, _('_Open...'), None, None, file_chooser_main_dialog.open_main_filechooser_dialog), ('enhance_image', 'mcomix-enhance-image', _('En_hance image...'), None, None, enhance_dialog.open_dialog)], window) self._actiongroup.add_actions([ ('library', 'mcomix-library', _('_Library...'), None, None, library_main_dialog.open_dialog)], window) # fix some gtk magic: removing unreqired accelerators gtk.accel_map_change_entry('<Actions>/mcomix-main/%s' % 'close', 0, 0, True) ui_description = """ <ui> <toolbar name="Tool"> <toolitem action="previous_archive" /> <toolitem action="first_page" /> <toolitem action="previous_page" /> <toolitem action="go_to" /> <toolitem action="next_page" /> <toolitem action="last_page" /> <toolitem action="next_archive" /> <separator /> <toolitem action="fullscreen" /> <toolitem action="slideshow" /> <toolitem action="expander" /> <toolitem action="best_fit_mode" /> <toolitem action="fit_width_mode" /> <toolitem action="fit_height_mode" /> <toolitem action="fit_size_mode" /> <toolitem action="fit_manual_mode" /> <separator /> <toolitem action="double_page" /> <toolitem action="manga_mode" /> <separator /> <toolitem action="lens" /> </toolbar> <menubar name="Menu"> <menu action="menu_file"> <menuitem action="open" /> <menu action="menu_recent" /> <menuitem action="library" /> <separator /> <menuitem action="extract_page" /> <menuitem action="refresh_archive" /> <menuitem action="properties" /> <separator /> <menu action="menu_open_with"></menu> <separator /> <menuitem action="delete" /> <separator /> <menuitem action="minimize" /> <menuitem action="close" /> <menuitem action="save_and_quit" /> <menuitem action="quit" /> </menu> <menu action="menu_edit"> <menuitem action="copy_page" /> <separator /> <menuitem action="edit_archive" /> <menuitem action="comments" /> <separator /> <menuitem action="preferences" /> </menu> <menu action="menu_view"> <menuitem action="fullscreen" /> <menuitem action="double_page" /> <menuitem action="manga_mode" /> <separator /> <menuitem action="best_fit_mode" /> <menuitem action="fit_width_mode" /> <menuitem action="fit_height_mode" /> <menuitem action="fit_size_mode" /> <menuitem action="fit_manual_mode" /> <separator /> <menuitem action="slideshow" /> <separator /> <menuitem action="stretch" /> <menuitem action="invert_scroll" /> <menuitem action="lens" /> <menu action="menu_zoom"> <menuitem action="zoom_in" /> <menuitem action="zoom_out" /> <menuitem action="zoom_original" /> </menu> <separator /> <menu action="menu_toolbars"> <menuitem action="menubar" /> <menuitem action="toolbar" /> <menuitem action="statusbar" /> <menuitem action="scrollbar" /> <menuitem action="thumbnails" /> <separator /> <menuitem action="hide_all" /> </menu> </menu> <menu action="menu_go"> <menuitem action="next_page" /> <menuitem action="previous_page" /> <menuitem action="go_to" /> <menuitem action="first_page" /> <menuitem action="last_page" /> <separator /> <menuitem action="next_archive" /> <menuitem action="previous_archive" /> <separator /> <menuitem action="next_directory" /> <menuitem action="previous_directory" /> </menu> <menu action="menu_bookmarks"> </menu> <menu action="menu_tools"> <menuitem action="enhance_image" /> <menu action="menu_transform"> <menuitem action="rotate_90" /> <menuitem action="rotate_270" /> <menuitem action="rotate_180" /> <separator /> <menu action="menu_autorotate"> <menuitem action="no_autorotation" /> <separator /> <menuitem action="menu_autorotate_height" /> <separator /> <menuitem action="rotate_90_height" /> <menuitem action="rotate_270_height" /> <separator /> <menuitem action="menu_autorotate_width" /> <separator /> <menuitem action="rotate_90_width" /> <menuitem action="rotate_270_width" /> </menu> <separator /> <menuitem action="flip_horiz" /> <menuitem action="flip_vert" /> <separator /> <menuitem action="keep_transformation" /> </menu> </menu> <menu action="menu_help"> <menuitem action="about" /> </menu> </menubar> <popup name="Popup"> <menu action="menu_go_popup"> <menuitem action="next_page" /> <menuitem action="previous_page" /> <menuitem action="go_to" /> <menuitem action="first_page" /> <menuitem action="last_page" /> <separator /> <menuitem action="next_archive" /> <menuitem action="previous_archive" /> <separator /> <menuitem action="next_directory" /> <menuitem action="previous_directory" /> </menu> <menu action="menu_view_popup"> <menuitem action="fullscreen" /> <menuitem action="double_page" /> <menuitem action="manga_mode" /> <separator /> <menuitem action="best_fit_mode" /> <menuitem action="fit_width_mode" /> <menuitem action="fit_height_mode" /> <menuitem action="fit_size_mode" /> <menuitem action="fit_manual_mode" /> <separator /> <menuitem action="slideshow" /> <separator /> <menuitem action="enhance_image" /> <separator /> <menuitem action="stretch" /> <menuitem action="invert_scroll" /> <menuitem action="lens" /> <menu action="menu_zoom"> <menuitem action="zoom_in" /> <menuitem action="zoom_out" /> <menuitem action="zoom_original" /> </menu> <separator /> <menu action="menu_toolbars"> <menuitem action="menubar" /> <menuitem action="toolbar" /> <menuitem action="statusbar" /> <menuitem action="scrollbar" /> <menuitem action="thumbnails" /> <separator /> <menuitem action="hide_all" /> </menu> </menu> <menu action="menu_bookmarks_popup"> </menu> <separator /> <menuitem action="open" /> <menu action="menu_recent" /> <menuitem action="library" /> <separator /> <menu action="menu_open_with_popup"></menu> <separator /> <menuitem action="preferences" /> <separator /> <menuitem action="close" /> <menuitem action="quit" /> </popup> </ui> """ self.add_ui_from_string(ui_description) self.insert_action_group(self._actiongroup, 0) self.bookmarks = bookmark_menu.BookmarksMenu(self, window) self.get_widget('/Menu/menu_bookmarks').set_submenu(self.bookmarks) self.get_widget('/Menu/menu_bookmarks').show() self.bookmarks_popup = bookmark_menu.BookmarksMenu(self, window) self.get_widget('/Popup/menu_bookmarks_popup').set_submenu(self.bookmarks_popup) self.get_widget('/Popup/menu_bookmarks_popup').show() self.recent = recent.RecentFilesMenu(self, window) self.get_widget('/Menu/menu_file/menu_recent').set_submenu(self.recent) self.get_widget('/Menu/menu_file/menu_recent').show() self.recentPopup = recent.RecentFilesMenu(self, window) self.get_widget('/Popup/menu_recent').set_submenu(self.recentPopup) self.get_widget('/Popup/menu_recent').show() openwith = openwith_menu.OpenWithMenu(self, window) self.get_widget('/Menu/menu_file/menu_open_with').set_submenu(openwith) self.get_widget('/Menu/menu_file/menu_open_with').show() openwith = openwith_menu.OpenWithMenu(self, window) self.get_widget('/Popup/menu_open_with_popup').set_submenu(openwith) self.get_widget('/Popup/menu_open_with_popup').show() window.add_accel_group(self.get_accel_group()) # Is there no built-in way to do this? self.get_widget('/Tool/expander').set_expand(True) self.get_widget('/Tool/expander').set_sensitive(False)
def cmd_disable_document_accelerators(self): for act in self.__file_fallback.action_group.list_actions(): gtk.accel_map_change_entry(act.accel_path, 0, 0, True)
def __init__(self, no_dialog=False): self.settings = EventCore() self.gui_is_active = False # during initialization any dialog (e.g. "Unit change") is not allowed # we set the final value later self.no_dialog = True self._batch_queue = [] self._undo_states = [] self.gui = gtk.Builder() gtk_build_file = get_ui_file_location(GTKBUILD_FILE) if gtk_build_file is None: gtk.main_quit() self.gui.add_from_file(gtk_build_file) if pycam.Utils.get_platform() == pycam.Utils.PLATFORM_WINDOWS: gtkrc_file = get_ui_file_location(GTKRC_FILE_WINDOWS) if gtkrc_file: gtk.rc_add_default_file(gtkrc_file) gtk.rc_reparse_all_for_settings(gtk.settings_get_default(), True) self.window = self.gui.get_object("ProjectWindow") self.settings.set("main_window", self.window) # show stock items on buttons # increase the initial width of the window (due to hidden elements) self.window.set_default_size(400, -1) # initialize the RecentManager (TODO: check for Windows) if False and pycam.Utils.get_platform( ) == pycam.Utils.PLATFORM_WINDOWS: # The pyinstaller binary for Windows fails mysteriously when trying # to display the stock item. # Error message: Gtk:ERROR:gtkrecentmanager.c:1942:get_icon_fallback: assertion failed: (retval != NULL) self.recent_manager = None else: try: self.recent_manager = gtk.recent_manager_get_default() except AttributeError: # GTK 2.12.1 seems to have problems with "RecentManager" on # Windows. Sadly this is the version, that is shipped with the # "appunti" GTK packages for Windows (April 2010). # see http://www.daa.com.au/pipermail/pygtk/2009-May/017052.html self.recent_manager = None # file loading self.last_dirname = None self.last_task_settings_uri = None self.last_model_uri = None # define callbacks and accelerator keys for the menu actions for objname, callback, data, accel_key in ( ("LoadTaskSettings", self.load_task_settings_file, None, "<Control>t"), ("SaveTaskSettings", self.save_task_settings_file, lambda: self.last_task_settings_uri, None), ("SaveAsTaskSettings", self.save_task_settings_file, None, None), ("OpenModel", self.load_model_file, None, "<Control>o"), ("Quit", self.destroy, None, "<Control>q"), ("GeneralSettings", self.toggle_preferences_window, None, "<Control>p"), ("UndoButton", self._restore_undo_state, None, "<Control>z"), ("HelpUserManual", self.show_help, "User_Manual", "F1"), ("HelpIntroduction", self.show_help, "Introduction", None), ("HelpSupportedFormats", self.show_help, "SupportedFormats", None), ("HelpModelTransformations", self.show_help, "ModelTransformations", None), ("HelpToolTypes", self.show_help, "ToolTypes", None), ("HelpProcessSettings", self.show_help, "ProcessSettings", None), ("HelpBoundsSettings", self.show_help, "BoundsSettings", None), ("HelpTaskSetup", self.show_help, "TaskSetup", None), ("HelpGCodeExport", self.show_help, "GCodeExport", None), ("HelpTouchOff", self.show_help, "TouchOff", None), ("HelpSimulation", self.show_help, "Simulation", None), ("Help3DView", self.show_help, "3D_View", None), ("HelpServerMode", self.show_help, "ServerMode", None), ("HelpCommandLine", self.show_help, "CommandlineExamples", None), ("HelpHotkeys", self.show_help, "KeyboardShortcuts", None), ("ProjectWebsite", self.show_help, "http://pycam.sourceforge.net", None), ("DevelopmentBlog", self.show_help, "http://fab.senselab.org/pycam", None), ("Forum", self.show_help, "http://sourceforge.net/projects/pycam/forums", None), ("BugTracker", self.show_help, "http://sourceforge.net/tracker/?group_id=237831&atid=1104176", None), ("FeatureRequest", self.show_help, "http://sourceforge.net/tracker/?group_id=237831&atid=1104179", None)): item = self.gui.get_object(objname) action = "activate" if data is None: item.connect(action, callback) else: item.connect(action, callback, data) if accel_key: key, mod = gtk.accelerator_parse(accel_key) accel_path = "<pycam>/%s" % objname item.set_accel_path(accel_path) gtk.accel_map_change_entry(accel_path, key, mod, True) # LinkButton does not work on Windows: https://bugzilla.gnome.org/show_bug.cgi?id=617874 if pycam.Utils.get_platform() == pycam.Utils.PLATFORM_WINDOWS: def open_url(widget, data=None): webbrowser.open(widget.get_uri()) gtk.link_button_set_uri_hook(open_url) # no undo is allowed at the beginning self.gui.get_object("UndoButton").set_sensitive(False) self.settings.register_event("model-change-before", self._store_undo_state) self.settings.register_event( "model-change-after", lambda: self.settings.emit_event("visual-item-updated")) # set the availability of ODE self.enable_ode_control = self.gui.get_object("SettingEnableODE") self.settings.add_item("enable_ode", self.enable_ode_control.get_active, self.enable_ode_control.set_active) self.settings.register_event("parallel-processing-changed", self.update_ode_settings) # configure drag-n-drop for config files and models self.settings.set("configure-drag-drop-func", self.configure_drag_and_drop) self.settings.get("configure-drag-drop-func")(self.window) # other events self.window.connect("destroy", self.destroy) self.window.connect("delete-event", self.destroy) # the settings window self.gui.get_object("CloseSettingsWindow").connect( "clicked", self.toggle_preferences_window, False) self.gui.get_object("ResetPreferencesButton").connect( "clicked", self.reset_preferences) self.preferences_window = self.gui.get_object("GeneralSettingsWindow") self.preferences_window.connect("delete-event", self.toggle_preferences_window, False) self._preferences_window_position = None self._preferences_window_visible = False # "about" window self.about_window = self.gui.get_object("AboutWindow") self.about_window.set_version(VERSION) self.gui.get_object("About").connect("activate", self.toggle_about_window, True) # we assume, that the last child of the window is the "close" button # TODO: fix this ugly hack! self.gui.get_object("AboutWindowButtons").get_children()[-1].connect( "clicked", self.toggle_about_window, False) self.about_window.connect("delete-event", self.toggle_about_window, False) # menu bar uimanager = gtk.UIManager() self.settings.set("gtk-uimanager", uimanager) self._accel_group = uimanager.get_accel_group() # send a "delete" event on "CTRL-w" for every window def handle_window_close(accel_group, window, *args): window.emit("delete-event", gtk.gdk.Event(gtk.gdk.DELETE)) self._accel_group.connect_group(ord('w'), gtk.gdk.CONTROL_MASK, gtk.ACCEL_LOCKED, handle_window_close) self.settings.add_item("gtk-accel-group", lambda: self._accel_group) for obj in self.gui.get_objects(): if isinstance(obj, gtk.Window): obj.add_accel_group(self._accel_group) # preferences tab preferences_book = self.gui.get_object("PreferencesNotebook") def clear_preferences(): for child in preferences_book.get_children(): preferences_book.remove(child) def add_preferences_item(item, name): preferences_book.append_page(item, gtk.Label(name)) self.settings.register_ui_section("preferences", add_preferences_item, clear_preferences) for obj_name, label, priority in (("GeneralSettingsPrefTab", "General", -50), ("ProgramsPrefTab", "Programs", 50)): obj = self.gui.get_object(obj_name) obj.unparent() self.settings.register_ui("preferences", label, obj, priority) # general preferences general_prefs = self.gui.get_object("GeneralPreferencesBox") def clear_general_prefs(): for item in general_prefs.get_children(): general_prefs.remove(item) def add_general_prefs_item(item, name): general_prefs.pack_start(item, expand=False, padding=3) self.settings.register_ui_section("preferences_general", add_general_prefs_item, clear_general_prefs) for obj_name, priority in (("SettingEnableODE", 10), ("TaskSettingsDefaultFileBox", 30)): obj = self.gui.get_object(obj_name) obj.unparent() self.settings.register_ui("preferences_general", None, obj, priority) # set defaults self.cutter = None # add some dummies - to be implemented later ... self.settings.add_item("cutter", lambda: self.cutter) main_tab = self.gui.get_object("MainTabs") def clear_main_tab(): while main_tab.get_n_pages() > 0: main_tab.remove_page(0) def add_main_tab_item(item, name): main_tab.append_page(item, gtk.Label(name)) # TODO: move these to plugins, as well self.settings.register_ui_section("main", add_main_tab_item, clear_main_tab) main_window = self.gui.get_object("WindowBox") def clear_main_window(): main_window.foreach(lambda x: main_window.remove(x)) def add_main_window_item(item, name, **extra_args): # some widgets may want to override the defaults args = {"expand": False, "fill": False} args.update(extra_args) main_window.pack_start(item, **args) main_tab.unparent() self.settings.register_ui_section("main_window", add_main_window_item, clear_main_window) self.settings.register_ui("main_window", "Tabs", main_tab, -20, args_dict={ "expand": True, "fill": True }) # autoload task settings file on startup autoload_enable = self.gui.get_object("AutoLoadTaskFile") autoload_box = self.gui.get_object("StartupTaskFileBox") autoload_source = self.gui.get_object("StartupTaskFile") # TODO: fix the extension filter #for one_filter in get_filters_from_list(FILTER_CONFIG): # autoload_source.add_filter(one_filter) # autoload_source.set_filter(one_filter) def get_autoload_task_file(autoload_source=autoload_source): if autoload_enable.get_active(): return autoload_source.get_filename() else: return "" def set_autoload_task_file(filename): if filename: autoload_enable.set_active(True) autoload_box.show() autoload_source.set_filename(filename) else: autoload_enable.set_active(False) autoload_box.hide() autoload_source.unselect_all() def autoload_enable_switched(widget, box): if not widget.get_active(): set_autoload_task_file(None) else: autoload_box.show() autoload_enable.connect("toggled", autoload_enable_switched, autoload_box) self.settings.add_item("default_task_settings_file", get_autoload_task_file, set_autoload_task_file) def disable_gui(): self.menubar.set_sensitive(False) main_tab.set_sensitive(False) def enable_gui(): self.menubar.set_sensitive(True) main_tab.set_sensitive(True) self.settings.register_event("gui-disable", disable_gui) self.settings.register_event("gui-enable", enable_gui) # configure locations of external programs for auto_control_name, location_control_name, browse_button, key in ( ("ExternalProgramInkscapeAuto", "ExternalProgramInkscapeControl", "ExternalProgramInkscapeBrowse", "inkscape"), ("ExternalProgramPstoeditAuto", "ExternalProgramPstoeditControl", "ExternalProgramPstoeditBrowse", "pstoedit")): self.gui.get_object(auto_control_name).connect( "clicked", self._locate_external_program, key) location_control = self.gui.get_object(location_control_name) self.settings.add_item("external_program_%s" % key, location_control.get_text, location_control.set_text) self.gui.get_object(browse_button).connect( "clicked", self._browse_external_program_location, key) # set the icons (in different sizes) for all windows gtk.window_set_default_icon_list(*get_icons_pixbuffers()) # load menu data gtk_menu_file = get_ui_file_location(GTKMENU_FILE) if gtk_menu_file is None: gtk.main_quit() uimanager.add_ui_from_file(gtk_menu_file) # make the actions defined in the GTKBUILD file available in the menu actiongroup = gtk.ActionGroup("menubar") for action in [ action for action in self.gui.get_objects() if isinstance(action, gtk.Action) ]: actiongroup.add_action(action) # the "pos" parameter is optional since 2.12 - we can remove it later uimanager.insert_action_group(actiongroup, pos=-1) # the "recent files" sub-menu if not self.recent_manager is None: recent_files_menu = gtk.RecentChooserMenu(self.recent_manager) recent_files_menu.set_name("RecentFilesMenu") recent_menu_filter = gtk.RecentFilter() case_converter = pycam.Utils.get_case_insensitive_file_pattern for filter_name, patterns in FILTER_MODEL: if not isinstance(patterns, (list, set, tuple)): patterns = [patterns] # convert it into a mutable list (instead of set/tuple) patterns = list(patterns) for index in range(len(patterns)): patterns[index] = case_converter(patterns[index]) for pattern in patterns: recent_menu_filter.add_pattern(pattern) recent_files_menu.add_filter(recent_menu_filter) recent_files_menu.set_show_numbers(True) # non-local files (without "file://") are not supported. yet recent_files_menu.set_local_only(False) # most recent files to the top recent_files_menu.set_sort_type(gtk.RECENT_SORT_MRU) # show only ten files recent_files_menu.set_limit(10) uimanager.get_widget("/MenuBar/FileMenu/OpenRecentModelMenu")\ .set_submenu(recent_files_menu) recent_files_menu.connect("item-activated", self.load_recent_model_file) else: self.gui.get_object("OpenRecentModel").set_visible(False) # load the menubar and connect functions to its items self.menubar = uimanager.get_widget("/MenuBar") # dict of all merge-ids menu_merges = {} def clear_menu(menu_key): for merge in menu_merges.get(menu_key, []): uimanager.remove_ui(merge) def append_menu_item(menu_key, base_path, widget, name): merge_id = uimanager.new_merge_id() if widget: action_group = widget.props.action_group if not action_group in uimanager.get_action_groups(): uimanager.insert_action_group(action_group, -1) widget_name = widget.get_name() item_type = gtk.UI_MANAGER_MENUITEM else: widget_name = name item_type = gtk.UI_MANAGER_SEPARATOR uimanager.add_ui(merge_id, base_path, name, widget_name, item_type, False) if not menu_key in menu_merges: menu_merges[menu_key] = [] menu_merges[menu_key].append(merge_id) def get_menu_funcs(menu_key, base_path): append_func = lambda widget, name: \ append_menu_item(menu_key, base_path, widget, name) clear_func = lambda: clear_menu(menu_key) return append_func, clear_func for ui_name, base_path in (("view_menu", "/MenuBar/ViewMenu"), ("file_menu", "/MenuBar/FileMenu"), ("edit_menu", "/MenuBar/EditMenu"), ("export_menu", "/MenuBar/FileMenu/ExportMenu")): append_func, clear_func = get_menu_funcs(ui_name, base_path) self.settings.register_ui_section(ui_name, append_func, clear_func) self.settings.register_ui("file_menu", "Quit", self.gui.get_object("Quit"), 100) self.settings.register_ui("file_menu", "QuitSeparator", None, 95) self.settings.register_ui("main_window", "Main", self.menubar, -100) # initialize plugins self.plugin_manager = pycam.Plugins.PluginManager(core=self.settings) self.plugin_manager.import_plugins() # some more initialization self.reset_preferences() # TODO: preferences are not loaded until the new format is stable #self.load_preferences() #self.load_task_settings() self.settings.register_event("notify-file-saved", self.add_to_recent_file_list) self.settings.register_event("notify-file-opened", self.add_to_recent_file_list) # fallback - in case of a failure when opening a model file model = pycam.Importers.TestModel.get_test_model() self.settings.get("models").add_model(model, "Tiny pyramid") # Without this "gkt.main_iteration" loop the task settings file # control would not be updated in time. while gtk.events_pending(): gtk.main_iteration() autoload_task_filename = self.settings.get( "default_task_settings_file") if autoload_task_filename: self.open_task_settings_file(autoload_task_filename) self.update_all_controls() self.no_dialog = no_dialog if not self.no_dialog: # register a logging handler for displaying error messages pycam.Utils.log.add_gtk_gui(self.window, logging.ERROR) self.window.show()
def __init__(self, no_dialog=False): self.settings = EventCore() self.gui_is_active = False # during initialization any dialog (e.g. "Unit change") is not allowed # we set the final value later self.no_dialog = True self._batch_queue = [] self._undo_states = [] self.gui = gtk.Builder() gtk_build_file = get_ui_file_location(GTKBUILD_FILE) if gtk_build_file is None: gtk.main_quit() self.gui.add_from_file(gtk_build_file) if pycam.Utils.get_platform() == pycam.Utils.PLATFORM_WINDOWS: gtkrc_file = get_ui_file_location(GTKRC_FILE_WINDOWS) if gtkrc_file: gtk.rc_add_default_file(gtkrc_file) gtk.rc_reparse_all_for_settings(gtk.settings_get_default(), True) self.window = self.gui.get_object("ProjectWindow") self.settings.set("main_window", self.window) # show stock items on buttons # increase the initial width of the window (due to hidden elements) self.window.set_default_size(400, -1) # initialize the RecentManager (TODO: check for Windows) if False and pycam.Utils.get_platform() == pycam.Utils.PLATFORM_WINDOWS: # The pyinstaller binary for Windows fails mysteriously when trying # to display the stock item. # Error message: Gtk:ERROR:gtkrecentmanager.c:1942:get_icon_fallback: assertion failed: (retval != NULL) self.recent_manager = None else: try: self.recent_manager = gtk.recent_manager_get_default() except AttributeError: # GTK 2.12.1 seems to have problems with "RecentManager" on # Windows. Sadly this is the version, that is shipped with the # "appunti" GTK packages for Windows (April 2010). # see http://www.daa.com.au/pipermail/pygtk/2009-May/017052.html self.recent_manager = None # file loading self.last_dirname = None self.last_task_settings_uri = None self.last_model_uri = None # define callbacks and accelerator keys for the menu actions for objname, callback, data, accel_key in ( ("LoadTaskSettings", self.load_task_settings_file, None, "<Control>t"), ("SaveTaskSettings", self.save_task_settings_file, lambda: self.last_task_settings_uri, None), ("SaveAsTaskSettings", self.save_task_settings_file, None, None), ("OpenModel", self.load_model_file, None, "<Control>o"), ("Quit", self.destroy, None, "<Control>q"), ("GeneralSettings", self.toggle_preferences_window, None, "<Control>p"), ("UndoButton", self._restore_undo_state, None, "<Control>z"), ("HelpUserManual", self.show_help, "User_Manual", "F1"), ("HelpIntroduction", self.show_help, "Introduction", None), ("HelpSupportedFormats", self.show_help, "SupportedFormats", None), ("HelpModelTransformations", self.show_help, "ModelTransformations", None), ("HelpToolTypes", self.show_help, "ToolTypes", None), ("HelpProcessSettings", self.show_help, "ProcessSettings", None), ("HelpBoundsSettings", self.show_help, "BoundsSettings", None), ("HelpTaskSetup", self.show_help, "TaskSetup", None), ("HelpGCodeExport", self.show_help, "GCodeExport", None), ("HelpTouchOff", self.show_help, "TouchOff", None), ("HelpSimulation", self.show_help, "Simulation", None), ("Help3DView", self.show_help, "3D_View", None), ("HelpServerMode", self.show_help, "ServerMode", None), ("HelpCommandLine", self.show_help, "CommandlineExamples", None), ("HelpHotkeys", self.show_help, "KeyboardShortcuts", None), ("ProjectWebsite", self.show_help, "http://pycam.sourceforge.net", None), ("DevelopmentBlog", self.show_help, "http://fab.senselab.org/pycam", None), ("Forum", self.show_help, "http://sourceforge.net/projects/pycam/forums", None), ("BugTracker", self.show_help, "http://sourceforge.net/tracker/?group_id=237831&atid=1104176", None), ("FeatureRequest", self.show_help, "http://sourceforge.net/tracker/?group_id=237831&atid=1104179", None)): item = self.gui.get_object(objname) action = "activate" if data is None: item.connect(action, callback) else: item.connect(action, callback, data) if accel_key: key, mod = gtk.accelerator_parse(accel_key) accel_path = "<pycam>/%s" % objname item.set_accel_path(accel_path) gtk.accel_map_change_entry(accel_path, key, mod, True) # LinkButton does not work on Windows: https://bugzilla.gnome.org/show_bug.cgi?id=617874 if pycam.Utils.get_platform() == pycam.Utils.PLATFORM_WINDOWS: def open_url(widget, data=None): webbrowser.open(widget.get_uri()) gtk.link_button_set_uri_hook(open_url) # no undo is allowed at the beginning self.gui.get_object("UndoButton").set_sensitive(False) self.settings.register_event("model-change-before", self._store_undo_state) self.settings.register_event("model-change-after", lambda: self.settings.emit_event("visual-item-updated")) # set the availability of ODE self.enable_ode_control = self.gui.get_object("SettingEnableODE") self.settings.add_item("enable_ode", self.enable_ode_control.get_active, self.enable_ode_control.set_active) self.settings.register_event("parallel-processing-changed", self.update_ode_settings) # configure drag-n-drop for config files and models self.settings.set("configure-drag-drop-func", self.configure_drag_and_drop) self.settings.get("configure-drag-drop-func")(self.window) # other events self.window.connect("destroy", self.destroy) self.window.connect("delete-event", self.destroy) # the settings window self.gui.get_object("CloseSettingsWindow").connect("clicked", self.toggle_preferences_window, False) self.gui.get_object("ResetPreferencesButton").connect("clicked", self.reset_preferences) self.preferences_window = self.gui.get_object("GeneralSettingsWindow") self.preferences_window.connect("delete-event", self.toggle_preferences_window, False) self._preferences_window_position = None self._preferences_window_visible = False # "about" window self.about_window = self.gui.get_object("AboutWindow") self.about_window.set_version(VERSION) self.gui.get_object("About").connect("activate", self.toggle_about_window, True) # we assume, that the last child of the window is the "close" button # TODO: fix this ugly hack! self.gui.get_object("AboutWindowButtons").get_children()[-1].connect("clicked", self.toggle_about_window, False) self.about_window.connect("delete-event", self.toggle_about_window, False) # menu bar uimanager = gtk.UIManager() self.settings.set("gtk-uimanager", uimanager) self._accel_group = uimanager.get_accel_group() # send a "delete" event on "CTRL-w" for every window def handle_window_close(accel_group, window, *args): window.emit("delete-event", gtk.gdk.Event(gtk.gdk.DELETE)) self._accel_group.connect_group(ord('w'), gtk.gdk.CONTROL_MASK, gtk.ACCEL_LOCKED, handle_window_close) self.settings.add_item("gtk-accel-group", lambda: self._accel_group) for obj in self.gui.get_objects(): if isinstance(obj, gtk.Window): obj.add_accel_group(self._accel_group) # preferences tab preferences_book = self.gui.get_object("PreferencesNotebook") def clear_preferences(): for child in preferences_book.get_children(): preferences_book.remove(child) def add_preferences_item(item, name): preferences_book.append_page(item, gtk.Label(name)) self.settings.register_ui_section("preferences", add_preferences_item, clear_preferences) for obj_name, label, priority in ( ("GeneralSettingsPrefTab", "General", -50), ("ProgramsPrefTab", "Programs", 50)): obj = self.gui.get_object(obj_name) obj.unparent() self.settings.register_ui("preferences", label, obj, priority) # general preferences general_prefs = self.gui.get_object("GeneralPreferencesBox") def clear_general_prefs(): for item in general_prefs.get_children(): general_prefs.remove(item) def add_general_prefs_item(item, name): general_prefs.pack_start(item, expand=False, padding=3) self.settings.register_ui_section("preferences_general", add_general_prefs_item, clear_general_prefs) for obj_name, priority in (("SettingEnableODE", 10), ("TaskSettingsDefaultFileBox", 30)): obj = self.gui.get_object(obj_name) obj.unparent() self.settings.register_ui("preferences_general", None, obj, priority) # set defaults self.cutter = None # add some dummies - to be implemented later ... self.settings.add_item("cutter", lambda: self.cutter) main_tab = self.gui.get_object("MainTabs") def clear_main_tab(): while main_tab.get_n_pages() > 0: main_tab.remove_page(0) def add_main_tab_item(item, name): main_tab.append_page(item, gtk.Label(name)) # TODO: move these to plugins, as well self.settings.register_ui_section("main", add_main_tab_item, clear_main_tab) main_window = self.gui.get_object("WindowBox") def clear_main_window(): main_window.foreach(lambda x: main_window.remove(x)) def add_main_window_item(item, name, **extra_args): # some widgets may want to override the defaults args = {"expand": False, "fill": False} args.update(extra_args) main_window.pack_start(item, **args) main_tab.unparent() self.settings.register_ui_section("main_window", add_main_window_item, clear_main_window) self.settings.register_ui("main_window", "Tabs", main_tab, -20, args_dict={"expand": True, "fill": True}) # autoload task settings file on startup autoload_enable = self.gui.get_object("AutoLoadTaskFile") autoload_box = self.gui.get_object("StartupTaskFileBox") autoload_source = self.gui.get_object("StartupTaskFile") # TODO: fix the extension filter #for one_filter in get_filters_from_list(FILTER_CONFIG): # autoload_source.add_filter(one_filter) # autoload_source.set_filter(one_filter) def get_autoload_task_file(autoload_source=autoload_source): if autoload_enable.get_active(): return autoload_source.get_filename() else: return "" def set_autoload_task_file(filename): if filename: autoload_enable.set_active(True) autoload_box.show() autoload_source.set_filename(filename) else: autoload_enable.set_active(False) autoload_box.hide() autoload_source.unselect_all() def autoload_enable_switched(widget, box): if not widget.get_active(): set_autoload_task_file(None) else: autoload_box.show() autoload_enable.connect("toggled", autoload_enable_switched, autoload_box) self.settings.add_item("default_task_settings_file", get_autoload_task_file, set_autoload_task_file) def disable_gui(): self.menubar.set_sensitive(False) main_tab.set_sensitive(False) def enable_gui(): self.menubar.set_sensitive(True) main_tab.set_sensitive(True) self.settings.register_event("gui-disable", disable_gui) self.settings.register_event("gui-enable", enable_gui) # configure locations of external programs for auto_control_name, location_control_name, browse_button, key in ( ("ExternalProgramInkscapeAuto", "ExternalProgramInkscapeControl", "ExternalProgramInkscapeBrowse", "inkscape"), ("ExternalProgramPstoeditAuto", "ExternalProgramPstoeditControl", "ExternalProgramPstoeditBrowse", "pstoedit")): self.gui.get_object(auto_control_name).connect("clicked", self._locate_external_program, key) location_control = self.gui.get_object(location_control_name) self.settings.add_item("external_program_%s" % key, location_control.get_text, location_control.set_text) self.gui.get_object(browse_button).connect("clicked", self._browse_external_program_location, key) # set the icons (in different sizes) for all windows gtk.window_set_default_icon_list(*get_icons_pixbuffers()) # load menu data gtk_menu_file = get_ui_file_location(GTKMENU_FILE) if gtk_menu_file is None: gtk.main_quit() uimanager.add_ui_from_file(gtk_menu_file) # make the actions defined in the GTKBUILD file available in the menu actiongroup = gtk.ActionGroup("menubar") for action in [action for action in self.gui.get_objects() if isinstance(action, gtk.Action)]: actiongroup.add_action(action) # the "pos" parameter is optional since 2.12 - we can remove it later uimanager.insert_action_group(actiongroup, pos=-1) # the "recent files" sub-menu if not self.recent_manager is None: recent_files_menu = gtk.RecentChooserMenu(self.recent_manager) recent_files_menu.set_name("RecentFilesMenu") recent_menu_filter = gtk.RecentFilter() case_converter = pycam.Utils.get_case_insensitive_file_pattern for filter_name, patterns in FILTER_MODEL: if not isinstance(patterns, (list, set, tuple)): patterns = [patterns] # convert it into a mutable list (instead of set/tuple) patterns = list(patterns) for index in range(len(patterns)): patterns[index] = case_converter(patterns[index]) for pattern in patterns: recent_menu_filter.add_pattern(pattern) recent_files_menu.add_filter(recent_menu_filter) recent_files_menu.set_show_numbers(True) # non-local files (without "file://") are not supported. yet recent_files_menu.set_local_only(False) # most recent files to the top recent_files_menu.set_sort_type(gtk.RECENT_SORT_MRU) # show only ten files recent_files_menu.set_limit(10) uimanager.get_widget("/MenuBar/FileMenu/OpenRecentModelMenu")\ .set_submenu(recent_files_menu) recent_files_menu.connect("item-activated", self.load_recent_model_file) else: self.gui.get_object("OpenRecentModel").set_visible(False) # load the menubar and connect functions to its items self.menubar = uimanager.get_widget("/MenuBar") # dict of all merge-ids menu_merges = {} def clear_menu(menu_key): for merge in menu_merges.get(menu_key, []): uimanager.remove_ui(merge) def append_menu_item(menu_key, base_path, widget, name): merge_id = uimanager.new_merge_id() if widget: action_group = widget.props.action_group if not action_group in uimanager.get_action_groups(): uimanager.insert_action_group(action_group, -1) widget_name = widget.get_name() item_type = gtk.UI_MANAGER_MENUITEM else: widget_name = name item_type = gtk.UI_MANAGER_SEPARATOR uimanager.add_ui(merge_id, base_path, name, widget_name, item_type, False) if not menu_key in menu_merges: menu_merges[menu_key] = [] menu_merges[menu_key].append(merge_id) def get_menu_funcs(menu_key, base_path): append_func = lambda widget, name: \ append_menu_item(menu_key, base_path, widget, name) clear_func = lambda: clear_menu(menu_key) return append_func, clear_func for ui_name, base_path in (("view_menu", "/MenuBar/ViewMenu"), ("file_menu", "/MenuBar/FileMenu"), ("edit_menu", "/MenuBar/EditMenu"), ("export_menu", "/MenuBar/FileMenu/ExportMenu")): append_func, clear_func = get_menu_funcs(ui_name, base_path) self.settings.register_ui_section(ui_name, append_func, clear_func) self.settings.register_ui("file_menu", "Quit", self.gui.get_object("Quit"), 100) self.settings.register_ui("file_menu", "QuitSeparator", None, 95) self.settings.register_ui("main_window", "Main", self.menubar, -100) # initialize plugins self.plugin_manager = pycam.Plugins.PluginManager(core=self.settings) self.plugin_manager.import_plugins() # some more initialization self.reset_preferences() # TODO: preferences are not loaded until the new format is stable #self.load_preferences() #self.load_task_settings() self.settings.register_event("notify-file-saved", self.add_to_recent_file_list) self.settings.register_event("notify-file-opened", self.add_to_recent_file_list) # fallback - in case of a failure when opening a model file model = pycam.Importers.TestModel.get_test_model() self.settings.get("models").add_model(model, "Tiny pyramid") # Without this "gkt.main_iteration" loop the task settings file # control would not be updated in time. while gtk.events_pending(): gtk.main_iteration() autoload_task_filename = self.settings.get("default_task_settings_file") if autoload_task_filename: self.open_task_settings_file(autoload_task_filename) self.update_all_controls() self.no_dialog = no_dialog if not self.no_dialog: # register a logging handler for displaying error messages pycam.Utils.log.add_gtk_gui(self.window, logging.ERROR) self.window.show()