00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <QDebug>
00025 #include <QApplication>
00026 #include <QMap>
00027 #include <QUrl>
00028 #include <QBuffer>
00029 #include <QDir>
00030 #include <QDomDocument>
00031 #include <QDomNode>
00032 #include <QDomElement>
00033 #include <QPainter>
00034 #include <QTextCodec>
00035
00036 #include <klfbackend.h>
00037
00038 #include <klfguiutil.h>
00039 #include "klfconfig.h"
00040 #include "klflib.h"
00041 #include "klfmime.h"
00042 #include "klfmime_p.h"
00043
00044 #ifdef Q_WS_MAC
00045 #include "macosx/klfmacclipboard.h"
00046 #endif
00047
00048 #define OPENOFFICE_DRAWING_MIMETYPE "application/x-openoffice-drawing;windows_formatname=\"Drawing Format\""
00049
00050 #ifndef Q_WS_MAC
00051
00052
00053 inline void __klf_init_the_macpasteboardmime() { }
00054 #endif
00055
00056
00057
00058 bool KLFMimeExporter::supportsKey(const QString& key) const
00059 {
00060 bool result = (keys().indexOf(key) >= 0) ;
00061 klfDbg("key = "<<key<<" ; result="<<result) ;
00062 return result;
00063 }
00064
00065
00066 KLFMimeExporter * KLFMimeExporter::mimeExporterLookup(const QString& key)
00067 {
00068 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00069 initMimeExporterList();
00070
00071 int k;
00072 for (k = 0; k < p_mimeExporterList.size(); ++k) {
00073 klfDbg("Testing exporter #"<<k<<": "<<p_mimeExporterList[k]);
00074 klfDbg("\t: "<<p_mimeExporterList[k]->exporterName()) ;
00075 if (p_mimeExporterList[k]->supportsKey(key))
00076 return p_mimeExporterList[k];
00077 }
00078
00079
00080 return NULL;
00081 }
00082
00083 KLFMimeExporter * KLFMimeExporter::mimeExporterLookupByName(const QString& exporter, const QString& key)
00084 {
00085 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00086 initMimeExporterList();
00087
00088 int k;
00089 for (k = 0; k < p_mimeExporterList.size(); ++k)
00090 if (p_mimeExporterList[k]->exporterName() == exporter)
00091 if (key.isEmpty() || p_mimeExporterList[k]->supportsKey(key))
00092 return p_mimeExporterList[k];
00093
00094
00095 return NULL;
00096 }
00097
00098
00099
00100 QList<KLFMimeExporter *> KLFMimeExporter::mimeExporterList()
00101 {
00102 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00103 initMimeExporterList();
00104 return p_mimeExporterList;
00105 }
00106
00107
00108 void KLFMimeExporter::registerMimeExporter(KLFMimeExporter *exporter, bool overrides)
00109 {
00110 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00111
00112 initMimeExporterList();
00113
00114 KLF_ASSERT_NOT_NULL( exporter ,
00115 "Cannot register a NULL exporter!",
00116 return ) ;
00117
00118 QString ename = exporter->exporterName();
00119 klfDbg("want to register exporter "<<ename<<", making sure no duplicate names...") ;
00120
00121
00122 int k;
00123 for (k = 0; k < p_mimeExporterList.size(); ++k) {
00124 klfDbg("making sure p_mimeExporterList["<<k<<"]->exporterName() [="<<p_mimeExporterList[k]->exporterName()<<"]"
00125 <<" != ename [="<<ename<<"]") ;
00126 KLF_ASSERT_CONDITION(p_mimeExporterList[k]->exporterName() != ename,
00127 "An exporter with same name "<<ename<<" is already registered!",
00128 return ) ;
00129 }
00130
00131 klfDbg("registering exporter "<<ename<<", overrides="<<overrides) ;
00132
00133 if (overrides)
00134 p_mimeExporterList.push_front(exporter);
00135 else
00136 p_mimeExporterList.push_back(exporter);
00137 }
00138
00139 void KLFMimeExporter::unregisterMimeExporter(KLFMimeExporter *exporter)
00140 {
00141 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00142 p_mimeExporterList.removeAll(exporter);
00143 }
00144
00145
00146 void KLFMimeExporter::initMimeExporterList()
00147 {
00148 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00149 if (p_mimeExporterList.isEmpty()) {
00150
00151 __klf_init_the_macpasteboardmime();
00152 p_mimeExporterList
00153 << new KLFMimeExporterImage(qApp)
00154 << new KLFMimeExporterUrilist(qApp)
00155 << new KLFMimeExporterHTML(qApp)
00156 << new KLFMimeExporterLibFmts(qApp)
00157 << new KLFMimeExporterGlowImage(qApp)
00158 ;
00159 }
00160 }
00161
00162
00163 QList<KLFMimeExporter*> KLFMimeExporter::p_mimeExporterList = QList<KLFMimeExporter*>();
00164
00165
00166
00167 KLFMimeExportProfile::KLFMimeExportProfile(const QString& pname, const QString& desc,
00168 const QList<ExportType>& exporttypes)
00169 : p_profileName(pname), p_description(desc), p_exportTypes(exporttypes)
00170 {
00171 }
00172
00173 KLFMimeExportProfile::KLFMimeExportProfile(const KLFMimeExportProfile& o)
00174 : p_profileName(o.p_profileName), p_description(o.p_description),
00175 p_exportTypes(o.p_exportTypes)
00176 {
00177 }
00178
00179 KLFMimeExporter * KLFMimeExportProfile::exporterLookupFor(int k, bool warnNotFound) const
00180 {
00181 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00182
00183 KLF_ASSERT_CONDITION(k >= 0 && k < p_exportTypes.size(),
00184 "Index "<<k<<" out of bounds (size="<<p_exportTypes.size()<<")",
00185 return NULL ) ;
00186
00187 KLFMimeExporter * exporter = NULL;
00188 if ( ! p_exportTypes[k].exporter.isEmpty() ) {
00189
00190 exporter = KLFMimeExporter::mimeExporterLookupByName(p_exportTypes[k].exporter, p_exportTypes[k].mimetype);
00191 } else {
00192
00193 exporter = KLFMimeExporter::mimeExporterLookup(p_exportTypes[k].mimetype);
00194 }
00195
00196 if (warnNotFound)
00197 KLF_ASSERT_NOT_NULL(exporter,
00198 "Can't find exporter "<<p_exportTypes[k].exporter<<" for export-type #"<<k
00199 <<"for key "<<p_exportTypes[k].mimetype, return NULL ) ;
00200 return exporter;
00201 }
00202
00203 QStringList KLFMimeExportProfile::mimeTypes() const
00204 {
00205 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00206
00207 QStringList mimetypes;
00208 int k;
00209 for (k = 0; k < p_exportTypes.size(); ++k)
00210 mimetypes << p_exportTypes[k].mimetype;
00211 return mimetypes;
00212 }
00213
00214 int KLFMimeExportProfile::indexOfMimeType(const QString& mimeType) const
00215 {
00216 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00217
00218 int k;
00219 for (k = 0; k < p_exportTypes.size(); ++k)
00220 if (p_exportTypes[k].mimetype == mimeType)
00221 return k;
00222 return -1;
00223 }
00224
00225 QStringList KLFMimeExportProfile::respectiveWinTypes() const
00226 {
00227 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00228
00229 QStringList wintypes;
00230 int k;
00231 for (k = 0; k < p_exportTypes.size(); ++k)
00232 wintypes << respectiveWinType(k);
00233 return wintypes;
00234 }
00235 QString KLFMimeExportProfile::respectiveWinType(int k) const
00236 {
00237 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ; klfDbg("k="<<k) ;
00238
00239 KLF_ASSERT_CONDITION(k >= 0 && k < p_exportTypes.size(),
00240 "Index "<<k<<" out of bounds (size="<<p_exportTypes.size()<<")",
00241 return QString() ) ;
00242
00243 if ( ! p_exportTypes[k].wintype.isEmpty() )
00244 return p_exportTypes[k].wintype;
00245
00246 KLFMimeExporter *exporter = exporterLookupFor(k, true);
00247 if (exporter == NULL)
00248 return QString();
00249
00250 return exporter->windowsFormatName(p_exportTypes[k].mimetype);
00251 }
00252
00253 QStringList KLFMimeExportProfile::availableExporterMimeTypes() const
00254 {
00255 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00256
00257 QStringList oktypes;
00258 int k;
00259 for (k = 0; k < p_exportTypes.size(); ++k) {
00260 if (exporterLookupFor(k, false) != NULL)
00261 oktypes << p_exportTypes[k].mimetype;
00262 }
00263 return oktypes;
00264 }
00265
00266
00267
00268 QList<KLFMimeExportProfile> KLFMimeExportProfile::p_exportProfileList = QList<KLFMimeExportProfile>();
00269
00270
00271 QList<KLFMimeExportProfile> KLFMimeExportProfile::exportProfileList()
00272 {
00273 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00274
00275 ensureLoadedExportProfileList();
00276 return p_exportProfileList;
00277 }
00278
00279 void KLFMimeExportProfile::addExportProfile(const KLFMimeExportProfile& exportProfile)
00280 {
00281 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00282
00283 ensureLoadedExportProfileList();
00284 p_exportProfileList.push_front(exportProfile);
00285 }
00286
00287 KLFMimeExportProfile KLFMimeExportProfile::findExportProfile(const QString& pname)
00288 {
00289 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00290
00291 ensureLoadedExportProfileList();
00292
00293 int k;
00294 for (k = 0; k < p_exportProfileList.size(); ++k)
00295 if (p_exportProfileList[k].profileName() == pname)
00296 return p_exportProfileList[k];
00297
00298
00299 return p_exportProfileList[0];
00300 }
00301
00302 void KLFMimeExportProfile::ensureLoadedExportProfileList()
00303 {
00304 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00305
00306 if ( ! p_exportProfileList.isEmpty())
00307 return;
00308
00309
00310
00311
00312 QStringList fcandidates;
00313
00314 QStringList dirs;
00315 dirs << klfconfig.homeConfigDir + "/conf/export_mime_profiles.d"
00316 << klfconfig.globalShareDir + "/conf/export_mime_profiles.d"
00317 << ":/conf/export_mime_profiles.d";
00318 int j, k;
00319 for (j = 0; j < dirs.size(); ++j) {
00320
00321 QDir d(dirs[j]);
00322 QStringList entrylist;
00323 entrylist = d.entryList(QStringList()<<QLatin1String("*.xml"), QDir::Files|QDir::Readable, QDir::Name);
00324 for (k = 0; k < entrylist.size(); ++k)
00325 fcandidates << d.filePath(entrylist[k]);
00326 }
00327
00328 for (k = 0; k < fcandidates.size(); ++k) {
00329 if (QFile::exists(fcandidates[k]))
00330 loadFromXMLFile(fcandidates[k]);
00331 }
00332
00333
00334
00335 QList<ExportType> exporttypes;
00336 KLFMimeExporterImage imgexporter(NULL);
00337 QStringList mimetypes = imgexporter.keys();
00338 for (k = 0; k < mimetypes.size(); ++k) {
00339 if (mimetypes[k].startsWith("image/") || mimetypes[k] == "application/x-qt-image")
00340 exporttypes << ExportType(mimetypes[k], imgexporter.windowsFormatName(mimetypes[k]));
00341 }
00342 KLFMimeExportProfile allimgfmts
00343 = KLFMimeExportProfile("all_image_formats",
00344 QObject::tr("All Available Image Formats"),
00345 exporttypes);
00346 p_exportProfileList << allimgfmts;
00347
00348 }
00349
00350
00351
00352 void KLFMimeExportProfile::loadFromXMLFile(const QString& fname)
00353 {
00354 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00355
00356 klfDbg("Loading from file "<<fname<<"; our locale is "<<klfconfig.UI.locale) ;
00357
00358 QFile file(fname);
00359 if ( ! file.open(QIODevice::ReadOnly) ) {
00360 qWarning()<<KLF_FUNC_NAME<<": Error: Can't open export mime profiles XML file "<<fname<<": "
00361 <<file.errorString()<<"!";
00362 return;
00363 }
00364
00365 QDomDocument doc("export-profile-list");
00366 QString errMsg; int errLine, errCol;
00367 bool r = doc.setContent(&file, false, &errMsg, &errLine, &errCol);
00368 if (!r) {
00369 qWarning()<<KLF_FUNC_NAME<<": Error parsing file "<<fname<<": "<<errMsg<<" at line "<<errLine<<", col "<<errCol;
00370 return;
00371 }
00372 file.close();
00373
00374 QDomElement root = doc.documentElement();
00375 if (root.nodeName() != "export-profile-list") {
00376 qWarning("%s: Error parsing XML for export mime profiles from file `%s': Bad root node `%s'.\n",
00377 KLF_FUNC_NAME, qPrintable(fname), qPrintable(root.nodeName()));
00378 return;
00379 }
00380
00381 QStringList descriptionLangs;
00382
00383
00384 QDomNode n;
00385 for (n = root.firstChild(); ! n.isNull(); n = n.nextSibling()) {
00386 QDomElement e = n.toElement();
00387 if ( e.isNull() || n.nodeType() != QDomNode::ElementNode )
00388 continue;
00389 if ( e.nodeName() == "add-macosx-type-rules" ) {
00390 #ifdef Q_WS_MAC
00391 __klf_add_macosx_type_rules(fname, e);
00392 #else
00393 klfDbg("Ignoring Mac OS X type rules on non-mac window system") ;
00394 #endif
00395 continue;
00396 }
00397 if ( e.nodeName() != "profile" ) {
00398 qWarning("%s: WARNING in parsing XML \"%s\" : ignoring unexpected tag `%s', expected <profile>.\n",
00399 KLF_FUNC_NAME, qPrintable(fname), qPrintable(e.nodeName()));
00400 continue;
00401 }
00402
00403 QString pname = e.attribute("name");
00404
00405
00406
00407 klfDbg("Reading profile "<<pname<<" ...") ;
00408
00409 QString description;
00410
00411 QString curDescriptionLang;
00412 QList<ExportType> exporttypes;
00413
00414 QDomNode en;
00415 for (en = e.firstChild(); ! en.isNull(); en = en.nextSibling() ) {
00416 if ( en.isNull() || en.nodeType() != QDomNode::ElementNode )
00417 continue;
00418 QDomElement ee = en.toElement();
00419 if ( en.nodeName() == "description" ) {
00420
00421 QString lang = ee.hasAttribute("xml:lang") ? ee.attribute("xml:lang") : QString() ;
00422 klfDbg("<description>: lang="<<lang<<"; hasAttribute(xml:lang)="<<ee.hasAttribute("xml:lang")
00423 <<"; current description="<<description<<",lang="<<curDescriptionLang) ;
00424 if (description.isEmpty()) {
00425
00426 if (lang.isEmpty() || lang.startsWith(klfconfig.UI.locale) || klfconfig.UI.locale.startsWith(lang)) {
00427
00428
00429 description = qApp->translate("xmltr_exportprofiles", ee.text().toUtf8().constData(),
00430 "[[tag: <description>]]", QCoreApplication::UnicodeUTF8);
00431
00432 curDescriptionLang = lang;
00433 }
00434
00435 } else {
00436
00437 if ( (lang.startsWith(klfconfig.UI.locale) || klfconfig.UI.locale.startsWith(lang)) &&
00438 (curDescriptionLang.isEmpty() || lang.startsWith(curDescriptionLang) ) ) {
00439
00440
00441 description = ee.text();
00442 curDescriptionLang = lang;
00443 }
00444
00445 }
00446 continue;
00447 }
00448 if ( en.nodeName() != "export-type" ) {
00449 qWarning("%s: WARNING in parsing XML '%s': ignoring unexpected tag `%s' in profile `%s'!\n",
00450 KLF_FUNC_NAME, qPrintable(fname), qPrintable(en.nodeName()), qPrintable(pname));
00451 continue;
00452 }
00453 QDomNodeList mimetypetags = ee.elementsByTagName("mime-type");
00454 if (mimetypetags.size() != 1) {
00455 qWarning()<<KLF_FUNC_NAME<<": in XML file "<<fname<<", profile "<<pname
00456 <<": exactly ONE <mime-type> tag must be present in each <export-type>...</export-type>.";
00457 continue;
00458 }
00459 QDomNodeList wintypetags = ee.elementsByTagName("windows-type");
00460 if (wintypetags.size() > 1) {
00461 qWarning()<<KLF_FUNC_NAME<<": in XML file "<<fname<<", profile "<<pname
00462 <<": expecting at most ONE <windows-type> tag in each <export-type>...</export-type>.";
00463 continue;
00464 }
00465 QDomNodeList exporternametags = ee.elementsByTagName("exporter-name");
00466 if (exporternametags.size() > 1) {
00467 qWarning()<<KLF_FUNC_NAME<<": in XML file "<<fname<<", profile "<<pname
00468 <<": expected at most ONE <exporter-name> tag in each <export-type>...</export-type>.";
00469 continue;
00470 }
00471 QString mimetype = mimetypetags.at(0).toElement().text().trimmed();
00472 QString wintype = QString();
00473 if (wintypetags.size() == 1) {
00474 wintype = wintypetags.at(0).toElement().text().trimmed();
00475 }
00476 QString exportername = QString();
00477 if (exporternametags.size() == 1) {
00478 exportername = exporternametags.at(0).toElement().text().trimmed();
00479 }
00480
00481 exporttypes << ExportType(mimetype, wintype, exportername);
00482 }
00483
00484
00485 KLFMimeExportProfile profile(pname, description, exporttypes);
00486
00487
00488 int kp;
00489 for (kp = 0; kp < p_exportProfileList.size(); ++kp) {
00490 if (p_exportProfileList[kp].profileName() == pname) {
00491 break;
00492 }
00493 }
00494 if (kp == p_exportProfileList.size()) {
00495
00496 klfDbg("Adding profile "<<pname<<" to mime export profiles") ;
00497 if (pname == "default") {
00498
00499 p_exportProfileList.prepend(profile);
00500 } else {
00501 p_exportProfileList << profile;
00502
00503 descriptionLangs << curDescriptionLang;
00504 }
00505 } else {
00506
00507 KLFMimeExportProfile oldp = p_exportProfileList[kp];
00508
00509 if (!description.isEmpty() &&
00510 (descriptionLangs[kp].isEmpty() || curDescriptionLang.startsWith(descriptionLangs[kp]))) {
00511
00512 } else {
00513 description = oldp.description();
00514 }
00515 KLFMimeExportProfile finalp(pname, description,
00516 oldp.exportTypes()+exporttypes
00517 );
00518 p_exportProfileList[kp] = finalp;
00519 }
00520 }
00521 }
00522
00523
00524
00525
00526
00527
00528
00529 KLFMimeData::KLFMimeData(const QString& exportProfile, const KLFBackend::klfOutput& output)
00530 : QMimeData(), pExportProfile(KLFMimeExportProfile::findExportProfile(exportProfile))
00531 {
00532 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00533
00534
00535 __klf_init_the_macpasteboardmime();
00536
00537 pOutput = output;
00538
00539 set_possible_qt_image_data();
00540 }
00541 KLFMimeData::~KLFMimeData()
00542 {
00543 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00544 }
00545
00546
00547 void KLFMimeData::set_possible_qt_image_data()
00548 {
00549 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00550
00551
00552 int index;
00553 if ( (index=pExportProfile.indexOfMimeType(QLatin1String("application/x-qt-image"))) >= 0) {
00554
00555 KLFMimeExporter * exporter = pExportProfile.exporterLookupFor(index);
00556 if (exporter != NULL) {
00557 QByteArray img_data = exporter->data(QLatin1String("application/x-qt-image"), pOutput);
00558 QImage img;
00559 QList<QByteArray> try_formats = QList<QByteArray>() << "PNG" << "JPEG" << "BMP";
00560 int k;
00561 for (k = 0; k < try_formats.size() && img.isNull(); ++k)
00562 img.loadFromData(img_data, try_formats[k].constData());
00563 KLF_ASSERT_CONDITION( ! img.isNull() ,
00564 "Can't get image for application/x-qt-image for profile "<<pExportProfile.profileName(),
00565 return; ) ;
00566 setImageData(img);
00567 }
00568 }
00569 }
00570
00571 QStringList KLFMimeData::formats() const
00572 {
00573 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00574
00575 QStringList fmts = pExportProfile.availableExporterMimeTypes();
00576 if (fmts.contains("application/x-qt-image")) {
00577 if (pQtOwnedFormats.size() == 0)
00578 pQtOwnedFormats = QMimeData::formats();
00579 fmts << pQtOwnedFormats;
00580 }
00581
00582 klfDbg("format list: "<<fmts) ;
00583 return fmts;
00584 }
00585
00586 QVariant KLFMimeData::retrieveData(const QString& mimetype, QVariant::Type type) const
00587 {
00588 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00589
00590 if (mimetype == QLatin1String("application/x-qt-image") ||
00591 pQtOwnedFormats.contains(mimetype))
00592 return QMimeData::retrieveData(mimetype, type);
00593
00594 int index = pExportProfile.indexOfMimeType(mimetype);
00595 if (index < 0) {
00596
00597
00598 klfDbg("Can't find mime-type "<<mimetype<<" in export profile "<<pExportProfile.profileName()
00599 <<" ?!?");
00600 return QVariant();
00601 }
00602
00603 klfDbg("exporting "<<mimetype<<" ...");
00604 KLFMimeExporter *exporter = pExportProfile.exporterLookupFor(index);
00605
00606 KLF_ASSERT_NOT_NULL(exporter,
00607 "Can't find an exporter for mime-type "<<mimetype<<"." ,
00608 return QVariant(); ) ;
00609
00610
00611 QByteArray data = exporter->data(mimetype, pOutput);
00612
00613 klfDbg("exporting mimetype "<<mimetype<<": data length is "<<data.size());
00614
00615 return QVariant::fromValue<QByteArray>(data);
00616 }
00617
00618
00619
00620
00621
00622
00623 static QMap<QString,QByteArray> get_qt_image_formats()
00624 {
00625 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00626
00627 QMap<QString,QByteArray> imageFormats;
00628
00629 QList<QByteArray> qtimgfmts = QImageWriter::supportedImageFormats();
00630 int k;
00631 for (k = 0; k < qtimgfmts.size(); ++k) {
00632 if ( imageFormats.key(qtimgfmts[k]).isEmpty() ) {
00633 QString mime = QString::fromLatin1("image/")+QString::fromLatin1(qtimgfmts[k]).toLower();
00634 imageFormats[mime] = qtimgfmts[k];
00635 }
00636 }
00637 return imageFormats;
00638 }
00639
00640 QMap<QString,QByteArray> KLFMimeExporterImage::imageFormats = QMap<QString,QByteArray>();
00641
00642 QStringList KLFMimeExporterImage::keys() const
00643 {
00644 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00645
00646
00647 static QStringList staticKeys
00648 = QStringList() << "image/png" << "image/eps" << "application/eps" << "application/postscript"
00649 << OPENOFFICE_DRAWING_MIMETYPE << "application/x-qt-image"
00650
00651 << "image/x-win-png-office-art";
00652
00653 if (imageFormats.isEmpty()) {
00654
00655 QMap<QString,QByteArray> ifmts = get_qt_image_formats();
00656 QMap<QString,QByteArray>::iterator it;
00657 for (it = ifmts.begin(); it != ifmts.end(); ++it) {
00658 QString mime = it.key();
00659 QByteArray qtfmt = it.value();
00660
00661 if (staticKeys.indexOf(mime) == -1)
00662 imageFormats[mime] = qtfmt;
00663
00664
00665 if (mime == "image/bmp") {
00666 imageFormats["image/x-win-bmp"] = qtfmt;
00667 } else if (mime == "image/jpeg") {
00668 imageFormats["image/x-win-jfif"] = qtfmt;
00669 imageFormats["image/x-win-jfif-office-art"] = qtfmt;
00670 } else if (mime == "image/png") {
00671 imageFormats["image/x-win-png-office-art"] = qtfmt;
00672 }
00673 }
00674 }
00675
00676 QStringList keys = staticKeys;
00677
00678 if (!klfconfig.BackendSettings.execEpstopdf.isEmpty())
00679 keys <<"application/pdf";
00680
00681 keys << imageFormats.keys();
00682
00683 return keys;
00684 }
00685
00686 QString KLFMimeExporterImage::windowsFormatName(const QString& mime) const
00687 {
00688 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00689
00690 QString wtype;
00691 if (mime == "application/pdf")
00692 return "PDF";
00693 else if (mime == "application/eps")
00694 return "Encapsulated PostScript";
00695 else if (mime == "image/png")
00696 return "PNG";
00697 else if (mime == "image/jpg" || mime == "image/jpeg")
00698
00699 return "JPEG";
00700 else if (mime == "image/x-win-jfif")
00701 return "JFIF";
00702 else if (mime == "image/x-win-jfif-office-art")
00703 return "JFIF+Office Art";
00704 else if (mime == "image/x-win-png-office-art")
00705 return "PNG+Office Art";
00706 else if (mime == "image/bmp")
00707 return "Bitmap";
00708 else if (mime == "image/x-win-bmp")
00709 return "Windows Bitmap";
00710 else if (mime == OPENOFFICE_DRAWING_MIMETYPE)
00711 return "Drawing Format";
00712 else if (mime == "application/x-qt-image")
00713 return mime;
00714
00715 return mime;
00716 }
00717
00718 QByteArray klf_openoffice_drawing(const KLFBackend::klfOutput& klfoutput);
00719
00720 QByteArray KLFMimeExporterImage::data(const QString& keymime, const KLFBackend::klfOutput& klfoutput)
00721 {
00722 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00723
00724 QString key = keymime;
00725 klfDbg("key="<<key);
00726
00727 if (key == "image/png")
00728 return klfoutput.pngdata;
00729 if (key == "image/eps" || key == "application/eps" || key == "application/postscript")
00730 return klfoutput.epsdata;
00731 if (key == "application/pdf") {
00732 #ifdef KLF_DEBUG
00733 if (klfoutput.pdfdata.isEmpty())
00734 klfDbg("---warning: don't have PDF data ---") ;
00735 #endif
00736 return klfoutput.pdfdata;
00737 }
00738 if (key == OPENOFFICE_DRAWING_MIMETYPE)
00739 return klf_openoffice_drawing(klfoutput);
00740 if (key == "application/x-qt-image")
00741 return klfoutput.pngdata;
00742
00743
00744 klfDbg("Will use Qt's image format exporting");
00745
00746 if ( ! imageFormats.contains(key) )
00747 return QByteArray();
00748
00749 QByteArray imgdata;
00750 QBuffer imgdatawriter(&imgdata);
00751 imgdatawriter.open(QIODevice::WriteOnly);
00752 klfoutput.result.save(&imgdatawriter, imageFormats[key]);
00753 imgdatawriter.close();
00754
00755 klfDbg("got data: size="<<imgdata.size());
00756 return imgdata;
00757 }
00758
00759
00760
00761
00762
00763 QMap<qint64,QString> KLFMimeExporterUrilist::tempFilesForImageCacheKey = QMap<qint64,QString>();
00764
00765 QStringList KLFMimeExporterUrilist::keys() const
00766 {
00767 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00768 return QStringList() << "text/x-moz-url" << "text/uri-list";
00769 }
00770
00771
00772 QString KLFMimeExporterUrilist::tempFileForOutput(const KLFBackend::klfOutput& output)
00773 {
00774 qint64 imgcachekey = output.result.cacheKey();
00775
00776 QString tempfilename;
00777
00778 if (tempFilesForImageCacheKey.contains(imgcachekey)) {
00779 tempfilename = tempFilesForImageCacheKey[imgcachekey];
00780 } else {
00781 QString templ = klfconfig.BackendSettings.tempDir +
00782 QString("/klf_%1_XXXXXX.png").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd_hh-mm"));
00783 QTemporaryFile *tempfile = new QTemporaryFile(templ, qApp);
00784 tempfile->setAutoRemove(true);
00785 if (tempfile->open() == false) {
00786 qWarning("Can't open temp png file for mimetype text/uri-list: template is %s",
00787 qPrintable(templ));
00788 return QByteArray();
00789 } else {
00790 QString errStr;
00791 bool res = KLFBackend::saveOutputToFile(output, tempfile->fileName(), "PNG", &errStr);
00792 if (!res) {
00793 qWarning()<<KLF_FUNC_NAME<<": Can't save to temp file "<<tempfile->fileName()<<": "<<errStr;
00794 } else {
00795 tempfilename = tempfile->fileName();
00796 tempfile->write(output.pngdata);
00797 tempfile->close();
00798
00799 tempFilesForImageCacheKey[imgcachekey] = tempfilename;
00800 }
00801 }
00802 }
00803
00804 return tempfilename;
00805 }
00806
00807 QByteArray KLFMimeExporterUrilist::data(const QString& key, const KLFBackend::klfOutput& output)
00808 {
00809 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00810
00811 Q_UNUSED(key) ;
00812 klfDbg("key="<<key) ;
00813
00814 QString tempfilename = tempFileForOutput(output);
00815 QByteArray urilist = (QUrl::fromLocalFile(tempfilename).toString()+QLatin1String("\n")).toLatin1();
00816 return urilist;
00817 }
00818
00819 QString KLFMimeExporterUrilist::windowsFormatName(const QString& mime) const
00820 {
00821 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00822
00823 if (mime == "text/x-moz-url")
00824 return "FileName";
00825 return mime;
00826 }
00827
00828
00829
00830
00831
00832 static QString toAttrTextS(const QString& sbase)
00833 {
00834 QString s = sbase;
00835 klfDbg("s="<<s);
00836 QRegExp replaceCharsRX("([^a-zA-Z0-9/ ._-])");
00837 int pos = 0;
00838 while ((pos = replaceCharsRX.indexIn(s, pos)) != -1) {
00839 QString entity = "&#x"+QString::number(replaceCharsRX.cap(1)[0].unicode(), 16).toUpper()+";" ;
00840 klfDbg("replacing char at pos="<<pos<<" by entity="<<entity<<": s(pos...pos+5)="<<s.mid(pos,5));
00841 s.replace(pos, replaceCharsRX.matchedLength(), entity);
00842 pos += entity.length();
00843 }
00844 klfDbg("final string: "<<s);
00845 return s;
00846
00847
00848
00849
00850
00851 }
00852
00853 static QByteArray toAttrText(const QString& sbase)
00854 {
00855 return toAttrTextS(sbase).toUtf8();
00856 }
00857
00858 QStringList KLFMimeExporterHTML::keys() const
00859 {
00860 return QStringList() << QLatin1String("text/html");
00861 }
00862
00863 QByteArray KLFMimeExporterHTML::data(const QString& key, const KLFBackend::klfOutput& klfoutput)
00864 {
00865 if (key != QLatin1String("text/html")) {
00866 qWarning()<<KLF_FUNC_NAME<<": key="<<key<<" is not \"text/html\"";
00867 return QByteArray();
00868 }
00869
00870 QString fname = KLFMimeExporterUrilist::tempFileForOutput(klfoutput);
00871
00872 QSize imgsize = klfoutput.result.size();
00873 int imgDpi = klfoutput.input.dpi;
00874 int dispDpi = 100;
00875
00876 QString latex = klfoutput.input.latex;
00877
00878 QStringList latexlines = latex.split("\n");
00879 while (latexlines.size() && QRegExp("\\s*\\%.*").exactMatch(latexlines[0]))
00880 latexlines.removeAt(0);
00881 latex = latexlines.join("\n");
00882
00883 QString fn = toAttrTextS(fname);
00884 QString l = toAttrTextS(latex);
00885 fn.replace("\"", """);
00886 l.replace("\"", """);
00887 QString w = QString::number((int)(1.5 * imgsize.width() * dispDpi/imgDpi));
00888 QString h = QString::number((int)(1.5 * imgsize.height() * dispDpi/imgDpi));
00889 QString win = QString::number(1.5 * imgsize.width() / imgDpi);
00890 QString hin = QString::number(1.5 * imgsize.height() / imgDpi);
00891
00892 QString html =
00893 QString("<img src=\"file://%1\" alt=\"%2\" title=\"%3\" "
00894 " style=\"width: %4in; height: %5in; vertical-align: middle;\">")
00895 .arg(fn, l, l, win, hin);
00896
00897 #ifdef Q_WS_MAC
00898 return html.toUtf8();
00899 #else
00900 QTextCodec *codec = QTextCodec::codecForName("UTF-16");
00901 return codec->fromUnicode(html);
00902 #endif
00903 }
00904
00905 QString KLFMimeExporterHTML::windowsFormatName(const QString& key) const
00906 {
00907 if (key == QLatin1String("text/html"))
00908 return "HTML";
00909 return key;
00910 }
00911
00912
00913
00914
00915
00916 QByteArray klf_openoffice_drawing(const KLFBackend::klfOutput& klfoutput)
00917 {
00918 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00919
00920 QByteArray pngdata = klfoutput.pngdata;
00921
00922 QFile templfile(":/data/ooodrawingtemplate");
00923 templfile.open(QIODevice::ReadOnly);
00924 QByteArray templ = templfile.readAll();
00925
00926 QString fgcols = QColor(klfoutput.input.fg_color).name();
00927 QString bgcols;
00928 if (qAlpha(klfoutput.input.bg_color) > 0)
00929 bgcols = QColor(klfoutput.input.fg_color).name();
00930 else
00931 bgcols = "-";
00932
00933 templ.replace(QByteArray("<!--KLF_PNG_BASE64_DATA-->"), pngdata.toBase64());
00934
00935 templ.replace(QByteArray("<!--KLF_INPUT_LATEX-->"), toAttrText(klfoutput.input.latex));
00936 templ.replace(QByteArray("<!--KLF_INPUT_MATHMODE-->"), toAttrText(klfoutput.input.mathmode));
00937 templ.replace(QByteArray("<!--KLF_INPUT_PREAMBLE-->"), toAttrText(klfoutput.input.preamble));
00938 templ.replace(QByteArray("<!--KLF_INPUT_FGCOLOR-->"), toAttrText(fgcols));
00939 templ.replace(QByteArray("<!--KLF_INPUT_BGCOLOR-->"), toAttrText(bgcols));
00940 templ.replace(QByteArray("<!--KLF_INPUT_DPI-->"), toAttrText(QString::number(klfoutput.input.dpi)));
00941 templ.replace(QByteArray("<!--KLF_SETTINGS_TBORDEROFFSET_PSPT-->"),
00942 toAttrText(QString::number(klfoutput.settings.tborderoffset)));
00943 templ.replace(QByteArray("<!--KLF_SETTINGS_RBORDEROFFSET_PSPT-->"),
00944 toAttrText(QString::number(klfoutput.settings.rborderoffset)));
00945 templ.replace(QByteArray("<!--KLF_SETTINGS_BBORDEROFFSET_PSPT-->"),
00946 toAttrText(QString::number(klfoutput.settings.bborderoffset)));
00947 templ.replace(QByteArray("<!--KLF_SETTINGS_LBORDEROFFSET_PSPT-->"),
00948 toAttrText(QString::number(klfoutput.settings.lborderoffset)));
00949
00950 templ.replace(QByteArray("<!--KLF_INPUT_LATEX_BASE64-->"), klfoutput.input.latex.toLocal8Bit().toBase64());
00951 templ.replace(QByteArray("<!--KLF_INPUT_MATHMODE_BASE64-->"), klfoutput.input.mathmode.toLocal8Bit().toBase64());
00952 templ.replace(QByteArray("<!--KLF_INPUT_PREAMBLE_BASE64-->"), klfoutput.input.preamble.toLocal8Bit().toBase64());
00953 templ.replace(QByteArray("<!--KLF_INPUT_FGCOLOR_BASE64-->"), fgcols.toLocal8Bit().toBase64());
00954 templ.replace(QByteArray("<!--KLF_INPUT_BGCOLOR_BASE64-->"), bgcols.toLocal8Bit().toBase64());
00955
00956 templ.replace(QByteArray("<!--KLF_OOOLATEX_ARGS-->"), toAttrText("12§display§"+klfoutput.input.latex));
00957
00958
00959 const double DPI_FACTOR = 1.6;
00960
00961
00962 templ.replace(QByteArray("<!--KLF_IMAGE_WIDTH_CM-->"),
00963 QString::number(DPI_FACTOR * 2.54 * klfoutput.result.width()/klfoutput.input.dpi, 'f', 2).toUtf8());
00964 templ.replace(QByteArray("<!--KLF_IMAGE_HEIGHT_CM-->"),
00965 QString::number(DPI_FACTOR * 2.54 * klfoutput.result.height()/klfoutput.input.dpi, 'f', 2).toUtf8());
00966
00967 templ.replace(QByteArray("<!--KLF_IMAGE_ORIG_WIDTH_CM-->"),
00968 QString::number(2.54 * klfoutput.result.width()/klfoutput.input.dpi, 'f', 2).toUtf8());
00969 templ.replace(QByteArray("<!--KLF_IMAGE_ORIG_HEIGHT_CM-->"),
00970 QString::number(2.54 * klfoutput.result.height()/klfoutput.input.dpi, 'f', 2).toUtf8());
00971
00972 templ.replace(QByteArray("<!--KLF_IMAGE_WIDTH_PX-->"), QString::number(klfoutput.result.width()).toUtf8());
00973 templ.replace(QByteArray("<!--KLF_IMAGE_HEIGHT_PX-->"), QString::number(klfoutput.result.height()).toUtf8());
00974 templ.replace(QByteArray("<!--KLF_IMAGE_ASPECT_RATIO-->"),
00975 QString::number((double)klfoutput.result.width()/klfoutput.result.height(), 'f', 3).toUtf8());
00976
00977 klfDbg("final templ: "<<templ);
00978
00979 return templ;
00980 }
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990 QStringList KLFMimeExporterLibFmts::keys() const
00991 {
00992 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00993
00994 klfDbg("list of keys: "<<KLFAbstractLibEntryMimeEncoder::allEncodingMimeTypes());
00995 return KLFAbstractLibEntryMimeEncoder::allEncodingMimeTypes();
00996 }
00997
00998 QByteArray KLFMimeExporterLibFmts::data(const QString& key, const KLFBackend::klfOutput& output)
00999 {
01000 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
01001
01002 klfDbg("key="<<key);
01003 KLFAbstractLibEntryMimeEncoder *encoder =
01004 KLFAbstractLibEntryMimeEncoder::findEncoderFor(key, true);
01005 if (encoder == NULL) {
01006
01007 return QByteArray();
01008 }
01009
01010 KLFLibEntry e = KLFLibEntry(output.input.latex, QDateTime::currentDateTime(),
01011 output.result.scaled(klfconfig.UI.labelOutputFixedSize, Qt::KeepAspectRatio,
01012 Qt::SmoothTransformation),
01013 KLFStyle(output.input));
01014
01015 QByteArray data = encoder->encodeMime(KLFLibEntryList()<<e, QVariantMap(), key);
01016
01017 if (!data.size())
01018 qWarning()<<KLF_FUNC_NAME<<": "<<key<<" encoder returned empty data!";
01019
01020 klfDbg("got data, size="<<data.size());
01021 return data;
01022 }
01023
01024
01025
01026
01027
01028
01029 QStringList KLFMimeExporterGlowImage::keys() const
01030 {
01031 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
01032
01033 return QStringList() << "image/png" << "application/x-qt-image";
01034 }
01035
01036 QByteArray KLFMimeExporterGlowImage::data(const QString& key, const KLFBackend::klfOutput& output)
01037 {
01038 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
01039
01040 klfDbg("key = "<<key) ;
01041
01042 QImage img(output.result.size() + QSize(1,1)*2*klfconfig.UI.glowEffectRadius, QImage::Format_ARGB32);
01043
01044
01045 img.fill(qRgba(0,0,0,0));
01046
01047 {
01048 QPainter p(&img);
01049 p.translate(klfconfig.UI.glowEffectRadius, klfconfig.UI.glowEffectRadius);
01050 klfDrawGlowedImage(&p, output.result, klfconfig.UI.glowEffectColor, klfconfig.UI.glowEffectRadius);
01051 }
01052
01053 QByteArray data;
01054 {
01055 QBuffer buf(&data);
01056 buf.open(QIODevice::WriteOnly);
01057 img.save(&buf, "PNG");
01058 }
01059
01060
01061 return data;
01062 }
01063
01064
01065