[KLF Application][KLF Tools][KLF Backend][KLF Home]
KLatexFormula Project

src/klfmain.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   file klfmain.cpp
00003  *   This file is part of the KLatexFormula Project.
00004  *   Copyright (C) 2009 by Philippe Faist
00005  *   philippe.faist at bluewin.ch
00006  *                                                                         *
00007  *   This program is free software; you can redistribute it and/or modify  *
00008  *   it under the terms of the GNU General Public License as published by  *
00009  *   the Free Software Foundation; either version 2 of the License, or     *
00010  *   (at your option) any later version.                                   *
00011  *                                                                         *
00012  *   This program is distributed in the hope that it will be useful,       *
00013  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00014  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00015  *   GNU General Public License for more details.                          *
00016  *                                                                         *
00017  *   You should have received a copy of the GNU General Public License     *
00018  *   along with this program; if not, write to the                         *
00019  *   Free Software Foundation, Inc.,                                       *
00020  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00021  ***************************************************************************/
00022 /* $Id: klfmain.cpp 577 2010-12-01 21:09:42Z philippe $ */
00023 
00024 #include <QDebug>
00025 #include <QString>
00026 #include <QList>
00027 #include <QObject>
00028 #include <QDomDocument>
00029 #include <QFile>
00030 #include <QFileInfo>
00031 #include <QResource>
00032 #include <QDir>
00033 #include <QTranslator>
00034 #include <QLibraryInfo>
00035 
00036 #include <klfutil.h>
00037 #include "klfpluginiface.h"
00038 #include "klfconfig.h"
00039 #include "klfmain.h"
00040 
00041 
00042 KLF_EXPORT QList<KLFTranslationInfo> klf_avail_translations;
00043 
00044 KLF_EXPORT QList<QTranslator*> klf_translators;
00045 
00046 
00047 
00048 
00049 
00050 QList<KLFPluginInfo> klf_plugins;
00051 
00052 
00053 
00054 QList<KLFAddOnInfo> klf_addons;
00055 bool klf_addons_canimport = false;
00056 
00057 
00058 
00059 KLFAddOnInfo::KLFAddOnInfo(QString rccfpath, bool isFresh)
00060 {
00061   d = new Private;
00062   d->ref = 1;
00063   klfDbg( "KLFAddOnInfo: rccfpath="<<rccfpath<<", Private has ref "<< d->ref ) ;
00064 
00065   QFileInfo fi(rccfpath);
00066   
00067   d->fname = fi.fileName();
00068   d->dir = fi.absolutePath();
00069   d->fpath = fi.absoluteFilePath();
00070 
00071   d->islocal = fi.isWritable() || QFileInfo(d->dir).isWritable();
00072 
00073   d->isfresh = isFresh;
00074 
00075   QByteArray rccinfodata;
00076 
00077   // mount the resource locally
00078   QString mountroot;
00079   QString suffix;
00080   QString minrccfpath = rccfpath.section("/", -1, -1, QString::SectionSkipEmpty);
00081   int k = 0;
00082   // find a unique mountroot name
00083   while (QFileInfo(mountroot = QString(":/klfaddon_rccmount/%1%2").arg(minrccfpath, suffix)).exists()) {
00084     suffix = QString("_%1").arg(++k);
00085   }
00086   d->rccmountroot = mountroot;
00087   klfDbg( "Mounting resource "<<rccfpath<<" to "<<d->rccmountroot ) ;
00088 
00089   bool ok = QResource::registerResource(d->fpath, mountroot);
00090   KLF_ASSERT_CONDITION(ok, "Failed to register resource "<<rccfpath, return; ) ;
00091 
00092   // read the RCC's info.xml content
00093   { // code block brackets {} are to close the file immediately after reading.
00094     QFile infofile(mountroot+QLatin1String("/rccinfo/info.xml"));
00095     infofile.open(QIODevice::ReadOnly);
00096     rccinfodata = infofile.readAll();
00097   }
00098 
00099   // read translation list
00100   QDir i18ndir(mountroot+QLatin1String("/i18n/"));
00101   d->translations = i18ndir.entryList(QStringList() << "*.qm", QDir::Files);
00102 
00103   // set default values for title, author, description, and klfminversion in case the XML file
00104   // does not provide any
00105   d->title = QObject::tr("(Name Not Provided)", "[KLFAddOnInfo: add-on information XML data is invalid]");
00106   d->description = QObject::tr("(Invalid XML Data Provided By Add-On)",
00107                                "[KLFAddOnInfo: add-on information XML data is invalid]");
00108   d->klfminversion = QString();
00109   d->author = QObject::tr("(No Author Provided)",
00110                           "[KLFAddOnInfo: add-on information XML data is invalid]");
00111   
00112   // parse resource's rccinfo/info.xml file
00113   QDomDocument xmldoc;
00114   xmldoc.setContent(rccinfodata);
00115   // and explore the document
00116   QDomElement xmlroot = xmldoc.documentElement();
00117   if (xmlroot.nodeName() != "rccinfo") {
00118     qWarning("Add-on file `%s' has invalid XML information.", qPrintable(rccfpath));
00119     return;
00120   }
00121   QDomNode n;
00122   for (n = xmlroot.firstChild(); ! n.isNull(); n = n.nextSibling()) {
00123     QDomElement e = n.toElement();
00124     if ( e.isNull() || n.nodeType() != QDomNode::ElementNode )
00125       continue;
00126     if ( e.nodeName() == "title" ) {
00127       d->title = e.text().trimmed();
00128     }
00129     if ( e.nodeName() == "author" ) {
00130       d->author = e.text().trimmed();
00131     }
00132     if ( e.nodeName() == "description" ) {
00133       d->description = e.text().trimmed();
00134     }
00135     if ( e.nodeName() == "klfminversion" ) {
00136       d->klfminversion = e.text().trimmed();
00137     }
00138   }
00139 
00140   initPlugins();
00141 }
00142 
00143 KLF_EXPORT QDebug& operator<<(QDebug& str, const KLFAddOnInfo::PluginSysInfo& i)
00144 {
00145   return str << "KLFAddOnInfo::PluginSysInfo(qtminver="<<i.qtminversion<<"; klfminver="<<i.klfminversion
00146              << "; os="<<i.os<<"; arch="<<i.arch<<")";
00147 }
00148 
00149 
00150 bool KLFAddOnInfo::PluginSysInfo::isCompatibleWithCurrentSystem() const
00151 {
00152   return
00153     (klfminversion.isEmpty()
00154      || klfVersionCompare(klfminversion, KLF_VERSION_STRING) <= 0) &&
00155     (qtminversion.isEmpty()
00156      || klfVersionCompare(qtminversion, qVersion()) <= 0) &&
00157     os == KLFSysInfo::osString() &&
00158     arch == KLFSysInfo::arch() ;
00159 }
00160 
00161 
00162 void KLFAddOnInfo::initPlugins()
00163 {
00164   // read plugin list
00165   QDir plugdir(d->rccmountroot+QLatin1String("/plugins/"));
00166   PluginSysInfo defpinfo;
00167   defpinfo.qtminversion = ""; // by default -> no version check (empty string)
00168   defpinfo.klfminversion = ""; // by default -> no version check (empty string)
00169   defpinfo.os = KLFSysInfo::osString(); // by default, current OS.
00170   defpinfo.arch = KLFSysInfo::arch(); // by default, current arch.
00171   d->plugins = QMap<QString,PluginSysInfo>();
00172   d->pluginList = QStringList();
00173 
00174   // first add all plugins that are in :/plugins
00175   QStringList unorderedplugins = plugdir.entryList(KLF_DLL_EXT_LIST, QDir::Files);
00176   int k;
00177   for (k = 0; k < unorderedplugins.size(); ++k) {
00178     d->pluginList << unorderedplugins[k];
00179     d->plugins[unorderedplugins[k]] = defpinfo;
00180   }
00181 
00182   if (!QFile::exists(plugdir.absoluteFilePath("plugindirinfo.xml"))) {
00183     klfDbg( "KLFAddOnInfo("<<d->fname<<"): No specific plugin directories. plugdirinfo.xml="
00184             <<plugdir.absoluteFilePath("plugindirinfo.xml") ) ;
00185     return;
00186   }
00187 
00188   // no plugin dirs.
00189   QFile plugdirinfofile(d->rccmountroot+QLatin1String("/plugins/plugindirinfo.xml"));
00190   plugdirinfofile.open(QIODevice::ReadOnly);
00191   QByteArray plugdirinfodata = plugdirinfofile.readAll();
00192 
00193   // here, key is the plugin _dir_ itself.
00194   QMap<QString,PluginSysInfo> pdirinfos;
00195 
00196   // parse resource's plugins/plugindirinfo.xml file
00197   QDomDocument xmldoc;
00198   xmldoc.setContent(plugdirinfodata);
00199   // and explore the document
00200   QDomElement xmlroot = xmldoc.documentElement();
00201   if (xmlroot.nodeName() != "klfplugindirs") {
00202     qWarning("KLFAddOnInfo: Add-on plugin dir info file `%s' has invalid XML information.",
00203              qPrintable(d->fpath));
00204     return;
00205   }
00206   QDomNode n;
00207   for (n = xmlroot.firstChild(); ! n.isNull(); n = n.nextSibling()) {
00208     QDomElement e = n.toElement();
00209     if ( e.isNull() || n.nodeType() != QDomNode::ElementNode )
00210       continue;
00211     if ( e.nodeName() != "klfplugindir" ) {
00212       qWarning("KLFAddOnInfo(%s): plugindirinfo.xml: skipping unexpected node %s.", qPrintable(d->fpath),
00213                qPrintable(e.nodeName()));
00214       continue;
00215     }
00216     // read a plugin dir info
00217     PluginSysInfo psi;
00218     QDomNode nn;
00219     for (nn = e.firstChild(); ! nn.isNull(); nn = nn.nextSibling()) {
00220       QDomElement ee = nn.toElement();
00221       klfDbg( "Node: type="<<nn.nodeType()<<"; name="<<ee.nodeName() ) ;
00222       if ( ee.isNull() || nn.nodeType() != QDomNode::ElementNode )
00223         continue;
00224       if ( ee.nodeName() == "dir" ) {
00225         psi.dir = ee.text().trimmed();
00226       } else if ( ee.nodeName() == "qtminversion" ) {
00227         psi.qtminversion = ee.text().trimmed();
00228       } else if ( ee.nodeName() == "klfminversion" ) {
00229         psi.klfminversion = ee.text().trimmed();
00230       } else if ( ee.nodeName() == "os" ) {
00231         psi.os = ee.text().trimmed();
00232       } else if ( ee.nodeName() == "arch" ) {
00233         psi.arch = ee.text().trimmed();
00234       } else {
00235         qWarning("KLFAddOnInfo(%s): plugindirinfo.xml: skipping unexpected node in <klfplugindirs>: %s.",
00236                  qPrintable(d->fpath), qPrintable(ee.nodeName()));
00237       }
00238     }
00239     klfDbg( "\tRead psi="<<psi ) ;
00240     // add this plugin dir info
00241     pdirinfos[psi.dir] = psi;
00242   }
00243 
00244   QStringList morePluginsList;
00245   for (QMap<QString,PluginSysInfo>::const_iterator it = pdirinfos.begin(); it != pdirinfos.end(); ++it) {
00246     QString dir = it.key();
00247     PluginSysInfo psi = it.value();
00248     if ( ! QFileInfo(d->rccmountroot + "/plugins/" + dir).exists() ) {
00249       qWarning("KLFAddOnInfo(%s): Plugin dir '%s' given in XML info does not exist in resource!",
00250                qPrintable(d->fpath), qPrintable(dir));
00251       continue;
00252     }
00253     QDir plugsubdir(d->rccmountroot + "/plugins/" + dir);
00254     QStringList plugins = plugsubdir.entryList(KLF_DLL_EXT_LIST, QDir::Files);
00255     int j;
00256     for (j = 0; j < plugins.size(); ++j) {
00257       QString p = dir+"/"+plugins[j];
00258       morePluginsList << p;
00259       d->plugins[p] = psi;
00260     }
00261   }
00262   // prepend morePluginsList to d->pluginList
00263   QStringList fullList = morePluginsList;
00264   fullList << d->pluginList;
00265   d->pluginList = fullList;
00266 
00267   klfDbg( "Loaded plugins: list="<<d->pluginList<<"; map="<<d->plugins ) ;
00268 }
00269 
00270 
00271 QStringList KLFAddOnInfo::localPluginList() const
00272 {
00273   QStringList lplugins;
00274   for (int k = 0; k < d->pluginList.size(); ++k) {
00275     if ( d->plugins[d->pluginList[k]].isCompatibleWithCurrentSystem() )
00276       lplugins << QDir::cleanPath(pluginLocalSubDirName(d->pluginList[k])+"/"+QFileInfo(d->pluginList[k]).fileName());
00277   }
00278   return lplugins;
00279 }
00280 
00281 
00282 KLFAddOnInfo::KLFAddOnInfo(const KLFAddOnInfo& other)
00283 {
00284   d = other.d;
00285   if (d)
00286     d->ref++;
00287 }
00288 
00289 KLFAddOnInfo::~KLFAddOnInfo()
00290 {
00291   if (d) {
00292     d->ref--;
00293     if (d->ref <= 0) {
00294       // finished reading this resource, un-register it.
00295       QResource::unregisterResource(d->fpath, d->rccmountroot);
00296       delete d;
00297     }
00298   }
00299 }
00300 
00301 
00302 
00303 
00304 KLFI18nFile::KLFI18nFile(QString filepath)
00305 {
00306   QFileInfo fi(filepath);
00307   QString fn = fi.fileName();
00308   QDir d = fi.absoluteDir();
00309 
00310   int firstunderscore = fn.indexOf('_');
00311   int endbasename = fn.endsWith(".qm") ? fn.length() - 3 : fn.length() ;
00312   if (firstunderscore == -1)
00313     firstunderscore = endbasename; // no locale part if no underscore
00314   // ---
00315   fpath = d.absoluteFilePath(fn);
00316   name = fn.mid(0, firstunderscore);
00317   locale = fn.mid(firstunderscore+1, endbasename-(firstunderscore+1));
00318   locale_specificity = (locale.split('_', QString::SkipEmptyParts)).size() ;
00319 }
00320 
00321 
00322 
00323 
00324 void klf_add_avail_translation(KLFI18nFile i18nfile)
00325 {
00326   KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00327   klfDbg("i18nfile.fpath="<<i18nfile.fpath<<" is translation to "<<i18nfile.locale) ;
00328 
00329   QFileInfo fi(i18nfile.fpath);
00330 
00331   klfDbg("fi.canonicalPath()="<<fi.canonicalPath()<<", Qt translations location="
00332          <<QFileInfo(QLibraryInfo::location(QLibraryInfo::TranslationsPath)).canonicalFilePath()) ;
00333 
00334   if ( fi.canonicalPath() ==
00335        QFileInfo(QLibraryInfo::location(QLibraryInfo::TranslationsPath)).canonicalFilePath()
00336        || i18nfile.name == "qt" ) {
00337     // ignore Qt's translations as available languages (identified as being in Qt's
00338     // translation path or as a locally named qt_XX.qm
00339     return;
00340   }
00341 
00342   // Check if this locale is registered, and if it has a nice translated name.
00343   bool needsRegistration = true;
00344   bool needsNiceName = true;
00345   int alreadyRegisteredIndex = -1;
00346 
00347   int kk;
00348   for (kk = 0; kk < klf_avail_translations.size(); ++kk) {
00349     if (klf_avail_translations[kk].localename == i18nfile.locale) {
00350       needsRegistration = false;
00351       alreadyRegisteredIndex = kk;
00352       needsNiceName = ! klf_avail_translations[kk].hasnicetranslatedname;
00353       klfDbg("translation "<<i18nfile.locale<<" is already registered. needs nice name?="<< needsNiceName) ;
00354     }
00355   }
00356 
00357   klfDbg("Needs registration?="<<needsRegistration<<"; needs nice name?="<<needsNiceName) ;
00358   if ( ! needsRegistration && ! needsNiceName ) {
00359     // needs nothing more !
00360     return;
00361   }
00362 
00363   klfDbg("will load translation file "<<fi.completeBaseName()<<", abs path="<<fi.absolutePath()) ;
00364 
00365   // needs something (registration and/or nice name)
00366   QTranslator translator;
00367   translator.load(fi.completeBaseName(), fi.absolutePath(), "_", "."+fi.suffix());
00368   KLFTranslationInfo ti;
00369   ti.localename = i18nfile.locale;
00370   struct klf_qtTrNoop3 { const char *source; const char *comment; };
00371   klf_qtTrNoop3 lang
00372     = QT_TRANSLATE_NOOP3("QObject", "English (US)",
00373                          "[[The Language (possibly with Country) you are translating to, e.g. `Deutsch']]");
00374   ti.translatedname = translator.translate("QObject", lang.source, lang.comment);
00375   ti.hasnicetranslatedname = true;
00376   if (ti.translatedname == "English" || ti.translatedname.isEmpty()) {
00377     QLocale lc(i18nfile.locale);
00378     QString s;
00379     if ( i18nfile.locale.indexOf("_") != -1 ) {
00380       // has country information in locale
00381       s = QString("%1 (%2)").arg(QLocale::languageToString(lc.language()))
00382         .arg(QLocale::countryToString(lc.country()));
00383     } else {
00384       s = QString("%1").arg(QLocale::languageToString(lc.language()));
00385     }
00386     ti.translatedname = s;
00387     ti.hasnicetranslatedname = false;
00388   }
00389   if (needsRegistration)
00390     klf_avail_translations.append(ti);
00391   else if (needsNiceName && ti.hasnicetranslatedname)
00392     klf_avail_translations[alreadyRegisteredIndex] = ti;
00393 }
00394 
00395 
00396 KLF_EXPORT void klf_reload_translations(QCoreApplication *app, const QString& currentLocale)
00397 {
00398   // refresh and load all translations. Translations are files found in the form
00399   //   :/i18n/<name>_<locale>.qm   or   homeconfig/i18n/<name>_<locale>.qm
00400   //
00401   // this function may be called at run-time to change language.
00402 
00403   int j, k;
00404 
00405   // clear any already set translators
00406   for (k = 0; k < klf_translators.size(); ++k) {
00407     app->removeTranslator(klf_translators[k]);
00408     delete klf_translators[k];
00409   }
00410   klf_translators.clear();
00411 
00412   // we will find all possible .qm files and store them in this structure for easy access
00413   // structure is indexed by name, then locale specificity
00414   QMap<QString, QMap<int, QList<KLFI18nFile> > > i18nFiles;
00415   // a list of names. this is redundant for  i18nFiles.keys()
00416   QSet<QString> names;
00417 
00418   QStringList i18ndirlist;
00419   // add any add-on specific translations
00420   for (k = 0; k < klf_addons.size(); ++k) {
00421     i18ndirlist << klf_addons[k].rccmountroot()+"/i18n";
00422   }
00423   i18ndirlist << ":/i18n"
00424               << klfconfig.homeConfigDirI18n
00425               << klfconfig.globalShareDir+"/i18n"
00426               << QLibraryInfo::location(QLibraryInfo::TranslationsPath);
00427 
00428   for (j = 0; j < i18ndirlist.size(); ++j) {
00429     // explore this directory; we expect a list of *.qm files
00430     QDir i18ndir(i18ndirlist[j]);
00431     if ( ! i18ndir.exists() )
00432       continue;
00433     QStringList files = i18ndir.entryList(QStringList() << QString::fromLatin1("*.qm"), QDir::Files);
00434     for (k = 0; k < files.size(); ++k) {
00435       KLFI18nFile i18nfile(i18ndir.absoluteFilePath(files[k]));
00436       //      qDebug("Found i18n file %s (name=%s,locale=%s,lc-spcif.=%d)", qPrintable(i18nfile.fpath),
00437       //             qPrintable(i18nfile.name), qPrintable(i18nfile.locale), i18nfile.locale_specificity);
00438       i18nFiles[i18nfile.name][i18nfile.locale_specificity] << i18nfile;
00439       names << i18nfile.name;
00440       qDebug("Found translation %s", qPrintable(i18nfile.fpath));
00441       klf_add_avail_translation(i18nfile);
00442     }
00443   }
00444 
00445   // get locale
00446   QString lc = currentLocale;
00447   if (lc.isEmpty())
00448     lc = "en_US";
00449   QStringList lcparts = lc.split("_");
00450 
00451   //  qDebug("Required locale is %s", qPrintable(lc));
00452 
00453   // a list of translation files to load (absolute paths)
00454   QStringList translationsToLoad;
00455 
00456   // now, load a suitable translator for each encountered name.
00457   for (QSet<QString>::const_iterator it = names.begin(); it != names.end(); ++it) {
00458     QString name = *it;
00459     QMap< int, QList<KLFI18nFile> > translations = i18nFiles[name];
00460     int specificity = lcparts.size();  // start with maximum specificity for required locale
00461     while (specificity >= 0) {
00462       // try to load a translation matching this specificity and locale
00463       QString testlocale = QStringList(lcparts.mid(0, specificity)).join("_");
00464       //      qDebug("Testing locale string %s...", qPrintable(testlocale));
00465       // search list:
00466       QList<KLFI18nFile> list = translations[specificity];
00467       for (j = 0; j < list.size(); ++j) {
00468         if (list[j].locale == testlocale) {
00469           //      qDebug("Found translation file.");
00470           // got matching translation file ! Load it !
00471           translationsToLoad << list[j].fpath;
00472           // and stop searching translation files for this name (break while condition);
00473           specificity = -1;
00474         }
00475       }
00476       // If we didn't find a suitable translation, try less specific locale name
00477       specificity--;
00478     }
00479   }
00480   // now we have a full list of translation files to load stored in  translationsToLoad .
00481 
00482   // Load Translations:
00483   for (j = 0; j < translationsToLoad.size(); ++j) {
00484     // load this translator
00485     //    qDebug("Loading translator %s for %s", qPrintable(translationsToLoad[j]), qPrintable(lc));
00486     QTranslator *translator = new QTranslator(app);
00487     QFileInfo fi(translationsToLoad[j]);
00488     //    qDebug("translator->load(\"%s\", \"%s\", \"_\", \"%s\")", qPrintable(fi.completeBaseName()),
00489     //     qPrintable(fi.absolutePath()),  qPrintable("."+fi.suffix()));
00490     bool res = translator->load(fi.completeBaseName(), fi.absolutePath(), "_", "."+fi.suffix());
00491     if ( res ) {
00492       app->installTranslator(translator);
00493       klf_translators << translator;
00494     } else {
00495       qWarning("Failed to load translator %s.", qPrintable(translationsToLoad[j]));
00496       delete translator;
00497     }
00498   }
00499 }
00500 
00501 
00502 
00503 
00504 KLF_EXPORT QString klfFindTranslatedDataFile(const QString& baseFileName, const QString& extension)
00505 {
00506   QString loc = klfconfig.UI.locale;
00507   QStringList suffixes;
00508   suffixes << "_"+loc
00509            << "_"+loc.section('_',0,0)
00510            << "";
00511   int k = 0;
00512   QString fn;
00513   while ( k < suffixes.size() &&
00514           ! QFile::exists(fn = QString("%1%2%3").arg(baseFileName, suffixes[k], extension)) ) {
00515     klfDbg( "base="<<baseFileName<<" extn="<<extension<<"; tried fn="<<fn ) ;
00516     ++k;
00517   }
00518   if (k >= suffixes.size()) {
00519     qWarning()<<KLF_FUNC_NAME<<": Can't find good translated file for "<<qPrintable(baseFileName+extension)
00520               <<"! last try was "<<fn;
00521     return QString();
00522   }
00523   return fn;
00524 }
00525 
00526 
00527 
00528 
00529 KLF_EXPORT void klfDataStreamWriteHeader(QDataStream& stream, const QString headermagic)
00530 {
00531   // QIODevice inherits QObject ... use dynamic properties
00532   stream.device()->setProperty("klfDataStreamAppVersion",
00533                                QVariant::fromValue<QString>(KLF_DATA_STREAM_APP_VERSION));
00534 
00535   // header always written in QDataStream version Qt_3_3
00536   stream.setVersion(QDataStream::Qt_3_3);
00537   stream << headermagic
00538          << (qint16)KLF_DATA_STREAM_APP_VERSION_MAJ
00539          << (qint16)KLF_DATA_STREAM_APP_VERSION_MIN
00540          << (qint16)QDataStream::Qt_4_4;
00541   stream.setVersion(QDataStream::Qt_4_4);
00542   // stream is ready to be written to
00543 
00544 }
00545 
00546 KLF_EXPORT bool klfDataStreamReadHeader(QDataStream& stream, const QStringList possibleHeaders,
00547                                         QString *readHeader, QString *readCompatKLFVersion)
00548 {
00549   KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00550 
00551   QString s;
00552   stream.setVersion(QDataStream::Qt_3_3);
00553   stream >> s;
00554   if (!possibleHeaders.contains(s) || stream.status() != QDataStream::Ok) {
00555     klfDbg("Read bad header: "<<s) ;
00556     if (readHeader != NULL)
00557       *readHeader = QString();
00558     return false;
00559   }
00560   if (readHeader != NULL)
00561     *readHeader = s;
00562 
00563   // read KLF-compat writing version
00564   qint16 vmaj, vmin;
00565   stream >> vmaj >> vmin;
00566   if (stream.status() != QDataStream::Ok) {
00567     if (readCompatKLFVersion)
00568       *readCompatKLFVersion = QString();
00569     return false;
00570   }
00571   klfDbg("read app compat version = "<<vmaj<<"."<<vmin) ;
00572 
00573   QString compatKLFVersion = QString("%1.%2").arg(vmaj).arg(vmin);
00574 
00575   if (vmaj > klfVersionMaj() || (vmaj == klfVersionMaj() && vmin > klfVersionMin())) {
00576     if (readCompatKLFVersion != NULL)
00577       *readCompatKLFVersion = compatKLFVersion; 
00578     return false;
00579   }
00580 
00581   // decide on QDataStream version
00582   if (vmaj <= 2) { // 2.x: version # not saved into stream, use Qt_3_3
00583     stream.setVersion(QDataStream::Qt_3_3);
00584   } else { // 3.x+: read version # from stream and set it
00585     qint16 version;
00586     stream >> version;
00587     stream.setVersion(version);
00588   }
00589 
00590   // set the compatibility version for reading data
00591   // QIODevice inherits QObject ... use dynamic properties
00592   stream.device()->setProperty("klfDataStreamAppVersion", QVariant::fromValue<QString>(compatKLFVersion));
00593 
00594   // the stream is ready to read data from
00595   return true;
00596 }

Generated by doxygen 1.7.3