Index: /trunk/src/gui/kernel/kernel.pri
===================================================================
--- /trunk/src/gui/kernel/kernel.pri	(revision 322)
+++ /trunk/src/gui/kernel/kernel.pri	(revision 323)
@@ -98,4 +98,5 @@
 		kernel/qdesktopwidget_pm.cpp \
 		kernel/qdnd_pm.cpp \
+		kernel/qmime_pm.cpp \
 		kernel/qkeymapper_pm.cpp \
 		kernel/qsound_pm.cpp \
Index: /trunk/src/gui/kernel/qclipboard_pm.cpp
===================================================================
--- /trunk/src/gui/kernel/qclipboard_pm.cpp	(revision 322)
+++ /trunk/src/gui/kernel/qclipboard_pm.cpp	(revision 323)
@@ -55,4 +55,6 @@
 #include "qdnd_p.h"
 
+#define QCLIPBOARD_DEBUG
+
 QT_BEGIN_NAMESPACE
 
@@ -75,8 +77,8 @@
         ULONG cf = 0;
         while ((cf = WinEnumClipbrdFmts(NULLHANDLE, cf))) {
-//          if (QPMMime::converterToMime(mime, cf)) {
-//              ok = true;
-//              break;
-//          }
+            if (QPMMime::converterToMime(mime, cf)) {
+                ok = true;
+                break;
+            }
         }
         WinCloseClipbrd(NULLHANDLE);
@@ -94,5 +96,9 @@
     QStringList fmts;
     if (WinOpenClipbrd(NULLHANDLE)) {
-//      fmts = QPMMime::allMimesForFormats();
+        QVector<ULONG> cfs;
+        ULONG cf = 0;
+        while ((cf = WinEnumClipbrdFmts(NULLHANDLE, cf)))
+            cfs << cf;
+        fmts = QPMMime::allMimesForFormats(cfs);
         WinCloseClipbrd(NULLHANDLE);
     }
@@ -108,10 +114,21 @@
                                              QVariant::Type type) const
 {
-    QStringList fmts;
+    QVariant result;
+
     if (WinOpenClipbrd(NULLHANDLE)) {
-        // @todo enumerate all formats and select the best converter
-//      QPMMime *converter = QPMMime::converterToMime(mime, cf);
-//      if (converter)
-//          result = converter->convertToMime(mime, cf, type);
+        ULONG cf = 0;
+        while ((cf = WinEnumClipbrdFmts(NULLHANDLE, cf))) {
+            QPMMime *converter = QPMMime::converterToMime(mime, cf);
+            if (converter) {
+                ULONG flags;
+                if (WinQueryClipbrdFmtInfo(NULLHANDLE, cf, &flags)) {
+                    ULONG data = WinQueryClipbrdData(NULLHANDLE, cf);
+                    if (data) {
+                        result = converter->convertToMime(mime, type, cf, flags, data);
+                    }
+                }
+                break;
+            }
+        }
         WinCloseClipbrd(NULLHANDLE);
     }
@@ -121,5 +138,5 @@
                  WinGetLastError(NULLHANDLE));
 #endif
-    return fmts;
+    return result;
 }
 
@@ -171,5 +188,20 @@
 void QClipboard::setMimeData(QMimeData *src, Mode mode)
 {
-    // @todo implement
+    if (mode != Clipboard)
+        return;
+
+    if (!WinOpenClipbrd(NULLHANDLE)) {
+#ifndef QT_NO_DEBUG
+        qWarning("QClipboard: WinOpenClipbrd failed with %lX",
+                 WinGetLastError(NULLHANDLE));
+#endif
+        return;
+    }
+
+    // @todo
+//  QClipboardData *d = clipboardData();
+//  d->setSource(src);
+
+    WinCloseClipbrd(NULLHANDLE);
 }
 
Index: /trunk/src/gui/kernel/qmime.h
===================================================================
--- /trunk/src/gui/kernel/qmime.h	(revision 322)
+++ /trunk/src/gui/kernel/qmime.h	(revision 323)
@@ -114,4 +114,6 @@
 */
 
+typedef unsigned long ULONG;
+
 class Q_GUI_EXPORT QPMMime
 {
@@ -119,4 +121,26 @@
     QPMMime();
     virtual ~QPMMime();
+
+    // for converting from Qt
+    virtual bool canConvertFromMime(ULONG format, const QMimeData *mimeData) const = 0;
+    virtual bool convertFromMime(ULONG format, const QMimeData *mimeData,
+                                 ULONG &flags, ULONG &data) const = 0;
+    virtual QVector<ULONG> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const = 0;
+
+    // for converting to Qt
+    virtual bool canConvertToMime(const QString &mimeType, ULONG format) const = 0;
+    virtual QVariant convertToMime(const QString &mimeType, QVariant::Type preferredType,
+                                   ULONG format, ULONG flags, ULONG data) const = 0;
+    virtual QString mimeForFormat(ULONG format) const = 0;
+
+    static ULONG registerMimeType(const QString &mime);
+
+private:
+    friend class QClipboardWatcher;
+
+    static QPMMime *converterToMime(const QString &mimeType, ULONG format);
+    static QStringList allMimesForFormats(const QVector<ULONG> &formats);
+    static QPMMime *converterFromMime(ULONG format, const QMimeData *mimeData);
+    static QVector<ULONG> allFormatsForMime(const QMimeData *mimeData);
 };
 
