def DispatchToControl(self, evt): """Catches events that need to be passed to the current text control for processing. @param evt: Event fired that called this handler @type evt: wxMenuEvent """ if not self.IsActive() or \ not (self.FindFocus() == self.nb.GetCurrentCtrl()): evt.Skip() return menu_ids = syntax.SyntaxIds() menu_ids.extend([ ID_SHOW_EOL, ID_SHOW_WS, ID_INDENT_GUIDES, ID_SYNTAX, ID_KWHELPER, ID_WORD_WRAP, ID_BRACKETHL, ID_ZOOM_IN, ID_ZOOM_OUT, ID_ZOOM_NORMAL, ID_EOL_MAC, ID_EOL_UNIX, ID_EOL_WIN, ID_JOIN_LINES, ID_CUT_LINE, ID_COPY_LINE, ID_INDENT, ID_UNINDENT, ID_TRANSPOSE, ID_NEXT_MARK, ID_PRE_MARK, ID_ADD_BM, ID_DEL_BM, ID_DEL_ALL_BM, ID_FOLDING, ID_AUTOCOMP, ID_SHOW_LN, ID_COMMENT, ID_UNCOMMENT, ID_AUTOINDENT, ID_LINE_AFTER, ID_LINE_BEFORE, ID_TAB_TO_SPACE, ID_SPACE_TO_TAB, ID_TRIM_WS, ID_SHOW_EDGE, ID_MACRO_START, ID_MACRO_STOP, ID_MACRO_PLAY, ID_TO_LOWER, ID_TO_UPPER, ID_SELECTALL, ID_UNDO, ID_REDO, ID_CUT, ID_COPY, ID_PASTE ]) if evt.GetId() in menu_ids: self.nb.GetCurrentCtrl().ControlDispatch(evt) self.UpdateToolBar() else: evt.Skip() return
def CreateBitmap(self, art_id, client, size): """Lookup and return an associated bitmap from the current theme if one exisists. If the art_id is not a theme defined id and is a wx defined art resource then it is passed to the next ArtProvider in the stack to evaluate. @return: Requested bitmap from current theme if one exists @rtype: wx.Bitmap """ # All art ids we can handle can be converted to int try: art_id = int(art_id) except ValueError: return wx.NullBitmap # If using default theme let the system provide the art when possible # this is mostly for GTK where there is a native art provider that can # provide theme icons. if Profile_Get('ICONS', 'str').lower() == u'default' and \ DEFAULT.has_key(art_id): if client == wx.ART_MENU: size = (16, 16) elif client == wx.ART_TOOLBAR: size = Profile_Get('ICON_SZ', default=(24, 24)) return wx.ArtProvider.GetBitmap(DEFAULT[art_id], client, size) # If a custom theme is set fetch the requested bitmap bmp = self._library.GetBitmap(art_id, client) if not bmp.IsNull() and bmp.IsOk(): # Dont scale toolbar icons on wxMac as the toolbar handles it # internally and produces much nicer results. Only allow images # to be scaled down as scaling up degrades quality. if client == wx.ART_TOOLBAR and not wx.Platform == '__WXMAC__': if size == wx.DefaultSize: size = Profile_Get('ICON_SZ', 'size_tuple') img = wx.ImageFromBitmap(bmp) img_sz = img.GetSize() if size[0] < img_sz[0]: img.Rescale(size[0], size[1], wx.IMAGE_QUALITY_HIGH) bmp = wx.BitmapFromImage(img) elif client == wx.ART_MENU and bmp.GetSize() != (16, 16): img = wx.ImageFromBitmap(bmp) img.Rescale(16, 16, wx.IMAGE_QUALITY_HIGH) bmp = wx.BitmapFromImage(img) elif client == wx.ART_TOOLBAR: # Dont fail on a toolbar icon return a warning icon when nothing is # found in the bitmap provider. bmp = wx.ArtProvider.GetBitmap(wx.ART_WARNING, client, size) elif art_id in syntax.SyntaxIds(): # Dont fail when requesting mime type icons, fallback to the system # icon for a normal file in this case. bmp = wx.ArtProvider.GetBitmap(wx.ART_NORMAL_FILE, wx.ART_MENU, (16, 16)) if bmp.IsOk() and not bmp.IsNull(): return bmp # All failed so return a Null return wx.NullBitmap
def DispatchToControl(self, evt): """Catches events that need to be passed to the current text control for processing. @param evt: Event fired that called this handler @type evt: wxMenuEvent """ e_id = evt.GetId() if not self.IsActive() and e_id != ID_KWHELPER: evt.Skip() return ctrl = self.nb.GetCurrentCtrl() active_only = [ ID_ZOOM_IN, ID_ZOOM_OUT, ID_ZOOM_NORMAL, ID_JOIN_LINES, ID_CUT_LINE, ID_COPY_LINE, ID_INDENT, ID_UNINDENT, ID_TRANSPOSE, ID_COMMENT, ID_UNCOMMENT, ID_SELECTALL, ID_UNDO, ID_REDO, ID_CUT, ID_COPY, ID_PASTE, ID_LINE_BEFORE, ID_LINE_AFTER, ID_DUP_LINE, ID_PASTE_AFTER ] has_focus = self.FindFocus() if has_focus != ctrl and e_id in active_only: if has_focus is not None: if e_id == ID_PASTE and hasattr(has_focus, 'Paste'): has_focus.Paste() elif e_id == ID_CUT and hasattr(has_focus, 'Cut'): has_focus.Cut() elif e_id == ID_COPY and hasattr(has_focus, 'Copy'): has_focus.Copy() elif e_id == ID_REDO and hasattr(has_focus, 'Redo'): has_focus.Redo() elif e_id == ID_UNDO and hasattr(has_focus, 'Undo'): has_focus.Undo() else: evt.Skip() else: evt.Skip() return menu_ids = syntax.SyntaxIds() menu_ids.extend([ ID_SHOW_EOL, ID_SHOW_WS, ID_INDENT_GUIDES, ID_SYNTAX, ID_WORD_WRAP, ID_BRACKETHL, ID_EOL_MAC, ID_EOL_UNIX, ID_EOL_WIN, ID_NEXT_MARK, ID_PRE_MARK, ID_ADD_BM, ID_DEL_ALL_BM, ID_FOLDING, ID_AUTOCOMP, ID_SHOW_LN, ID_AUTOINDENT, ID_TAB_TO_SPACE, ID_SPACE_TO_TAB, ID_TRIM_WS, ID_SHOW_EDGE, ID_MACRO_START, ID_MACRO_STOP, ID_MACRO_PLAY, ID_TO_LOWER, ID_TO_UPPER, ID_KWHELPER, ID_USE_SOFTTABS, ID_GOTO_MBRACE, ID_HLCARET_LINE, ID_REVERT_FILE ]) menu_ids.extend(active_only) if e_id in menu_ids: ctrl.ControlDispatch(evt) else: evt.Skip() return
def OnUpdateLexerUI(self, evt): """Update status of lexer menu @param evt: wxEVT_UPDATE_UI """ if not self.IsActive(): return e_id = evt.GetId() if e_id in syntax.SyntaxIds(): lang = self.nb.GetCurrentCtrl().GetLangId() evt.Check(lang == evt.GetId()) else: evt.Skip()
def GetFileBitmap(self, bmp_id): bmp = None if bmp_id in ed_theme.MIME_ART: path = MIME_PATH + ed_theme.MIME_ART[bmp_id] bmp = self.__LoadBitmapData(path) if bmp is not None: return bmp if bmp is None and bmp_id in syntax.SyntaxIds(): # Fail back to plain text bitmap bkup = MIME_PATH + ed_theme.MIME_ART[synglob.ID_LANG_TXT] bmp = self.__LoadBitmapData(bkup) if bmp is not None: return bmp return wx.NullBitmap
def OnUpdateLexerUI(self, evt): """Update status of lexer menu @param evt: wxEVT_UPDATE_UI """ if not self.IsActive(): return e_id = evt.GetId() evt.SetMode(wx.UPDATE_UI_PROCESS_SPECIFIED) evt.SetUpdateInterval(400) if e_id in syntax.SyntaxIds(): lang = self.nb.GetCurrentCtrl().GetLangId() evt.Check(lang == evt.GetId()) else: evt.Skip()
def __init__(self, parent, id_, wsize, title): """Initialiaze the Frame and Event Handlers. @param wsize: Windows initial size @param title: Windows Title """ wx.Frame.__init__(self, parent, id_, title, size=wsize, style=wx.DEFAULT_FRAME_STYLE) self._mgr = wx.aui.AuiManager(flags=wx.aui.AUI_MGR_DEFAULT | \ wx.aui.AUI_MGR_TRANSPARENT_DRAG | \ wx.aui.AUI_MGR_TRANSPARENT_HINT) self._mgr.SetManagedWindow(self) viewmgr.PerspectiveManager.__init__(self, self._mgr, \ CONFIG['CACHE_DIR']) # Setup app icon and title self.SetTitle() util.SetWindowIcon(self) # Attributes self.LOG = wx.GetApp().GetLog() self._exiting = False self._handlers = dict(menu=list(), ui=list()) #---- Sizers to hold subapplets ----# self.sizer = wx.BoxSizer(wx.VERTICAL) #---- Setup File History ----# self.filehistory = wx.FileHistory(_PGET('FHIST_LVL', 'int', 5)) #---- Status bar on bottom of window ----# self.SetStatusBar(ed_statbar.EdStatBar(self)) #---- End Statusbar Setup ----# #---- Notebook that contains the editting buffers ----# edit_pane = wx.Panel(self) self.nb = ed_pages.EdPages(edit_pane, wx.ID_ANY) edit_pane.nb = self.nb self.sizer.Add(self.nb, 1, wx.EXPAND) edit_pane.SetSizer(self.sizer) self._mgr.AddPane(edit_pane, wx.aui.AuiPaneInfo(). \ Name("EditPane").Center().Layer(1).Dockable(False). \ CloseButton(False).MaximizeButton(False). \ CaptionVisible(False)) #---- Command Bar ----# self._cmdbar = ed_cmdbar.CommandBar(edit_pane, ID_COMMAND_BAR) self._cmdbar.Hide() #---- Setup Toolbar ----# self.SetToolBar(ed_toolbar.EdToolBar(self)) self.GetToolBar().Show(_PGET('TOOLBAR')) #---- End Toolbar Setup ----# #---- Menus ----# menbar = ed_menu.EdMenuBar() # Todo this should not be hard coded menbar.GetMenuByName("view").InsertMenu(5, ID_PERSPECTIVES, _("Perspectives"), self.GetPerspectiveControls()) ## Setup additional menu items self.filehistory.UseMenu(menbar.GetMenuByName("filehistory")) menbar.GetMenuByName("settings").AppendMenu(ID_LEXER, _("Lexers"), syntax.GenLexerMenu(), _("Manually Set a Lexer/Syntax")) # On mac, do this to make help menu appear in correct location # Note it must be done before setting the menu bar and after the # menus have been created. if wx.Platform == '__WXMAC__': wx.GetApp().SetMacHelpMenuTitleName(_("&Help")) #---- Menu Bar ----# self.SetMenuBar(menbar) #---- Actions to take on menu events ----# # Collect Menu Event handler pairs self._handlers['menu'].extend([# File Menu (ID_NEW, self.OnNew), (ID_OPEN, self.OnOpen), (ID_CLOSE, self.OnClosePage), (ID_CLOSEALL, self.OnClosePage), (ID_SAVE, self.OnSave), (ID_SAVEAS, self.OnSaveAs), (ID_SAVEALL, self.OnSave), (ID_SAVE_PROFILE, self.OnSaveProfile), (ID_LOAD_PROFILE, self.OnLoadProfile), (ID_EXIT, wx.GetApp().OnExit), (ID_PRINT, self.OnPrint), (ID_PRINT_PRE, self.OnPrint), (ID_PRINT_SU, self.OnPrint), # Edit Menu (ID_FIND, self.nb.FindService.OnShowFindDlg), (ID_FIND_REPLACE, self.nb.FindService.OnShowFindDlg), (ID_QUICK_FIND, self.OnCommandBar), (ID_PREF, OnPreferences), # View Menu (ID_GOTO_LINE, self.OnCommandBar), (ID_GOTO_MBRACE, self.DispatchToControl), (ID_VIEW_TOOL, self.OnViewTb), # Format Menu (ID_FONT, self.OnFont), # Tool Menu (ID_COMMAND, self.OnCommandBar), (ID_STYLE_EDIT, self.OnStyleEdit), (ID_PLUGMGR, self.OnPluginMgr), # Help Menu (ID_ABOUT, OnAbout), (ID_HOMEPAGE, self.OnHelp), (ID_DOCUMENTATION, self.OnHelp), (ID_TRANSLATE, self.OnHelp), (ID_CONTACT, self.OnHelp)]) self._handlers['menu'].extend([(l_id, self.DispatchToControl) for l_id in syntax.SyntaxIds()]) # Extra menu handlers (need to work these into above system yet) self.Bind(wx.EVT_MENU, self.DispatchToControl) self.Bind(wx.EVT_MENU, self.OnGenerate) self.Bind(wx.EVT_MENU_RANGE, self.OnFileHistory, id=wx.ID_FILE1, id2=wx.ID_FILE9) # Update UI Handlers self._handlers['ui'].extend([# Edit Menu (ID_COPY, self.OnUpdateClipboardUI), (ID_CUT, self.OnUpdateClipboardUI), (ID_PASTE, self.OnUpdateClipboardUI), (ID_UNDO, self.OnUpdateClipboardUI), (ID_REDO, self.OnUpdateClipboardUI), # Format Menu (ID_INDENT, self.OnUpdateFormatUI), (ID_USE_SOFTTABS, self.OnUpdateFormatUI), (ID_TO_UPPER, self.OnUpdateFormatUI), (ID_TO_LOWER, self.OnUpdateFormatUI), (ID_WORD_WRAP, self.OnUpdateFormatUI), (ID_EOL_MAC, self.OnUpdateFormatUI), (ID_EOL_WIN, self.OnUpdateFormatUI), (ID_EOL_UNIX, self.OnUpdateFormatUI), # Settings Menu (ID_AUTOCOMP, self.OnUpdateSettingsUI), (ID_AUTOINDENT, self.OnUpdateSettingsUI), (ID_SYNTAX, self.OnUpdateSettingsUI), (ID_FOLDING, self.OnUpdateSettingsUI), (ID_BRACKETHL, self.OnUpdateSettingsUI), # View Menu (ID_ZOOM_NORMAL, self.OnUpdateViewUI), (ID_ZOOM_IN, self.OnUpdateViewUI), (ID_ZOOM_OUT, self.OnUpdateViewUI), (ID_GOTO_MBRACE, self.OnUpdateViewUI), (ID_HLCARET_LINE, self.OnUpdateViewUI), (ID_VIEW_TOOL, self.OnUpdateViewUI), (ID_SHOW_WS, self.OnUpdateViewUI), (ID_SHOW_EDGE, self.OnUpdateViewUI), (ID_SHOW_EOL, self.OnUpdateViewUI), (ID_SHOW_LN, self.OnUpdateViewUI), (ID_INDENT_GUIDES, self.OnUpdateViewUI) ]) # Lexer Menu self._handlers['ui'].extend([(l_id, self.OnUpdateLexerUI) for l_id in syntax.SyntaxIds()]) # Perspectives self._handlers['ui'].extend(self.GetPersectiveHandlers()) #---- End Menu Setup ----# #---- Other Event Handlers ----# # Frame self.Bind(wx.EVT_ACTIVATE, self.OnActivate) self.Bind(wx.EVT_CLOSE, self.OnClose) self.Bind(ed_event.EVT_STATUS, self.OnStatus) # Find Dialog self.Bind(wx.EVT_FIND, self.nb.FindService.OnFind) self.Bind(wx.EVT_FIND_NEXT, self.nb.FindService.OnFind) self.Bind(wx.EVT_FIND_REPLACE, self.nb.FindService.OnFind) self.Bind(wx.EVT_FIND_REPLACE_ALL, self.nb.FindService.OnFind) self.Bind(wx.EVT_FIND_CLOSE, self.nb.FindService.OnFindClose) #---- End other event actions ----# #---- Final Setup Calls ----# self.LoadFileHistory(_PGET('FHIST_LVL', fmt='int')) # Call add on plugins self.LOG("[ed_main][info] Loading MainWindow Plugins") plgmgr = wx.GetApp().GetPluginManager() addons = MainWindowAddOn(plgmgr) addons.Init(self) self._handlers['menu'].extend(addons.GetEventHandlers()) self._handlers['ui'].extend(addons.GetEventHandlers(ui_evt=True)) self._shelf = iface.Shelf(plgmgr) self._shelf.Init(self) self._handlers['ui'].extend(self._shelf.GetUiHandlers()) self.LOG("[ed_main][info] Loading Generator plugins") generator.Generator(plgmgr).InstallMenu(menbar.GetMenuByName("tools")) # Set Perspective self.SetPerspective(_PGET('DEFAULT_VIEW')) self._mgr.Update()
def __init__(self, parent, id_, wsize, title): """Initialiaze the Frame and Event Handlers. @param wsize: Windows initial size @param title: Windows Title """ wx.Frame.__init__(self, parent, id_, title, size=wsize, style=wx.DEFAULT_FRAME_STYLE) self._mgr = wx.aui.AuiManager(flags=wx.aui.AUI_MGR_DEFAULT | \ wx.aui.AUI_MGR_TRANSPARENT_DRAG | \ wx.aui.AUI_MGR_TRANSPARENT_HINT) self._mgr.SetManagedWindow(self) viewmgr.PerspectiveManager.__init__(self, self._mgr, \ CONFIG['CACHE_DIR']) # Setup app icon and title self.SetTitle() util.SetWindowIcon(self) # Check if user wants Metal Style under OS X # NOTE: soon to be deprecated if wx.Platform == '__WXMAC__' and _PGET('METAL'): self.SetExtraStyle(wx.FRAME_EX_METAL) # Attributes self.LOG = wx.GetApp().GetLog() self._handlers = dict(menu=list(), ui=list()) #---- Sizers to hold subapplets ----# self.sizer = wx.BoxSizer(wx.VERTICAL) #---- Setup File History ----# self.filehistory = wx.FileHistory(_PGET('FHIST_LVL', 'int', 5)) #---- Status bar on bottom of window ----# self.CreateStatusBar(3, style=wx.ST_SIZEGRIP) self.SetStatusWidths([-1, 120, 155]) #---- End Statusbar Setup ----# #---- Notebook that contains the editting buffers ----# edit_pane = wx.Panel(self) self.nb = ed_pages.EdPages(edit_pane, wx.ID_ANY) edit_pane.nb = self.nb self.sizer.Add(self.nb, 1, wx.EXPAND) edit_pane.SetSizer(self.sizer) self._mgr.AddPane(edit_pane, wx.aui.AuiPaneInfo(). \ Name("EditPane").Center().Layer(1).Dockable(False). \ CloseButton(False).MaximizeButton(False). \ CaptionVisible(False)) #---- Command Bar ----# self._cmdbar = ed_cmdbar.CommandBar(edit_pane, ID_COMMAND_BAR) self._cmdbar.Hide() #---- Setup Toolbar ----# self.SetToolBar(ed_toolbar.EdToolBar(self)) if not _PGET('TOOLBAR'): self.GetToolBar().Hide() #---- End Toolbar Setup ----# #---- Menus ----# menbar = ed_menu.EdMenuBar() self._menus = dict(file=menbar.GetMenuByName("file"), edit=menbar.GetMenuByName("edit"), view=menbar.GetMenuByName("view"), viewedit=menbar.GetMenuByName("viewedit"), format=menbar.GetMenuByName("format"), settings=menbar.GetMenuByName("settings"), tools=menbar.GetMenuByName("tools"), lineformat=menbar.GetMenuByName("lineformat"), language=syntax.GenLexerMenu()) # Todo this should not be hard coded self._menus['view'].InsertMenu(5, ID_PERSPECTIVES, _("Perspectives"), self.GetPerspectiveControls()) ## Setup additional menu items self.filehistory.UseMenu(menbar.GetMenuByName("filehistory")) self._menus['settings'].AppendMenu(ID_LEXER, _("Lexers"), self._menus['language'], _("Manually Set a Lexer/Syntax")) # On mac, do this to make help menu appear in correct location # Note it must be done before setting the menu bar and after the # menus have been created. if wx.Platform == '__WXMAC__': wx.GetApp().SetMacHelpMenuTitleName(_("Help")) #---- Menu Bar ----# self.SetMenuBar(menbar) #---- Actions to take on menu events ----# self.Bind(wx.EVT_MENU_OPEN, self.UpdateMenu) if wx.Platform == '__WXGTK__': self.Bind(wx.EVT_MENU_HIGHLIGHT, \ self.OnMenuHighlight, id=ID_LEXER) self.Bind(wx.EVT_MENU_HIGHLIGHT, \ self.OnMenuHighlight, id=ID_EOL_MODE) # Collect Menu Event handler pairs self._handlers['menu'].extend([ # File Menu (ID_NEW, self.OnNew), (ID_OPEN, self.OnOpen), (ID_CLOSE, self.OnClosePage), (ID_CLOSE_WINDOW, self.OnClose), (ID_CLOSEALL, self.OnClosePage), (ID_SAVE, self.OnSave), (ID_SAVEAS, self.OnSaveAs), (ID_SAVEALL, self.OnSave), (ID_SAVE_PROFILE, self.OnSaveProfile), (ID_LOAD_PROFILE, self.OnLoadProfile), (ID_EXIT, wx.GetApp().OnExit), (ID_PRINT, self.OnPrint), (ID_PRINT_PRE, self.OnPrint), (ID_PRINT_SU, self.OnPrint), # Edit Menu (ID_FIND, self.nb.FindService.OnShowFindDlg), (ID_FIND_REPLACE, self.nb.FindService.OnShowFindDlg), (ID_QUICK_FIND, self.OnCommandBar), (ID_PREF, self.OnPreferences), # View Menu (ID_GOTO_LINE, self.OnCommandBar), (ID_VIEW_TOOL, self.OnViewTb), # Format Menu (ID_FONT, self.OnFont), # Tool Menu (ID_COMMAND, self.OnCommandBar), (ID_STYLE_EDIT, self.OnStyleEdit), (ID_PLUGMGR, self.OnPluginMgr), # Help Menu (ID_ABOUT, self.OnAbout), (ID_HOMEPAGE, self.OnHelp), (ID_DOCUMENTATION, self.OnHelp), (ID_CONTACT, self.OnHelp) ]) self._handlers['menu'].extend([(l_id, self.DispatchToControl) for l_id in syntax.SyntaxIds()]) # Extra menu handlers (need to work these into above system yet self.Bind(wx.EVT_MENU, self.DispatchToControl) self.Bind(wx.EVT_MENU, self.OnGenerate) self.Bind(wx.EVT_MENU_RANGE, self.OnFileHistory, id=wx.ID_FILE1, id2=wx.ID_FILE9) #---- End Menu Setup ----# #---- Other Event Handlers ----# # Frame self.Bind(wx.EVT_ACTIVATE, self.OnActivate) self.Bind(wx.EVT_CLOSE, self.OnClose) self.Bind(ed_event.EVT_STATUS, self.OnStatus) # Find Dialog self.Bind(wx.EVT_FIND, self.nb.FindService.OnFind) self.Bind(wx.EVT_FIND_NEXT, self.nb.FindService.OnFind) self.Bind(wx.EVT_FIND_REPLACE, self.nb.FindService.OnFind) self.Bind(wx.EVT_FIND_REPLACE_ALL, self.nb.FindService.OnFind) self.Bind(wx.EVT_FIND_CLOSE, self.nb.FindService.OnFindClose) #---- End other event actions ----# #---- Final Setup Calls ----# self._exiting = False self.LoadFileHistory(_PGET('FHIST_LVL', fmt='int')) self.UpdateToolBar() # Call add on plugins self.LOG("[main][info] Loading MainWindow Plugins ") plgmgr = wx.GetApp().GetPluginManager() addons = MainWindowAddOn(plgmgr) addons.Init(self) self._handlers['menu'].extend(addons.GetEventHandlers()) self._handlers['ui'].extend(addons.GetEventHandlers(ui_evt=True)) self._shelf = iface.Shelf(plgmgr) self._shelf.Init(self) self.LOG("[main][info] Loading Generator plugins") generator.Generator(plgmgr).InstallMenu(self._menus['tools']) # Set Perspective self.SetPerspective(_PGET('DEFAULT_VIEW')) self._mgr.Update()
def get_language_list(): #ids = [v[0] for v in synglob.LANG_MAP.values()] ids = syntax.SyntaxIds() names = [synglob.GetDescriptionFromId(id) for id in ids] names.sort() return names
def testSyntaxIds(self): """Test getting the Syntax Id List""" sids = syntax.SyntaxIds() self.assertTrue(sids is syntax.SYNTAX_IDS) for sid in sids: self.assertTrue(isinstance(sid, int))