def loadSingle(fileName, package=None):
    """Load a plugin that consists of a single .py module in a plugins
    directory.

    @param fileName File name of the the plugin.
    """
    name = paths.getBase(fileName)

    obsoletePluginNames = ['tab1_summary', 'tab2_addons', 'tab3_settings', 'tab30_addons']
    
    # Old plugin names.
    if name in obsoletePluginNames:
        logger.add(logger.MEDIUM, 'warning-obsolete-plugin', name, fileName)
    
    sysPath = sys.path
    if os.path.dirname(fileName) not in sysPath:
        sysPath = [os.path.dirname(fileName)] + sys.path   
        
    if package:
        prefix = package + '.'
    else:
        prefix = ''
   
    # Initialization will be done after everything has been loaded.
    initCommands.append(('import ' + prefix + name, prefix + name + '.init()', sysPath))
def loadBundle(path):
    """Load a plugin bundle that may contain multiple .py modules,
    plus directories.  The bundle directories will be included in file
    searching in paths.py.

    @param path The location of the plugin bundle.
    """
    contentsPath = os.path.join(path, 'Contents')

    # Include the bundle contents in the module search path (for the
    # duration of this function).
    oldSysPath = sys.path
    sys.path = [contentsPath] + sys.path
    
    # Register the bundle path into paths.py.
    paths.addBundlePath(contentsPath)

    # Make the appropriate calls to read the configuration and
    # language files in the bundle.
    readBundleConfig(contentsPath)

    # Load all of the .py modules in the bundle's Python package.
    package = paths.getBase(path)
    packagePath = os.path.join(contentsPath, package)
    for name in os.listdir(packagePath):
        fullName = os.path.join(packagePath, name)
        if name != '__init__.py' and paths.hasExtension('py', fullName):
            loadSingle(fullName, package)

    # Restore the previous module search path.
    sys.path = oldSysPath
def load(path, notify=True):
    """Loads a single profile from disk.  After the profile has been
    loaded, sends a "profile-updated" notification so that the plugins
    may react to the new profile.  If a profile with the

    @param path The file name of the profile to load.
    """

    # Parameter "path" stands for profile's file name. Every time a
    # profile is being loaded, we'll have to check if the profile
    # allready exists. In that case, old profile will be updated by
    # new profile's information. Finally when the loading is complete,

    # The identifier of the profile (the base name of the file).
    identifier = paths.getBase(path)

    # Parse the file.
    elements = []
    p = cfparser.FileParser(path)
    try:
        while True:
            elements.append(p.get())

    except cfparser.OutOfElements:
        # The file ended normally.
        pass

    except cfparser.ParseFailed, ex:
        # Show the error dialog.
        logger.add(logger.HIGH, 'error-parsing-profile', path, str(ex))
        return
def load(fileName):
    """Loads a language file and stores the strings into the database.
    @param fileName Name of the language file.
    """
    p = cfparser.FileParser(fileName)

    # Construct a block element to hold all the strings.
    languageName = paths.getBase(fileName)
    impliedBlock = cfparser.BlockElement('language', languageName)

    try:
        while True:
            # Get the next string from the language file.
            e = p.get()
            
            # Only key elements are recognized.
            if e.isKey():
                impliedBlock.add(e)
    
    except cfparser.OutOfElements:
        # All OK.
        pass

    except:
        import logger
        logger.add(logger.MEDIUM, 'warning-read-language', languageName, 
                   fileName)

    processLanguageBlock(impliedBlock)
Exemple #5
0
def load(path, notify=True):
    """Loads a single profile from disk.  After the profile has been
    loaded, sends a "profile-updated" notification so that the plugins
    may react to the new profile.  If a profile with the

    @param path The file name of the profile to load.
    """

    # Parameter "path" stands for profile's file name. Every time a
    # profile is being loaded, we'll have to check if the profile
    # allready exists. In that case, old profile will be updated by
    # new profile's information. Finally when the loading is complete,

    # The identifier of the profile (the base name of the file).
    identifier = paths.getBase(path)

    # Parse the file.
    elements = []
    p = cfparser.FileParser(path)
    try:
        while True:
            elements.append(p.get())

    except cfparser.OutOfElements:
        # The file ended normally.
        pass

    except cfparser.ParseFailed, ex:
        # Show the error dialog.
        logger.add(logger.HIGH, 'error-parsing-profile', path, str(ex))
        return
def getLanguages():
    langs = []
    for fileName in paths.listFiles(paths.LANG):
        # We'll load all the files with the .lang extension.
        if paths.hasExtension('lang', fileName):
            langs.append(paths.getBase(fileName))

    return langs                    
