__init__.py :  » GUI » MenuMaker » menumaker-0.99.7 » Prophet » Desktop » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » GUI » MenuMaker 
MenuMaker » menumaker 0.99.7 » Prophet » Desktop » __init__.py
import sys, types, os, os.path, fnmatch, re, Prophet




from Keywords import Keyword
from Paths import ValidPathSet
from Prophet.Categories import *
from Prophet import msg,verbose




class DesktopSet(PS) :

  def adopt(self, path) :
    path = super(DesktopSet, self).adopt(path)
    for x in os.walk(path) :
      if len(fnmatch.filter(x[2], "*.desktop")) :
        return path
    raise ValueError




_genMap = (
  ("gnome", GNOME),
  ("kde", KDE),
  ("devel*", Development),
  ("edit*", TextEditor),
  ("educ*", Education),
  ("edut*", Education),

  ("*game*", Game),
    ("arcade", ArcadeGame),
    ("board*", BoardGame),
    ("card*", CardGame),
    ("kids*", KidsGame),
    ("rogue*", AdventureGame),
    ("*tactic*", StrategyGame),
    ("*strat*", StrategyGame),
  ("*toy*", Amusement),
  ("*amus*", Amusement),

  ("*graphic*", Graphics),
  ("*sound*", Audio),
  ("*music*", Audio),
  ("*video*", Video),
  ("*internet*", Network),
  ("*netw*", Network),
  ("*news*", News),
  ("*remote*", Network),
  ("*www*", Network),
  ("*transfer*", FileTransfer),
  ("irc", IRCClient),
  ("*instant*", InstantMessaging),
  ("*messag*", InstantMessaging),
  ("*mail*", Email),
  ("multimedia", AudioVideo),
  ("*docum*", Office), # ???
  ("*office*", Office),
  ("*graphs*", Chart),
  ("pda", PDA),
  ("*present*", Presentation),
  ("*spread*", Spreadsheet),
  ("*word*proc*", WordProcessor),
  ("*time*manag*", ProjectManagement),
  ("*sett*", Settings),
  ("*syst*", System),
  ("*admin*", System),
  ("accessib*", Accessibility),
  ("archiv*", Archiving),
  ("comm*", Network),
  ("*file*tool*", FileManager),
  ("monitor*", Monitor),
  ("*publish*", Office),
  ("science", Science),
  ("*math*", Math),
  ("*text*tool*", TextEditor), # ???
  ("*config*", Settings),
    ("*boot*", System),
    ("*init*", System),
  ("*hardw*", HardwareSettings),
  ("packag*", PackageManager),
  ("print*", Settings),
  ("*terminal*", TerminalEmulator),
)




_kdeCfgMap = (
  ("look*feel", Kw("X-KDE-settings-looknfeel")),
  ("*sound*", Kw("X-KDE-settings-sound")),
  ("*syst*", Kw("X-KDE-settings-system")),
  ("accessib*", Kw("X-KDE-settings-accessibility")),
  ("component*", Kw("X-KDE-settings-components")),
  ("netw*", Kw("X-KDE-settings-network")),
  ("secur*", Kw("X-KDE-settings-security")),
  ("*web*", Kw("X-KDE-settings-webbrowsing")),
  ("*desk*", Kw("X-KDE-settings-desktop")),
  ("periph*", Kw("X-KDE-settings-peripherials")),
  ("Hardware", Kw("X-KDE-settings-hardware")),
  ("power*", Kw("X-KDE-settings-power")),
  
  ("*info*", Kw("X-KDE-information"))
)




# Some ugly Linux distros, notably Mandrake, are known for shipping broken (???!)
# .desktop's which have no Categories section (thx, $!N, mein Freund :) that is the main method for distributing
# the apps throughout the menu thus here's the alternative method for guessing the keywords




def _dir2kws(dir) :
  """Convert the directory name to the corresponding keyword set, if possible"""
  parts = [x.strip().lower() for x in dir.split("/")]
  if len(fnmatch.filter(parts, "kde")) and len(fnmatch.filter(parts, "*config*") + fnmatch.filter(parts, "*sett*")) :
    # Catching KDE/Configuration or KDE/Settings
    kws = [KDE, Kw("X-KDE-settings")]
    kws += [k for m, k in _kdeCfgMap for x in parts if fnmatch.fnmatch(x, m)]
  else :
    kws = [k for m, k in _genMap for x in parts if fnmatch.fnmatch(x, m)]
  if len(kws) :
    return KwS(*kws)
  else :
    return None




_kws = None




def scan() :
  """Scan through all containers and return a list of found valid entries"""
  global _kws
  result = []
  msg("  desktop...", newline = False)
  for c in dirs :
    for w in os.walk(c) :
      _kws = _dir2kws(w[0])
      if verbose > 1 : msg("\nentering " + w[0])
      for x in fnmatch.filter(w[2], "*.desktop") :
        if verbose > 1 : msg("parsing %s..." % x, newline = False)
        try :
          result.append(App(os.path.join(w[0], x)))
          if verbose > 1 : msg("ok")
        except (NotDesktop, Prophet.NotSet), e :
          if verbose > 1 : msg("REJECTED : " + str(e))
  msg(" %d apps found" % len(result))
  return result




dirs = DesktopSet([os.path.join(p, x) for p in Prophet.prefixes for x in ("share/applications", "share/applnk", "share/gnome/apps")]) \
  + ("/usr/share/applications", "~/.kde/share/applnk", "~/.local/share/applications")




