|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2012 - 2022 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing a class to write Netscape HTML bookmark files. |
|
8 """ |
|
9 |
|
10 from PyQt6.QtCore import QObject, QIODevice, QFile |
|
11 |
|
12 from .BookmarkNode import BookmarkNode |
|
13 |
|
14 import Utilities |
|
15 |
|
16 |
|
17 class NsHtmlWriter(QObject): |
|
18 """ |
|
19 Class implementing a writer object to generate Netscape HTML bookmark |
|
20 files. |
|
21 """ |
|
22 indentSize = 4 |
|
23 |
|
24 def __init__(self): |
|
25 """ |
|
26 Constructor |
|
27 """ |
|
28 super().__init__() |
|
29 |
|
30 def write(self, fileNameOrDevice, root): |
|
31 """ |
|
32 Public method to write an Netscape HTML bookmark file. |
|
33 |
|
34 @param fileNameOrDevice name of the file to write (string) |
|
35 or device to write to (QIODevice) |
|
36 @param root root node of the bookmark tree (BookmarkNode) |
|
37 @return flag indicating success (boolean) |
|
38 """ |
|
39 if isinstance(fileNameOrDevice, QIODevice): |
|
40 f = fileNameOrDevice |
|
41 else: |
|
42 f = QFile(fileNameOrDevice) |
|
43 if root is None or not f.open(QIODevice.OpenModeFlag.WriteOnly): |
|
44 return False |
|
45 |
|
46 self.__dev = f |
|
47 return self.__write(root) |
|
48 |
|
49 def __write(self, root): |
|
50 """ |
|
51 Private method to write an Netscape HTML bookmark file. |
|
52 |
|
53 @param root root node of the bookmark tree (BookmarkNode) |
|
54 @return flag indicating success (boolean) |
|
55 """ |
|
56 self.__dev.write( |
|
57 "<!DOCTYPE NETSCAPE-Bookmark-file-1>\n" |
|
58 "<!-- This is an automatically generated file.\n" |
|
59 " It will be read and overwritten.\n" |
|
60 " DO NOT EDIT! -->\n" |
|
61 "<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html;" |
|
62 " charset=UTF-8\">\n" |
|
63 "<TITLE>Bookmarks</TITLE>\n" |
|
64 "<H1>Bookmarks</H1>\n" |
|
65 "\n" |
|
66 "<DL><p>\n") |
|
67 if root.type() == BookmarkNode.Root: |
|
68 for child in root.children(): |
|
69 self.__writeItem(child, self.indentSize) |
|
70 else: |
|
71 self.__writeItem(root, self.indentSize) |
|
72 self.__dev.write("</DL><p>\n") |
|
73 return True |
|
74 |
|
75 def __writeItem(self, node, indent): |
|
76 """ |
|
77 Private method to write an entry for a node. |
|
78 |
|
79 @param node reference to the node to be written (BookmarkNode) |
|
80 @param indent size of the indentation (integer) |
|
81 """ |
|
82 if node.type() == BookmarkNode.Folder: |
|
83 self.__writeFolder(node, indent) |
|
84 elif node.type() == BookmarkNode.Bookmark: |
|
85 self.__writeBookmark(node, indent) |
|
86 elif node.type() == BookmarkNode.Separator: |
|
87 self.__writeSeparator(indent) |
|
88 |
|
89 def __writeSeparator(self, indent): |
|
90 """ |
|
91 Private method to write a separator. |
|
92 |
|
93 @param indent size of the indentation (integer) |
|
94 """ |
|
95 self.__dev.write(" " * indent) |
|
96 self.__dev.write("<HR>\n") |
|
97 |
|
98 def __writeBookmark(self, node, indent): |
|
99 """ |
|
100 Private method to write a bookmark node. |
|
101 |
|
102 @param node reference to the node to be written (BookmarkNode) |
|
103 @param indent size of the indentation (integer) |
|
104 """ |
|
105 added = ( |
|
106 " ADD_DATE=\"{0}\"".format(node.added.toTime_t()) |
|
107 if node.added.isValid() else |
|
108 "" |
|
109 ) |
|
110 modified = ( |
|
111 " LAST_MODIFIED=\"{0}\"".format(node.modified.toTime_t()) |
|
112 if node.modified.isValid() else |
|
113 "" |
|
114 ) |
|
115 visited = ( |
|
116 " LAST_VISIT=\"{0}\"".format(node.visited.toTime_t()) |
|
117 if node.visited.isValid() else |
|
118 "" |
|
119 ) |
|
120 |
|
121 self.__dev.write(" " * indent) |
|
122 self.__dev.write("<DT><A HREF=\"{0}\"{1}{2}{3}>{4}</A>\n".format( |
|
123 node.url, added, modified, visited, |
|
124 Utilities.html_uencode(node.title) |
|
125 )) |
|
126 |
|
127 if node.desc: |
|
128 self.__dev.write(" " * indent) |
|
129 self.__dev.write("<DD>{0}\n".format( |
|
130 Utilities.html_uencode("".join(node.desc.splitlines())))) |
|
131 |
|
132 def __writeFolder(self, node, indent): |
|
133 """ |
|
134 Private method to write a bookmark node. |
|
135 |
|
136 @param node reference to the node to be written (BookmarkNode) |
|
137 @param indent size of the indentation (integer) |
|
138 """ |
|
139 folded = "" if node.expanded else " FOLDED" |
|
140 |
|
141 added = ( |
|
142 " ADD_DATE=\"{0}\"".format(node.added.toTime_t()) |
|
143 if node.added.isValid() else |
|
144 "" |
|
145 ) |
|
146 |
|
147 self.__dev.write(" " * indent) |
|
148 self.__dev.write("<DT><H3{0}{1}>{2}</H3>\n".format( |
|
149 folded, added, Utilities.html_uencode(node.title) |
|
150 )) |
|
151 |
|
152 if node.desc: |
|
153 self.__dev.write(" " * indent) |
|
154 self.__dev.write("<DD>{0}\n".format( |
|
155 "".join(node.desc.splitlines()))) |
|
156 |
|
157 self.__dev.write(" " * indent) |
|
158 self.__dev.write("<DL><p>\n") |
|
159 |
|
160 for child in node.children(): |
|
161 self.__writeItem(child, indent + self.indentSize) |
|
162 |
|
163 self.__dev.write(" " * indent) |
|
164 self.__dev.write("</DL><p>\n") |