Exemple #7
0
    def updateList():
        # Update the found addons list.
        foundList.clear()
        dialog.disableWidget(actionButton)
        extensions = ao.getAddonExtensions() + ['manifest']

        # This should be done in addons.py.
        fileNames = os.listdir(pathField.getText())
        for name in fileNames:
            type = ''
            for ext in extensions:
                if paths.hasExtension(ext, name):
                    type = ext
                    break

            if not type:
                # Unknown files are skipped.
                continue

            # Manifests don't appear in the list if the corresponding
            # addon is in the same directory.
            if paths.hasExtension('manifest', name):
                foundSame = False

                # Identifier of the addon the manifest belongs to.
                manifestId = paths.getBase(name)

                # See if the addon is in the list.
                for other in fileNames:
                    if other == name:
                        continue
                    if manifestId == ao.formIdentifier(other)[0]:
                        foundSame = True
                        break                    
                if foundSame:
                    # Don't add it.
                    continue
            
            foundList.addItemWithColumns(
                name, name, language.translate('addon-dialog-type-' + type))
    def updateList():
        # Update the found addons list.
        foundList.clear()
        dialog.disableWidget(actionButton)
        extensions = ao.getAddonExtensions() + ['manifest']

        # This should be done in addons.py.
        fileNames = os.listdir(pathField.getText())
        for name in fileNames:
            type = ''
            for ext in extensions:
                if paths.hasExtension(ext, name):
                    type = ext
                    break

            if not type:
                # Unknown files are skipped.
                continue

            # Manifests don't appear in the list if the corresponding
            # addon is in the same directory.
            if paths.hasExtension('manifest', name):
                foundSame = False

                # Identifier of the addon the manifest belongs to.
                manifestId = paths.getBase(name)

                # See if the addon is in the list.
                for other in fileNames:
                    if other == name:
                        continue
                    if manifestId == ao.formIdentifier(other)[0]:
                        foundSame = True
                        break
                if foundSame:
                    # Don't add it.
                    continue

            foundList.addItemWithColumns(
                name, name, language.translate('addon-dialog-type-' + type))
def loadManifest(fileName):
    """Manifests contain metadata for other addons.  A manifest may
    augment or replace the metadata of an existing addon, or define an
    entirely new addon.

    @param fileName  Path of the manifest file.

    @return  Identifier of the addon the manifest is associated with.
    """
    identifier = paths.getBase(fileName)

    if exists(identifier):
        a = get(identifier)
    else:
        # Create a new addon.
        a = ao.Addon(identifier, fileName)
        addons[identifier] = a

    # The manifest contains metadata configuration.
    try:
        a.parseConfiguration(file(fileName).read())

    except Exception, x:
        logger.add(logger.HIGH, 'error-read-manifest', fileName, str(x))
Exemple #10
0
def loadManifest(fileName):
    """Manifests contain metadata for other addons.  A manifest may
    augment or replace the metadata of an existing addon, or define an
    entirely new addon.

    @param fileName  Path of the manifest file.

    @return  Identifier of the addon the manifest is associated with.
    """
    identifier = paths.getBase(fileName)

    if exists(identifier):
        a = get(identifier)
    else:
        # Create a new addon.
        a = ao.Addon(identifier, fileName)
        addons[identifier] = a

    # The manifest contains metadata configuration.
    try:
        a.parseConfiguration(file(fileName).read())

    except Exception, x:
        logger.add(logger.HIGH, "error-read-manifest", fileName, str(x))
