Changeset 324 for trunk/src


Ignore:
Timestamp:
Nov 18, 2009, 1:49:31 AM (16 years ago)
Author:
Dmitry A. Kuminov
Message:

gui/kernel: Improved mime <-> PM clipboard format conversion interfaces.

Location:
trunk/src
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/corelib/kernel/qcoreapplication.h

    r68 r324  
    217217    friend Q_CORE_EXPORT QString qAppName();
    218218    friend class QClassFactory;
     219
     220
     221
     222
    219223};
    220224
  • trunk/src/gui/kernel/qclipboard_pm.cpp

    r323 r324  
    5252#include "qevent.h"
    5353#include "qmime.h"
     54
     55
    5456#include "qt_os2.h"
    55 #include "qdnd_p.h"
     57#include "_p.h"
    5658
    5759#define QCLIPBOARD_DEBUG
    5860
     61
     62
     63
     64
    5965QT_BEGIN_NAMESPACE
    6066
     
    6470{
    6571public:
    66     QClipboardWatcher() {}
     72    QClipboardWatcher() {}
    6773
    6874    bool hasFormat_sys(const QString &mimetype) const;
    6975    QStringList formats_sys() const;
    7076    QVariant retrieveData_sys(const QString &mimetype, QVariant::Type preferredType) const;
     77
     78
     79
     80
     81
     82
     83
     84
    7185};
    7286
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
     100
     101
     102
     103
     104
     105
     106
     107
     108
     109
     110
    73111bool QClipboardWatcher::hasFormat_sys(const QString &mime) const
    74112{
    75     bool ok = false;
    76     if (WinOpenClipbrd(NULLHANDLE)) {
    77         ULONG cf = 0;
    78         while ((cf = WinEnumClipbrdFmts(NULLHANDLE, cf))) {
    79             if (QPMMime::converterToMime(mime, cf)) {
    80                 ok = true;
    81                 break;
    82             }
    83         }
    84         WinCloseClipbrd(NULLHANDLE);
    85     }
    86 #ifndef QT_NO_DEBUG
    87     else
    88         qWarning("QClipboardWatcher: WinOpenClipbrd failed with %lX",
    89                  WinGetLastError(NULLHANDLE));
    90 #endif
    91     return ok;
     113    peekData();
     114    if (isDirty)
     115        return false; // peekData() failed
     116
     117    foreach (QPMMime::Match match, matches)
     118        if (match.mime == mime)
     119            return true;
     120
     121    return false;
    92122}
    93123
     
    95125{
    96126    QStringList fmts;
    97     if (WinOpenClipbrd(NULLHANDLE)) {
    98         QVector<ULONG> cfs;
    99         ULONG cf = 0;
    100         while ((cf = WinEnumClipbrdFmts(NULLHANDLE, cf)))
    101             cfs << cf;
    102         fmts = QPMMime::allMimesForFormats(cfs);
    103         WinCloseClipbrd(NULLHANDLE);
    104     }
    105 #ifndef QT_NO_DEBUG
    106     else
    107         qWarning("QClipboardWatcher: WinOpenClipbrd failed with %lX",
    108                  WinGetLastError(NULLHANDLE));
    109 #endif
     127
     128    peekData();
     129    if (isDirty)
     130        return fmts; // peekData() failed
     131
     132    foreach (QPMMime::Match match, matches)
     133        fmts << match.mime;
     134
    110135    return fmts;
    111136}
     
    116141    QVariant result;
    117142
    118     if (WinOpenClipbrd(NULLHANDLE)) {
    119         ULONG cf = 0;
    120         while ((cf = WinEnumClipbrdFmts(NULLHANDLE, cf))) {
    121             QPMMime *converter = QPMMime::converterToMime(mime, cf);
    122             if (converter) {
    123                 ULONG flags;
    124                 if (WinQueryClipbrdFmtInfo(NULLHANDLE, cf, &flags)) {
    125                     ULONG data = WinQueryClipbrdData(NULLHANDLE, cf);
    126                     if (data) {
    127                         result = converter->convertToMime(mime, type, cf, flags, data);
    128                     }
    129                 }
    130                 break;
     143    peekData();
     144    if (isDirty)
     145        return result; // peekData() failed
     146
     147    foreach (QPMMime::Match match, matches) {
     148        if (match.mime == mime) {
     149            ULONG flags;
     150            if (WinQueryClipbrdFmtInfo(NULLHANDLE, match.format, &flags)) {
     151                ULONG data = WinQueryClipbrdData(NULLHANDLE, match.format);
     152                result = match.converter->convertFromFormat(match.format, flags,
     153                                                            data, match.mime, type);
    131154            }
     155
    132156        }
    133         WinCloseClipbrd(NULLHANDLE);
    134     }
    135 #ifndef QT_NO_DEBUG
    136     else
    137         qWarning("QClipboardWatcher: WinOpenClipbrd failed with %lX",
    138                  WinGetLastError(NULLHANDLE));
    139 #endif
     157    }
     158
    140159    return result;
    141160}
     
    143162////////////////////////////////////////////////////////////////////////////////
    144163
    145 class QClipboardData
     164class QClipboardData
    146165{
    147166public:
     
    149168    ~QClipboardData();
    150169
    151     // @todo ...
     170    void setSource(QMimeData *s)
     171    {
     172        if (s == src)
     173            return;
     174        delete src;
     175        src = s;
     176    }
     177
     178    QMimeData *source()
     179    {
     180        return src;
     181    }
     182
     183    bool setClipboard(QPMMime *converter, ULONG format, bool isDelayed);
     184
     185    MRESULT message(ULONG msg, MPARAM mp1, MPARAM mp2);
    152186
    153187private:
     188
    154189};
    155190
    156 QClipboardData::QClipboardData()
     191QClipboardData::QClipboardData()
    157192{
    158193}
     
    160195QClipboardData::~QClipboardData()
    161196{
     197
     198
     199
     200
     201
     202
     203
     204
     205
     206
     207
     208
     209
     210
     211
     212
     213
     214
     215
     216
     217
     218
     219
     220
     221
     222
     223
     224
     225
     226
     227
     228
     229
     230
     231
     232
     233
    162234}
    163235
     
    168240    if (ptrClipboardData == 0) {
    169241        ptrClipboardData = new QClipboardData;
    170         // @todo ...
    171242    }
    172243    return ptrClipboardData;
     
    181252////////////////////////////////////////////////////////////////////////////////
    182253
     254
     255
    183256QClipboard::~QClipboard()
    184257{
     
    188261void QClipboard::setMimeData(QMimeData *src, Mode mode)
    189262{
    190     if (mode != Clipboard)
     263    if (mode != Clipboard) {
     264        delete src;
    191265        return;
     266
    192267
    193268    if (!WinOpenClipbrd(NULLHANDLE)) {
    194269#ifndef QT_NO_DEBUG
    195         qWarning("QClipboard: WinOpenClipbrd failed with %lX",
     270        qWarning("QClipboard:%lX",
    196271                 WinGetLastError(NULLHANDLE));
    197272#endif
     273
    198274        return;
    199275    }
    200276
    201     // @todo
    202 //  QClipboardData *d = clipboardData();
    203 //  d->setSource(src);
     277    QClipboardData *d = clipboardData();
     278    d->setSource(src);
     279
     280    ignore_WM_DESTROYCLIPBOARD = TRUE;
     281    BOOL ok = WinEmptyClipbrd(NULLHANDLE);
     282    ignore_WM_DESTROYCLIPBOARD = FALSE;
     283#ifndef QT_NO_DEBUG
     284    if (!ok)
     285        qWarning("QClipboard::setMimeData: WinEmptyClipbrd failed with 0x%lX",
     286                 WinGetLastError(NULLHANDLE));
     287#else
     288    Q_UNUSED(ok);
     289#endif
     290
     291    if (!src)
     292        return; // nothing to do
     293
     294    bool runsEventLoop = QCoreApplication::instance() &&
     295                         QCoreApplication::instance()->d_func()->in_exec;
     296
     297    QStringList formats = src->formats();
     298    foreach(QString mime, formats) {
     299#ifdef QCLIPBOARD_DEBUG
     300        qDebug() << "QClipboard::setMimeData: src mime" << mime;
     301#endif
     302        QList<QPMMime::Match> matches = QPMMime::allConvertersFromMimeData(src);
     303        foreach(QPMMime::Match match, matches) {
     304            d->setClipboard(match.converter, match.format, !runsEventLoop);
     305        }
     306    }
    204307
    205308    WinCloseClipbrd(NULLHANDLE);
  • trunk/src/gui/kernel/qmime.h

    r323 r324  
    123123
    124124    // for converting from Qt
    125     virtual bool canConvertFromMime(ULONG format, const QMimeData *mimeData) const = 0;
    126     virtual bool convertFromMime(ULONG format, const QMimeData *mimeData,
    127                                  ULONG &flags, ULONG &data) const = 0;
    128     virtual QVector<ULONG> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const = 0;
     125    virtual QList<ULONG> formatsForMimeData(const QMimeData *mimeData) const = 0;
     126    virtual bool convertFromMimeData(const QMimeData *mimeData, ULONG format,
     127                                     ULONG &flags, ULONG *data) const = 0;
    129128
    130129    // for converting to Qt
    131     virtual bool canConvertToMime(const QString &mimeType, ULONG format) const = 0;
    132     virtual QVariant convertToMime(const QString &mimeType, QVariant::Type preferredType,
    133                                    ULONG format, ULONG flags, ULONG data) const = 0;
    134     virtual QString mimeForFormat(ULONG format) const = 0;
     130    virtual ) const = 0;
     131    virtual QVariant convert,
     132                                   
     133    ) const = 0;
    135134
    136135    static ULONG registerMimeType(const QString &mime);
     
    138137private:
    139138    friend class QClipboardWatcher;
    140 
    141     static QPMMime *converterToMime(const QString &mimeType, ULONG format);
    142     static QStringList allMimesForFormats(const QVector<ULONG> &formats);
    143     static QPMMime *converterFromMime(ULONG format, const QMimeData *mimeData);
    144     static QVector<ULONG> allFormatsForMime(const QMimeData *mimeData);
     139    friend class QClipboard;
     140
     141    struct Match
     142    {
     143        Match(QPMMime *c, const QString f, int p) :
     144            converter(c), mime(f), format(0), priority(p) {}
     145
     146        Match(QPMMime *c, ULONG f, int p) :
     147            converter(c), format(f), priority(p) {}
     148
     149        QPMMime *converter;
     150        QString mime; // used by allConvertersFromFormats()
     151        ULONG format; // used by allConvertersFromMimeData()
     152        int priority;
     153    };
     154
     155    static QList<Match> allConvertersFromFormats(const QList<ULONG> &formats);
     156    static QList<Match> allConvertersFromMimeData(const QMimeData *mimeData);
    145157};
    146158
  • trunk/src/gui/kernel/qmime_pm.cpp

    r323 r324  
    114114    header, or even just passing on the data. See \l{Drag and Drop} for more
    115115    information on choosing and definition MIME types.
    116 
    117     You can check if a MIME type is convertible using canConvertFromMime() and
    118     can perform conversions with convertToMime() and convertFromMime().
    119116*/
    120117
     
    158155
    159156/*!
    160     \fn bool QPMMime::canConvertFromMime(ULONG format, const QMimeData *mimeData) const
    161 
    162     Returns true if the converter can convert from the \a mimeData to
    163     the specified \a format.
     157    \fn QList<ULONG> QPMMime::formatsForMimeData(const QMimeData *mimeData) const
     158
     159    Returns a list of ULONG values representing the different OS/2 PM
     160    clipboard formats that can be provided for the \a mimeData, in order of
     161    precedence (the most suitable format goes first), or an empty list if
     162    neither of the mime types provided by \a mimeData is supported by this
     163    converter.
    164164
    165165    All subclasses must reimplement this pure virtual function.
     
    167167
    168168/*!
    169     \fn bool QPMMime::convertFromMime(ULONG format, const QMimeData *mimeData,
    170                                       ULONG &flags, ULONG &data) const
    171 
    172     Convert the \a mimeData to the specified \a format.
    173     The converted data should then be placed in the \a data variable with the
    174     necessary flags returned in the \a flags variable.
     169    \fn bool QPMMime::convertFromMimeData(const QMimeData *mimeData, ULONG format,
     170                                          ULONG &flags, ULONG *data) const
     171
     172    Converts the \a mimeData to the specified \a format.
     173
     174    If \a data is not NULL, a handle to the converted data should then be placed
     175    in a variable pointed to by \a data and with the necessary flags describing
     176    the handle returned in the \a flags variable.
     177
     178    The following flags describing the data type are recognized:
     179
     180    \table
     181    \row \o \c CFI_POINTER        \o \a data is a pointer to a block of memory
     182                                      allocated with QPMMime::allocMem()
     183    \row \o \c CFI_HANDLE         \o \a data is a handle to the appropriate
     184                                      PM resource
     185    \endtable
     186
     187    If \a data is NULL then a delayed conversion is requested by the caller.
     188    The implementation should return the appropriate flags in the \a flags
     189    variable and may perform the real data conversion later when this method is
     190    called again with \a data being non-NULL.
    175191
    176192    Return true if the conversion was successful.
     
    180196
    181197/*!
    182     \fn QVector<ULONG> QPMMime::formatsForMime(const QString &mimeType, const QMimeData *mimeData) const
    183 
    184     Returns a QVector of ULONG values representing the different OS/2 PM clipboard
    185     formats that can be provided for the \a mimeType from the \a mimeData.
     198    \fn QStringList QPMMime::mimesForFormats(const QList<ULONG> &formats) const
     199
     200    Returns a list of mime types that will be created form the specified \a list
     201    of \a formats, in order of precedence (the most suitable mime type comes
     202    first), or an empty list if neither of the \a formats is supported by this
     203    converter.
    186204
    187205    All subclasses must reimplement this pure virtual function.
     
    189207
    190208/*!
    191     \fn bool QPMMime::canConvertToMime(const QString &mimeType, ULONG format) const
    192 
    193     Returns true if the converter can convert to the \a mimeType from
    194     the specified \a format.
     209    \fn QVariant QPMMime::convertFromFormat(ULONG format, ULONG flags, ULONG data,
     210                                            const QString &mimeType,
     211                                            QVariant::Type preferredType) const
     212
     213    Returns a QVariant containing the converted from the \a data in the
     214    specified \a format with the given \a flags to the requested \a mimeType. If
     215    possible the QVariant should be of the \a preferredType to avoid needless
     216    conversions.
    195217
    196218    All subclasses must reimplement this pure virtual function.
    197219*/
    198220
    199 /*!
    200     \fn QVariant QPMMime::convertToMime(const QString &mimeType, QVariant::Type preferredType,
    201                                         ULONG format, ULONG flags, ULONG data) const
    202 
    203     Returns a QVariant containing the converted data for \a mimeType from the
    204     \a data in the specified \a format and \a flags. If possible the QVariant
    205     should be of the \a preferredType to avoid needless conversions.
    206 
    207     All subclasses must reimplement this pure virtual function.
    208 */
    209 
    210 /*!
    211     \fn QString QPMMime::mimeForFormat(ULONG format) const
    212 
    213     Returns the mime type that will be created form the specified \a format, or an
    214     empty string if this converter does not support \a format.
    215 
    216     All subclasses must reimplement this pure virtual function.
    217 */
    218 
    219221// static
    220 QPMMime *QPMMime::converterToMime(const QString &mimeType, ULONG format)
    221 {
     222QList<QPMMime::Match> QPMMime::allConvertersFromFormats(const QList<ULONG> &formats)
     223{
     224    QList<Match> matches;
     225
    222226    QList<QPMMime*> mimes = theMimeList()->mimes();
    223227    for (int i = mimes.size()-1; i >= 0; --i) {
    224         if (mimes.at(i)->canConvertToMime(mimeType, format))
    225             return mimes.at(i);
    226     }
    227     return 0;
    228 }
    229 
    230 // static
    231 QStringList QPMMime::allMimesForFormats(const QVector<ULONG> &formats)
    232 {
    233     QList<QPMMime*> mimes = theMimeList()->mimes();
    234     QStringList fmts;
    235 
    236     foreach(ULONG cf, formats) {
    237 #ifdef QMIME_DEBUG
    238         HATOMTBL tbl = WinQuerySystemAtomTable();
    239         ULONG len = WinQueryAtomLength(tbl, cf);
    240         QByteArray atom(len, 0);
    241         WinQueryAtomName(tbl, cf, atom.data(), atom.size() + 1 /* '\0' */);
    242         qDebug("QPMMime::allMimesForFormats() CF %lu (%s)", cf, atom.constData());
    243 #endif
    244         for (int i = mimes.size()-1; i >= 0; --i) {
    245             QString format = mimes.at(i)->mimeForFormat(cf);
    246             if (!format.isEmpty() && !fmts.contains(format)) {
    247                 fmts += format;
     228        QStringList fmts = mimes[i]->mimesForFormats(formats);
     229        int priority = 0;
     230        foreach (QString fmt, fmts) {
     231            ++priority;
     232            QList<Match>::iterator it = matches.begin();
     233            for (; it != matches.end(); ++it) {
     234                Match &match = *it;
     235                if (match.mime == fmt) {
     236                    // replace if priority is higher, ignore otherwise
     237                    if (priority < match.priority) {
     238                        match.converter = mimes[i];
     239                        match.priority = priority;
     240                    }
     241                    break;
     242                }
     243            }
     244            if (it == matches.end()) {
     245                matches += Match(mimes[i], fmt, priority);
    248246            }
    249247        }
    250248    }
    251249
    252     return fmts;
     250    return s;
    253251}
    254252
    255253// static
    256 QPMMime *QPMMime::converterFromMime(ULONG format, const QMimeData *mimeData)
    257 {
     254QList<QPMMime::Match> QPMMime::allConvertersFromMimeData(const QMimeData *mimeData)
     255{
     256    QList<Match> matches;
     257
    258258    QList<QPMMime*> mimes = theMimeList()->mimes();
    259259    for (int i = mimes.size()-1; i >= 0; --i) {
    260         if (mimes.at(i)->canConvertFromMime(format, mimeData))
    261             return mimes.at(i);
     260        QList<ULONG> cfs = mimes[i]->formatsForMimeData(mimeData);
     261        int priority = 0;
     262        foreach (ULONG cf, cfs) {
     263            ++priority;
     264            QList<Match>::iterator it = matches.begin();
     265            for (; it != matches.end(); ++it) {
     266                Match &match = *it;
     267                if (match.format == cf) {
     268                    // replace if priority is higher, ignore otherwise
     269                    if (priority < match.priority) {
     270                        match.converter = mimes[i];
     271                        match.priority = priority;
     272                    }
     273                    break;
     274                }
     275            }
     276            if (it == matches.end()) {
     277                matches += Match(mimes[i], cf, priority);
     278            }
     279        }
    262280    }
    263     return 0;
    264 }
    265 
    266 // static
    267 QVector<ULONG> QPMMime::allFormatsForMime(const QMimeData *mimeData)
    268 {
    269     QList<QPMMime*> mimes = theMimeList()->mimes();
    270     QVector<ULONG> cfs(4);
    271     QStringList formats = QInternalMimeData::formatsHelper(mimeData);
    272     for (int f = 0; f < formats.size(); ++f) {
    273         for (int i = mimes.size()-1; i >= 0; --i)
    274             cfs += mimes.at(i)->formatsForMime(formats.at(f), mimeData);
    275     }
    276     return cfs;
     281
     282    return matches;
    277283}
    278284
Note: See TracChangeset for help on using the changeset viewer.