def Start(): # # make this plugin show up in the 'Video' section # # in Plex. The L() function pulls the string out of the strings # # file in the Contents/Strings/ folder in the bundle # # see also: # # http://dev.plexapp.com/docs/mod_Plugin.html # # http://dev.plexapp.com/docs/Bundle.html#the-strings-directory Plugin.AddPrefixHandler(VIDEO_PREFIX, MainMenu, NAME, ICON, ART) Plugin.AddViewGroup("InfoList", viewMode="InfoList", mediaType="items") Plugin.AddViewGroup("List", viewMode="List", mediaType="items") # # set some defaults so that you don't have to # # pass these parameters to these object types # # every single time # # see also: # # http://dev.plexapp.com/docs/Objects.html MediaContainer.title1 = NAME MediaContainer.viewGroup = "List" MediaContainer.art = Resource.Load(ART) DirectoryItem.thumb = Resource.Load(ICON) VideoItem.thumb = Resource.Load(ICON) HTTP.CacheTime = CACHE_1HOUR check_login_token()
def __loadDB(): global __dbThread __dbThread = Thread.Create(__loadDBInThread) # Give the database thread time to start accepting queries while not __alive: time.sleep(0.1) # If the database needs to be created, load the defaults file & call the create function if __shouldCreate: try: path = "%s/Contents/DefaultDatabase.sql" % Plugin.__bundlePath if os.path.exists(path): f = open(path, "r") string = f.read() f.close() Exec(string) PMS.Log("(Framework) Loaded the default database file") Commit() Plugin.__callNamed("CreateDatabase") PMS.Log("(Framework) Created database tables") except: PMS.Log("(Framework) Error creating database tables", False) finally: Commit()
def configure(self): '''display a configuration dialog''' # name, optionType, label, description, value, options status, langs = commands.getstatusoutput('enchant-lsmod -list-dicts') if status == 0: langs = sorted(list(set(re.sub(' \(.*?\)', '', langs).split('\n')))) else: self.error(_("Error getting dictionaries list")) langs = [] if not langs: self.error(_("No dictionaries found.")) return l = [] l.append( Plugin.Option('lang', list, _('Default language'), _('Set the default language'), self.config.getPluginValue(self.name, 'lang', ''), langs)) response = Plugin.ConfigWindow(_('Spell configuration'), l).run() if response != None and response.has_key('lang'): self.config.setPluginValue(self.name, 'lang', str(response['lang'].value)) self.lang = self.config.getPluginValue(self.name, 'lang', '') self.applyAllConv(self.setLang) return True
def plugins(self): result = [] for p in Plugin.all_plugins("spanhandlers"): result.append(Plugin.spanhandler_description(p)) for p in Plugin.all_plugins("sublanguages"): result.append(Plugin.sublanguage_description(p)) result.sort(lambda a, b: cmp(a["keyword"], b["keyword"])) return result
def plugins(self): result = [] for p in Plugin.all_plugins('spanhandlers'): result.append(Plugin.spanhandler_description(p)) for p in Plugin.all_plugins('sublanguages'): result.append(Plugin.sublanguage_description(p)) result.sort(lambda a, b: cmp(a['keyword'], b['keyword'])) return result
def all_plugin_descriptions(): import json import Plugin return json.write({"spanhandlers": [Plugin.spanhandler_description(p) for p in Plugin.all_plugins('spanhandlers')], "sublanguages": [Plugin.sublanguage_description(p) for p in Plugin.all_plugins('sublanguages')] })
def windowConfigure(self): ''' show a window to choose encryptation''' l = [] l.append(Plugin.Option('encodeType', list, _('Encode:'), \ _('Select the Encryption of this conversation'), 'rijndael', \ self.getEncodeList())) l.append(Plugin.Option('defaultType', bool, _('Default type for this conversation:'), \ _('Is this option default?'), False)) self.configWindow = Plugin.ConfigWindow(_('Config Plugin'), l) response = self.configWindow.run() return response
def configure(self): '''Configuration Dialog''' l=[] l.append(Plugin.Option('users', str, _('Alowed users:'), '', self.config.getPluginValue( self.name, 'users', '' ))) response = Plugin.ConfigWindow(_('Remote Configuration'), l).run() if response != None: self.users = str(response['users'].value) self.allowed = self.users.split() self.config.setPluginValue(self.name,'users', self.users) return True
def __loadDefaults(): global __dict __dict = {} path = "%s/Contents/DefaultDict.json" % Plugin.__bundlePath if os.path.exists(path): f = open(path, "r") string = f.read() f.close() __dict = JSON.ObjectFromString(string) PMS.Log("(Framework) Loaded the default dictionary file") Plugin.__callNamed("CreateDict", addToLog=False) Set("Framework.LastCompatibilityVersion", PMS.FrameworkCompatibilityVersion, addToLog=False)
def configure(self): '''Configuration Dialog''' l = [] l.append(Plugin.Option('method', list, _('Formatting:'), '', self.config.getPluginValue\ ( self.name, 'method', '' ), METHODLIST)) response = Plugin.ConfigWindow(_('PlusPlus Configuration'), l).run() if response != None: self.method = response['method'].value self.config.setPluginValue(self.name, 'method', self.method) self.controller.refreshUserList() return True
def __loadDB(): import sqlite3 global __db shouldCreateTables = not os.path.exists(Plugin.__databasePath) __db = sqlite3.connect(Plugin.__databasePath) if shouldCreateTables: try: Plugin.__call(Plugin.__pluginModule.CreateTables) Commit() Log.Add("(Framework) Created database tables") except AttributeError: Log.Add("(Framework) Error creating database tables", False) pass
def __init__(self, videofile='', jsonfile=''): QMainWindow.__init__(self) self.settings = Settings.loadSettings() # play state self.playStat = GuiWindow.V_PAUSE self.videofile = videofile self.jsonfile = jsonfile self.txtfile = '' self.imgSource = ImageSource(self.videofile, self.jsonfile) self.plugin = Plugin(self.imgSource) self.lastPluginFnum = -1 self.frameW = self.settings['frameW'] self.frameH = self.settings[ 'frameH'] # will be updated when open video file self.scale = 1.0 self.offset = [0, 0] self.zoomed = False self.holdShift = False self.holdControl = False self.holdAlt = False self.labelfile = '' # self.rate = 30 self.fnum = 0 self.focusRoiId = -1 self.selRoiId = -1 self.fcnt = self.imgSource.getFrameCount() self.roiLabels = ( # name, editable ("label_name", False), ("label_id", False), ("roi_score", False), ("roi_x", True), ("roi_y", True), ("roi_w", True), ("roi_h", True), ("roi_id", False)) # setup timer tick self.timer = QTimer(self) self.timer.timeout.connect(self.tick) self.timer.start(1000 / self.rate) self.liftPressed = False # init gui self.guiInit() self.updateImage(self.fnum, True)
def ExternalPath(itemName): if len(Plugin.Prefixes()) == 0: return None global __publicResources global __mimeTypes if itemName is None: return ext = itemName[itemName.rfind("."):] if __mimeTypes.has_key(ext): __exposeResource(itemName, __mimeTypes[ext]) else: __exposeResource(itemName, "application/octet-stream") if __publicResources.has_key(itemName): return "%s/:/resources/%s" % (Plugin.Prefixes()[0], itemName) else: return None
def __init__(self, url, title=None, subtitle=None, summary=None, duration=None, thumb=None, art=None, **kwargs): if Plugin.LastPrefix: prefix = Plugin.LastPrefix else: prefix = Plugin.Prefixes()[0] if isinstance(url, basestring): key = "plex://127.0.0.1/video/:/webkit?url=%s&prefix=%s" % ( String.Quote(url, usePlus=True), prefix) else: key = url XMLObject.__init__(self, key=key, title=title, subtitle=subtitle, summary=summary, duration=duration, thumb=thumb, art=art, **kwargs) self.tagName = "Video"
def __init__(self, art=None, viewGroup=None, title1=None, title2=None, noHistory=False, replaceParent=False, disabledViewModes=None, **kwargs): XMLContainer.__init__(self, art=art, title1=title1, title2=title2, noHistory=noHistory, replaceParent=replaceParent, **kwargs) self.addTest(**testDefaults) if viewGroup is not None: if viewGroup in Plugin.ViewGroups().keys(): self.viewGroup = viewGroup else: PMS.Log( "(Framework) Couldn't assign view group '%s' to a MediaContainer - group doesn't exist" % viewGroup) if type(disabledViewModes).__name__ == "list": dvString = "" for view in disabledViewModes: if view in Plugin.ViewModes: if len(dvString) > 0: dvString += "," dvString += str(Plugin.ViewModes[view]) self.disabledViewModes = dvString
def __init__(self, controller, msn): '''Contructor''' Plugin.Plugin.__init__(self, controller, msn) self.description = _('Notify about diferent events using pynotify') self.authors = {'Mariano Guerra': 'luismarianoguerra at gmail dot com'} self.website = 'http://emesene-msn.blogspot.com' self.displayName = _('LibNotify') self.name = 'LibNotify' self.config = controller.config self.config.readPluginConfig(self.name) self.notifyOnline = int(self.config.getPluginValue(self.name, 'notifyOnline', '1')) self.notifyOffline = int(self.config.getPluginValue(self.name, 'notifyOffline', '1')) self.notifyNewMail = int(self.config.getPluginValue(self.name, 'notifyMail', '1')) self.notifyTyping = int(self.config.getPluginValue(self.name, 'typing', '0')) self.notifyNewMsg = int(self.config.getPluginValue(self.name, 'notifyMessage', '1')) self.notifyBusy = int(self.config.getPluginValue(self.name, 'notifyBusy', '0')) self.tray = self.controller.trayIcon.getNotifyObject() self.pixbuf = self.controller.theme.getImage('userPanel') self.controller = controller self.parser = controller.unifiedParser self.contacts = controller.contacts # ref.. self.notifications = [] self.onlineId = None self.offlineId = None self.newMsgId = None self.offMsgId = None self.typingId = None self.newMailId = None self.initMailId = None if Plugin.module_require(self.require, globals()): global error ERROR = _('there was a problem initializing the pynotify module')
def configure(self): l = [] l.append( Plugin.Option('showStatusImage', bool, _('Show status image:'), _('Show status image:'), self.showStatusImage)) response = Plugin.ConfigWindow(_('StatusHistory plugin config'), l).run() if response != None: self.showStatusImage = response['showStatusImage'].value self.config.setPluginValue(self.name, 'showStatusImage', str(int(self.showStatusImage))) if self.enabled: self.box.remove(self.comboBox) self.addComboBox(self.box) return True
def configure( self ): configuration = [] configuration.append(Plugin.Option('', gtk.Widget, '', '', gtk.Label(_("Enable/disable events to be logged:")))) for signal in self.signals: configuration.append(Plugin.Option(signal, bool, self.signals_labels[signal], \ '', bool(int(self.config.getPluginValue(self.name, signal, True))))) configWindow = Plugin.ConfigWindow( 'Logger', configuration ) configWindow.vbox.set_spacing(0) response = configWindow.run() if response != None: for signal in self.signals: if response.has_key(signal): self.config.setPluginValue( self.name, signal, str(int(response[signal].value)) ) self.stop() self.start() return True
def plugin_class(self): """ Get the actual plugin class for this cell, or None if the plugin class isn't available. :return: Plugin or None. :rtype: Plugin|None """ return Plugin.load(self.plugin_identifier, self.theme)
def test_plugin_init(self): sys.path.append('../plugins/') plugin = Plugin.Plugin('output_txt') self.assertEqual(plugin.name, 'output_txt') self.assertEqual(plugin.extension, 'txt') self.assertEqual(plugin.language, 'manual') self.assertEqual(plugin.type, plugin.OUTPUT_MODULE)
def load_plugins(self): potential_plugins = os.listdir(PLUGINS_MAIN_FOLDER) potential_plugins.remove(PLUGINS_INIT) self.pluginList = [] for plugin_name in potential_plugins: if not (PLUGINS_INIT in plugin_name) and not ('Plugin.py' in plugin_name): if ('.py' in plugin_name) and ('.pyc' not in plugin_name): plugin_name = plugin_name.replace('.py', '') self.pluginList.append(Plugin(plugin_name))
def __init__(self, controller, msn): '''Contructor''' Plugin.Plugin.__init__(self, controller, msn) self.description = _('Notifies various events using the new system notifications') self.authors = {'Mariano Guerra': 'luismarianoguerra at gmail dot com', 'Nicolas Espina Tacchetti': 'nicolasespina at gmail dot com', 'Panagiotis Koutsias': 'pkoutsias at gmail dot com',} self.website = 'http://emesene-msn.blogspot.com' self.displayName = _('NotifyOsdImproved') self.name = 'NotifyOsdImproved' self.config = controller.config self.config.readPluginConfig(self.name) self.controller = controller self.notifyOnline = int(self.config.getPluginValue(self.name, 'notifyOnline', '1')) self.notifyOffline = int(self.config.getPluginValue(self.name, 'notifyOffline', '1')) self.notifyNewMail = int(self.config.getPluginValue(self.name, 'notifyMail', '1')) self.notifyTyping = int(self.config.getPluginValue(self.name, 'typing', '0')) self.notifyFTInvite = int(self.config.getPluginValue(self.name, 'notifyFTInvite', '0')) self.notifyFTFinished = int(self.config.getPluginValue(self.name, 'notifyFTFinished', '0')) self.notifyNewMsg = int(self.config.getPluginValue(self.name, 'notifyMessage', '1')) #self.notifyStarted = int(self.config.getPluginValue(self.name, 'notifyStarted', '0')) self.notifyBusy = int(self.config.getPluginValue(self.name, 'notifyBusy', '0')) self.showNotification = int(self.config.getPluginValue(self.name, 'showNotification', '0')) #Disable Notification on Systray if not TrayIcon.disabled: self.checkBox = gtk.CheckMenuItem(_('Disable Notifications')) self.checkBox.set_active(self.showNotification) self.checkBox.connect('activate', self.on_showNotification_activate) self.tray = self.controller.trayIcon.getNotifyObject() self.pixbuf = self.controller.theme.getImage('userPanel') self.parser = controller.unifiedParser self.contacts = controller.contacts # ref.. self.notifications = [] # callbacks ids self.onlineId = None self.offlineId = None self.newMsgId = None self.offMsgId = None self.typingId = None self.fTInviteId = None self.fTFinishedId = None self.newMailId = None self.initMailId = None if Plugin.module_require(self.require, globals()): global error ERROR = _('there was a problem initializing the pynotify module')
def OnInit(self): c = {} c['icq'] = None p = Plugin.load_plugins('../../plugins', '../plugins', connector = c) frame = OptionsFrame(None, -1, wx.EmptyIcon(), p) self.SetTopWindow(frame) frame.CentreOnParent() frame.Show(True) return True
def __str__(self): if "key" in self.__dict__: if type(self.key).__name__ == "function": queryString = create_query_string(self.__kwargs) if queryString and len(queryString) > 0: queryString = '?' + queryString else: queryString = '' return "%s/:/function/%s%s%s" % (Plugin.CurrentPrefix(), self.key.__name__, self.__ext, queryString) return XMLObject.__str__(self)
def __init__(self, host, port=1604): """Initialize a Plugin class. Keyword arguments: host -- server host port -- used port [default: 1604] """ self._host = host self._port = port self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Creates an INET socket STREAM-type self.s.bind((host, port)) # Binds the socket to an host and a port self.plugin = Plugin.Plugin("Plugins")
def configure(self): dataM = [] dataM.append(Plugin.Option('time', str, _('Check every [min]:'), '',\ self.config.getPluginValue( self.name, 'time', '5' )) ) dataM.append(Plugin.Option('client', str, _('Client to execute:'), '',\ self.config.getPluginValue( self.name, 'client', 'thunderbird' ))) dataM.append( Plugin.Option( 'user', str, _('Username:'******'', self.config.getPluginValue(self.name, 'user', _('user')))) #dataM.append( Plugin.Option( 'pass', str, 'password:'******'', # self.config.getPluginValue( self.name, 'pass', '*****')) ) self.confW = Plugin.ConfigWindow(_('Mail checker config'), dataM) #Let's keep the pass entry secret label = gtk.Label(_('Password:'******'pass', '')) entry.set_visibility(False) #with this op. hbox = gtk.HBox() hbox.pack_start(label) hbox.pack_start(entry) self.confW.vbox.pack_start(hbox) self.confW.vbox.show_all() r = self.confW.run() passwd = str(entry.get_text()) if r is not None: self.config.setPluginValue(self.name, 'time', r['time'].value) self.config.setPluginValue(self.name, 'user', r['user'].value) self.config.setPluginValue(self.name, 'pass', passwd) self.config.setPluginValue(self.name, 'client', r['client'].value) #self.start() return True
def ToElement(self): # Modify the key to call a function with the given kwargs queryString = create_query_string(self.__kwargs) if queryString and len(queryString) > 0: queryString = '?' + queryString else: queryString = '' self.key = "%s/:/function/%s%s%s" % (Plugin.CurrentPrefix(), self.__obj.key.__name__, self.__ext, queryString) return XMLObject.ToElement(self)
def __init__(self,videofile='',jsonfile=''): QMainWindow.__init__(self) self.settings = Settings.loadSettings(); # play state self.playStat = GuiWindow.V_PAUSE self.videofile = videofile self.jsonfile = jsonfile self.txtfile = '' self.imgSource = ImageSource(self.videofile,self.jsonfile) self.plugin = Plugin(self.imgSource) self.lastPluginFnum = -1 self.frameW = self.settings['frameW'] self.frameH = self.settings['frameH'] # will be updated when open video file self.scale = 1.0 self.offset = [0,0] self.zoomed = False self.holdShift = False self.holdControl = False self.holdAlt = False self.labelfile = '' # self.rate = 30 self.fnum = 0 self.focusRoiId = -1 self.selRoiId = -1 self.fcnt = self.imgSource.getFrameCount() self.roiLabels=( # name, editable ("label_name",False), ("label_id", False), ("roi_score", False), ("roi_x", True), ("roi_y", True), ("roi_w", True), ("roi_h", True), ("roi_id", False) ) # setup timer tick self.timer = QTimer(self) self.timer.timeout.connect(self.tick) self.timer.start(1000/self.rate) self.liftPressed = False # init gui self.guiInit() self.updateImage(self.fnum,True)
def __init__(self, title=None, subtitle=None, summary=None, thumb=None, **kwargs): DirectoryItem.__init__(self, "%s/:/prefs" % Plugin.Prefixes()[0], title=title, subtitle=subtitle, summary=summary, thumb=thumb, settings=True, **kwargs)
def __load(): global __prefs global __prefsPath path = "%s/Contents/DefaultPrefs.json" % Plugin.__bundlePath if os.path.exists(path): f = open(path, "r") string = f.read() f.close() __prefs = JSON.ObjectFromString(string) PMS.Log("(Framework) Loaded the default preferences file") Plugin.__callNamed("CreatePrefs", addToLog=False) if os.path.exists(__prefsPath): try: f = open(__prefsPath, "r") userPrefs = XML.ElementFromString(f.read()) f.close() for userPref in userPrefs: for pref in __prefs: if pref["id"] == userPref.tag: pref["value"] = userPref.text PMS.Log("(Framework) Loaded the user preferences file") except: PMS.Log("(Framework) Exception when reading preferences")
def configure(self): dataM = [] dataM.append( Plugin.Option( 'use_ssl', bool, _('Use SSL'), '', \ bool(int(self.config.getPluginValue(self.name, 'use_ssl', '1' )))) ) dataM.append( Plugin.Option( 'notifications', bool, \ _('Email notification - requires: ') + _('NotifyOsdImproved'), '', \ bool(int(self.config.getPluginValue(self.name, \ 'notifications', '0' )))) ) dataM.append( Plugin.Option( 'time', str, _('Check every [min]:'), '',\ self.config.getPluginValue( self.name, 'time', '5' )) ) dataM.append( Plugin.Option( 'server', str, _('IMAP server:'), '', \ self.config.getPluginValue( self.name, 'server', 'pop.test.com' ))) dataM.append( Plugin.Option('client', str, _('Client to execute:'),'',\ self.config.getPluginValue( self.name, 'client', 'thunderbird' )) ) dataM.append( Plugin.Option( 'user', str, _('Username:'******'', \ self.config.getPluginValue( self.name, 'user', _('user'))) ) #dataM.append( Plugin.Option( 'pass', str, 'password:'******'', self.config.getPluginValue( self.name, 'pass', '*****')) ) self.confW = Plugin.ConfigWindow(_('Mail checker config'), dataM) #Let's keep the pass entry secret label = gtk.Label(_('Password:'******'') entry.set_visibility(False) #with this op. hbox = gtk.HBox() hbox.pack_start(label) hbox.pack_start(entry) self.confW.vbox.pack_start(hbox) self.confW.vbox.show_all() r = self.confW.run() passwd = str(entry.get_text()) if r is not None: self.config.setPluginValue(self.name, 'time', r['time'].value) self.config.setPluginValue(self.name, 'server', r['server'].value) self.config.setPluginValue(self.name, 'user', r['user'].value) self.config.setPluginValue(self.name, 'pass', passwd) self.config.setPluginValue(self.name, 'client', r['client'].value) self.config.setPluginValue(self.name, 'use_ssl', str(int(r['use_ssl'].value))) self.notifications = r['notifications'].value self.config.setPluginValue(self.name, 'notifications', \ str(int(self.notifications))) #self.start() return True
def __init__(self, art=None, viewGroup=None, title1=None, title2=None, noHistory=False, replaceParent=False): """ Creates an empty MediaContainer object. @param art: The name of an exposed artwork image in the resources directory. @return: MediaContainer """ MediaObject.__init__(self, "MediaContainer") self.SetAttr("size", "0") self.SetAttr("art", Plugin.ExposedResourcePath(art)) self.SetAttr("title1", title1) self.SetAttr("title2", title2) if noHistory: self.SetNoHistory(True) if replaceParent: self.SetReplaceParent(True) if viewGroup is not None: self.SetViewGroup(viewGroup)
def visit_sublanguage(self, commandline, doc): commandparts = commandline.split(' ', 1) command = commandparts[0] if len(commandparts) > 1: args = commandparts[1] else: args = '' (err, plugin) = Plugin.find_plugin('sublanguages', command, 'SublanguageHandler') if plugin: try: plugin(args, doc, self) except BlockSyntaxError, e: import Inline self.add(Inline.MarkupError(True, 'pluginerror', e.message)) except:
def _loadPlugins(self): self.importPlugins = [] self.exportPlugins = [] self.plugins = [] def loadPlugins(pluginModule, collection, loader): plugins = loader(self, pluginModule) if self.options.verbose: for p in plugins: self.reportDebug("Loaded plugin: %s" % p) collection.extend(plugins) for plugin in Plugin.getAvailablePluginModules(): loadPlugins(plugin, self.plugins, Plugin.loadInteractivePlugins) loadPlugins(plugin, self.importPlugins, Plugin.loadImporterPlugins) loadPlugins(plugin, self.exportPlugins, Plugin.loadExporterPlugins)
def __init__(self, controller, msn): Plugin.Plugin.__init__(self, controller, msn) self.description = _('A gmail notifier') self.authors = {'Jacopo Lamanna': '*****@*****.**'} self.website = 'www.jazzenco.org' self.displayName = _('gmailNotify') self.name = 'gmailNotify' self.config = controller.config self.config.readPluginConfig(self.name) self.enabled = False self.controller = controller self.isbutt = 0 self.checking = False self.deffun = Plugin.Function(self.function, self.callback)
def loadPlugins(self): '''this method loads all Plugins from the directory''' self.plugins = [] PClasses = getPluginClasses() for pluginClass in PClasses: try: p = pluginClass( self, Plugin.PyCCPluginToBackendInterface(self, self.server), config.PyCCPluginConfig(self.config, pluginClass.__name__)) p.init() p.registerInManager() except Exception as e: traceback.print_exception(*sys.exc_info()) print('Could not load plugin {0}:\n{1}: {2}'.format( pluginClass.__name__, type(e).__name__, str(e)), file=sys.stderr)
def run(self,configfile,register=False,verbose=False): self.cwd = os.getcwd() self.ph = Plugin.plghandler(self) self.configfile = configfile self.config = ParseConfig.readconfigfile(configfile) self.admins = ParseConfig.parselist(self.config["admins"],",") self.verbose = verbose self.tasclient = Client.tasclient(self) for p in ParseConfig.parselist(self.config["plugins"],","): self.ph.addplugin(p,self.tasclient) self.tasclient.events.onconnected = self.Dologin self.tasclient.events.onloggedin = self.onlogin self.reg = register notice("Connecting to %s:%i" % (self.config["serveraddr"],int(self.config["serverport"]))) self.tasclient.connect(self.config["serveraddr"],int(self.config["serverport"]))
def parse(s, result = None): if result is None: result = [] while s: (frag, what, rest) = _collectFragment(s) _appendRegexMarkup(frag, result) if what is None or what == ']': return (result, rest) elif what == '[': (name, pos) = nearest_match(rest, [('spacepos', ' '), ('spacepos', '\n'), ('spacepos', '\r'), ('spacepos', '\t'), ('closepos', ']')]) if name == 'spacepos': handlername = rest[:pos] args = rest[pos + 1:] elif name == 'closepos': handlername = rest[:pos] args = rest[pos:] else: handlername = rest args = '' if not handlername or not handlername[0].isalpha(): handlername = 'invalid_spanhandler_name' args = rest (err, plugin) = Plugin.find_plugin('spanhandlers', handlername, 'SpanHandler') if plugin: s = plugin(args, result) else: result.append(MarkupError(False, 'missingspanhandler', err)) s = args else: raise 'Invalid result from _collectFragment', what return (result, '')
class GuiWindow(QMainWindow): # state for self.playStat V_PAUSE = 0 V_PLAYING = 1 def __init__(self,videofile='',jsonfile=''): QMainWindow.__init__(self) self.settings = Settings.loadSettings(); # play state self.playStat = GuiWindow.V_PAUSE self.videofile = videofile self.jsonfile = jsonfile self.txtfile = '' self.imgSource = ImageSource(self.videofile,self.jsonfile) self.plugin = Plugin(self.imgSource) self.lastPluginFnum = -1 self.frameW = self.settings['frameW'] self.frameH = self.settings['frameH'] # will be updated when open video file self.scale = 1.0 self.offset = [0,0] self.zoomed = False self.holdShift = False self.holdControl = False self.holdAlt = False self.labelfile = '' # self.rate = 30 self.fnum = 0 self.focusRoiId = -1 self.selRoiId = -1 self.fcnt = self.imgSource.getFrameCount() self.roiLabels=( # name, editable ("label_name",False), ("label_id", False), ("roi_score", False), ("roi_x", True), ("roi_y", True), ("roi_w", True), ("roi_h", True), ("roi_id", False) ) # setup timer tick self.timer = QTimer(self) self.timer.timeout.connect(self.tick) self.timer.start(1000/self.rate) self.liftPressed = False # init gui self.guiInit() self.updateImage(self.fnum,True) def guiInit(self): # create main menu mainMenu = self.menuBar() mainMenu.setNativeMenuBar(False) # File fileMenu = mainMenu.addMenu('&File') # add Open to File openButton = QAction('Open...',self) openButton.triggered.connect(self.openFileWin) fileMenu.addAction(openButton) saveVideoButton = QAction('Save Video With ROIs',self) saveVideoButton.triggered.connect(self.saveVideo) fileMenu.addAction(saveVideoButton) saveJsonButton = QAction('Save Json',self) saveJsonButton.triggered.connect(self.saveJson) fileMenu.addAction(saveJsonButton) # add SaveMask to File saveMaskButton = QAction('Save Mask',self) saveMaskButton.triggered.connect(self.saveMask) fileMenu.addAction(saveMaskButton) # add exit to File exitButton = QAction('Exit',self) exitButton.triggered.connect(self.close) fileMenu.addAction(exitButton) # settings settingsMenu = mainMenu.addMenu('&Settings') colorButton = QAction('Color',self) colorButton.triggered.connect(self.pickColor) settingsMenu.addAction(colorButton) bgColorButton = QAction('BgColor',self) bgColorButton.triggered.connect(self.pickBgColor) settingsMenu.addAction(bgColorButton) focusColorButton = QAction('FocusColor',self) focusColorButton.triggered.connect(self.pickFocusColor) settingsMenu.addAction(focusColorButton) focusBgColorButton = QAction('FocusBgColor',self) focusBgColorButton.triggered.connect(self.pickFocusBgColor) settingsMenu.addAction(focusBgColorButton) selColorButton = QAction('SelColor',self) selColorButton.triggered.connect(self.pickSelColor) settingsMenu.addAction(selColorButton) saveSettingsButton = QAction('Save',self) saveSettingsButton.triggered.connect(self.saveSettings) settingsMenu.addAction(saveSettingsButton) # help helpMenu = mainMenu.addMenu('&Help') # create layouts widget = QWidget(self) layout = QHBoxLayout(widget) widgetL = QWidget(self) layoutL = QVBoxLayout(widgetL) widgetR = QWidget(self) layoutR = QGridLayout(widgetR); layoutR.setAlignment(Qt.AlignTop) layout.addWidget(widgetL) layout.addWidget(widgetR) # left panel self.picture = QLabel(self) self.picture.setPixmap(QPixmap(self.frameW,self.frameH)) self.slider = QSlider(Qt.Horizontal) self.slider.resize(self.frameW,10) self.slider.valueChanged.connect(self.sliderChanged) widgetCtrl = QWidget(self) layoutCtrl = QHBoxLayout(widgetCtrl); self.playButton = QPushButton('Play') self.playButton.clicked.connect(self.playClicked) self.nextButton = QPushButton('Next') self.nextButton.clicked.connect(self.nextClicked) self.lastButton = QPushButton('Last') self.lastButton.clicked.connect(self.lastClicked) self.beginButton = QPushButton('Begin') self.beginButton.clicked.connect(self.beginClicked) self.endButton = QPushButton('End') self.endButton.clicked.connect(self.endClicked) self.gotoLabel = QLabel(self) self.gotoLabel.setText(' fnum:') self.gotoInput = QLineEdit(self) self.gotoInput.setText('0') self.gotoInput.editingFinished.connect(self.gotoChanged) layoutCtrl.addWidget(self.beginButton) layoutCtrl.addWidget(self.lastButton) layoutCtrl.addWidget(self.playButton) layoutCtrl.addWidget(self.nextButton) layoutCtrl.addWidget(self.endButton) layoutCtrl.addWidget(self.gotoLabel) layoutCtrl.addWidget(self.gotoInput) layoutL.addWidget(self.picture) layoutL.addWidget(self.slider) layoutL.addWidget(widgetCtrl) # right panel space = QLabel(self) layoutR.addWidget(space,0,0) self.RoiInfo = {} for i in range(8): label = QLabel(self) label.setText(self.roiLabels[i][0]) if self.roiLabels[i][1]: edit = QLineEdit(self) edit.editingFinished.connect(self.inputChanged) elif self.roiLabels[i][0] == 'label_name': edit = QPushButton(self) edit.clicked.connect(self.chLabelClicked) else: edit = QLabel(self) edit.setFixedWidth(150) self.RoiInfo[self.roiLabels[i][0]] = edit layoutR.addWidget(label,i+1,0) layoutR.addWidget(edit,i+1,1) space = QLabel(self) layoutR.addWidget(space,9,0) self.addButton = QPushButton('Add ROI') self.addButton.setCheckable(True) self.addButton.clicked.connect(self.addClicked) layoutR.addWidget(self.addButton,10,0) self.delButton = QPushButton('Delete ROI') self.delButton.clicked.connect(self.delClicked) layoutR.addWidget(self.delButton,11,0) self.tmplMatchButton = QPushButton('TmplMatch') self.tmplMatchButton.setCheckable(True) self.tmplMatchButton.clicked.connect(self.tmplMatch) layoutR.addWidget(self.tmplMatchButton,12,0) self.slider.setValue(0) self.setCentralWidget(widget) def openFileWin(self): self.fileWin = FileWindow(self) self.fileWin.show() def openVideo(self): self.videofile = str(QFileDialog.getOpenFileName(self)) self.updateVideo(self.videofile) def updateVideo(self,filename): self.imgSource.openVideo(filename) self.videoParamUpdate() def openImgDir(self): dirname = str(QFileDialog.getExistingDirectory(self)) self.updateImgDir(dirname) def updateImgDir(self,dirname): self.imgSource.openImgDir(dirname) self.videoParamUpdate() def videoParamUpdate(self): self.fcnt = self.imgSource.getFrameCount() self.fnum = 0 self.slider.setValue(self.fnum) # will call sliderChanged (w,h) = self.imgSource.getSize() self.imgSize = (w,h) self.scale = float(self.frameW) / w self.frameW = int(w*self.scale+0.5) self.frameH = int(h*self.scale+0.5) self.updateImage(self.fnum,True) def openJson(self): self.jsonfile = str(QFileDialog.getOpenFileName(self)) self.updateJson(self.jsonfile) def updateJson(self,filename): self.imgSource.openRoiJson(filename) self.lastPluginFnum = -1 self.updateImage(self.fnum,True) def updateTxt(self,filename): self.imgSource.openRoiTxt(filename) self.lastPluginFnum = -1 self.updateImage(self.fnum,True) def openLabel(self): self.labelfile = str(QFileDialog.getOpenFileName(self)) self.updateLabel(self.labelfile) def updateLabel(self,filename): if not os.path.isfile(filename): return self.imgSource.openLabel(filename) self.imgSource.updateRoiLabel() def openUpdateDir(self): dirname = str(QFileDialog.getExistingDirectory(self)) self.imgSource.updateInfoFromDir(dirname) def saveVideo(self): self.imgSource.saveVideo() def saveJson(self): self.imgSource.saveJson() def saveMask(self): self.imgSource.saveMask() def pickColor(self): color = QColorDialog.getColor() self.settings['Color'] = (color.red(),color.green(),color.blue()) self.updateImage(self.fnum,False) def pickBgColor(self): color = QColorDialog.getColor() self.settings['BgColor'] = (color.red(),color.green(),color.blue()) self.updateImage(self.fnum,False) def pickFocusColor(self): color = QColorDialog.getColor() self.settings['FocusColor'] = (color.red(),color.green(),color.blue()) self.updateImage(self.fnum,False) def pickFocusBgColor(self): color = QColorDialog.getColor() self.settings['FocusBgColor'] = (color.red(),color.green(),color.blue()) self.updateImage(self.fnum,False) def pickSelColor(self): color = QColorDialog.getColor() self.settings['SelColor'] = (color.red(),color.green(),color.blue()) self.updateImage(self.fnum,False) def saveSettings(self): Settings.saveSettings(self.settings) def distance(self,pos1,pos2): dx = pos1[0]-pos2[0] dy = pos1[1]-pos2[1] return math.sqrt(dx*dx+dy*dy) def eventFilter(self, source, event): """ pick up mouse event """ if self.playStat == GuiWindow.V_PAUSE and self.imgSource.roisInputEnable and source == self.picture: update = False if event.type() == QEvent.MouseMove: pos = event.pos() (id,touch) = self.roiEditor.touched( (int((pos.x()-self.offset[0])/self.scale), int((pos.y()-self.offset[1])/self.scale))) self.updateCursor(id,touch) if event.buttons() == Qt.LeftButton: update,self.selRoiId = self.roiEditor.dragging( (int((pos.x()-self.offset[0])/self.scale), int((pos.y()-self.offset[1])/self.scale)), self.selRoiId) elif self.roiEditor.dragged: update,self.selRoiId = self.roiEditor.dragging((),self.selRoiId) if id != self.focusRoiId: self.focusRoiId = id update = True elif event.type() == QEvent.MouseButtonPress: if event.buttons() == Qt.LeftButton: source.setFocus() self.liftPressed = True self.pressedPos = event.pos() elif event.type() == QEvent.MouseButtonRelease: pos = event.pos() if self.liftPressed: distance = self.distance((pos.x(),pos.y()), (self.pressedPos.x(), self.pressedPos.y())) # select only press and release at same position if distance < 10: # pos on real image transPos = (int((pos.x()-self.offset[0])/self.scale), int((pos.y()-self.offset[1])/self.scale)) if self.roiEditor.addVertexState: # add vertex only if mouse not in movinge self.roiEditor.addVertex(transPos,self.selRoiId) update = True else: (id,touch) = self.roiEditor.touched(transPos) if id != self.selRoiId: self.selRoiId = id update = True else: update,self.selRoiId = self.roiEditor.dragging((),self.selRoiId) if self.roiEditor.zoomState: self.roiEditor.setZoomStateOff() if distance > 10: # minimum zoom size (ret,scale,offset) = self.zoom( (self.roiEditor.zoomRoi[0], self.roiEditor.zoomRoi[1], self.roiEditor.zoomRoi[2]-self.roiEditor.zoomRoi[0], self.roiEditor.zoomRoi[3]-self.roiEditor.zoomRoi[1]) ) if ret: self.zoomed = True self.scale = scale self.offset = offset update = True if update: self.updateImage(self.fnum,False) return QMainWindow.eventFilter(self, source, event) def keyPressEvent(self,event): if self.holdShift: v = -1 else: v = 1 if event.key() == Qt.Key_Delete or event.key() == Qt.Key_Backspace: if self.holdShift: self.delRois() else: self.delClicked() elif event.key() == Qt.Key_Up: pass #if self.holdControl: # self.roiEditor.changeY(-1,self.focusRoiId) #else: # self.roiEditor.changeY(-v,self.focusRoiId) # self.roiEditor.changeH(v,self.focusRoiId) elif event.key() == Qt.Key_Down: pass #if self.holdControl: # self.roiEditor.changeY(1,self.focusRoiId) #else: # self.roiEditor.changeH(v,self.focusRoiId) elif event.key() == Qt.Key_Left: pass #if self.holdControl: # self.roiEditor.changeX(-1,self.focusRoiId) #else: # self.roiEditor.changeX(-v,self.focusRoiId) # self.roiEditor.changeW(v,self.focusRoiId) elif event.key() == Qt.Key_Right: pass #if self.holdControl: # self.roiEditor.changeX(1,self.focusRoiId) #else: # self.roiEditor.changeW(v,self.focusRoiId) elif event.key() == Qt.Key_Space: if self.holdShift: self.lastClicked() else: self.nextClicked() elif event.key() == Qt.Key_Shift: self.holdShift = True elif event.key() == Qt.Key_Control: self.holdControl = True self.roiEditor.setAddVertexState(True,self.selRoiId) elif event.key() == Qt.Key_Alt: self.holdAlt = True elif event.key() == Qt.Key_Escape: self.zoomed = False (w,h) = self.imgSource.getSize() self.scale = float(self.frameW) / w self.offset = [0,0] self.updateImage(self.fnum,False) def keyReleaseEvent(self,event): if event.key() == Qt.Key_Alt: self.holdAlt = False elif event.key() == Qt.Key_Shift: self.holdShift = False elif event.key() == Qt.Key_Control: self.holdControl = False self.roiEditor.setAddVertexState(False,self.selRoiId) self.updateImage(self.fnum,False) def updateCursor(self,id,touch): if self.roiEditor.addVertexState and self.selRoiId >= 0: QApplication.setOverrideCursor(Qt.CrossCursor) return if id >= 0 and id == self.selRoiId: if touch == RoiEditor.TopLeft or touch == RoiEditor.BottomRight: QApplication.setOverrideCursor(Qt.SizeFDiagCursor) elif touch == RoiEditor.Top or touch == RoiEditor.Bottom: QApplication.setOverrideCursor(Qt.SizeVerCursor) elif touch == RoiEditor.TopRight or touch == RoiEditor.BottomLeft: QApplication.setOverrideCursor(Qt.SizeBDiagCursor) elif touch == RoiEditor.Left or touch == RoiEditor.Right: QApplication.setOverrideCursor(Qt.SizeHorCursor) elif touch == RoiEditor.Center: QApplication.setOverrideCursor(Qt.SizeAllCursor) else: QApplication.setOverrideCursor(Qt.ArrowCursor) else: QApplication.setOverrideCursor(Qt.ArrowCursor) def tick(self): """ timer callback to play """ # if sources are opened self.slider.setValue(self.fnum) # will call sliderChanged if(self.playStat == GuiWindow.V_PLAYING): if self.fnum < self.fcnt-1: self.fnum += 1 def playClicked(self): if self.playStat == GuiWindow.V_PLAYING: self.playStat = GuiWindow.V_PAUSE self.playButton.setText('Play') else: self.playStat = GuiWindow.V_PLAYING self.playButton.setText('Pause') def lastClicked(self): if self.fnum>0: self.fnum -= 1 self.slider.setValue(self.fnum) # will call sliderChanged def nextClicked(self): if self.fnum < self.fcnt-1: self.fnum += 1 self.slider.setValue(self.fnum) # will call sliderChanged def beginClicked(self): self.fnum = 0 self.slider.setValue(self.fnum) # will call sliderChanged def endClicked(self): self.fnum = self.fcnt - 1 self.slider.setValue(self.fnum) # will call sliderChanged def delClicked(self): if self.imgSource.roisInputEnable: self.roiEditor.delRoi(self.selRoiId) self.updateImage(self.fnum,False) def delRois(self): """ delete all rois in view except selected """ if self.imgSource.roisInputEnable: self.roiEditor.delRois(self.zoomed,self.selRoiId) self.updateImage(self.fnum,False) def addClicked(self): if self.imgSource.roisInputEnable: self.roiEditor.setAddRoiState(self.addButton.isChecked()) self.selRoiId = -1 self.updateImage(self.fnum,False) def tmplMatch(self): self.plugin.setTmplMatchEnable(self.tmplMatchButton.isChecked()) def gotoChanged(self): v = int(self.gotoInput.text()) if v < 0: self.fnum = 0 elif v >= self.fcnt: self.fnum = self.fcnt else: self.fnum = v self.slider.setValue(self.fnum) # will call sliderChanged def inputChanged(self): if self.imgSource.roisInputEnable: self.roiEditor.setValues(self.RoiInfo,self.selRoiId) self.updateImage(self.fnum,False) def chLabelClicked(self): if self.selRoiId <0: return items = self.imgSource.getLabelNameList() qitem,ok = QInputDialog.getItem(self,'Label_Name selection','list of labels',items,0,False) if ok: item = str(qitem) ret,id = self.imgSource.getLabelId(item) self.RoiInfo['label_name'].setText(item) self.RoiInfo['label_id'].setText(str(id)) self.inputChanged() def sliderChanged(self): # if sources are opened self.fnum = self.slider.value() self.selRoiId = -1 self.gotoInput.setText(str(self.fnum)) self.updateImage(self.fnum,True) def zoom(self,roi): ''' roi: (x,y,w,h) return (ret,scale,offset) ''' if roi[2] == 0 or roi[3] == 0: return (False,1.0,(0,0)) x,y,w,h = float(roi[0]),float(roi[1]),float(roi[2]),float(roi[3]) r = float(self.frameW)/float(self.frameH) if w/h >= r: w1,h1 = w,w/r x1,y1 = x,y-(h1-h)/2 else: w1,h1 = h*r,h x1,y1 = x-(w1-w)/2,y scale = float(self.frameW) / w1 return (True,scale,(-x1*scale,-y1*scale)) def updateImage(self,fnum,newEditor): if self.lastPluginFnum == fnum: ret1,img = self.imgSource.getImage(fnum) ret2,rois = self.imgSource.getRois(fnum) else: (ret1,img),(ret2,rois) = self.plugin.beginProcess(fnum) if ret1 and ret2: self.lastPluginFnum = fnum newEditor = True if ret2 and newEditor: self.roiEditor = RoiEditor(rois,self.imgSize) self.addButton.setChecked(False) if ret1: w,h = self.frameW,self.frameH affine = np.float32([[self.scale,0,self.offset[0]], [0,self.scale,self.offset[1]]]) img1 = cv2.warpAffine(img,affine,(w,h)) img2 = cv2.cvtColor(img1,cv2.COLOR_BGR2RGB) if ret2: self.drawRois(img2,rois,self.selRoiId,self.focusRoiId) img3 = QImage(img2,w,h,QImage.Format_RGB888) self.picture.setPixmap(QPixmap.fromImage(img3)) self.slider.resize(w,10) self.slider.setMaximum(self.fcnt-1) self.addButton.setChecked(self.roiEditor.addRoiState) def drawRois(self,frame,rois,selRoiId,focusId): edge = 3 hasSel = False for roi in rois: x0,y0 = self.posToScr((roi['roi_x'],roi['roi_y'])) w,h = self.sizeToScr((roi['roi_w'],roi['roi_h'])) x1 = x0 + w - 1 y1 = y0 + h - 1 label_id = roi['roi_label']['label_id'] label_name = roi['roi_label']['label_name'] if roi['roi_id'] == selRoiId: hasSel = True self.updateRoiInfo(roi) self.drawSelRoi(frame,roi,edge) elif roi['roi_id'] == focusId: if label_id > 0: cv2.rectangle(frame,(x0,y0),(x1,y1), self.settings['FocusColor'],1) else: cv2.rectangle(frame,(x0,y0),(x1,y1), self.settings['FocusBgColor'],1) else: if label_id > 0: cv2.rectangle(frame,(x0,y0),(x1,y1), self.settings['Color'],1) #cv2.rectangle(frame,(x0,y0),(x1,y1), # ColorTable[getColor(label_id)],1) else: cv2.rectangle(frame,(x0,y0),(x1,y1),self. settings['BgColor'],1) self.drawVertex(frame,roi) # end of for if not hasSel: self.clearRoiInfo() if self.imgSource.roisInputEnable and self.roiEditor.zoomState: cv2.rectangle(frame, (int(self.roiEditor.zoomRoi[0]*self.scale+self.offset[0]), int(self.roiEditor.zoomRoi[1]*self.scale+self.offset[1])), (int(self.roiEditor.zoomRoi[2]*self.scale+self.offset[0]), int(self.roiEditor.zoomRoi[3]*self.scale+self.offset[1])), (200,0,200),1) def drawSelRoi(self,frame,roi,edge=3): x0,y0 = self.posToScr((roi['roi_x'],roi['roi_y'])) w,h = self.sizeToScr((roi['roi_w'],roi['roi_h'])) x1 = x0 + w - 1 y1 = y0 + h - 1 cv2.rectangle(frame,(x0,y0),(x1,y1),self.settings['SelColor'],1) if not self.holdControl: cv2.circle(frame,(x0,y0),edge+1,self.settings['SelColor'],1) cv2.circle(frame,(x0,y1),edge+1,self.settings['SelColor'],1) cv2.circle(frame,(x1,y0),edge+1,self.settings['SelColor'],1) cv2.circle(frame,(x1,y1),edge+1,self.settings['SelColor'],1) cv2.rectangle(frame, (x0+w/2-edge,y0-edge), (x0+w/2+edge,y0+edge), self.settings['SelColor'],1) cv2.rectangle(frame, (x0-edge,y0+h/2-edge), (x0+edge,y0+h/2+edge), self.settings['SelColor'],1) cv2.rectangle(frame, (x1-edge,y0+h/2-edge), (x1+edge,y0+h/2+edge), self.settings['SelColor'],1) cv2.rectangle(frame, (x0+w/2-edge,y1-edge), (x0+edge+w/2,y1+edge), self.settings['SelColor'],1) def drawVertex(self,frame,roi,edge=3): if not 'vertices' in roi: return beginPos = () lastPos = () for pos in roi['vertices']: scrPos = self.posToScr(pos) if self.roiEditor.addVertexState: cv2.circle(frame,scrPos,edge+1,self.settings['VertexColor'],1) if len(beginPos) == 0: beginPos = scrPos if len(lastPos) > 0: cv2.line(frame,lastPos,scrPos,self.settings['VertexColor'],1) lastPos = scrPos if len(beginPos)> 0 and len(lastPos)> 0: cv2.line(frame,lastPos,beginPos,self.settings['VertexColor'],1) def posToScr(self,pos): """ convert pos to screen pos """ return (int(pos[0]*self.scale+self.offset[0]), int(pos[1]*self.scale+self.offset[1])) def sizeToScr(self,size): """ convert size to screen size """ return (int(size[0]*self.scale), int(size[1]*self.scale)) def clearRoiInfo(self): for key,_ in self.roiLabels: self.RoiInfo[key].setText('') def updateRoiInfo(self,roi): for key,value in roi.iteritems(): if key == "roi_label": for key1,value1 in value.iteritems(): self.RoiInfo[key1].setText(str(value1)) elif key == "vertices": pass #todo else: self.RoiInfo[key].setText(str(value))