source: vendor/trolltech/current/src/kernel/qmime.cpp

Last change on this file was 2, checked in by dmik, 20 years ago

Imported xplatform parts of the official release 3.3.1 from Trolltech

  • Property svn:keywords set to Id
File size: 18.2 KB
Line 
1/****************************************************************************
2** $Id: qmime.cpp 2 2005-11-16 15:49:26Z dmik $
3**
4** Implementation of MIME support
5**
6** Copyright (C) 1992-2001 Trolltech AS. All rights reserved.
7**
8** This file is part of the kernel module of the Qt GUI Toolkit.
9**
10** This file may be distributed under the terms of the Q Public License
11** as defined by Trolltech AS of Norway and appearing in the file
12** LICENSE.QPL included in the packaging of this file.
13**
14** This file may be distributed and/or modified under the terms of the
15** GNU General Public License version 2 as published by the Free Software
16** Foundation and appearing in the file LICENSE.GPL included in the
17** packaging of this file.
18**
19** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
20** licenses may use this file in accordance with the Qt Commercial License
21** Agreement provided with the Software.
22**
23** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
24** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
25**
26** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
27** information about Qt Commercial License Agreements.
28** See http://www.trolltech.com/qpl/ for QPL licensing information.
29** See http://www.trolltech.com/gpl/ for GPL licensing information.
30**
31** Contact info@trolltech.com if any conditions of this licensing are
32** not clear to you.
33**
34**********************************************************************/
35
36#include "qmime.h"
37
38#ifndef QT_NO_MIME
39
40#include "qmap.h"
41#include "qstringlist.h"
42#include "qfileinfo.h"
43#include "qdir.h"
44#include "qdragobject.h"
45#include "qcleanuphandler.h"
46#include "qapplication.h" // ### for now
47#include "qclipboard.h" // ### for now
48
49/*!
50 \class QMimeSource qmime.h
51 \brief The QMimeSource class is an abstraction of objects which provide formatted data of a certain MIME type.
52
53 \ingroup io
54 \ingroup draganddrop
55 \ingroup misc
56
57 \link dnd.html Drag-and-drop\endlink and
58 \link QClipboard clipboard\endlink use this abstraction.
59
60 \sa \link http://www.isi.edu/in-notes/iana/assignments/media-types/
61 IANA list of MIME media types\endlink
62*/
63
64static int qt_mime_serial_number = 0;
65static QMimeSourceFactory* defaultfactory = 0;
66static QSingleCleanupHandler<QMimeSourceFactory> qmime_cleanup_factory;
67
68/*!
69 Constructs a mime source and assigns a globally unique serial
70 number to it.
71
72 \sa serialNumber()
73*/
74
75QMimeSource::QMimeSource()
76{
77 ser_no = qt_mime_serial_number++;
78 cacheType = NoCache;
79}
80
81/*!
82 \fn int QMimeSource::serialNumber() const
83
84 Returns the mime source's globally unique serial number.
85*/
86
87
88void QMimeSource::clearCache()
89{
90 if ( cacheType == Text ) {
91 delete cache.txt.str;
92 delete cache.txt.subtype;
93 cache.txt.str = 0;
94 cache.txt.subtype = 0;
95 } else if ( cacheType == Graphics ) {
96 delete cache.gfx.img;
97 delete cache.gfx.pix;
98 cache.gfx.img = 0;
99 cache.gfx.pix = 0;
100 }
101 cacheType = NoCache;
102}
103
104/*!
105 Provided to ensure that subclasses destroy themselves correctly.
106*/
107QMimeSource::~QMimeSource()
108{
109 clearCache();
110}
111
112/*!
113 \fn QByteArray QMimeSource::encodedData(const char*) const
114
115 Returns the encoded data of this object in the specified MIME
116 format.
117
118 Subclasses must reimplement this function.
119*/
120
121
122
123/*!
124 Returns TRUE if the object can provide the data in format \a
125 mimeType; otherwise returns FALSE.
126
127 If you inherit from QMimeSource, for consistency reasons it is
128 better to implement the more abstract canDecode() functions such
129 as QTextDrag::canDecode() and QImageDrag::canDecode().
130*/
131bool QMimeSource::provides(const char* mimeType) const
132{
133 const char* fmt;
134 for (int i=0; (fmt = format(i)); i++) {
135 if ( !qstricmp(mimeType,fmt) )
136 return TRUE;
137 }
138 return FALSE;
139}
140
141
142/*!
143 \fn const char * QMimeSource::format(int i) const
144
145 Returns the \a{i}-th supported MIME format, or 0.
146*/
147
148
149
150class QMimeSourceFactoryData {
151public:
152 QMimeSourceFactoryData() :
153 last(0)
154 {
155 }
156
157 ~QMimeSourceFactoryData()
158 {
159 QMap<QString, QMimeSource*>::Iterator it = stored.begin();
160 while ( it != stored.end() ) {
161 delete *it;
162 ++it;
163 }
164 delete last;
165 }
166
167 QMap<QString, QMimeSource*> stored;
168 QMap<QString, QString> extensions;
169 QStringList path;
170 QMimeSource* last;
171 QPtrList<QMimeSourceFactory> factories;
172};
173
174
175/*!
176 \class QMimeSourceFactory qmime.h
177 \brief The QMimeSourceFactory class is an extensible provider of mime-typed data.
178
179 \ingroup io
180 \ingroup environment
181
182 A QMimeSourceFactory provides an abstract interface to a
183 collection of information. Each piece of information is
184 represented by a QMimeSource object which can be examined and
185 converted to concrete data types by functions such as
186 QImageDrag::canDecode() and QImageDrag::decode().
187
188 The base QMimeSourceFactory can be used in two ways: as an
189 abstraction of a collection of files or as specifically stored
190 data. For it to access files, call setFilePath() before accessing
191 data. For stored data, call setData() for each item (there are
192 also convenience functions, e.g. setText(), setImage() and
193 setPixmap(), that simply call setData() with appropriate
194 parameters).
195
196 The rich text widgets, QTextEdit and QTextBrowser, use
197 QMimeSourceFactory to resolve references such as images or links
198 within rich text documents. They either access the default factory
199 (see \l{defaultFactory()}) or their own (see
200 \l{QTextEdit::setMimeSourceFactory()}). Other classes that are
201 capable of displaying rich text (such as QLabel, QWhatsThis or
202 QMessageBox) always use the default factory.
203
204 A factory can also be used as a container to store data associated
205 with a name. This technique is useful whenever rich text contains
206 images that are stored in the program itself, not loaded from the
207 hard disk. Your program may, for example, define some image data
208 as:
209 \code
210 static const char* myimage_data[]={
211 "...",
212 ...
213 "..."};
214 \endcode
215
216 To be able to use this image within some rich text, for example
217 inside a QLabel, you must create a QImage from the raw data and
218 insert it into the factory with a unique name:
219 \code
220 QMimeSourceFactory::defaultFactory()->setImage( "myimage", QImage(myimage_data) );
221 \endcode
222
223 Now you can create a rich text QLabel with
224
225 \code
226 QLabel* label = new QLabel(
227 "Rich text with embedded image:<img source=\"myimage\">"
228 "Isn't that <em>cute</em>?" );
229 \endcode
230
231 When no longer needed, you can clear the data from the factory:
232
233 \code
234 delete label;
235 QMimeSourceFactory::defaultFactory()->setData( "myimage", 0 );
236 \endcode
237*/
238
239
240/*!
241 Constructs a QMimeSourceFactory that has no file path and no
242 stored content.
243*/
244QMimeSourceFactory::QMimeSourceFactory() :
245 d(new QMimeSourceFactoryData)
246{
247 // add some reasonable defaults
248 setExtensionType("htm", "text/html;charset=iso8859-1");
249 setExtensionType("html", "text/html;charset=iso8859-1");
250 setExtensionType("txt", "text/plain");
251 setExtensionType("xml", "text/xml;charset=UTF-8");
252 setExtensionType("jpg", "image/jpeg"); // support misspelled jpeg files
253}
254
255/*!
256 Destroys the QMimeSourceFactory, deleting all stored content.
257*/
258QMimeSourceFactory::~QMimeSourceFactory()
259{
260 if ( defaultFactory() == this )
261 defaultfactory = 0;
262 delete d;
263}
264
265QMimeSource* QMimeSourceFactory::dataInternal(const QString& abs_name, const QMap<QString, QString> &extensions ) const
266{
267 QMimeSource* r = 0;
268 QFileInfo fi(abs_name);
269 if ( fi.isReadable() ) {
270
271 // get the right mimetype
272 QString e = fi.extension(FALSE);
273 QCString mimetype = "application/octet-stream";
274 const char* imgfmt;
275 if ( extensions.contains(e) )
276 mimetype = extensions[e].latin1();
277 else if ( ( imgfmt = QImage::imageFormat( abs_name ) ) )
278 mimetype = QCString("image/")+QCString(imgfmt).lower();
279
280 QFile f(abs_name);
281 if ( f.open(IO_ReadOnly) && f.size() ) {
282 QByteArray ba(f.size());
283 f.readBlock(ba.data(), ba.size());
284 QStoredDrag* sr = new QStoredDrag( mimetype );
285 sr->setEncodedData( ba );
286 delete d->last;
287 d->last = r = sr;
288 }
289 }
290
291 // we didn't find the mime-source, so ask the default factory for
292 // the mime-source (this one will iterate over all installed ones)
293 //
294 // this looks dangerous, as this dataInternal() function will be
295 // called again when the default factory loops over all installed
296 // factories (including this), but the static bool looping in
297 // data() avoids endless recursions
298 if ( !r && this != defaultFactory() )
299 r = (QMimeSource*)defaultFactory()->data( abs_name );
300
301 return r;
302}
303
304
305/*!
306 Returns a reference to the data associated with \a abs_name. The
307 return value remains valid only until the next data() or setData()
308 call, so you should immediately decode the result.
309
310 If there is no data associated with \a abs_name in the factory's
311 store, the factory tries to access the local filesystem. If \a
312 abs_name isn't an absolute file name, the factory will search for
313 it in all defined paths (see \l{setFilePath()}).
314
315 The factory understands all the image formats supported by
316 QImageIO. Any other mime types are determined by the file name
317 extension. The default settings are
318 \code
319 setExtensionType("html", "text/html;charset=iso8859-1");
320 setExtensionType("htm", "text/html;charset=iso8859-1");
321 setExtensionType("txt", "text/plain");
322 setExtensionType("xml", "text/xml;charset=UTF-8");
323 \endcode
324 The effect of these is that file names ending in "txt" will be
325 treated as text encoded in the local encoding; those ending in
326 "xml" will be treated as text encoded in Unicode UTF-8 encoding.
327 The text/html type is treated specially, since the encoding can be
328 specified in the html file itself. "html" or "htm" will be treated
329 as text encoded in the encoding specified by the html meta tag, if
330 none could be found, the charset of the mime type will be used.
331 The text subtype ("html", "plain", or "xml") does not affect the
332 factory, but users of the factory may behave differently. We
333 recommend creating "xml" files where practical. These files can be
334 viewed regardless of the runtime encoding and can encode any
335 Unicode characters without resorting to encoding definitions
336 inside the file.
337
338 Any file data that is not recognized will be retrieved as a
339 QMimeSource providing the "application/octet-stream" mime type,
340 meaning uninterpreted binary data.
341
342 You can add further extensions or change existing ones with
343 subsequent calls to setExtensionType(). If the extension mechanism
344 is not sufficient for your problem domain, you can inherit
345 QMimeSourceFactory and reimplement this function to perform some
346 more specialized mime-type detection. The same applies if you want
347 to use the mime source factory to access URL referenced data over
348 a network.
349*/
350const QMimeSource* QMimeSourceFactory::data(const QString& abs_name) const
351{
352 if ( d->stored.contains(abs_name) )
353 return d->stored[abs_name];
354
355 QMimeSource* r = 0;
356 QStringList::Iterator it;
357 if ( abs_name[0] == '/'
358#ifdef Q_WS_WIN
359 || ( abs_name[0] && abs_name[1] == ':' ) || abs_name.startsWith("\\\\")
360#endif
361 )
362 {
363 // handle absolute file names directly
364 r = dataInternal( abs_name, d->extensions);
365 }
366 else { // check list of paths
367 for ( it = d->path.begin(); !r && it != d->path.end(); ++it ) {
368 QString filename = *it;
369 if ( filename[(int)filename.length()-1] != '/' )
370 filename += '/';
371 filename += abs_name;
372 r = dataInternal( filename, d->extensions );
373 }
374 }
375
376 static bool looping = FALSE;
377 if ( !r && this == defaultFactory() ) {
378 // we found no mime-source and we are the default factory, so
379 // we know all the other installed mime-source factories, so
380 // ask them
381 if ( !looping ) {
382 // to avoid endless recustions, don't enter the loop below
383 // if data() got called from within the loop below
384 looping = TRUE;
385 QPtrListIterator<QMimeSourceFactory> it( d->factories );
386 QMimeSourceFactory *f;
387 while ( ( f = it.current() ) ) {
388 ++it;
389 if ( f == this )
390 continue;
391 r = (QMimeSource*)f->data( abs_name );
392 if ( r ) {
393 looping = FALSE;
394 return r;
395 }
396 }
397 looping = FALSE;
398 }
399 } else if ( !r ) {
400 // we are not the default mime-source factory, so ask the
401 // default one for the mime-source, as this one will loop over
402 // all installed mime-source factories and ask these
403 r = (QMimeSource*)defaultFactory()->data( abs_name );
404 }
405
406 return r;
407}
408
409/*!
410 Sets the list of directories that will be searched when named data
411 is requested to the those given in the string list \a path.
412
413 \sa filePath()
414*/
415void QMimeSourceFactory::setFilePath( const QStringList& path )
416{
417 d->path = path;
418}
419
420/*!
421 Returns the currently set search paths.
422*/
423QStringList QMimeSourceFactory::filePath() const
424{
425 return d->path;
426}
427
428/*!
429 Adds another search path, \a p to the existing search paths.
430
431 \sa setFilePath()
432*/
433void QMimeSourceFactory::addFilePath( const QString& p )
434{
435 d->path += p;
436}
437
438/*!
439 Sets the mime-type to be associated with the file name extension,
440 \a ext to \a mimetype. This determines the mime-type for files
441 found via the paths set by setFilePath().
442*/
443void QMimeSourceFactory::setExtensionType( const QString& ext, const char* mimetype )
444{
445 d->extensions.replace(ext, mimetype);
446}
447
448/*!
449 Converts the absolute or relative data item name \a
450 abs_or_rel_name to an absolute name, interpreted within the
451 context (path) of the data item named \a context (this must be an
452 absolute name).
453*/
454QString QMimeSourceFactory::makeAbsolute(const QString& abs_or_rel_name, const QString& context) const
455{
456 if ( context.isNull() ||
457 !(context[0] == '/'
458#ifdef Q_WS_WIN
459 || ( context[0] && context[1] == ':')
460#endif
461 ))
462 return abs_or_rel_name;
463 if ( abs_or_rel_name.isEmpty() )
464 return context;
465 QFileInfo c( context );
466 if (!c.isDir()) {
467 QFileInfo r( c.dir(TRUE), abs_or_rel_name );
468 return r.absFilePath();
469 } else {
470 QDir d(context);
471 QFileInfo r(d, abs_or_rel_name);
472 return r.absFilePath();
473 }
474}
475
476/*!
477 \overload
478 A convenience function. See data(const QString& abs_name). The
479 file name is given in \a abs_or_rel_name and the path is in \a
480 context.
481*/
482const QMimeSource* QMimeSourceFactory::data(const QString& abs_or_rel_name, const QString& context) const
483{
484 const QMimeSource* r = data(makeAbsolute(abs_or_rel_name,context));
485 if ( !r && !d->path.isEmpty() )
486 r = data(abs_or_rel_name);
487 return r;
488}
489
490
491/*!
492 Sets \a text to be the data item associated with the absolute name
493 \a abs_name.
494
495 Equivalent to setData(abs_name, new QTextDrag(text)).
496*/
497void QMimeSourceFactory::setText( const QString& abs_name, const QString& text )
498{
499 setData(abs_name, new QTextDrag(text));
500}
501
502/*!
503 Sets \a image to be the data item associated with the absolute
504 name \a abs_name.
505
506 Equivalent to setData(abs_name, new QImageDrag(image)).
507*/
508void QMimeSourceFactory::setImage( const QString& abs_name, const QImage& image )
509{
510 setData(abs_name, new QImageDrag(image));
511}
512
513/*!
514 Sets \a pixmap to be the data item associated with the absolute
515 name \a abs_name.
516*/
517void QMimeSourceFactory::setPixmap( const QString& abs_name, const QPixmap& pixmap )
518{
519 setData(abs_name, new QImageDrag(pixmap.convertToImage()));
520}
521
522/*!
523 Sets \a data to be the data item associated with
524 the absolute name \a abs_name. Note that the ownership of \a data is
525 transferred to the factory: do not delete or access the pointer after
526 passing it to this function.
527
528 Passing 0 for data removes previously stored data.
529*/
530void QMimeSourceFactory::setData( const QString& abs_name, QMimeSource* data )
531{
532 if ( d->stored.contains(abs_name) )
533 delete d->stored[abs_name];
534 d->stored.replace(abs_name,data);
535}
536
537
538/*!
539 Returns the application-wide default mime source factory. This
540 factory is used by rich text rendering classes such as
541 QSimpleRichText, QWhatsThis and QMessageBox to resolve named
542 references within rich text documents. It serves also as the
543 initial factory for the more complex render widgets, QTextEdit and
544 QTextBrowser.
545
546 \sa setDefaultFactory()
547*/
548QMimeSourceFactory* QMimeSourceFactory::defaultFactory()
549{
550 if (!defaultfactory)
551 {
552 defaultfactory = new QMimeSourceFactory();
553 qmime_cleanup_factory.set( &defaultfactory );
554 }
555 return defaultfactory;
556}
557
558/*!
559 Sets the default \a factory, destroying any previously set mime
560 source provider. The ownership of the factory is transferred to
561 Qt.
562
563 \sa defaultFactory()
564*/
565void QMimeSourceFactory::setDefaultFactory( QMimeSourceFactory* factory)
566{
567 if ( !defaultfactory )
568 qmime_cleanup_factory.set( &defaultfactory );
569 else if ( defaultfactory != factory )
570 delete defaultfactory;
571 defaultfactory = factory;
572}
573
574/*!
575 Sets the defaultFactory() to 0 and returns the previous one.
576*/
577
578QMimeSourceFactory* QMimeSourceFactory::takeDefaultFactory()
579{
580 QMimeSourceFactory *f = defaultfactory;
581 defaultfactory = 0;
582 return f;
583}
584
585/*!
586 Adds the QMimeSourceFactory \a f to the list of available
587 mimesource factories. If the defaultFactory() can't resolve a
588 data() it iterates over the list of installed mimesource factories
589 until the data can be resolved.
590
591 \sa removeFactory();
592*/
593
594void QMimeSourceFactory::addFactory( QMimeSourceFactory *f )
595{
596 QMimeSourceFactory::defaultFactory()->d->factories.append( f );
597}
598
599/*!
600 Removes the mimesource factory \a f from the list of available
601 mimesource factories.
602
603 \sa addFactory();
604*/
605
606void QMimeSourceFactory::removeFactory( QMimeSourceFactory *f )
607{
608 QMimeSourceFactory::defaultFactory()->d->factories.removeRef( f );
609}
610
611#endif // QT_NO_MIME
Note: See TracBrowser for help on using the repository browser.