/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** Copyright (C) 2009 netlabs.org. OS/2 parts. ** ** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain ** additional rights. These rights are described in the Nokia Qt LGPL ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qmime.h" #include "qimagereader.h" #include "qimagewriter.h" #include "qdatastream.h" #include "qbuffer.h" #include "qt_os2.h" #include "qapplication_p.h" #include "qtextcodec.h" #include "qregexp.h" #include "qalgorithms.h" #include "qmap.h" #include "qdnd_p.h" #include "qurl.h" #include "qvariant.h" #include "qtextdocument.h" #include "qdir.h" #define QMIME_DEBUG QT_BEGIN_NAMESPACE class QPMMimeList { public: QPMMimeList(); ~QPMMimeList(); void addMime(QPMMime *mime); void removeMime(QPMMime *mime); QList mimes(); private: void init(); bool initialized; QList list; }; Q_GLOBAL_STATIC(QPMMimeList, theMimeList); /*! \class QPMMime \brief The QMPMime class maps open-standard MIME to OS/2 PM Clipboard formats. \ingroup io \ingroup draganddrop \ingroup misc Qt's drag-and-drop and clipboard facilities use the MIME standard. On X11, this maps trivially to the Xdnd protocol, but on OS/2 although some applications use MIME types to describe clipboard formats, others use arbitrary non-standardized naming conventions, or unnamed built-in formats of the Presentation Manager. By instantiating subclasses of QPMMime that provide conversions between OS/2 PM Clipboard and MIME formats, you can convert proprietary clipboard formats to MIME formats. Qt has predefined support for the following PM Clipboard formats: \table \header \o PM Format \o Equivalent MIME type \row \o \c CF_TEXT \o \c text/plain \row \o \c CF_BITMAP \o \c{image/xyz}, where \c xyz is a \l{QImageWriter::supportedImageFormats()}{Qt image format} \endtable An example use of this class would be to map the PM Metafile clipboard format (\c CF_METAFILE) to and from the MIME type \c{image/x-metafile}. This conversion might simply be adding or removing a header, or even just passing on the data. See \l{Drag and Drop} for more information on choosing and definition MIME types. */ /*! Constructs a new conversion object, adding it to the globally accessed list of available converters. */ QPMMime::QPMMime() { theMimeList()->addMime(this); } /*! Destroys a conversion object, removing it from the global list of available converters. */ QPMMime::~QPMMime() { theMimeList()->removeMime(this); } /*! Registers the MIME type \a mime, and returns an ID number identifying the format on OS/2. */ ULONG QPMMime::registerMimeType(const QString &mime) { QString atom = QLatin1String("mime:") + mime; ULONG cf = WinAddAtom(WinQuerySystemAtomTable(), atom.toLocal8Bit()); if (!cf) { #ifndef QT_NO_DEBUG qWarning("QPMMime: WinAddAtom failed with %lX", WinGetLastError(NULLHANDLE)); #endif return 0; } return cf; } /*! \fn QList QPMMime::formatsForMimeData(const QMimeData *mimeData) const Returns a list of ULONG values representing the different OS/2 PM clipboard formats that can be provided for the \a mimeData, in order of precedence (the most suitable format goes first), or an empty list if neither of the mime types provided by \a mimeData is supported by this converter. All subclasses must reimplement this pure virtual function. */ /*! \fn bool QPMMime::convertFromMimeData(const QMimeData *mimeData, ULONG format, ULONG &flags, ULONG *data) const Converts the \a mimeData to the specified \a format. If \a data is not NULL, a handle to the converted data should then be placed in a variable pointed to by \a data and with the necessary flags describing the handle returned in the \a flags variable. The following flags describing the data type are recognized: \table \row \o \c CFI_POINTER \o \a data is a pointer to a block of memory allocated with QPMMime::allocMem() \row \o \c CFI_HANDLE \o \a data is a handle to the appropriate PM resource \endtable If \a data is NULL then a delayed conversion is requested by the caller. The implementation should return the appropriate flags in the \a flags variable and may perform the real data conversion later when this method is called again with \a data being non-NULL. Return true if the conversion was successful. All subclasses must reimplement this pure virtual function. */ /*! \fn QStringList QPMMime::mimesForFormats(const QList &formats) const Returns a list of mime types that will be created form the specified \a list of \a formats, in order of precedence (the most suitable mime type comes first), or an empty list if neither of the \a formats is supported by this converter. All subclasses must reimplement this pure virtual function. */ /*! \fn QVariant QPMMime::convertFromFormat(ULONG format, ULONG flags, ULONG data, const QString &mimeType, QVariant::Type preferredType) const Returns a QVariant containing the converted from the \a data in the specified \a format with the given \a flags to the requested \a mimeType. If possible the QVariant should be of the \a preferredType to avoid needless conversions. All subclasses must reimplement this pure virtual function. */ // static QList QPMMime::allConvertersFromFormats(const QList &formats) { QList matches; QList mimes = theMimeList()->mimes(); for (int i = mimes.size()-1; i >= 0; --i) { QStringList fmts = mimes[i]->mimesForFormats(formats); int priority = 0; foreach (QString fmt, fmts) { ++priority; QList::iterator it = matches.begin(); for (; it != matches.end(); ++it) { Match &match = *it; if (match.mime == fmt) { // replace if priority is higher, ignore otherwise if (priority < match.priority) { match.converter = mimes[i]; match.priority = priority; } break; } } if (it == matches.end()) { matches += Match(mimes[i], fmt, priority); } } } return matches; } // static QList QPMMime::allConvertersFromMimeData(const QMimeData *mimeData) { QList matches; QList mimes = theMimeList()->mimes(); for (int i = mimes.size()-1; i >= 0; --i) { QList cfs = mimes[i]->formatsForMimeData(mimeData); int priority = 0; foreach (ULONG cf, cfs) { ++priority; QList::iterator it = matches.begin(); for (; it != matches.end(); ++it) { Match &match = *it; if (match.format == cf) { // replace if priority is higher, ignore otherwise if (priority < match.priority) { match.converter = mimes[i]; match.priority = priority; } break; } } if (it == matches.end()) { matches += Match(mimes[i], cf, priority); } } } return matches; } //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// QPMMimeList::QPMMimeList() : initialized(false) { } QPMMimeList::~QPMMimeList() { while (list.size()) delete list.first(); } void QPMMimeList::init() { if (!initialized) { initialized = true; // @todo new QPMMimeXXX; } } void QPMMimeList::addMime(QPMMime *mime) { init(); list.append(mime); } void QPMMimeList::removeMime(QPMMime *mime) { init(); list.removeAll(mime); } QList QPMMimeList::mimes() { init(); return list; } QT_END_NAMESPACE