- Timestamp:
- Nov 22, 2009, 9:48:35 PM (16 years ago)
- Location:
- trunk/src/gui/kernel
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/gui/kernel/qmime.h
r334 r337 135 135 QVariant::Type preferredType) const = 0; 136 136 137 protected: 138 137 139 static ULONG registerMimeType(const QString &mime); 138 140 139 141 static ULONG allocateMemory(size_t size); 140 142 static void freeMemory(ULONG addr); 143 144 static QString formatName(ULONG format); 141 145 142 146 private: -
trunk/src/gui/kernel/qmime_pm.cpp
r335 r337 100 100 to MIME formats. 101 101 102 Qt has predefined support for the following PM Clipboard formats: 102 Qt has predefined support for the following PM Clipboard formats (custom 103 formats registered in the system atom table by name are given in double 104 quotes): 103 105 104 106 \table 105 107 \header \o PM Format \o Equivalent MIME type 106 \row \o \c CF_TEXT \o \c text/plain 107 \row \o \c CF_BITMAP \o \c{image/xyz}, where \c xyz is 108 a \l{QImageWriter::supportedImageFormats()}{Qt image format} 108 \row \o \c CF_TEXT \o \c text/plain (system codepage, 109 zero-terminated string) 110 \row \o \c "text/unicode" \o \c text/plain (16-bit Unicode, Mozilla-compatible, 111 zero-terminated string) 112 \row \o \c CF_BITMAP \o \c{image/xyz}, where \c xyz is 113 a \l{QImageWriter::supportedImageFormats()}{Qt image format} 114 \row \o \c "x-mime:<mime>" \o data in the format corresponding to the given 115 MIME type \c <mime> 109 116 \endtable 110 117 111 An example use of this class would be to map the PM Metafile 112 clipboard format (\c CF_METAFILE) to and from the MIME type 118 Note that all "x-mime:<mime>" formats use the CFI_POINTER storage type. That 119 is, the clipboard contains a pointer to the memory block containing the MIME 120 data in the corresponding format. The first 4 bytes of this memory block 121 always contain the length of the subsequent MIME data array, in bytes. 122 123 An example use of this class by the user application would be to map the 124 PM Metafile clipboard format (\c CF_METAFILE) to and from the MIME type 113 125 \c{image/x-metafile}. This conversion might simply be adding or removing a 114 126 header, or even just passing on the data. See \l{Drag and Drop} for more … … 167 179 ULONG data = 0; 168 180 169 // allocate giveable memory for the array + dword for its size170 APIRET arc = DosAllocSharedMem((PVOID *)&data, NULL, size + 4,181 // allocate giveable memory for the array 182 APIRET arc = DosAllocSharedMem((PVOID *)&data, NULL, size, 171 183 PAG_WRITE | PAG_COMMIT | OBJ_GIVEABLE); 172 184 if (arc != NO_ERROR) { … … 177 189 } 178 190 179 /// @todo I think we don't need it any more180 #if 0181 // get the size rounded to the page boundary (4K)182 ULONG sz = ~0, flags = 0;183 arc = DosQueryMem((PVOID)(data + size - 1), &sz, &flags);184 if (arc != NO_ERROR) {185 #ifndef QT_NO_DEBUG186 qWarning("QPMMime::allocateMemory: DosQueryMem failed with %lu", arc);187 #endif188 DosFreeMem((PVOID)data);189 return 0;190 }191 sz += (size - 1);192 // store the exact size to the last dword of the last page193 *(((ULONG *)(data + sz)) - 1) = size;194 #endif195 196 191 return data; 197 192 } … … 226 221 Converts the \a mimeData to the specified \a format. 227 222 228 If \a data is not NULL, a handle to the converted data should then beplaced223 If \a data is not NULL, a handle to the converted data should be then placed 229 224 in a variable pointed to by \a data and with the necessary flags describing 230 225 the handle returned in the \a flags variable. 231 226 232 The following flags describing the data type are recognized:227 The following flags describing the data storage type are recognized: 233 228 234 229 \table … … 280 275 281 276 QList<QPMMime*> mimes = theMimeList()->mimes(); 282 for (int i = mimes.size()-1; i >= 0; --i) {283 QList<MimeCFPair> fmts = mime s[i]->mimesForFormats(formats);277 foreach(QPMMime *mime, mimes) { 278 QList<MimeCFPair> fmts = mime->mimesForFormats(formats); 284 279 int priority = 0; 285 280 foreach (MimeCFPair fmt, fmts) { … … 291 286 // replace if priority is higher, ignore otherwise 292 287 if (priority < match.priority) { 293 match.converter = mime s[i];288 match.converter = mime; 294 289 match.format = fmt.second; 295 290 match.priority = priority; … … 299 294 } 300 295 if (it == matches.end()) { 301 matches += Match(mime s[i], fmt.first, fmt.second, priority);296 matches += Match(mime, fmt.first, fmt.second, priority); 302 297 } 303 298 } … … 313 308 314 309 QList<QPMMime*> mimes = theMimeList()->mimes(); 315 for (int i = mimes.size()-1; i >= 0; --i) {316 QList<ULONG> cfs = mime s[i]->formatsForMimeData(mimeData);310 foreach(QPMMime *mime, mimes) { 311 QList<ULONG> cfs = mime->formatsForMimeData(mimeData); 317 312 int priority = 0; 318 313 foreach (ULONG cf, cfs) { … … 324 319 // replace if priority is higher, ignore otherwise 325 320 if (priority < match.priority) { 326 match.converter = mime s[i];321 match.converter = mime; 327 322 match.priority = priority; 328 323 } … … 331 326 } 332 327 if (it == matches.end()) { 333 matches += Match(mime s[i], cf, priority);328 matches += Match(mime, cf, priority); 334 329 } 335 330 } … … 337 332 338 333 return matches; 334 } 335 336 QString QPMMime::formatName(ULONG format) 337 { 338 QString name; 339 HATOMTBL tbl = WinQuerySystemAtomTable(); 340 if (tbl != NULLHANDLE) { 341 ULONG len = WinQueryAtomLength(tbl, format); 342 QByteArray atom(len, '\0'); 343 WinQueryAtomName(tbl, format, atom.data(), atom.size() + 1); 344 name = QString::fromLocal8Bit(atom); 345 } 346 return name; 339 347 } 340 348 … … 346 354 QPMMimeText(); 347 355 356 // for converting from Qt 348 357 QList<ULONG> formatsForMimeData(const QMimeData *mimeData) const; 349 358 bool convertFromMimeData(const QMimeData *mimeData, ULONG format, 350 359 ULONG &flags, ULONG *data) const; 351 360 361 // for converting to Qt 352 362 QList<MimeCFPair> mimesForFormats(const QList<ULONG> &formats) const; 353 363 QVariant convertFromFormat(ULONG format, ULONG flags, ULONG data, … … 519 529 //////////////////////////////////////////////////////////////////////////////// 520 530 531 class QPMMimeAnyMime : public QPMMime 532 { 533 public: 534 QPMMimeAnyMime(); 535 536 // for converting from Qt 537 QList<ULONG> formatsForMimeData(const QMimeData *mimeData) const; 538 bool convertFromMimeData(const QMimeData *mimeData, ULONG format, 539 ULONG &flags, ULONG *data) const; 540 541 // for converting to Qt 542 QList<MimeCFPair> mimesForFormats(const QList<ULONG> &formats) const; 543 QVariant convertFromFormat(ULONG format, ULONG flags, ULONG data, 544 const QString &mimeType, 545 QVariant::Type preferredType) const; 546 547 private: 548 ULONG registerMimeType(const QString &mime) const; 549 QString registerFormat(ULONG format) const; 550 551 mutable QMap<QString, ULONG> cfMap; 552 mutable QMap<ULONG, QString> mimeMap; 553 554 static QStringList ianaTypes; 555 static QString mimePrefix; 556 static QString customPrefix; 557 }; 558 559 // static 560 QStringList QPMMimeAnyMime::ianaTypes; 561 QString QPMMimeAnyMime::mimePrefix; 562 QString QPMMimeAnyMime::customPrefix; 563 564 QPMMimeAnyMime::QPMMimeAnyMime() 565 { 566 //MIME Media-Types 567 if (!ianaTypes.size()) { 568 ianaTypes.append(QLatin1String("application/")); 569 ianaTypes.append(QLatin1String("audio/")); 570 ianaTypes.append(QLatin1String("example/")); 571 ianaTypes.append(QLatin1String("image/")); 572 ianaTypes.append(QLatin1String("message/")); 573 ianaTypes.append(QLatin1String("model/")); 574 ianaTypes.append(QLatin1String("multipart/")); 575 ianaTypes.append(QLatin1String("text/")); 576 ianaTypes.append(QLatin1String("video/")); 577 578 mimePrefix = QLatin1String("x-mime:"); 579 customPrefix = QLatin1String("application/x-qt-pm-mime;value=\""); 580 } 581 } 582 583 QList<ULONG> QPMMimeAnyMime::formatsForMimeData(const QMimeData *mimeData) const 584 { 585 QList<ULONG> cfs; 586 587 QStringList mimes = QInternalMimeData::formatsHelper(mimeData); 588 foreach (QString mime, mimes) { 589 ULONG cf = cfMap.value(mime); 590 if (!cf) 591 cf = registerMimeType(mime); 592 if (cf) 593 cfs << cf; 594 } 595 596 return cfs; 597 } 598 599 bool QPMMimeAnyMime::convertFromMimeData(const QMimeData *mimeData, ULONG format, 600 ULONG &flags, ULONG *data) const 601 { 602 QString mime = mimeMap.value(format); 603 if (mime.isNull()) 604 return false; 605 606 flags = CFI_POINTER; 607 608 if (data == NULL) 609 return true; // delayed rendering, nothing to do 610 611 QByteArray r = QInternalMimeData::renderDataHelper(mime, mimeData); 612 if (r.isNull()) 613 return false; 614 615 *data = QPMMime::allocateMemory(r.size() + sizeof(ULONG)); 616 if (!*data) 617 return false; 618 619 *((ULONG *)(*data)) = r.size(); 620 memcpy((void *)(*data + sizeof(ULONG)), r.data(), r.size()); 621 return true; 622 } 623 624 QList<QPMMime::MimeCFPair> QPMMimeAnyMime::mimesForFormats(const QList<ULONG> &formats) const 625 { 626 QList<MimeCFPair> mimes; 627 628 foreach (ULONG format, formats) { 629 QString mime = mimeMap.value(format); 630 if (mime.isEmpty()) 631 mime = registerFormat(format); 632 if (!mime.isEmpty()) 633 mimes << qMakePair(mime, format); 634 } 635 636 return mimes; 637 } 638 639 QVariant QPMMimeAnyMime::convertFromFormat(ULONG format, ULONG flags, ULONG data, 640 const QString &mimeType, 641 QVariant::Type preferredType) const 642 { 643 Q_UNUSED(preferredType); 644 645 QVariant ret; 646 647 if (cfMap.value(mimeType) != format) 648 return ret; 649 650 if (!(flags & CFI_POINTER) || !data) 651 return ret; 652 653 // get the real block size (always rounded to the page boundary (4K)) 654 ULONG sz = ~0, fl = 0, arc; 655 arc = DosQueryMem((PVOID)data, &sz, &fl); 656 if (arc != NO_ERROR) { 657 #ifndef QT_NO_DEBUG 658 qWarning("QPMMimeText::convertFromFormat: DosQueryMem failed with %lu", arc); 659 #endif 660 return ret; 661 } 662 ULONG size = *((ULONG *)data); 663 if (!size || size + sizeof(ULONG) > sz) 664 return ret; 665 666 // it should be enough to return the data and let QMimeData do the rest. 667 ret = QByteArray((const char *)(data + sizeof(ULONG)), size); 668 return ret; 669 } 670 671 ULONG QPMMimeAnyMime::registerMimeType(const QString &mime) const 672 { 673 if (mime.isEmpty()) 674 return 0; 675 676 QString mimeToReg = mime; 677 678 bool ianaType = false; 679 foreach(QString prefix, ianaTypes) { 680 if (mime.startsWith(prefix)) { 681 ianaType = true; 682 break; 683 } 684 } 685 if (!ianaType) { 686 // prepend the non-standard type with the prefix that makes it comply 687 // with the standard 688 mimeToReg = customPrefix + mime + QChar('\"'); 689 } 690 691 mimeToReg = mimePrefix + mimeToReg; 692 ULONG cf = QPMMime::registerMimeType(mimeToReg); 693 if (cf) { 694 cfMap[mime] = cf; 695 mimeMap[cf] = mime; 696 } 697 return cf; 698 } 699 700 QString QPMMimeAnyMime::registerFormat(ULONG format) const 701 { 702 QString mime; 703 704 if (!format) 705 return mime; 706 707 QString atomStr = formatName(format); 708 if (atomStr.startsWith(mimePrefix)) { 709 // the format represents the mime type we can recognize 710 mime = atomStr.mid(mimePrefix.size()); 711 if (!mime.isEmpty()) { 712 cfMap[mime] = format; 713 mimeMap[format] = mime; 714 } 715 } 716 return mime; 717 } 718 719 //////////////////////////////////////////////////////////////////////////////// 720 521 721 QPMMimeList::QPMMimeList() 522 722 : initialized(false) … … 535 735 if (!initialized) { 536 736 initialized = true; 737 new QPMMimeAnyMime; // must be the first (used as a fallback) 537 738 new QPMMimeText; 538 739 } … … 542 743 { 543 744 init(); 544 list. append(mime);745 list.prepend(mime); 545 746 } 546 747
Note:
See TracChangeset
for help on using the changeset viewer.