1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the Qt Assistant of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21 ** included in the packaging of this file. Please review the following
22 ** information to ensure the GNU General Public License requirements will
23 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24 **
25 ** $QT_END_LICENSE$
26 **
27 ****************************************************************************/
28 #include "tracer.h"
29 
30 #include "xbelsupport.h"
31 
32 #include "bookmarkitem.h"
33 #include "bookmarkmodel.h"
34 
35 #include <QtCore/QDate>
36 #include <QtCore/QModelIndex>
37 
38 QT_BEGIN_NAMESPACE
39 
40 struct Bookmark {
41     QString title;
42     QString url;
43     bool folded;
44 };
45 
XbelWriter(BookmarkModel * model)46 XbelWriter::XbelWriter(BookmarkModel *model)
47     : QXmlStreamWriter()
48     , bookmarkModel(model)
49 {
50     TRACE_OBJ
51     setAutoFormatting(true);
52 }
53 
writeToFile(QIODevice * device)54 void XbelWriter::writeToFile(QIODevice *device)
55 {
56     TRACE_OBJ
57     setDevice(device);
58 
59     writeStartDocument();
60     writeDTD(QLatin1String("<!DOCTYPE xbel>"));
61     writeStartElement(QLatin1String("xbel"));
62     writeAttribute(QLatin1String("version"), QLatin1String("1.0"));
63 
64     const QModelIndex root;
65     for (int i = 0; i < bookmarkModel->rowCount(root); ++i)
66         writeData(bookmarkModel->index(i, 0, root));
67     writeEndDocument();
68 }
69 
writeData(const QModelIndex & index)70 void XbelWriter::writeData(const QModelIndex &index)
71 {
72     TRACE_OBJ
73     if (index.isValid()) {
74         Bookmark entry;
75         entry.title = index.data().toString();
76         entry.url = index.data(UserRoleUrl).toString();
77 
78         if (index.data(UserRoleFolder).toBool()) {
79             writeStartElement(QLatin1String("folder"));
80             entry.folded = !index.data(UserRoleExpanded).toBool();
81             writeAttribute(QLatin1String("folded"), entry.folded
82                 ? QLatin1String("yes") : QLatin1String("no"));
83             writeTextElement(QLatin1String("title"), entry.title);
84 
85             for (int i = 0; i < bookmarkModel->rowCount(index); ++i)
86                 writeData(bookmarkModel->index(i, 0 , index));
87             writeEndElement();
88         } else {
89             writeStartElement(QLatin1String("bookmark"));
90             writeAttribute(QLatin1String("href"), entry.url);
91             writeTextElement(QLatin1String("title"), entry.title);
92             writeEndElement();
93         }
94     }
95 }
96 
97 // -- XbelReader
98 
XbelReader(BookmarkModel * model)99 XbelReader::XbelReader(BookmarkModel *model)
100     : QXmlStreamReader()
101     , bookmarkModel(model)
102 {
103     TRACE_OBJ
104 }
105 
readFromFile(QIODevice * device)106 bool XbelReader::readFromFile(QIODevice *device)
107 {
108     TRACE_OBJ
109     setDevice(device);
110 
111     while (!atEnd()) {
112         readNext();
113 
114         if (isStartElement()) {
115             if (name() == QLatin1String("xbel")
116                 && attributes().value(QLatin1String("version"))
117                     == QLatin1String("1.0")) {
118                 const QModelIndex root;
119                 parents.append(bookmarkModel->addItem(root, true));
120                 readXBEL();
121                 bookmarkModel->setData(parents.first(),
122                     QDate::currentDate().toString(Qt::ISODate), Qt::EditRole);
123             } else {
124                 raiseError(QLatin1String("The file is not an XBEL version 1.0 file."));
125             }
126         }
127     }
128 
129     return !error();
130 }
131 
readXBEL()132 void XbelReader::readXBEL()
133 {
134     TRACE_OBJ
135     while (!atEnd()) {
136         readNext();
137 
138         if (isEndElement())
139             break;
140 
141         if (isStartElement()) {
142             if (name() == QLatin1String("folder"))
143                 readFolder();
144             else if (name() == QLatin1String("bookmark"))
145                 readBookmark();
146             else
147                 readUnknownElement();
148         }
149     }
150 }
151 
readFolder()152 void XbelReader::readFolder()
153 {
154     TRACE_OBJ
155     parents.append(bookmarkModel->addItem(parents.last(), true));
156     bookmarkModel->setData(parents.last(),
157         attributes().value(QLatin1String("folded")) == QLatin1String("no"),
158         UserRoleExpanded);
159 
160     while (!atEnd()) {
161         readNext();
162 
163         if (isEndElement())
164             break;
165 
166         if (isStartElement()) {
167             if (name() == QLatin1String("title")) {
168                 bookmarkModel->setData(parents.last(), readElementText(),
169                     Qt::EditRole);
170             } else if (name() == QLatin1String("folder"))
171                 readFolder();
172             else if (name() == QLatin1String("bookmark"))
173                 readBookmark();
174             else
175                 readUnknownElement();
176         }
177     }
178 
179     parents.removeLast();
180 }
181 
readBookmark()182 void XbelReader::readBookmark()
183 {
184     TRACE_OBJ
185     const QModelIndex &index = bookmarkModel->addItem(parents.last(), false);
186     if (BookmarkItem* item = bookmarkModel->itemFromIndex(index)) {
187         item->setData(UserRoleUrl, attributes().value(QLatin1String("href"))
188             .toString());
189     }
190 
191     while (!atEnd()) {
192         readNext();
193 
194         if (isEndElement())
195             break;
196 
197         if (isStartElement()) {
198             if (name() == QLatin1String("title"))
199                 bookmarkModel->setData(index, readElementText(), Qt::EditRole);
200             else
201                 readUnknownElement();
202         }
203     }
204 }
205 
readUnknownElement()206 void XbelReader::readUnknownElement()
207 {
208     TRACE_OBJ
209     while (!atEnd()) {
210         readNext();
211 
212         if (isEndElement())
213             break;
214 
215         if (isStartElement())
216             readUnknownElement();
217     }
218 }
219 
220 QT_END_NAMESPACE
221