_section  = re.compile("\s*?\[\s*(.*)\s*\].*?") # Match section definition, e.g. [Global Settings]
_skip    = re.compile("\s*[\#\;].*") # Match comments - lines starting with # or ;
_entry    = re.compile("\s*?(.*)\s*?\=\s*?(.*)\s*?") # Match any valid entry, e.g. key = value
_pkey    = re.compile("(\w+)\s*\[\s*(\w+)\s*\]") # Match parametrized key, e.g. key[param]




_DE = Kw("Desktop Entry")




def _parse(desktop) :
  section = []
  inSection = False
  try :
    xs = open(desktop).readlines()
  except IOError :
    raise NotDesktop("i/o error while reading .desktop file")
  for x in xs :
    if re.match(_skip, x) :
      continue
    rx = re.match(_section, x)
    if rx :
      inSection = (Kw(rx.group(1)) == _DE)
      continue
    if inSection :
      rx = re.match(_entry, x)
      if rx :
        section.append( (rx.group(1), rx.group(2)) ) # (key, value)
  if len(section) :
    return _parseEntries(section)
  raise NotDesktop("[Desktop Entry] section is either absent or empty")





def _parseEntries(entries) :
  e = {}
  for key, val in entries :
    rx = re.match(_pkey, key)
    if rx :
      pass # TODO : _parseLocale
    else :
      e[key] = _parseValue(val)
  return e




def _parseValue(value) :
  vl = [x.strip() for x in value.split(";") if not (x.strip() == "")]
  if len(vl) > 1 :
    return tuple(vl)
  else :
    return value.strip()




class NotDesktop(Exception) :
  """Exception is raised when parser fails to decode entry"""




def _string(x) :
  """Pick up the most appropriate string representation out of all specified variants
    Choice is made with respect to current locale and type of specified argument"""
  if type(x) == types.DictType :
    return x[""]
  # FIXME : locale handling
  else :
    # Now argument is assumed to be a string
    return x




def _bool(x) :
  """Convert string to boolean"""
  if x.lower() in ("yes", "true", "1") :
    return True
  else :
    return False




class App(Prophet.App) :

  pref = 20

  def __new__(cls, desktop) :
    self = object.__new__(cls)
    self.__setup__(desktop)
    return self

  def __setup__(self, desktop) :
    self.desktop = _parse(desktop)
    try :
      if not (self.desktop["Type"] == "Application") :
        raise NotDesktop("Entry type is not Application")
    except KeyError :
      raise NotDesktop("Entry type is not specified")
    try :
      if _bool(self.desktop["NoDisplay"]) :
        raise NotDesktop("NoDisplay is True")
    except KeyError :
      pass
    try :
      if _bool(self.desktop["Hidden"]) :
        raise NotDesktop("Hidden is True")
    except KeyError :
      pass
    super(App, self).__setup__()
    del self.desktop

  def setName(self) :
    for x in ("Name", "GenericName") :
      try :
        self.name = _string(self.desktop[x])
        return
      except KeyError :
        pass
    super(App, self).setName()

  def setComment(self) :
    try :
      self.comment = _string(self.desktop["Comment"])
    except KeyError :
      super(App, self).setComment()

  def setKeywords(self) :
    try :
      self.keywords = KwS(*self.desktop["Categories"])
    except KeyError :
      if _kws :
        self.keywords = _kws
      else :
        raise Prophet.NotSet("Categories not found")
    if fnmatch.fnmatch(self.exename, "*kcmshell") :
      self.keywords |= KwS(KDE, Kw("X-KDE-settings"))

  def setTerminal(self) :
    try :
      self.terminal = _bool(self.desktop["Terminal"])
    except KeyError :
      super(App, self).setTerminal()

  def setExename(self) :
    try :
      cmd = self.desktop["Exec"]
      # According to some reports, newer Debian-based distros
      # (notably, Ubuntu 5.10+) make an attempt to generate .desktop's
      # directly from their (Debian-style) database which means all those
      # ugly complex shell commands may emerge right here!
      # So we got to get rid of them for good.
      self.testGoodness(cmd)
      # Exec entry may contain the %-prefixed arguments that make no sense for us
      # and should be filtered out. If they're there, set exename to anything prior first
      # argument encountered
      scmd = cmd.split()
      if len(scmd) < 2 :
        self.exename = cmd
      else :
        self.exename = scmd[0].strip()
        self.exeargs = ""
        for i in range(1, len(scmd)) :
          if "%" in scmd[i] :
            break # First %arg encountered terminates the list
          try :
            if scmd[i].startswith("-") and "%" in scmd[i+1] :
              break # Filter out things like `-caption "%c"'
          except IndexError :
            pass
          self.exeargs += scmd[i] + " "
        self.exeargs = self.exeargs.rstrip()
        if not len(self.exeargs) :
          del self.exeargs
    except KeyError :
      try :
        # As a last resort, check for TryExec entry. It should not contain arguments so consume it all.
        self.exename = self.desktop["TryExec"]
      except KeyError :
        raise NotDesktop("Neither Exec nor TryExec specified")
        # If both entries are absent, this desktop file is totally useless for us

  def setNativenv(self) :
    super(App, self).setNativenv()
    # Not all Xfce apps have a distinguishing keywords therefore make an
    # additional check for the clues from its public name
    if fnmatch.fnmatch(self.name.lower(), "*xfce*") :
      self.nativenv = App.Xfce
    # A few GNOME apps do not manifest themselfs (according to their .desktop file)
    # as such
    elif fnmatch.fnmatch(os.path.basename(self.exename), "gnome*") :
      self.nativenv = App.GNOME
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.