Exemple #11
0
    def readMetaData(self):
        """Generate metadata by making guesses based on the WAD file
        name and contents."""

        metadata = ''

        # Defaults.
        game = ''

        # Look at the path where the WAD file is located.
        path = self.getContentPath().lower()
        # But ignore the user addon path.
        if path.find(paths.getUserPath(paths.ADDONS).lower()) == 0:
            path = path[len(paths.getUserPath(paths.ADDONS)) + 1:]

        if 'heretic' in path or 'htic' in path:
            game = 'jheretic'

        elif 'hexen' in path or 'hxn' in path or 'hexendk' in path or \
             'deathkings' in path:
            game = 'jhexen'

        elif 'doom' in path or 'doom2' in path or 'final' in path or \
             'finaldoom' in path or 'tnt' in path or 'plutonia' in path:
            game = 'jdoom'

        # Check for a game component name in the path.
        for component in confdb.getGameComponents():
            compName = component.getId()[5:] # skip "game-" prefix
            if compName in path:
                game = compName
                break

        # Read the WAD directory.
        self.lumps = self.readLumpDirectory()
        lumps = self.lumps
        
        if 'BEHAVIOR' in lumps:
            # Hexen-specific lumps.
            game = 'jhexen'

        if 'ADVISOR' in lumps or 'M_HTIC' in lumps:
            game = 'jheretic'

        if 'M_DOOM' in lumps:
            game = 'jdoom'

        # What can be determined by looking at the lump names?
        for lump in lumps:
            if lump[:2] == 'D_':
                # Doom music lump.
                game = 'jdoom'

        episodic = False
        maps = False

        # Are there any ExMy maps in the WAD?
        for lump in lumps:
            if len(lump) == 4 and lump[0] == 'E' and lump[2] == 'M' and \
               lump[1] in string.digits and lump[3] in string.digits:
                episodic = True

                # Episodes 5 and 6 exist in Heretic.
                if game == '' and (lump[1] == '5' or lump[1] == '6'):
                    game = 'jheretic'

        # Are there any MAPxy in the WAD?
        for lump in lumps:
            if len(lump) == 5 and lump[:3] == 'MAP' and \
               lump[3] in string.digits and lump[4] in string.digits:
                maps = True
                break

        if episodic and game == 'jhexen':
            # Guessed wrong.
            game = ''

        if maps and game == 'jheretic':
            # Guessed wrong.
            game = ''

        # Determine a category for the WAD.
        if self.wadType == 'IWAD':
            metadata += "category: gamedata/primary\n"
        elif self.wadType == 'JWAD':
            metadata += "category: gamedata/doomsday\n"
        elif self.wadType == 'PWAD':
            category = 'gamedata/'

            if maps or episodic:
                category += 'maps/'

                # Category based on the name.	 
                base = paths.getBase(self.getContentPath()).lower()	 

                if base[0] in string.digits:	 
                    category += '09/'	 
                if base[0] in 'abcdefg':	 
                    category += 'ag/'	 
                if base[0] in 'hijklm':	 
                    category += 'hm/'	 
                if base[0] in 'nopqrs':	 
                    category += 'ns/'	 
                if base[0] in 'tuvwxyz':	 
                    category += 'tz/'	 
             
            metadata += "category: %s\n" % category

        # Game component.
        if game != '':
            metadata += "component: game-%s\n" % game

        self.parseConfiguration(metadata)
    def readMetaData(self):
        """Generate metadata by making guesses based on the WAD file
        name and contents."""

        metadata = ''

        # Defaults.
        game = ''

        # Look at the path where the WAD file is located.
        path = self.getContentPath().lower()
        # But ignore the user addon path.
        if path.find(paths.getUserPath(paths.ADDONS).lower()) == 0:
            path = path[len(paths.getUserPath(paths.ADDONS)) + 1:]

        if 'heretic' in path or 'htic' in path:
            game = 'jheretic'

        elif 'hexen' in path or 'hxn' in path or 'hexendk' in path or \
             'deathkings' in path:
            game = 'jhexen'

        elif 'doom' in path or 'doom2' in path or 'final' in path or \
             'finaldoom' in path or 'tnt' in path or 'plutonia' in path:
            game = 'jdoom'

        # Check for a game component name in the path.
        for component in confdb.getGameComponents():
            compName = component.getId()[5:]  # skip "game-" prefix
            if compName in path:
                game = compName
                break

        # Read the WAD directory.
        self.lumps = self.readLumpDirectory()
        lumps = self.lumps

        if 'BEHAVIOR' in lumps:
            # Hexen-specific lumps.
            game = 'jhexen'

        if 'ADVISOR' in lumps or 'M_HTIC' in lumps:
            game = 'jheretic'

        if 'M_DOOM' in lumps:
            game = 'jdoom'

        # What can be determined by looking at the lump names?
        for lump in lumps:
            if lump[:2] == 'D_':
                # Doom music lump.
                game = 'jdoom'

        episodic = False
        maps = False

        # Are there any ExMy maps in the WAD?
        for lump in lumps:
            if len(lump) == 4 and lump[0] == 'E' and lump[2] == 'M' and \
               lump[1] in string.digits and lump[3] in string.digits:
                episodic = True

                # Episodes 5 and 6 exist in Heretic.
                if game == '' and (lump[1] == '5' or lump[1] == '6'):
                    game = 'jheretic'

        # Are there any MAPxy in the WAD?
        for lump in lumps:
            if len(lump) == 5 and lump[:3] == 'MAP' and \
               lump[3] in string.digits and lump[4] in string.digits:
                maps = True
                break

        if episodic and game == 'jhexen':
            # Guessed wrong.
            game = ''

        if maps and game == 'jheretic':
            # Guessed wrong.
            game = ''

        # Determine a category for the WAD.
        if self.wadType == 'IWAD':
            metadata += "category: gamedata/primary\n"
        elif self.wadType == 'JWAD':
            metadata += "category: gamedata/doomsday\n"
        elif self.wadType == 'PWAD':
            category = 'gamedata/'

            if maps or episodic:
                category += 'maps/'

                # Category based on the name.
                base = paths.getBase(self.getContentPath()).lower()

                if base[0] in string.digits:
                    category += '09/'
                if base[0] in 'abcdefg':
                    category += 'ag/'
                if base[0] in 'hijklm':
                    category += 'hm/'
                if base[0] in 'nopqrs':
                    category += 'ns/'
                if base[0] in 'tuvwxyz':
                    category += 'tz/'

            metadata += "category: %s\n" % category

        # Game component.
        if game != '':
            metadata += "component: game-%s\n" % game

        self.parseConfiguration(metadata)
