vim line
[drlaunch] / src / xdg / RecentFiles.py
1 """
2 Implementation of the XDG Recent File Storage Specification Version 0.2
3 http://standards.freedesktop.org/recent-file-spec
4 """
5
6 import xml.dom.minidom, xml.sax.saxutils
7 import os, time, fcntl
8 from xdg.Exceptions import *
9
10 class RecentFiles:
11     def __init__(self):
12         self.RecentFiles = []
13         self.filename = ""
14
15     def parse(self, filename=None):
16         if not filename:
17             filename = os.path.join(os.getenv("HOME"), ".recently-used")
18
19         try:
20             doc = xml.dom.minidom.parse(filename)
21         except IOError:
22             raise ParsingError('File not found', filename)
23         except xml.parsers.expat.ExpatError:
24             raise ParsingError('Not a valid .menu file', filename)
25
26         self.filename = filename
27
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)
35
36         self.sort()
37
38     def __parseRecentItem(self, item):
39         recent = RecentFile()
40         self.RecentFiles.append(recent)
41
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":
51                     recent.Prviate = True
52                 elif attribute.tagName == "Groups":
53
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)
58
59     def write(self, filename=None):
60         if not filename and not self.filename:
61             raise ParsingError('File not found', filename)
62         elif not filename:
63             filename = self.filename
64
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")
69
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)
75             if r.Private == True:
76                 f.write("    <Private/>\n")
77             if len(r.Groups) > 0:
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")
83
84         f.write("</RecentFiles>\n")
85         fcntl.lockf(f, fcntl.LOCK_UN)
86         f.close()
87
88     def getFiles(self, mimetypes=None, groups=None, limit=0):
89         tmp = []
90         i = 0
91         for item in self.RecentFiles:
92             if groups:
93                 for group in groups:
94                     if group in item.Groups:
95                         tmp.append(item)
96                         i += 1
97             elif mimetypes:
98                 for mimetype in mimetypes:
99                     if mimetype == item.MimeType:
100                         tmp.append(item)
101                         i += 1
102             else:
103                 if item.Private == False:
104                     tmp.append(item)
105                     i += 1
106             if limit != 0 and i == limit:
107                 break
108
109         return tmp
110
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]
116         else:
117             # delete if more then 500 files
118             if len(self.RecentFiles) == 500:
119                 self.RecentFiles.pop()
120             # add entry
121             recent = RecentFile()
122             self.RecentFiles.append(recent)
123
124         recent.URI = item
125         recent.MimeType = mimetype
126         recent.Timestamp = int(time.time())
127         recent.Private = private
128         recent.Groups = groups
129
130         self.sort()
131
132     def deleteFile(self, item):
133         if item in self.RecentFiles:
134             self.RecentFiles.remove(item)
135
136     def sort(self):
137         self.RecentFiles.sort()
138         self.RecentFiles.reverse()
139
140
141 class RecentFile:
142     def __init__(self):
143         self.URI = ""
144         self.MimeType = ""
145         self.Timestamp = ""
146         self.Private = False
147         self.Groups = []
148
149     def __cmp__(self, other):
150         return cmp(self.Timestamp, other.Timestamp)
151
152     def __eq__(self, other):
153         if self.URI == str(other):
154             return True
155         else:
156             return False
157
158     def __str__(self):
159         return self.URI