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 exporttypes << ExportType(mimetypes[k], imgexporter.windowsFormatName(mimetypes[k]));
00340 }
00341 KLFMimeExportProfile allimgfmts
00342 = KLFMimeExportProfile("all_image_formats",
00343 QObject::tr("All Available Image Formats"),
00344 exporttypes);
00345 p_exportProfileList << allimgfmts;
00346
00347 }
00348
00349
00350
00351 void KLFMimeExportProfile::loadFromXMLFile(const QString& fname)
00352 {
00353 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00354
00355 klfDbg("Loading from file "<<fname<<"; our locale is "<<klfconfig.UI.locale) ;
00356
00357 QFile file(fname);
00358 if ( ! file.open(QIODevice::ReadOnly) ) {
00359 qWarning()<<KLF_FUNC_NAME<<": Error: Can't open export mime profiles XML file "<<fname<<": "
00360 <<file.errorString()<<"!";
00361 return;
00362 }
00363
00364 QDomDocument doc("export-profile-list");
00365 QString errMsg; int errLine, errCol;
00366 bool r = doc.setContent(&file, false, &errMsg, &errLine, &errCol);
00367 if (!r) {
00368 qWarning()<<KLF_FUNC_NAME<<": Error parsing file "<<fname<<": "<<errMsg<<" at line "<<errLine<<", col "<<errCol;
00369 return;
00370 }
00371 file.close();
00372
00373 QDomElement root = doc.documentElement();
00374 if (root.nodeName() != "export-profile-list") {
00375 qWarning("%s: Error parsing XML for export mime profiles from file `%s': Bad root node `%s'.\n",
00376 KLF_FUNC_NAME, qPrintable(fname), qPrintable(root.nodeName()));
00377 return;
00378 }
00379
00380 QStringList descriptionLangs;
00381
00382
00383 QDomNode n;
00384 for (n = root.firstChild(); ! n.isNull(); n = n.nextSibling()) {
00385 QDomElement e = n.toElement();
00386 if ( e.isNull() || n.nodeType() != QDomNode::ElementNode )
00387 continue;
00388 if ( e.nodeName() == "add-macosx-type-rules" ) {
00389 #ifdef Q_WS_MAC
00390 __klf_add_macosx_type_rules(fname, e);
00391 #else
00392 klfDbg("Ignoring Mac OS X type rules on non-mac window system") ;
00393 #endif
00394 continue;
00395 }
00396 if ( e.nodeName() != "profile" ) {
00397 qWarning("%s: WARNING in parsing XML \"%s\" : ignoring unexpected tag `%s', expected <profile>.\n",
00398 KLF_FUNC_NAME, qPrintable(fname), qPrintable(e.nodeName()));
00399 continue;
00400 }
00401
00402 QString pname = e.attribute("name");
00403
00404
00405
00406 klfDbg("Reading profile "<<pname<<" ...") ;
00407
00408 QString description;
00409
00410 QString curDescriptionLang;
00411 QList<ExportType> exporttypes;
00412
00413 QDomNode en;
00414 for (en = e.firstChild(); ! en.isNull(); en = en.nextSibling() ) {
00415 if ( en.isNull() || en.nodeType() != QDomNode::ElementNode )
00416 continue;
00417 QDomElement ee = en.toElement();
00418 if ( en.nodeName() == "description" ) {
00419
00420 QString lang = ee.hasAttribute("xml:lang") ? ee.attribute("xml:lang") : QString() ;
00421 klfDbg("<description>: lang="<<lang<<"; hasAttribute(xml:lang)="<<ee.hasAttribute("xml:lang")
00422 <<"; current description="<<description<<",lang="<<curDescriptionLang) ;
00423 if (description.isEmpty()) {
00424
00425 if (lang.isEmpty() || lang.startsWith(klfconfig.UI.locale) || klfconfig.UI.locale.startsWith(lang)) {
00426
00427
00428 description = qApp->translate("xmltr_exportprofiles", ee.text().toUtf8().constData(),
00429 "[[tag: <description>]]", QCoreApplication::UnicodeUTF8);
00430
00431 curDescriptionLang = lang;
00432 }
00433
00434 } else {
00435
00436 if ( (lang.startsWith(klfconfig.UI.locale) || klfconfig.UI.locale.startsWith(lang)) &&
00437 (curDescriptionLang.isEmpty() || lang.startsWith(curDescriptionLang) ) ) {
00438
00439
00440 description = ee.text();
00441 curDescriptionLang = lang;
00442 }
00443
00444 }
00445 continue;
00446 }
00447 if ( en.nodeName() != "export-type" ) {
00448 qWarning("%s: WARNING in parsing XML '%s': ignoring unexpected tag `%s' in profile `%s'!\n",
00449 KLF_FUNC_NAME, qPrintable(fname), qPrintable(en.nodeName()), qPrintable(pname));
00450 continue;
00451 }
00452 QDomNodeList mimetypetags = ee.elementsByTagName("mime-type");
00453 if (mimetypetags.size() != 1) {
00454 qWarning()<<KLF_FUNC_NAME<<": in XML file "<<fname<<", profile "<<pname
00455 <<": exactly ONE <mime-type> tag must be present in each <export-type>...</export-type>.";
00456 continue;
00457 }
00458 QDomNodeList wintypetags = ee.elementsByTagName("windows-type");
00459 if (wintypetags.size() > 1) {
00460 qWarning()<<KLF_FUNC_NAME<<": in XML file "<<fname<<", profile "<<pname
00461 <<": expecting at most ONE <windows-type> tag in each <export-type>...</export-type>.";
00462 continue;
00463 }
00464 QDomNodeList exporternametags = ee.elementsByTagName("exporter-name");
00465 if (exporternametags.size() > 1) {
00466 qWarning()<<KLF_FUNC_NAME<<": in XML file "<<fname<<", profile "<<pname
00467 <<": expected at most ONE <exporter-name> tag in each <export-type>...</export-type>.";
00468 continue;
00469 }
00470 QString mimetype = mimetypetags.at(0).toElement().text().trimmed();
00471 QString wintype = QString();
00472 if (wintypetags.size() == 1) {
00473 wintype = wintypetags.at(0).toElement().text().trimmed();
00474 }
00475 QString exportername = QString();
00476 if (exporternametags.size() == 1) {
00477 exportername = exporternametags.at(0).toElement().text().trimmed();
00478 }
00479
00480 exporttypes << ExportType(mimetype, wintype, exportername);
00481 }
00482
00483
00484 KLFMimeExportProfile profile(pname, description, exporttypes);
00485
00486
00487 int kp;
00488 for (kp = 0; kp < p_exportProfileList.size(); ++kp) {
00489 if (p_exportProfileList[kp].profileName() == pname) {
00490 break;
00491 }
00492 }
00493 if (kp == p_exportProfileList.size()) {
00494
00495 klfDbg("Adding profile "<<pname<<" to mime export profiles") ;
00496 if (pname == "default") {
00497
00498 p_exportProfileList.prepend(profile);
00499 } else {
00500 p_exportProfileList << profile;
00501
00502 descriptionLangs << curDescriptionLang;
00503 }
00504 } else {
00505
00506 KLFMimeExportProfile oldp = p_exportProfileList[kp];
00507
00508 if (!description.isEmpty() &&
00509 (descriptionLangs[kp].isEmpty() || curDescriptionLang.startsWith(descriptionLangs[kp]))) {
00510
00511 } else {
00512 description = oldp.description();
00513 }
00514 KLFMimeExportProfile finalp(pname, description,
00515 oldp.exportTypes()+exporttypes
00516 );
00517 p_exportProfileList[kp] = finalp;
00518 }
00519 }
00520 }
00521
00522
00523
00524
00525
00526
00527
00528 KLFMimeData::KLFMimeData(const QString& exportProfile, const KLFBackend::klfOutput& output)
00529 : QMimeData(), pExportProfile(KLFMimeExportProfile::findExportProfile(exportProfile))
00530 {
00531 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00532
00533
00534 __klf_init_the_macpasteboardmime();
00535
00536 pOutput = output;
00537
00538 set_possible_qt_image_data();
00539 }
00540 KLFMimeData::~KLFMimeData()
00541 {
00542 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00543 }
00544
00545
00546 void KLFMimeData::set_possible_qt_image_data()
00547 {
00548 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00549
00550
00551 int index;
00552 if ( (index=pExportProfile.indexOfMimeType(QLatin1String("application/x-qt-image"))) >= 0) {
00553
00554 KLFMimeExporter * exporter = pExportProfile.exporterLookupFor(index);
00555 if (exporter != NULL) {
00556 QByteArray img_data = exporter->data(QLatin1String("application/x-qt-image"), pOutput);
00557 QImage img;
00558 QList<QByteArray> try_formats = QList<QByteArray>() << "PNG" << "JPEG" << "BMP";
00559 int k;
00560 for (k = 0; k < try_formats.size() && img.isNull(); ++k)
00561 img.loadFromData(img_data, try_formats[k].constData());
00562 KLF_ASSERT_CONDITION( ! img.isNull() ,
00563 "Can't get image for application/x-qt-image for profile "<<pExportProfile.profileName(),
00564 return; ) ;
00565 setImageData(img);
00566 }
00567 }
00568 }
00569
00570 QStringList KLFMimeData::formats() const
00571 {
00572 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00573
00574 QStringList fmts = pExportProfile.availableExporterMimeTypes();
00575 if (fmts.contains("application/x-qt-image")) {
00576 if (pQtOwnedFormats.size() == 0)
00577 pQtOwnedFormats = QMimeData::formats();
00578 fmts << pQtOwnedFormats;
00579 }
00580
00581 klfDbg("format list: "<<fmts) ;
00582 return fmts;
00583 }
00584
00585 QVariant KLFMimeData::retrieveData(const QString& mimetype, QVariant::Type type) const
00586 {
00587 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00588
00589 if (mimetype == QLatin1String("application/x-qt-image") ||
00590 pQtOwnedFormats.contains(mimetype))
00591 return QMimeData::retrieveData(mimetype, type);
00592
00593 int index = pExportProfile.indexOfMimeType(mimetype);
00594 if (index < 0) {
00595
00596
00597 klfDbg("Can't find mime-type "<<mimetype<<" in export profile "<<pExportProfile.profileName()
00598 <<" ?!?");
00599 return QVariant();
00600 }
00601
00602 klfDbg("exporting "<<mimetype<<" ...");
00603 KLFMimeExporter *exporter = pExportProfile.exporterLookupFor(index);
00604
00605 KLF_ASSERT_NOT_NULL(exporter,
00606 "Can't find an exporter for mime-type "<<mimetype<<"." ,
00607 return QVariant(); ) ;
00608
00609
00610 QByteArray data = exporter->data(mimetype, pOutput);
00611
00612 klfDbg("exporting mimetype "<<mimetype<<": data length is "<<data.size());
00613
00614 return QVariant::fromValue<QByteArray>(data);
00615 }
00616
00617
00618
00619
00620
00621
00622 static QMap<QString,QByteArray> get_qt_image_formats()
00623 {
00624 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00625
00626 QMap<QString,QByteArray> imageFormats;
00627
00628 QList<QByteArray> qtimgfmts = QImageWriter::supportedImageFormats();
00629 int k;
00630 for (k = 0; k < qtimgfmts.size(); ++k) {
00631 if ( imageFormats.key(qtimgfmts[k]).isEmpty() ) {
00632 QString mime = QString::fromLatin1("image/")+QString::fromLatin1(qtimgfmts[k]).toLower();
00633 imageFormats[mime] = qtimgfmts[k];
00634 }
00635 }
00636 return imageFormats;
00637 }
00638
00639 QMap<QString,QByteArray> KLFMimeExporterImage::imageFormats = QMap<QString,QByteArray>();
00640
00641 QStringList KLFMimeExporterImage::keys() const
00642 {
00643 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00644
00645
00646 static QStringList staticKeys
00647 = QStringList() << "image/png" << "image/eps" << "application/eps" << "application/postscript"
00648 << OPENOFFICE_DRAWING_MIMETYPE << "application/x-qt-image"
00649
00650 << "image/x-win-png-office-art";
00651
00652 if (imageFormats.isEmpty()) {
00653
00654 QMap<QString,QByteArray> ifmts = get_qt_image_formats();
00655 QMap<QString,QByteArray>::iterator it;
00656 for (it = ifmts.begin(); it != ifmts.end(); ++it) {
00657 QString mime = it.key();
00658 QByteArray qtfmt = it.value();
00659
00660 if (staticKeys.indexOf(mime) == -1)
00661 imageFormats[mime] = qtfmt;
00662
00663
00664 if (mime == "image/bmp") {
00665 imageFormats["image/x-win-bmp"] = qtfmt;
00666 } else if (mime == "image/jpeg") {
00667 imageFormats["image/x-win-jfif"] = qtfmt;
00668 imageFormats["image/x-win-jfif-office-art"] = qtfmt;
00669 } else if (mime == "image/png") {
00670 imageFormats["image/x-win-png-office-art"] = qtfmt;
00671 }
00672 }
00673 }
00674
00675 QStringList keys = staticKeys;
00676
00677 if (!klfconfig.BackendSettings.execEpstopdf.isEmpty())
00678 keys <<"application/pdf";
00679
00680 keys << imageFormats.keys();
00681
00682 return keys;
00683 }
00684
00685 QString KLFMimeExporterImage::windowsFormatName(const QString& mime) const
00686 {
00687 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00688
00689 QString wtype;
00690 if (mime == "application/pdf")
00691 return "PDF";
00692 else if (mime == "application/eps")
00693 return "Encapsulated PostScript";
00694 else if (mime == "image/png")
00695 return "PNG";
00696 else if (mime == "image/jpg" || mime == "image/jpeg")
00697
00698 return "JPEG";
00699 else if (mime == "image/x-win-jfif")
00700 return "JFIF";
00701 else if (mime == "image/x-win-jfif-office-art")
00702 return "JFIF+Office Art";
00703 else if (mime == "image/x-win-png-office-art")
00704 return "PNG+Office Art";
00705 else if (mime == "image/bmp")
00706 return "Bitmap";
00707 else if (mime == "image/x-win-bmp")
00708 return "Windows Bitmap";
00709 else if (mime == OPENOFFICE_DRAWING_MIMETYPE)
00710 return "Drawing Format";
00711 else if (mime == "application/x-qt-image")
00712 return mime;
00713
00714 return mime;
00715 }
00716
00717 QByteArray klf_openoffice_drawing(const KLFBackend::klfOutput& klfoutput);
00718
00719 QByteArray KLFMimeExporterImage::data(const QString& keymime, const KLFBackend::klfOutput& klfoutput)
00720 {
00721 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00722
00723 QString key = keymime;
00724 klfDbg("key="<<key);
00725
00726 if (key == "image/png")
00727 return klfoutput.pngdata;
00728 if (key == "image/eps" || key == "application/eps" || key == "application/postscript")
00729 return klfoutput.epsdata;
00730 if (key == "application/pdf") {
00731 #ifdef KLF_DEBUG
00732 if (klfoutput.pdfdata.isEmpty())
00733 klfDbg("---warning: don't have PDF data ---") ;
00734 #endif
00735 return klfoutput.pdfdata;
00736 }
00737 if (key == OPENOFFICE_DRAWING_MIMETYPE)
00738 return klf_openoffice_drawing(klfoutput);
00739 if (key == "application/x-qt-image")
00740 return klfoutput.pngdata;
00741
00742
00743 klfDbg("Will use Qt's image format exporting");
00744
00745 if ( ! imageFormats.contains(key) )
00746 return QByteArray();
00747
00748 QByteArray imgdata;
00749 QBuffer imgdatawriter(&imgdata);
00750 imgdatawriter.open(QIODevice::WriteOnly);
00751 klfoutput.result.save(&imgdatawriter, imageFormats[key]);
00752 imgdatawriter.close();
00753
00754 klfDbg("got data: size="<<imgdata.size());
00755 return imgdata;
00756 }
00757
00758
00759
00760
00761
00762 QMap<qint64,QString> KLFMimeExporterUrilist::tempFilesForImageCacheKey = QMap<qint64,QString>();
00763
00764 QStringList KLFMimeExporterUrilist::keys() const
00765 {
00766 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00767 return QStringList() << "text/x-moz-url" << "text/uri-list";
00768 }
00769
00770
00771 QString KLFMimeExporterUrilist::tempFileForOutput(const KLFBackend::klfOutput& output)
00772 {
00773 qint64 imgcachekey = output.result.cacheKey();
00774
00775 QString tempfilename;
00776
00777 if (tempFilesForImageCacheKey.contains(imgcachekey)) {
00778 tempfilename = tempFilesForImageCacheKey[imgcachekey];
00779 } else {
00780 QString templ = klfconfig.BackendSettings.tempDir +
00781 QString("/klf_%1_XXXXXX.png").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd_hh-mm"));
00782 QTemporaryFile *tempfile = new QTemporaryFile(templ, qApp);
00783 tempfile->setAutoRemove(true);
00784 if (tempfile->open() == false) {
00785 qWarning("Can't open temp png file for mimetype text/uri-list: template is %s",
00786 qPrintable(templ));
00787 return QByteArray();
00788 } else {
00789 QString errStr;
00790 bool res = KLFBackend::saveOutputToFile(output, tempfile->fileName(), "PNG", &errStr);
00791 if (!res) {
00792 qWarning()<<KLF_FUNC_NAME<<": Can't save to temp file "<<tempfile->fileName()<<": "<<errStr;
00793 } else {
00794 tempfilename = tempfile->fileName();
00795 tempfile->write(output.pngdata);
00796 tempfile->close();
00797
00798 tempFilesForImageCacheKey[imgcachekey] = tempfilename;
00799 }
00800 }
00801 }
00802
00803 return tempfilename;
00804 }
00805
00806 QByteArray KLFMimeExporterUrilist::data(const QString& key, const KLFBackend::klfOutput& output)
00807 {
00808 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00809
00810 Q_UNUSED(key) ;
00811 klfDbg("key="<<key) ;
00812
00813 QString tempfilename = tempFileForOutput(output);
00814 QByteArray urilist = (QUrl::fromLocalFile(tempfilename).toString()+QLatin1String("\n")).toLatin1();
00815 return urilist;
00816 }
00817
00818 QString KLFMimeExporterUrilist::windowsFormatName(const QString& mime) const
00819 {
00820 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00821
00822 if (mime == "text/x-moz-url")
00823 return "FileName";
00824 return mime;
00825 }
00826
00827
00828
00829
00830
00831 static QString toAttrTextS(const QString& sbase)
00832 {
00833 QString s = sbase;
00834 klfDbg("s="<<s);
00835 QRegExp replaceCharsRX("([^a-zA-Z0-9/ ._-])");
00836 int pos = 0;
00837 while ((pos = replaceCharsRX.indexIn(s, pos)) != -1) {
00838 QString entity = "&#x"+QString::number(replaceCharsRX.cap(1)[0].unicode(), 16).toUpper()+";" ;
00839 klfDbg("replacing char at pos="<<pos<<" by entity="<<entity<<": s(pos...pos+5)="<<s.mid(pos,5));
00840 s.replace(pos, replaceCharsRX.matchedLength(), entity);
00841 pos += entity.length();
00842 }
00843 klfDbg("final string: "<<s);
00844 return s;
00845
00846
00847
00848
00849
00850 }
00851
00852 static QByteArray toAttrText(const QString& sbase)
00853 {
00854 return toAttrTextS(sbase).toUtf8();
00855 }
00856
00857 QStringList KLFMimeExporterHTML::keys() const
00858 {
00859 return QStringList() << QLatin1String("text/html");
00860 }
00861
00862 QByteArray KLFMimeExporterHTML::data(const QString& key, const KLFBackend::klfOutput& klfoutput)
00863 {
00864 QString fname = KLFMimeExporterUrilist::tempFileForOutput(klfoutput);
00865
00866 QSize imgsize = klfoutput.result.size();
00867 int imgDpi = klfoutput.input.dpi;
00868 int dispDpi = 100;
00869
00870 QString latex = klfoutput.input.latex;
00871
00872 QStringList latexlines = latex.split("\n");
00873 while (latexlines.size() && QRegExp("\\s*\\%.*").exactMatch(latexlines[0]))
00874 latexlines.removeAt(0);
00875 latex = latexlines.join("\n");
00876
00877 QString fn = toAttrTextS(fname);
00878 QString l = toAttrTextS(latex);
00879 fn.replace("\"", """);
00880 l.replace("\"", """);
00881 QString w = QString::number((int)(1.5 * imgsize.width() * dispDpi/imgDpi));
00882 QString h = QString::number((int)(1.5 * imgsize.height() * dispDpi/imgDpi));
00883 QString win = QString::number(1.5 * imgsize.width() / imgDpi);
00884 QString hin = QString::number(1.5 * imgsize.height() / imgDpi);
00885
00886 QString html =
00887 QString("<img src=\"file://%1\" alt=\"%2\" title=\"%3\" "
00888 " style=\"width: %4in; height: %5in; vertical-align: middle;\">")
00889 .arg(fn, l, l, win, hin);
00890
00891 #ifdef Q_WS_MAC
00892 return html.toUtf8();
00893 #else
00894 QTextCodec *codec = QTextCodec::codecForName("UTF-16");
00895 return codec->fromUnicode(html);
00896 #endif
00897 }
00898
00899 QString KLFMimeExporterHTML::windowsFormatName(const QString& key) const
00900 {
00901 if (key == QLatin1String("text/html"))
00902 return "HTML";
00903 return key;
00904 }
00905
00906
00907
00908
00909
00910 QByteArray klf_openoffice_drawing(const KLFBackend::klfOutput& klfoutput)
00911 {
00912 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00913
00914 QByteArray pngdata = klfoutput.pngdata;
00915
00916 QFile templfile(":/data/ooodrawingtemplate");
00917 templfile.open(QIODevice::ReadOnly);
00918 QByteArray templ = templfile.readAll();
00919
00920 QString fgcols = QColor(klfoutput.input.fg_color).name();
00921 QString bgcols;
00922 if (qAlpha(klfoutput.input.bg_color) > 0)
00923 bgcols = QColor(klfoutput.input.fg_color).name();
00924 else
00925 bgcols = "-";
00926
00927 templ.replace(QByteArray("<!--KLF_PNG_BASE64_DATA-->"), pngdata.toBase64());
00928
00929 templ.replace(QByteArray("<!--KLF_INPUT_LATEX-->"), toAttrText(klfoutput.input.latex));
00930 templ.replace(QByteArray("<!--KLF_INPUT_MATHMODE-->"), toAttrText(klfoutput.input.mathmode));
00931 templ.replace(QByteArray("<!--KLF_INPUT_PREAMBLE-->"), toAttrText(klfoutput.input.preamble));
00932 templ.replace(QByteArray("<!--KLF_INPUT_FGCOLOR-->"), toAttrText(fgcols));
00933 templ.replace(QByteArray("<!--KLF_INPUT_BGCOLOR-->"), toAttrText(bgcols));
00934 templ.replace(QByteArray("<!--KLF_INPUT_DPI-->"), toAttrText(QString::number(klfoutput.input.dpi)));
00935 templ.replace(QByteArray("<!--KLF_SETTINGS_TBORDEROFFSET_PSPT-->"),
00936 toAttrText(QString::number(klfoutput.settings.tborderoffset)));
00937 templ.replace(QByteArray("<!--KLF_SETTINGS_RBORDEROFFSET_PSPT-->"),
00938 toAttrText(QString::number(klfoutput.settings.rborderoffset)));
00939 templ.replace(QByteArray("<!--KLF_SETTINGS_BBORDEROFFSET_PSPT-->"),
00940 toAttrText(QString::number(klfoutput.settings.bborderoffset)));
00941 templ.replace(QByteArray("<!--KLF_SETTINGS_LBORDEROFFSET_PSPT-->"),
00942 toAttrText(QString::number(klfoutput.settings.lborderoffset)));
00943
00944 templ.replace(QByteArray("<!--KLF_INPUT_LATEX_BASE64-->"), klfoutput.input.latex.toLocal8Bit().toBase64());
00945 templ.replace(QByteArray("<!--KLF_INPUT_MATHMODE_BASE64-->"), klfoutput.input.mathmode.toLocal8Bit().toBase64());
00946 templ.replace(QByteArray("<!--KLF_INPUT_PREAMBLE_BASE64-->"), klfoutput.input.preamble.toLocal8Bit().toBase64());
00947 templ.replace(QByteArray("<!--KLF_INPUT_FGCOLOR_BASE64-->"), fgcols.toLocal8Bit().toBase64());
00948 templ.replace(QByteArray("<!--KLF_INPUT_BGCOLOR_BASE64-->"), bgcols.toLocal8Bit().toBase64());
00949
00950 templ.replace(QByteArray("<!--KLF_OOOLATEX_ARGS-->"), toAttrText("12§display§"+klfoutput.input.latex));
00951
00952
00953 const double DPI_FACTOR = 2.0;
00954
00955
00956 templ.replace(QByteArray("<!--KLF_IMAGE_WIDTH_CM-->"),
00957 QString::number(DPI_FACTOR * 2.54 * klfoutput.result.width()/klfoutput.input.dpi, 'f', 2).toUtf8());
00958 templ.replace(QByteArray("<!--KLF_IMAGE_HEIGHT_CM-->"),
00959 QString::number(DPI_FACTOR * 2.54 * klfoutput.result.height()/klfoutput.input.dpi, 'f', 2).toUtf8());
00960
00961 templ.replace(QByteArray("<!--KLF_IMAGE_ORIG_WIDTH_CM-->"),
00962 QString::number(2.54 * klfoutput.result.width()/klfoutput.input.dpi, 'f', 2).toUtf8());
00963 templ.replace(QByteArray("<!--KLF_IMAGE_ORIG_HEIGHT_CM-->"),
00964 QString::number(2.54 * klfoutput.result.height()/klfoutput.input.dpi, 'f', 2).toUtf8());
00965
00966 templ.replace(QByteArray("<!--KLF_IMAGE_WIDTH_PX-->"), QString::number(klfoutput.result.width()).toUtf8());
00967 templ.replace(QByteArray("<!--KLF_IMAGE_HEIGHT_PX-->"), QString::number(klfoutput.result.height()).toUtf8());
00968 templ.replace(QByteArray("<!--KLF_IMAGE_ASPECT_RATIO-->"),
00969 QString::number((double)klfoutput.result.width()/klfoutput.result.height(), 'f', 3).toUtf8());
00970
00971 klfDbg("final templ: "<<templ);
00972
00973 return templ;
00974 }
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984 QStringList KLFMimeExporterLibFmts::keys() const
00985 {
00986 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00987
00988 klfDbg("list of keys: "<<KLFAbstractLibEntryMimeEncoder::allEncodingMimeTypes());
00989 return KLFAbstractLibEntryMimeEncoder::allEncodingMimeTypes();
00990 }
00991
00992 QByteArray KLFMimeExporterLibFmts::data(const QString& key, const KLFBackend::klfOutput& output)
00993 {
00994 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00995
00996 klfDbg("key="<<key);
00997 KLFAbstractLibEntryMimeEncoder *encoder =
00998 KLFAbstractLibEntryMimeEncoder::findEncoderFor(key, true);
00999 if (encoder == NULL) {
01000
01001 return QByteArray();
01002 }
01003
01004 KLFLibEntry e = KLFLibEntry(output.input.latex, QDateTime::currentDateTime(),
01005 output.result.scaled(klfconfig.UI.labelOutputFixedSize, Qt::KeepAspectRatio,
01006 Qt::SmoothTransformation),
01007 KLFStyle(output.input));
01008
01009 QByteArray data = encoder->encodeMime(KLFLibEntryList()<<e, QVariantMap(), key);
01010
01011 if (!data.size())
01012 qWarning()<<KLF_FUNC_NAME<<": "<<key<<" encoder returned empty data!";
01013
01014 klfDbg("got data, size="<<data.size());
01015 return data;
01016 }
01017
01018
01019
01020
01021
01022
01023 QStringList KLFMimeExporterGlowImage::keys() const
01024 {
01025 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
01026
01027 return QStringList() << "image/png" << "application/x-qt-image";
01028 }
01029
01030 QByteArray KLFMimeExporterGlowImage::data(const QString& key, const KLFBackend::klfOutput& output)
01031 {
01032 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
01033
01034 klfDbg("key = "<<key) ;
01035
01036 QImage img(output.result.size() + QSize(1,1)*2*klfconfig.UI.glowEffectRadius, QImage::Format_ARGB32);
01037
01038
01039 img.fill(qRgba(0,0,0,0));
01040
01041 {
01042 QPainter p(&img);
01043 p.translate(klfconfig.UI.glowEffectRadius, klfconfig.UI.glowEffectRadius);
01044 klfDrawGlowedImage(&p, output.result, klfconfig.UI.glowEffectColor, klfconfig.UI.glowEffectRadius);
01045 }
01046
01047 QByteArray data;
01048 {
01049 QBuffer buf(&data);
01050 buf.open(QIODevice::WriteOnly);
01051 img.save(&buf, "PNG");
01052 }
01053
01054
01055 return data;
01056 }
01057
01058
01059