src/eric7/WebBrowser/Bookmarks/XbelReader.py

branch
eric7
changeset 9209
b99e7fd55fd3
parent 8881
54e42bc2437a
child 9221
bf71ee032bb4
equal deleted inserted replaced
9208:3fc8dfeb6ebe 9209:b99e7fd55fd3
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2009 - 2022 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a class to read XBEL bookmark files.
8 """
9
10 from PyQt6.QtCore import (
11 QXmlStreamReader, QXmlStreamEntityResolver, QIODevice, QFile,
12 QCoreApplication, QXmlStreamNamespaceDeclaration, QDateTime, Qt
13 )
14
15 from .BookmarkNode import BookmarkNode
16
17
18 class XmlEntityResolver(QXmlStreamEntityResolver):
19 """
20 Class implementing an XML entity resolver for bookmark files.
21 """
22 def resolveUndeclaredEntity(self, entity):
23 """
24 Public method to resolve undeclared entities.
25
26 @param entity entity to be resolved (string)
27 @return resolved entity (string)
28 """
29 if entity == "nbsp":
30 return " "
31 return ""
32
33
34 class XbelReader(QXmlStreamReader):
35 """
36 Class implementing a reader object for XBEL bookmark files.
37 """
38 def __init__(self):
39 """
40 Constructor
41 """
42 super().__init__()
43
44 self.__resolver = XmlEntityResolver()
45 self.setEntityResolver(self.__resolver)
46
47 def read(self, fileNameOrDevice):
48 """
49 Public method to read an XBEL bookmark file.
50
51 @param fileNameOrDevice name of the file to read (string)
52 or reference to the device to read (QIODevice)
53 @return reference to the root node (BookmarkNode)
54 """
55 if isinstance(fileNameOrDevice, QIODevice):
56 self.setDevice(fileNameOrDevice)
57 else:
58 f = QFile(fileNameOrDevice)
59 if not f.exists():
60 return BookmarkNode(BookmarkNode.Root)
61 f.open(QIODevice.OpenModeFlag.ReadOnly)
62 self.setDevice(f)
63
64 root = BookmarkNode(BookmarkNode.Root)
65 while not self.atEnd():
66 self.readNext()
67 if self.isStartElement():
68 version = self.attributes().value("version")
69 if (
70 self.name() == "xbel" and
71 (not version or version == "1.0")
72 ):
73 self.__readXBEL(root)
74 else:
75 self.raiseError(QCoreApplication.translate(
76 "XbelReader",
77 "The file is not an XBEL version 1.0 file."))
78
79 return root
80
81 def __readXBEL(self, node):
82 """
83 Private method to read and parse the XBEL file.
84
85 @param node reference to the node to attach to (BookmarkNode)
86 """
87 if not self.isStartElement() and self.name() != "xbel":
88 return
89
90 while not self.atEnd():
91 self.readNext()
92 if self.isEndElement():
93 break
94
95 if self.isStartElement():
96 if self.name() == "folder":
97 self.__readFolder(node)
98 elif self.name() == "bookmark":
99 self.__readBookmarkNode(node)
100 elif self.name() == "separator":
101 self.__readSeparator(node)
102 else:
103 self.__skipUnknownElement()
104
105 def __readFolder(self, node):
106 """
107 Private method to read and parse a folder subtree.
108
109 @param node reference to the node to attach to (BookmarkNode)
110 """
111 if not self.isStartElement() and self.name() != "folder":
112 return
113
114 folder = BookmarkNode(BookmarkNode.Folder, node)
115 folder.expanded = self.attributes().value("folded") == "no"
116 folder.added = QDateTime.fromString(
117 self.attributes().value("added"), Qt.DateFormat.ISODate)
118
119 while not self.atEnd():
120 self.readNext()
121 if self.isEndElement():
122 break
123
124 if self.isStartElement():
125 if self.name() == "title":
126 self.__readTitle(folder)
127 elif self.name() == "desc":
128 self.__readDescription(folder)
129 elif self.name() == "folder":
130 self.__readFolder(folder)
131 elif self.name() == "bookmark":
132 self.__readBookmarkNode(folder)
133 elif self.name() == "separator":
134 self.__readSeparator(folder)
135 elif self.name() == "info":
136 self.__readInfo()
137 else:
138 self.__skipUnknownElement()
139
140 def __readTitle(self, node):
141 """
142 Private method to read the title element.
143
144 @param node reference to the bookmark node title belongs to
145 (BookmarkNode)
146 """
147 if not self.isStartElement() and self.name() != "title":
148 return
149
150 node.title = self.readElementText()
151
152 def __readDescription(self, node):
153 """
154 Private method to read the desc element.
155
156 @param node reference to the bookmark node desc belongs to
157 (BookmarkNode)
158 """
159 if not self.isStartElement() and self.name() != "desc":
160 return
161
162 node.desc = self.readElementText()
163
164 def __readSeparator(self, node):
165 """
166 Private method to read a separator element.
167
168 @param node reference to the bookmark node the separator belongs to
169 (BookmarkNode)
170 """
171 sep = BookmarkNode(BookmarkNode.Separator, node)
172 sep.added = QDateTime.fromString(
173 self.attributes().value("added"), Qt.DateFormat.ISODate)
174
175 # empty elements have a start and end element
176 while not self.atEnd():
177 self.readNext()
178 if self.isEndElement():
179 break
180
181 if self.isStartElement():
182 if self.name() == "info":
183 self.__readInfo()
184 else:
185 self.__skipUnknownElement()
186
187 def __readBookmarkNode(self, node):
188 """
189 Private method to read and parse a bookmark subtree.
190
191 @param node reference to the node to attach to (BookmarkNode)
192 """
193 if not self.isStartElement() and self.name() != "bookmark":
194 return
195
196 bookmark = BookmarkNode(BookmarkNode.Bookmark, node)
197 bookmark.url = self.attributes().value("href")
198 bookmark.added = QDateTime.fromString(
199 self.attributes().value("added"), Qt.DateFormat.ISODate)
200 bookmark.modified = QDateTime.fromString(
201 self.attributes().value("modified"), Qt.DateFormat.ISODate)
202 bookmark.visited = QDateTime.fromString(
203 self.attributes().value("visited"), Qt.DateFormat.ISODate)
204 try:
205 bookmark.visitCount = int(self.attributes().value("visitCount"))
206 except ValueError:
207 bookmark.visitCount = 0
208
209 while not self.atEnd():
210 self.readNext()
211 if self.isEndElement():
212 break
213
214 if self.isStartElement():
215 if self.name() == "title":
216 self.__readTitle(bookmark)
217 elif self.name() == "desc":
218 self.__readDescription(bookmark)
219 elif self.name() == "info":
220 self.__readInfo()
221 else:
222 self.__skipUnknownElement()
223
224 if not bookmark.title:
225 bookmark.title = QCoreApplication.translate(
226 "XbelReader", "Unknown title")
227
228 def __readInfo(self):
229 """
230 Private method to read and parse an info subtree.
231 """
232 self.addExtraNamespaceDeclaration(QXmlStreamNamespaceDeclaration(
233 "bookmark", "http://www.python.org"))
234 self.skipCurrentElement()
235
236 def __skipUnknownElement(self):
237 """
238 Private method to skip over all unknown elements.
239 """
240 self.skipCurrentElement()

eric ide

mercurial