def sortKey(name):
    return paths.getBase(name).lower()
def restore():
    """Reads all the profiles from disk.  Restores the currently active
    profile as well.  This function has to be called after starting
    the program before any profiles are accessed.

    System profiles that aren't present in the user's profile
    directory are copied to the user's profile directory.
    """
    global defaults
    global profiles
    global restoredActiveId

    # By default, restore selection to the Defaults profile.
    restoredActiveId = 'defaults'

    # Clear the current profile list.
    profiles = []

    systemProfilePaths = [paths.getSystemPath(paths.PROFILES)] + \
                          paths.getBundlePaths(paths.PROFILES)
    userProfilePath = paths.getUserPath(paths.PROFILES)

    # List all the system and user profiles.
    availSystem = _listProfilesIn(systemProfilePaths)
    availUser = _listProfilesIn([userProfilePath])

    # We are going to load only the profiles in the user's direcory,
    # but before that make sure that the user has an instance of each
    # system profile.
    for sysFile in availSystem:
        identifier = paths.getBase(sysFile)

        # Does this exist in the user's directory?
        gotIt = False
        for userFile in availUser:
            if paths.getBase(userFile) == identifier:
                gotIt = True
                break

        if not gotIt:
            # Since the system profile does not exist on the user,
            # copy it to the user profile directory.
            shutil.copyfile(
                sysFile,
                os.path.join(userProfilePath, os.path.basename(sysFile)))

    # Find every profile in system's and user's profile directories.
    # Files in the user's directory augment the files in the system
    # directory.
    for name in _listProfilesIn([userProfilePath]):
        load(os.path.join(userProfilePath, name), False)
    logger.show()

    defaults = get('defaults')

    if defaults is None:
        # Recreate the Defaults profile.
        load(os.path.join(systemProfilePath, "defaults.prof"), False)
        defaults = get('defaults')
        logger.show()

    # Set the default language.
    lang = defaults.getValue('language')
    if lang:
        language.change(lang.getValue())

    # Send profile-loaded notifications.
    for p in profiles:
        if not p.isHidden():
            events.send(events.ProfileNotify(p))

    # Restore the previously active profile.
    prof = get(restoredActiveId)
    if prof:
        setActive(prof)
    else:
        setActive(defaults)
Exemple #15
0
def restore():
    """Reads all the profiles from disk.  Restores the currently active
    profile as well.  This function has to be called after starting
    the program before any profiles are accessed.

    System profiles that aren't present in the user's profile
    directory are copied to the user's profile directory.
    """
    global defaults
    global profiles
    global restoredActiveId

    # By default, restore selection to the Defaults profile.
    restoredActiveId = 'defaults'

    # Clear the current profile list.
    profiles = []

    systemProfilePaths = [paths.getSystemPath(paths.PROFILES)] + \
                          paths.getBundlePaths(paths.PROFILES)
    userProfilePath = paths.getUserPath(paths.PROFILES)

    # List all the system and user profiles.
    availSystem = _listProfilesIn(systemProfilePaths)
    availUser = _listProfilesIn([userProfilePath])

    # We are going to load only the profiles in the user's direcory,
    # but before that make sure that the user has an instance of each
    # system profile.
    for sysFile in availSystem:
        identifier = paths.getBase(sysFile)

        # Does this exist in the user's directory?
        gotIt = False
        for userFile in availUser:
            if paths.getBase(userFile) == identifier:
                gotIt = True
                break

        if not gotIt:
            # Since the system profile does not exist on the user,
            # copy it to the user profile directory.
            shutil.copyfile(sysFile,
                            os.path.join(userProfilePath,
                                         os.path.basename(sysFile)))

    # Find every profile in system's and user's profile directories.
    # Files in the user's directory augment the files in the system
    # directory.
    for name in _listProfilesIn([userProfilePath]):
        load(os.path.join(userProfilePath, name), False)
    logger.show()

    defaults = get('defaults')

    if defaults is None:
        # Recreate the Defaults profile.
        load(os.path.join(systemProfilePath, "defaults.prof"), False)
        defaults = get('defaults')
        logger.show()

    # Set the default language.
    lang = defaults.getValue('language')
    if lang:
        language.change(lang.getValue())

    # Send profile-loaded notifications.
    for p in profiles:
        if not p.isHidden():
            events.send(events.ProfileNotify(p))

    # Restore the previously active profile.
    prof = get(restoredActiveId)
    if prof:
        setActive(prof)
    else:
        setActive(defaults)