1/****************************************************************************
2**
3** Copyright (C) 2015 The Qt Company Ltd.
4** Contact: http://www.qt.io/licensing/
5**
6** This file is part of the QtVersit module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL21$
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 http://www.qt.io/terms-conditions. For further
15** information use the contact form at http://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 2.1 or version 3 as published by the Free
20** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22** following information to ensure the GNU Lesser General Public License
23** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25**
26** As a special exception, The Qt Company gives you certain additional
27** rights. These rights are described in The Qt Company LGPL Exception
28** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29**
30** $QT_END_LICENSE$
31**
32****************************************************************************/
33
34#include "qversitwriter.h"
35#include "qversitwriter_p.h"
36
37#include <QtCore/qbuffer.h>
38#include <QtCore/qtextcodec.h>
39
40#include "qversitutils_p.h"
41
42QT_BEGIN_NAMESPACE_VERSIT
43
44/*!
45 \class QVersitWriter
46 \brief The QVersitWriter class writes Versit documents such as vCards to a device.
47 \ingroup versit
48 \inmodule QtVersit
49
50 QVersitWriter converts a QVersitDocument into its textual representation.
51 QVersitWriter supports writing to an abstract I/O device
52 which can be for example a file or a memory buffer.
53 The writing can be done asynchronously and the waitForFinished()
54 function can be used to implement a blocking write.
55
56 The serialization of the document is done in accordance with the type of the QVersitDocument
57 being written. The value of each QVersitProperty is encoded according to the type of object:
58 \list
59 \li \l{QString}{QStrings} are serialized verbatim, unless the default codec of the writer cannot
60 encode the string: in this case, UTF-8 is used to encode it (and the CHARSET parameter added to
61 the property, as per the vCard 2.1 specification). If the document type is vCard 2.1,
62 quoted-printable encoding may also be performed.
63 \li \l{QByteArray}{QByteArrays} are assumed to be binary data and are serialized as base-64 encoded
64 values.
65 \li \l{QVersitDocument}{QVersitDocuments} are serialized as a nested document (eg. as per the
66 AGENT property in vCard).
67 \endlist
68
69 \sa QVersitDocument, QVersitProperty
70 */
71
72
73/*!
74 * \enum QVersitWriter::Error
75 * This enum specifies an error that occurred during the most recent operation:
76 * \value NoError The most recent operation was successful
77 * \value UnspecifiedError The most recent operation failed for an undocumented reason
78 * \value IOError The most recent operation failed because of a problem with the device
79 * \value OutOfMemoryError The most recent operation failed due to running out of memory
80 * \value NotReadyError The most recent operation failed because there is an operation in progress
81 */
82
83/*!
84 * \enum QVersitWriter::State
85 * Enumerates the various states that a reader may be in at any given time
86 * \value InactiveState Write operation not yet started
87 * \value ActiveState Write operation started, not yet finished
88 * \value CanceledState Write operation is finished due to cancelation
89 * \value FinishedState Write operation successfully completed
90 */
91
92/*!
93 * \fn QVersitWriter::stateChanged(QVersitWriter::State state)
94 * The signal is emitted by the writer when its state has changed (eg. when it has finished
95 * writing to the device).
96 * \a state is the new state of the writer.
97 */
98
99/*! Constructs a new writer. */
100QVersitWriter::QVersitWriter() : d(new QVersitWriterPrivate)
101{
102 d->init(writer: this);
103}
104
105/*! Constructs a new writer that writes to \a outputDevice. */
106QVersitWriter::QVersitWriter(QIODevice *outputDevice) : d(new QVersitWriterPrivate)
107{
108 d->init(writer: this);
109 d->mIoDevice = outputDevice;
110}
111
112/*! Constructs a new writer that appends to \a outputBytes. */
113QVersitWriter::QVersitWriter(QByteArray *outputBytes) : d(new QVersitWriterPrivate)
114{
115 d->init(writer: this);
116 d->mOutputBytes.reset(other: new QBuffer);
117 d->mOutputBytes->setBuffer(outputBytes);
118 d->mOutputBytes->open(openMode: QIODevice::WriteOnly);
119 d->mIoDevice = d->mOutputBytes.data();
120}
121
122/*!
123 * Frees the memory used by the writer.
124 * Waits until a pending asynchronous writing has been completed.
125 */
126QVersitWriter::~QVersitWriter()
127{
128 d->wait();
129 delete d;
130}
131
132/*!
133 * Sets the device used for writing to \a device.
134 * Does not take ownership of the device.
135 */
136void QVersitWriter::setDevice(QIODevice* device)
137{
138 d->mOutputBytes.reset(other: 0);
139 d->mIoDevice = device;
140}
141
142/*!
143 * Returns the device used for writing, or 0 if no device has been set.
144 */
145QIODevice* QVersitWriter::device() const
146{
147 if (d->mOutputBytes.isNull())
148 return d->mIoDevice;
149 else
150 return 0;
151}
152
153/*!
154 * Sets the default codec for the writer to use for writing the entire output.
155 *
156 * If \a codec is NULL, the writer uses the codec according to the specification prescribed default.
157 * (for vCard 2.1, ASCII; for vCard 3.0, UTF-8).
158 */
159void QVersitWriter::setDefaultCodec(QTextCodec *codec)
160{
161 d->mDefaultCodec = codec;
162}
163
164/*!
165 * Returns the document's codec.
166 */
167QTextCodec* QVersitWriter::defaultCodec() const
168{
169 return d->mDefaultCodec;
170}
171
172/*!
173 * Returns the state of the writer.
174 */
175QVersitWriter::State QVersitWriter::state() const
176{
177 return d->state();
178}
179
180/*!
181 * Returns the error encountered by the last operation.
182 */
183QVersitWriter::Error QVersitWriter::error() const
184{
185 return d->error();
186}
187
188/*!
189 * Starts writing \a input to device() asynchronously. The serialization format is determined based
190 * on the contents of the input documents.
191 *
192 * Returns false if the output device has not been set or opened or if there is another asynchronous
193 * write operation already pending. Signal \l stateChanged() is emitted with parameter
194 * FinishedState when the writing has finished.
195 *
196 * The device must be already open. The client is responsible for closing it when finished.
197 */
198bool QVersitWriter::startWriting(const QList<QVersitDocument>& input)
199{
200 return startWriting(input, type: QVersitDocument::InvalidType);
201}
202
203/*!
204 * Starts writing \a input to device() asynchronously using the serialization format specified by \a
205 * type. If \a type is QVersitDocument::InvalidType, the format will be determined based on the
206 * contents of the input documents.
207 *
208 * Returns false if the output device has not been set or opened or if there is another asynchronous
209 * write operation already pending. Signal \l stateChanged() is emitted with parameter
210 * FinishedState when the writing has finished.
211 *
212 * The device must be already open. The client is responsible for closing it when finished.
213 */
214bool QVersitWriter::startWriting(const QList<QVersitDocument>& input, QVersitDocument::VersitType type)
215{
216 d->mInput = input;
217 if (d->state() == ActiveState || d->isRunning()) {
218 d->setError(QVersitWriter::NotReadyError);
219 return false;
220 } else if (!d->mIoDevice || !d->mIoDevice->isWritable()) {
221 d->setError(QVersitWriter::IOError);
222 return false;
223 } else {
224 d->setState(ActiveState);
225 d->setError(NoError);
226 d->setDocumentType(type);
227 d->start();
228 return true;
229 }
230}
231
232/*!
233 * Starts writing \a input to device() asynchronously. The serialization format is determined based
234 * on the contents of the input documents.
235 *
236 * Returns false if the output device has not been set or opened or if there is another asynchronous
237 * write operation already pending. Signal \l stateChanged() is emitted with parameter
238 * FinishedState when the writing has finished.
239 *
240 * The device must be already open. The client is responsible for closing it when finished.
241 */
242bool QVersitWriter::startWriting(const QVersitDocument& input)
243{
244 return startWriting(input: QList<QVersitDocument>() << input, type: QVersitDocument::InvalidType);
245}
246
247/*!
248 * Starts writing \a input to device() asynchronously using the serialization format specified by \a
249 * type. If \a type is QVersitDocument::InvalidType, the format will be determined based on the
250 * contents of the input documents.
251 *
252 * Returns false if the output device has not been set or opened or if there is another asynchronous
253 * write operation already pending. Signal \l stateChanged() is emitted with parameter
254 * FinishedState when the writing has finished.
255 *
256 * The device must be already open. The client is responsible for closing it when finished.
257 */
258bool QVersitWriter::startWriting(const QVersitDocument& input, QVersitDocument::VersitType type)
259{
260 return startWriting(input: QList<QVersitDocument>() << input, type);
261}
262
263/*!
264 * Attempts to asynchronously cancel the write request.
265 */
266void QVersitWriter::cancel()
267{
268 d->setCanceling(true);
269}
270
271/*!
272 * If the state is ActiveState, blocks until the writer has finished writing or \a msec milliseconds
273 * has elapsed, returning true if it successfully finishes or is cancelled by the user.
274 * If \a msec is negative or zero, the function blocks until the writer has finished, regardless of
275 * how long it takes.
276 * If the state is FinishedState, returns true immediately.
277 * Otherwise, returns false immediately.
278 */
279bool QVersitWriter::waitForFinished(int msec)
280{
281 State state = d->state();
282 if (state != InactiveState) {
283 if (msec <= 0)
284 return d->wait(ULONG_MAX);
285 else
286 return d->wait(time: msec);
287 } else {
288 return false;
289 }
290}
291
292#include "moc_qversitwriter.cpp"
293
294QT_END_NAMESPACE_VERSIT
295

source code of qtpim/src/versit/qversitwriter.cpp