1
/****************************************************************************
2
**
3
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4
** All rights reserved.
5
** Contact: Nokia Corporation (qt-info@nokia.com)
6
**
7
** This file is part of the QtGui module of the Qt Toolkit.
8
**
9
** $QT_BEGIN_LICENSE:LGPL$
10
** GNU Lesser General Public License Usage
11
** This file may be used under the terms of the GNU Lesser General Public
12
** License version 2.1 as published by the Free Software Foundation and
13
** appearing in the file LICENSE.LGPL included in the packaging of this
14
** file. Please review the following information to ensure the GNU Lesser
15
** General Public License version 2.1 requirements will be met:
16
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17
**
18
** In addition, as a special exception, Nokia gives you certain additional
19
** rights. These rights are described in the Nokia Qt LGPL Exception
20
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21
**
22
** GNU General Public License Usage
23
** Alternatively, this file may be used under the terms of the GNU General
24
** Public License version 3.0 as published by the Free Software Foundation
25
** and appearing in the file LICENSE.GPL included in the packaging of this
26
** file. Please review the following information to ensure the GNU General
27
** Public License version 3.0 requirements will be met:
28
** http://www.gnu.org/copyleft/gpl.html.
29
**
30
** Other Usage
31
** Alternatively, this file may be used in accordance with the terms and
32
** conditions contained in a signed written agreement between you and Nokia.
33
**
34
**
35
**
36
**
37
**
38
** $QT_END_LICENSE$
39
**
40
****************************************************************************/
41
#include "qtextdocumentwriter.h"
42
43
#include <QtCore/qfile.h>
44
#include <QtCore/qbytearray.h>
45
#include <QtCore/qfileinfo.h>
46
#include <QtCore/qtextcodec.h>
47
#include <QtCore/qtextstream.h>
48
#include <QtCore/qdebug.h>
49
#include "qtextdocument.h"
50
#include "qtextdocumentfragment.h"
51
52
#include "qtextdocumentfragment_p.h"
53
#include "qtextodfwriter_p.h"
54
55
QT_BEGIN_NAMESPACE
56
57
class QTextDocumentWriterPrivate
58
{
59
public:
60
    QTextDocumentWriterPrivate(QTextDocumentWriter* qq);
61
62
    // device
63
    QByteArray format;
64
    QIODevice *device;
65
    bool deleteDevice;
66
#ifndef QT_NO_TEXTCODEC
67
    QTextCodec *codec;
68
#endif
69
70
    QTextDocumentWriter *q;
71
};
72
73
/*!
74
    \since 4.5
75
    \class QTextDocumentWriter
76
77
    \brief The QTextDocumentWriter class provides a format-independent interface for writing a QTextDocument to files or other devices.
78
79
    \ingroup richtext-processing
80
    \ingroup io
81
82
    To write a document, construct a QTextDocumentWriter object with either a
83
    file name or a device object, and specify the document format to be
84
    written. You can construct a writer and set the format using setFormat()
85
    later.
86
87
    Call write() to write the document to the device. If the document is
88
    successfully written, this function returns true. However, if an error
89
    occurs when writing the document, it will return false.
90
91
    Call supportedDocumentFormats() for a list of formats that
92
    QTextDocumentWriter can write.
93
94
    Since the capabilities of the supported output formats vary considerably,
95
    the writer simply outputs the appropriate subset of objects for each format.
96
    This typically includes the formatted text and images contained in a
97
    document.
98
*/
99
100
/*!
101
    \internal
102
*/
103
QTextDocumentWriterPrivate::QTextDocumentWriterPrivate(QTextDocumentWriter *qq)
104
    : device(0),
105
    deleteDevice(false),
106
#ifndef QT_NO_TEXTCODEC
107
    codec(QTextCodec::codecForName("utf-8")),
108
#endif
109
    q(qq)
110
{
111
}
112
113
/*!
114
    Constructs an empty QTextDocumentWriter object. Before writing, you must
115
    call setFormat() to set a document format, then setDevice() or
116
    setFileName().
117
*/
118
QTextDocumentWriter::QTextDocumentWriter()
119
    : d(new QTextDocumentWriterPrivate(this))
