2 Implementation of the XDG Recent File Storage Specification Version 0.2
3 http://standards.freedesktop.org/recent-file-spec
6 import xml.dom.minidom, xml.sax.saxutils
8 from xdg.Exceptions import *
15 def parse(self, filename=None):
17 filename = os.path.join(os.getenv("HOME"), ".recently-used")
20 doc = xml.dom.minidom.parse(filename)
22 raise ParsingError('File not found', filename)
23 except xml.parsers.expat.ExpatError:
24 raise ParsingError('Not a valid .menu file', filename)
26 self.filename = filename
28 for child in doc.childNodes:
29 if child.nodeType == xml.dom.Node.ELEMENT_NODE:
30 if child.tagName == "RecentFiles":
31 for recent in child.childNodes:
32 if recent.nodeType == xml.dom.Node.ELEMENT_NODE:
33 if recent.tagName == "RecentItem":
34 self.__parseRecentItem(recent)
38 def __parseRecentItem(self, item):
40 self.RecentFiles.append(recent)
42 for attribute in item.childNodes:
43 if attribute.nodeType == xml.dom.Node.ELEMENT_NODE:
44 if attribute.tagName == "URI":
45 recent.URI = attribute.childNodes[0].nodeValue
46 elif attribute.tagName == "Mime-Type":
47 recent.MimeType = attribute.childNodes[0].nodeValue
48 elif attribute.tagName == "Timestamp":
49 recent.Timestamp = attribute.childNodes[0].nodeValue
50 elif attribute.tagName == "Private":
52 elif attribute.tagName == "Groups":
54 for group in attribute.childNodes:
55 if group.nodeType == xml.dom.Node.ELEMENT_NODE:
56 if group.tagName == "Group":
57 recent.Groups.append(group.childNodes[0].nodeValue)
59 def write(self, filename=None):
60 if not filename and not self.filename:
61 raise ParsingError('File not found', filename)
63 filename = self.filename
65 f = open(filename, "w")
66 fcntl.lockf(f, fcntl.LOCK_EX)
67 f.write('<?xml version="1.0"?>\n')
68 f.write("<RecentFiles>\n")
70 for r in self.RecentFiles:
71 f.write(" <RecentItem>\n")
72 f.write(" <URI>%s</URI>\n" % xml.sax.saxutils.escape(r.URI))
73 f.write(" <Mime-Type>%s</Mime-Type>\n" % r.MimeType)
74 f.write(" <Timestamp>%s</Timestamp>\n" % r.Timestamp)
76 f.write(" <Private/>\n")
78 f.write(" <Groups>\n")
79 for group in r.Groups:
80 f.write(" <Group>%s</Group>\n" % group)
81 f.write(" </Groups>\n")
82 f.write(" </RecentItem>\n")
84 f.write("</RecentFiles>\n")
85 fcntl.lockf(f, fcntl.LOCK_UN)
88 def getFiles(self, mimetypes=None, groups=None, limit=0):
91 for item in self.RecentFiles:
94 if group in item.Groups:
98 for mimetype in mimetypes:
99 if mimetype == item.MimeType:
103 if item.Private == False:
106 if limit != 0 and i == limit:
111 def addFile(self, item, mimetype, groups=None, private=False):
112 # check if entry already there
113 if item in self.RecentFiles:
114 index = self.RecentFiles.index(item)
115 recent = self.RecentFiles[index]
117 # delete if more then 500 files
118 if len(self.RecentFiles) == 500:
119 self.RecentFiles.pop()
121 recent = RecentFile()
122 self.RecentFiles.append(recent)
125 recent.MimeType = mimetype
126 recent.Timestamp = int(time.time())
127 recent.Private = private
128 recent.Groups = groups
132 def deleteFile(self, item):
133 if item in self.RecentFiles:
134 self.RecentFiles.remove(item)
137 self.RecentFiles.sort()
138 self.RecentFiles.reverse()
149 def __cmp__(self, other):
150 return cmp(self.Timestamp, other.Timestamp)
152 def __eq__(self, other):
153 if self.URI == str(other):