Index: /trunk/src/gui/kernel/qmime_pm.cpp
===================================================================
--- /trunk/src/gui/kernel/qmime_pm.cpp	(revision 322)
+++ /trunk/src/gui/kernel/qmime_pm.cpp	(revision 323)
@@ -60,5 +60,25 @@
 #include "qdir.h"
 
+#define QMIME_DEBUG
+
 QT_BEGIN_NAMESPACE
+
+class QPMMimeList
+{
+public:
+    QPMMimeList();
+    ~QPMMimeList();
+    void addMime(QPMMime *mime);
+    void removeMime(QPMMime *mime);
+    QList<QPMMime*> mimes();
+
+private:
+    void init();
+    bool initialized;
+    QList<QPMMime*> list;
+};
+
+Q_GLOBAL_STATIC(QPMMimeList, theMimeList);
+
 
 /*!
@@ -99,12 +119,202 @@
 */
 
-// @todo lots of stuff...
-
+/*!
+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 bool QPMMime::canConvertFromMime(ULONG format, const QMimeData *mimeData) const
+
+    Returns true if the converter can convert from the \a mimeData to
+    the specified \a format.
+
+    All subclasses must reimplement this pure virtual function.
+*/
+
+/*!
+    \fn bool QPMMime::convertFromMime(ULONG format, const QMimeData *mimeData,
+                                      ULONG &flags, ULONG &data) const
+
+    Convert the \a mimeData to the specified \a format.
+    The converted data should then be placed in the \a data variable with the
+    necessary flags returned in the \a flags variable.
+
+    Return true if the conversion was successful.
+
+    All subclasses must reimplement this pure virtual function.
+*/
+
+/*!
+    \fn QVector<ULONG> QPMMime::formatsForMime(const QString &mimeType, const QMimeData *mimeData) const
+
+    Returns a QVector of ULONG values representing the different OS/2 PM clipboard
+    formats that can be provided for the \a mimeType from the \a mimeData.
+
+    All subclasses must reimplement this pure virtual function.
+*/
+
+/*!
+    \fn bool QPMMime::canConvertToMime(const QString &mimeType, ULONG format) const
+
+    Returns true if the converter can convert to the \a mimeType from
+    the specified \a format.
+
+    All subclasses must reimplement this pure virtual function.
+*/
+
+/*!
+    \fn QVariant QPMMime::convertToMime(const QString &mimeType, QVariant::Type preferredType,
+                                        ULONG format, ULONG flags, ULONG data) const
+
+    Returns a QVariant containing the converted data for \a mimeType from the
+    \a data in the specified \a format and \a flags. If possible the QVariant
+    should be of the \a preferredType to avoid needless conversions.
+
+    All subclasses must reimplement this pure virtual function.
+*/
+
+/*!
+    \fn QString QPMMime::mimeForFormat(ULONG format) const
+
+    Returns the mime type that will be created form the specified \a format, or an
+    empty string if this converter does not support \a format.
+
+    All subclasses must reimplement this pure virtual function.
+*/
+
+// static
+QPMMime *QPMMime::converterToMime(const QString &mimeType, ULONG format)
+{
+    QList<QPMMime*> mimes = theMimeList()->mimes();
+    for (int i = mimes.size()-1; i >= 0; --i) {
+        if (mimes.at(i)->canConvertToMime(mimeType, format))
+            return mimes.at(i);
+    }
+    return 0;
+}
+
+// static
+QStringList QPMMime::allMimesForFormats(const QVector<ULONG> &formats)
+{
+    QList<QPMMime*> mimes = theMimeList()->mimes();
+    QStringList fmts;
+
+    foreach(ULONG cf, formats) {
+#ifdef QMIME_DEBUG
+        HATOMTBL tbl = WinQuerySystemAtomTable();
+        ULONG len = WinQueryAtomLength(tbl, cf);
+        QByteArray atom(len, 0);
+        WinQueryAtomName(tbl, cf, atom.data(), atom.size() + 1 /* '\0' */);
+        qDebug("QPMMime::allMimesForFormats() CF %lu (%s)", cf, atom.constData());
+#endif
+        for (int i = mimes.size()-1; i >= 0; --i) {
+            QString format = mimes.at(i)->mimeForFormat(cf);
+            if (!format.isEmpty() && !fmts.contains(format)) {
+                fmts += format;
+            }
+        }
+    }
+
+    return fmts;
+}
+
+// static
+QPMMime *QPMMime::converterFromMime(ULONG format, const QMimeData *mimeData)
+{
+    QList<QPMMime*> mimes = theMimeList()->mimes();
+    for (int i = mimes.size()-1; i >= 0; --i) {
+        if (mimes.at(i)->canConvertFromMime(format, mimeData))
+            return mimes.at(i);
+    }
+    return 0;
+}
+
+// static
+QVector<ULONG> QPMMime::allFormatsForMime(const QMimeData *mimeData)
+{
+    QList<QPMMime*> mimes = theMimeList()->mimes();
+    QVector<ULONG> cfs(4);
+    QStringList formats = QInternalMimeData::formatsHelper(mimeData);
+    for (int f = 0; f < formats.size(); ++f) {
+        for (int i = mimes.size()-1; i >= 0; --i)
+            cfs += mimes.at(i)->formatsForMime(formats.at(f), mimeData);
+    }
+    return cfs;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////
+
+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<QPMMime*> QPMMimeList::mimes()
+{
+    init();
+    return list;
 }
 