120
{
121
}
122
123
/*!
124
    Constructs a QTextDocumentWriter object to write to the given \a device
125
    in the document format specified by \a format.
126
*/
127
QTextDocumentWriter::QTextDocumentWriter(QIODevice *device, const QByteArray &format)
128
    : d(new QTextDocumentWriterPrivate(this))
129
{
130
    d->device = device;
131
    d->format = format;
132
}
133
134
/*!
135
    Constructs an QTextDocumentWriter object that will write to a file with
136
    the name \a fileName, using the document format specified by \a format.
137
    If \a format is not provided, QTextDocumentWriter will detect the document
138
    format by inspecting the extension of \a fileName.
139
*/
140
QTextDocumentWriter::QTextDocumentWriter(const QString &fileName, const QByteArray &format)
141
    : d(new QTextDocumentWriterPrivate(this))
142
{
143
    QFile *file = new QFile(fileName);
144
    d->device = file;
145
    d->deleteDevice = true;
146
    d->format = format;
147
}
148
149
/*!
150
    Destroys the QTextDocumentWriter object.
151
*/
152
QTextDocumentWriter::~QTextDocumentWriter()
153
{
154
    if (d->deleteDevice)
155
        delete d->device;
156
    delete d;
157
}
158
159
/*!
160
    Sets the format used to write documents to the \a format specified.
161
    \a format is a case insensitive text string. For example:
162
163
    \snippet doc/src/snippets/code/src.gui.text.qtextdocumentwriter.cpp 0
164
165
    You can call supportedDocumentFormats() for the full list of formats
166
    QTextDocumentWriter supports.
167
168
    \sa format()
169
*/
170
void QTextDocumentWriter::setFormat (const QByteArray &format)
171
{
172
    d->format = format;
173
}
174
175
/*!
176
    Returns the format used for writing documents.
177
178
    \sa setFormat()
179
*/
180
QByteArray QTextDocumentWriter::format () const
181
{
182
    return d->format;
183
}
184
185
/*!
186
    Sets the writer's device to the \a device specified. If a device has
187
    already been set, the old device is removed but otherwise left
188
    unchanged.
189
190
    If the device is not already open, QTextDocumentWriter will attempt to
191
    open the device in \l QIODevice::WriteOnly mode by calling open().
192
193
    \note This will not work for certain devices, such as QProcess,
194
    QTcpSocket and QUdpSocket, where some configuration is required before
195
    the device can be opened.
196
197
    \sa device(), setFileName()
198
*/
199
void QTextDocumentWriter::setDevice (QIODevice *device)
200
{
201
    if (d->device && d->deleteDevice)
202
        delete d->device;
203
204
    d->device = device;
205
    d->deleteDevice = false;
206
}
207
208
/*!
209
    Returns the device currently assigned, or 0 if no device has been
210
    assigned.
211
*/
212
QIODevice *QTextDocumentWriter::device () const
213
{
214
    return d->device;
215
}
216
217
/*!
218
    Sets the name of the file to be written to \a fileName. Internally,
219
    QTextDocumentWriter will create a QFile and open it in \l
220
    QIODevice::WriteOnly mode, and use this file when writing the document.
221
222
    \sa fileName(), setDevice()
223
*/
224
void QTextDocumentWriter::setFileName (const QString &fileName)
225
{
226
    setDevice(new QFile(fileName));
227
    d->deleteDevice = true;
228
}
229
230
/*!
231
    If the currently assigned device is a QFile, or if setFileName()
232
    has been called, this function returns the name of the file
233
    to be written to. In all other cases, it returns an empty string.
234
235
    \sa setFileName(), setDevice()
236
*/
237
QString QTextDocumentWriter::fileName () const
238
{
239
    QFile *file = qobject_cast<QFile *>(d->device);
240
    return file ? file->fileName() : QString();
241
}
242
243
/*!
244
    Writes the given \a document to the assigned device or file and
245
    returns true if successful; otherwise returns false.
246
*/
247
bool QTextDocumentWriter::write(const QTextDocument *document)
248
{
249
    QByteArray suffix;
250
251
    if (d->device && d->format.isEmpty()) {
252
        // if there's no format, see if device is a file, and if so, find
253
        // the file suffix
254
        if (QFile *file = qobject_cast<QFile *>(d->device))
255
            suffix = QFileInfo(file->fileName()).suffix().toLower().toLatin1();
256
    }
257
258
    QByteArray format = !d->format.isEmpty() ? d->format.toLower() : suffix;
259
260
#ifndef QT_NO_TEXTODFWRITER
261
    if (format == "odf" || format == "opendocumentformat" || format == "odt") {
262
        QTextOdfWriter writer(*document, d->device);
263
#ifndef QT_NO_TEXTCODEC
264
        writer.setCodec(d->codec);
265
#endif
266
        return writer.writeAll();
267
    }
268
#endif // QT_NO_TEXTODFWRITER
269
270
#ifndef QT_NO_TEXTHTMLPARSER
271
    if (format == "html" || format == "htm") {
272
        if (!d->device->isWritable() && ! d->device->open(QIODevice::WriteOnly)) {
273
            qWarning() << "QTextDocumentWriter::write: the device can not be opened for writing";
274
            return false;
275
        }
276
        QTextStream ts(d->device);
277
#ifndef QT_NO_TEXTCODEC
278
        ts.setCodec(d->codec);
279
        ts << document->toHtml(d->codec->name());
280
#endif
281
        d->device->close();
282
        return true;
283
    }
284
#endif
285
    if (format == "txt" || format == "plaintext") {
286
        if (!d->device->isWritable() && ! d->device->open(QIODevice::WriteOnly)) {
287
            qWarning() << "QTextDocumentWriter::write: the device can not be opened for writing";
288
            return false;
289
        }
290
        QTextStream ts(d->device);
291
#ifndef QT_NO_TEXTCODEC
292
        ts.setCodec(d->codec);
293
#endif
294
        ts << document->toPlainText();
295
        d->device->close();
296
        return true;
297
    }
298
299
    return false;
300
}
301
302
/*!
303
    Writes the document fragment specified by \a fragment to the assigned device
304
    or file and returns true if successful; otherwise returns false.
305
*/
306
bool QTextDocumentWriter::write(const QTextDocumentFragment &fragment)
307
{
308
    if (fragment.d == 0)
309
        return false; // invalid fragment.
310
    QTextDocument *doc = fragment.d->doc;
311
    if (doc)
312
        return write(doc);
313
    return false;
314
}
315
316
/*!
317
    Sets the codec for this stream to \a codec. The codec is used for
318
    encoding any data that is written. By default, QTextDocumentWriter
319
    uses UTF-8.
320
*/
321
322
#ifndef QT_NO_TEXTCODEC
323
void QTextDocumentWriter::setCodec(QTextCodec *codec)
324
{
325
    if (codec == 0)
326
        codec = QTextCodec::codecForName("UTF-8");
327
    Q_ASSERT(codec);
328
    d->codec = codec;
329
}
330
#endif
331
332
/*!
333
    Returns the codec that is currently assigned to the writer.
334
*/
335
#ifndef QT_NO_TEXTCODEC
336
QTextCodec *QTextDocumentWriter::codec() const
337
{
338
    return d->codec;
339
}
340
#endif
341
342
/*!
343
    Returns the list of document formats supported by QTextDocumentWriter.
344
345
    By default, Qt can write the following formats:
346
347
    \table
348
    \header \o Format    \o Description
349
    \row    \o plaintext \o Plain text
350
    \row    \o HTML      \o HyperText Markup Language
351
    \row    \o ODF       \o OpenDocument Format
352
    \endtable
353
354
    \sa setFormat()
355
*/
356
QList<QByteArray> QTextDocumentWriter::supportedDocumentFormats()
357
{
358
    QList<QByteArray> answer;
359
    answer << "plaintext";
360
361
#ifndef QT_NO_TEXTHTMLPARSER
362
    answer << "HTML";
363
#endif
364
#ifndef QT_NO_TEXTODFWRITER
365
    answer << "ODF";
366
#endif // QT_NO_TEXTODFWRITER
367
368
    qSort(answer);
369
    return answer;
370
}
371
372
QT_END_NAMESPACE