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

src/klfliblegacyengine.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   file klfliblegacyengine.cpp
00003  *   This file is part of the KLatexFormula Project.
00004  *   Copyright (C) 2010 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: klfliblegacyengine.cpp 581 2010-12-02 23:09:05Z philippe $ */
00023 
00024 
00025 #include <QString>
00026 #include <QObject>
00027 #include <QDataStream>
00028 #include <QDir>
00029 #include <QFile>
00030 #include <QFileInfo>
00031 #include <QMessageBox>
00032 #include <QApplication> // qApp
00033 
00034 #include "klflib.h"
00035 #include "klflibview.h"
00036 #include "klfconfig.h"
00037 #include <klfutil.h>
00038 #include "klfliblegacyengine.h"
00039 #include "klfliblegacyengine_p.h"
00040 
00041 
00069 quint32 KLFLegacyData::KLFLibraryItem::MaxId = 1;
00070 
00071 
00072 // debug
00073 
00074 QDebug& operator<<(QDebug& s, const KLFLegacyData::KLFLibraryItem& item)
00075 {
00076   return s << "KLFLegacyData::KLFLibraryItem(id="<<item.id<<"; latex="<<item.latex<<")" ;
00077 }
00078 
00079 QDebug& operator<<(QDebug& s, const KLFLegacyData::KLFLibraryResource& res)
00080 {
00081   return s << "KLFLegacyData::KLFLibraryResource(id="<<res.id<<"; name="<<res.name<<")";
00082 }
00083 
00084 
00085 
00086 
00087 
00088 KLF_EXPORT QDataStream& operator<<(QDataStream& stream, const KLFLegacyData::KLFLibraryItem& item)
00089 {
00090   return stream << item.id << item.datetime
00091       << item.latex // category and tags are included.
00092       << item.preview << item.style;
00093 }
00094 
00095 // it is important to note that the >> operator imports in a compatible way to KLF 2.0
00096 KLF_EXPORT QDataStream& operator>>(QDataStream& stream, KLFLegacyData::KLFLibraryItem& item)
00097 {
00098   stream >> item.id >> item.datetime >> item.latex >> item.preview >> item.style;
00099   item.category = KLFLibEntry::categoryFromLatex(item.latex);
00100   item.tags = KLFLibEntry::tagsFromLatex(item.latex);
00101   return stream;
00102 }
00103 
00104 
00105 KLF_EXPORT QDataStream& operator<<(QDataStream& stream, const KLFLegacyData::KLFLibraryResource& item)
00106 {
00107   return stream << item.id << item.name;
00108 }
00109 KLF_EXPORT QDataStream& operator>>(QDataStream& stream, KLFLegacyData::KLFLibraryResource& item)
00110 {
00111   return stream >> item.id >> item.name;
00112 }
00113 
00114 
00115 KLF_EXPORT bool operator==(const KLFLegacyData::KLFLibraryItem& a, const KLFLegacyData::KLFLibraryItem& b)
00116 {
00117   return
00118     //    a.id == b.id &&   // don't compare IDs since they should be different.
00119     //    a.datetime == b.datetime &&   // same for datetime
00120     a.latex == b.latex &&
00121     /* the following is unnecessary since category/tags information is contained in .latex
00122       a.category == b.category &&
00123       a.tags == b.tags &&
00124     */
00125     //    a.preview == b.preview && // don't compare preview: it's unnecessary and overkill
00126     a.style == b.style;
00127 }
00128 
00129 
00130 
00131 KLF_EXPORT bool operator<(const KLFLegacyData::KLFLibraryResource a, const KLFLegacyData::KLFLibraryResource b)
00132 {
00133   return a.id < b.id;
00134 }
00135 KLF_EXPORT bool operator==(const KLFLegacyData::KLFLibraryResource a, const KLFLegacyData::KLFLibraryResource b)
00136 {
00137   return a.id == b.id;
00138 }
00139 
00140 KLF_EXPORT bool resources_equal_for_import(const KLFLegacyData::KLFLibraryResource a,
00141                                            const KLFLegacyData::KLFLibraryResource b)
00142 {
00143   return a.name == b.name;
00144 }
00145 
00146 
00147 KLF_EXPORT QDataStream& operator<<(QDataStream& stream, const KLFLegacyData::KLFStyle& style)
00148 {
00149   return stream << style.name << (quint32)style.fg_color << (quint32)style.bg_color
00150                 << style.mathmode << style.preamble << (quint16)style.dpi;
00151 }
00152 KLF_EXPORT QDataStream& operator>>(QDataStream& stream, KLFLegacyData::KLFStyle& style)
00153 {
00154   quint32 fg, bg;
00155   quint16 dpi;
00156   stream >> style.name;
00157   stream >> fg >> bg >> style.mathmode >> style.preamble >> dpi;
00158   style.fg_color = fg;
00159   style.bg_color = bg;
00160   style.dpi = dpi;
00161   return stream;
00162 }
00163 KLF_EXPORT bool operator==(const KLFLegacyData::KLFStyle& a, const KLFLegacyData::KLFStyle& b)
00164 {
00165   return a.name == b.name &&
00166     a.fg_color == b.fg_color &&
00167     a.bg_color == b.bg_color &&
00168     a.mathmode == b.mathmode &&
00169     a.preamble == b.preamble &&
00170     a.dpi == b.dpi;
00171 }
00172 
00173 
00174 
00175 // -------------------------------------------
00176 
00177 // KLFLibLegacyFileDataPrivate
00178 
00179 
00180 // static
00181 QMap<QString,KLFLibLegacyFileDataPrivate*> KLFLibLegacyFileDataPrivate::staticFileDataObjects;
00182 
00183 
00184 
00185 bool KLFLibLegacyFileDataPrivate::load(const QString& fnm)
00186 {
00187   KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME+"("+fnm+")") ;
00188 
00189   QString fname = (!fnm.isEmpty() ? fnm : filename);    
00190 
00191   klfDbg("loading from file "<<fname<<" (our filename="<<filename<<")") ;
00192 
00193   QFile fimp(fname);
00194   if ( ! fimp.open(QIODevice::ReadOnly) ) {
00195     qWarning("Unable to open library file %s!", qPrintable(fname));
00196     return false;
00197   }
00198   QDataStream stream(&fimp);
00199   // Qt3-compatible stream input
00200   stream.setVersion(QDataStream::Qt_3_3);
00201   QString s1;
00202   stream >> s1;
00203   if (s1 == "KLATEXFORMULA_LIBRARY_EXPORT") {
00204     // opening an export file (*.klf)
00205     legacyLibType = ExportLibraryType;
00206     qint16 vmaj, vmin;
00207     stream >> vmaj >> vmin; // these are not needed, format has not changed in .klf export files.
00208     stream >> resources >> library;
00209     if (!stream.atEnd() && stream.status() == QDataStream::Ok)
00210       stream >> metadata;
00211   } else if (s1 == "KLATEXFORMULA_LIBRARY") {
00212     // opening a library file (~/.klatexformula/library)
00213     legacyLibType = LocalLibraryType;
00214     qint16 vmaj, vmin;
00215     stream >> vmaj >> vmin;
00216     if (vmaj <= 2) {
00217       stream.setVersion(QDataStream::Qt_3_3);
00218     } else {
00219       qint16 version;
00220       stream >> version;
00221       stream.setVersion(version);
00222     }
00223     quint32 lib_max_id;
00224     stream >> lib_max_id; // will not be used...
00225     // now read the library itself.
00226     stream >> resources >> library;
00227     // the meta-data cannot have been written by KLF 3.0--3.1 but we may possibly already have
00228     // written to this file with klf 3.2
00229     if (!stream.atEnd() && stream.status() == QDataStream::Ok)
00230       stream >> metadata;
00231   } else if (s1 == "KLATEXFORMULA_HISTORY") {
00232     // opening a post-2.0, pre-2.1 "history" file  (no "library" yet)
00233     legacyLibType = LocalHistoryType;
00234     qint16 vmaj, vmin;
00235     stream >> vmaj >> vmin;
00236     KLFLegacyData::KLFLibraryList history;
00237     quint32 lib_max_id;
00238     stream >> lib_max_id >> history;
00239 
00240     resources = KLFLegacyData::KLFLibraryResourceList();
00241     KLFLegacyData::KLFLibraryResource historyresource;
00242     historyresource.id = KLFLegacyData::LibResource_History;
00243     historyresource.name = tr("History");
00244     resources.append(historyresource);
00245     library = KLFLegacyData::KLFLibrary();
00246     library[historyresource] = history;
00247           
00248   } else {
00249     qWarning("Error: Library file `%s' is invalid library file or corrupt!", qPrintable(fname));
00250     return false;
00251   }
00252 
00253   // update KLFLibraryItem::MaxId
00254   int k;
00255   for (k = 0; k < resources.size(); ++k) {
00256     KLFLegacyData::KLFLibraryList ll = library[resources[k]];
00257     int j;
00258     for (j = 0; j < ll.size(); ++j) {
00259       if (ll[j].id >= KLFLegacyData::KLFLibraryItem::MaxId)
00260         KLFLegacyData::KLFLibraryItem::MaxId = ll[j].id+1;
00261     }
00262   }
00263   haschanges = false;
00264   return true;
00265 }
00266 
00267 bool KLFLibLegacyFileDataPrivate::save(const QString& fnm)
00268 {
00269   KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME+"("+fnm+")") ;
00270 
00271   QString fname = (!fnm.isEmpty() ? fnm : filename) ;
00272   klfDbg(" saving to file "<<fname<<" a "<<legacyLibType<<"-type library with N="<<resources.size()
00273          <<" resources (our filename="<<filename<<")") ;
00274   QFile fsav(fname);
00275   if ( ! fsav.open(QIODevice::WriteOnly) ) {
00276     qWarning("Can't write to file %s!", qPrintable(fname));
00277     QMessageBox::critical(NULL, tr("Error"), tr("Can't write to file %1").arg(fname));
00278     return false;
00279   }
00280   QDataStream stream(&fsav);
00281 
00282   // WE'RE WRITING KLF 2.1 compatible output, so we write as being version 2.1
00283   // This also implies that we write with QDataStream version "Qt 3.3"
00284 
00285   // write Qt 3.3-compatible data
00286   stream.setVersion(QDataStream::Qt_3_3);
00287 
00288   LegacyLibType llt = legacyLibType;
00289 
00290   // however, for old versions of klatexformula:
00291   QString cfname = canonicalFilePath(fname);
00292   if (legacyLibType == ExportLibraryType &&
00293       (cfname == canonicalFilePath(klfconfig.homeConfigDir+"/library") ||
00294        (cfname.startsWith(canonicalFilePath(QDir::homePath()+"/.kde")) &&
00295         (cfname.endsWith("/library") || cfname.endsWith("/history"))))) {
00296     // the file name is a legacy library or history.
00297     if (QFileInfo(fsav).fileName() == "history")
00298       llt = LocalHistoryType;
00299     if (QFileInfo(fsav).fileName() == "library")
00300       llt = LocalLibraryType;
00301     klfDbg("adjusted legacy lib type to save to type "<<llt<<" instead of "<<legacyLibType) ;
00302   }
00303 
00304   switch (llt) {
00305   case LocalHistoryType:
00306     {
00307       KLFLegacyData::KLFLibraryList liblist;
00308       if (resources.size() == 0) {
00309         liblist = KLFLegacyData::KLFLibraryList(); // no resources !
00310       } else {
00311         liblist = library[resources[0]];
00312       }
00313       if (resources.size() > 1) {
00314         qWarning("%s: Saving an old \"history\" resource. Only one resource can be saved, "
00315                  "it will be the first: %s", KLF_FUNC_NAME, qPrintable(resources[0].name));
00316         QMessageBox::warning(NULL, tr("Warning"),
00317                              tr("Saving an old \"history\" resource. Only one resource can be saved, "
00318                                 "it will be the first: %1").arg(resources[0].name));
00319       }
00320       // find history resource in our
00321       stream << QString("KLATEXFORMULA_HISTORY") << (qint16)2 << (qint16)0
00322              << (quint32)KLFLegacyData::KLFLibraryItem::MaxId << liblist;
00323       break;
00324     }
00325   case LocalLibraryType:
00326     {
00327       stream << QString("KLATEXFORMULA_LIBRARY") << (qint16)2 << (qint16)1;
00328       // don't save explicitely QDataStream version: we're writing KLF 2.1-compatible;
00329       // version explicitely saved only since KLF >= 3.x.
00330       stream << (quint32)KLFLegacyData::KLFLibraryItem::MaxId << resources << library;
00331       // additionally, save our meta-data at the end (this will be ignored by previous versions
00332       // of KLF)
00333       stream << metadata;
00334       break;
00335     }
00336   case ExportLibraryType:
00337   default:
00338     if (llt != ExportLibraryType) {
00339       qWarning("%s: bad library type %d! Falling back to '.klf'-library-export type",
00340                KLF_FUNC_NAME, llt);
00341     }
00342 
00343     stream << QString("KLATEXFORMULA_LIBRARY_EXPORT") << (qint16)2 << (qint16)1
00344            << resources << library;
00345     // additionally, save our meta-data at the end (this will be ignored by previous versions
00346     // of KLF)
00347     stream << metadata;
00348 
00349     klfDbg("saved export-library type. resource count: "<<resources.size()) ;
00350 #ifdef KLF_DEBUG
00351     if (resources.size()) {
00352       KLFLegacyData::KLFLibraryList llll = ((const KLFLegacyData::KLFLibrary)library)[resources[0]];
00353       klfDbg("in first resource wrote "<<llll.size()<<" items.");
00354     }
00355 #endif
00356     break;
00357   }
00358 
00359   if (fnm.isEmpty() || canonicalFilePath(fnm) == canonicalFilePath(filename))
00360     haschanges = false; // saving to the reference file, not a copy
00361   return true;
00362 }
00363 
00364 
00365 int KLFLibLegacyFileDataPrivate::getReservedResourceId(const QString& resname, int defaultId)
00366 {
00367   if ( ! QString::localeAwareCompare(resname, "History") ||
00368        ! QString::localeAwareCompare(resname, qApp->translate("KLFMainWin", "History")) ||
00369        ! QString::compare(resname, "History", Qt::CaseInsensitive) ||
00370        ! QString::compare(resname, qApp->translate("KLFMainWin", "History"), Qt::CaseInsensitive) )
00371     return KLFLegacyData::LibResource_History;
00372   if ( ! QString::localeAwareCompare(resname, "Archive") ||
00373        ! QString::localeAwareCompare(resname, qApp->translate("KLFMainWin", "Archive")) ||
00374        ! QString::compare(resname, "Archive", Qt::CaseInsensitive) ||
00375        ! QString::compare(resname, qApp->translate("KLFMainWin", "Archive"), Qt::CaseInsensitive) )
00376     return KLFLegacyData::LibResource_Archive;
00377 
00378   return defaultId;
00379 }
00380 
00381 int KLFLibLegacyFileDataPrivate::findResourceName(const QString& resname)
00382 {
00383   int k;
00384   for (k = 0; k < resources.size() && resources[k].name != resname; ++k)
00385     ;
00386   return k < resources.size() ? k : -1;
00387 }
00388 
00389 
00390 
00391 
00392 
00393 
00394 // -------------------------------------------
00395 
00396 
00397 // static
00398 KLFLibLegacyEngine * KLFLibLegacyEngine::openUrl(const QUrl& url, QObject *parent)
00399 {
00400   KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00401 
00402   QString fname = klfUrlLocalFilePath(url);
00403   if (fname.isEmpty()) {
00404     klfDbgSt("Requested empty fname.") ;
00405     return NULL;
00406   }
00407   if ( ! QFileInfo(fname).isReadable() ) {
00408     qWarning("%s: file %s does not exist!", KLF_FUNC_NAME, qPrintable(fname));
00409     return NULL;
00410   }
00411 
00412   if (url.scheme() != "klf+legacy") {
00413     qWarning("KLFLibLegacyEngine::openUrl(): unsupported scheme %s!", qPrintable(url.scheme()));
00414     return NULL;
00415   }
00416 
00417   QString legresname;
00418   if (url.hasQueryItem("klfDefaultSubResource"))
00419     legresname = url.queryItemValue("klfDefaultSubResource");
00420 
00421   return new KLFLibLegacyEngine(fname, legresname, url, parent);
00422 }
00423 
00424 // static
00425 KLFLibLegacyEngine * KLFLibLegacyEngine::createDotKLF(const QString& fname, QString legacyResourceName,
00426                                                       QObject *parent)
00427 {
00428   QString fileName = KLFLibLegacyFileDataPrivate::canonicalFilePath(fname);
00429 
00430   QString lrname = legacyResourceName;
00431   if (QFile::exists(fileName)) {
00432     // fail; we want to _CREATE_ a .klf file. Erase file before calling this function to overwrite.
00433     return NULL;
00434   }
00435 
00436   if (fileName.isEmpty()) {
00437     qWarning()<<KLF_FUNC_NAME<<": file name "<<fileName<<" is empty!";
00438     return NULL;
00439   }
00440   //  if (!QFileInfo(QFileInfo(fileName).absolutePath()).isWritable()) {
00441   //    qWarning()<<KLF_FUNC_NAME<<": containing directory "<<QFileInfo(fileName).absolutePath()<<" is not writable.";
00442   //    return NULL;
00443   //  }
00444 
00445   QUrl url = QUrl::fromLocalFile(fileName);
00446   url.setScheme("klf+legacy");
00447 
00448   if (lrname.isEmpty())
00449     lrname = tr("Default Resource"); // default name...?
00450   url.addQueryItem("klfDefaultSubResource", lrname);
00451 
00452   klfDbgSt("fileName="<<fileName<<"; canonical file path="<<QFileInfo(fileName).canonicalFilePath()
00453            <<"; legacyResourceName="<<legacyResourceName);
00454 
00455   return new KLFLibLegacyEngine(fileName, lrname, url, parent);
00456 }
00457 
00458 
00459 // private
00460 KLFLibLegacyEngine::KLFLibLegacyEngine(const QString& fileName, const QString& resname, const QUrl& url,
00461                                        QObject *parent)
00462   : KLFLibResourceSimpleEngine(url, FeatureReadOnly|FeatureLocked|FeatureSaveTo|FeatureSubResources, parent)
00463 {
00464   // get the data object
00465   d = KLFLibLegacyFileDataPrivate::instanceFor(fileName, !isReadOnly());
00466   if (d == NULL) {
00467     qWarning()<<KLF_FUNC_NAME<<": Couldn't get KLFLibLegacyFileDataPrivate instance for "<<fileName<<"! Expect Crash!";
00468     return;
00469   }
00470   d->ref();
00471 
00472   connect(d, SIGNAL(resourcePropertyChanged(int)), this, SLOT(updateResourceProperty(int)));
00473 
00474   updateResourceProperty(-1);
00475 
00476   // add at least one resource (baptized resname) if the library is empty
00477   if (d->resources.isEmpty()) {
00478     // create a resource
00479     KLFLegacyData::KLFLibraryResource res;
00480     res.name = resname;
00481     res.id = d->getReservedResourceId(resname, KLFLegacyData::LibResourceUSERMAX - 1);
00482     d->resources << res;
00483     // and initialize pLibrary to contain this one empty resource.
00484     d->library.clear();
00485     d->library[res] = KLFLegacyData::KLFLibraryList();
00486     d->haschanges = true;
00487   }
00488 
00489   klfDbg("Opened KLFLibLegacyEngine resource `"<<fileName<<"': d="<<d<<"; resources="<<d->resources
00490          <<" (me="<<this<<", d="<<d<<")\n") ;
00491 }
00492 
00493 KLFLibLegacyEngine::~KLFLibLegacyEngine()
00494 {
00495   KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00496 
00497   KLF_ASSERT_NOT_NULL( d , "d is NULL!" , return ) ;
00498 
00499   if ( ! d->deref() ) {
00500     klfDbg("last reference to the private liblegacyenginedataprivate object d="<<d<<", "
00501            "saving(?) and deleting. haschanges="<<d->haschanges) ;
00502     klfDbg("resources dump:\n"<<d->resources<<"\nlibrary:\n"<<d->library) ;
00503     if (d->haschanges)
00504       d->save();
00505     delete d;
00506   }
00507 }
00508 
00509 uint KLFLibLegacyEngine::compareUrlTo(const QUrl& other, uint interestFlags) const
00510 {
00511   // we can only test for these flags (see doc for KLFLibResourceEngine::compareUrlTo())
00512   interestFlags = interestFlags & (KlfUrlCompareBaseEqual);
00513 
00514   return klfUrlCompare(url(), other, interestFlags);
00515 }
00516 
00517 
00518 bool KLFLibLegacyEngine::canModifyData(const QString& subResource, ModifyType modifytype) const
00519 {
00520   if ( ! KLFLibResourceEngine::canModifyData(subResource, modifytype) ) {
00521     klfDbg("base cannot modify resource engine...") ;
00522     return false;
00523   }
00524 
00525   KLF_ASSERT_NOT_NULL( d , "d is NULL!" , return false ) ;
00526 
00527 #ifndef Q_WS_WIN
00528   // seems like windows doesn't like to test directories to be writable ...?
00529 
00530   if ( QFile::exists(d->fileName())  // depending on whether the file itself exists, check if
00531        ?  ! QFileInfo(d->fileName()).isWritable() // file itself writable
00532        :  ! QFileInfo(QFileInfo(d->fileName()).absolutePath()).isWritable() ) { // or containing dir writable
00533     return false;
00534   }
00535 #endif
00536 
00537   return true;
00538 }
00539 
00540 bool KLFLibLegacyEngine::canModifyProp(int propid) const
00541 {
00542   // all resource properties are stored in QVariantMap
00543   return KLFLibResourceEngine::canModifyProp(propid);
00544 }
00545 
00546 bool KLFLibLegacyEngine::canRegisterProperty(const QString& propName) const
00547 {
00548   // all resource properties are stored in QVariantMap
00549   return canModifyProp(-1);
00550 }
00551 
00552 KLFLibEntry KLFLibLegacyEngine::entry(const QString& resource, entryId id)
00553 {
00554   KLF_ASSERT_NOT_NULL( d , "d is NULL!" , return KLFLibEntry() ) ;
00555 
00556   int index = d->findResourceName(resource);
00557   if (index < 0)
00558     return KLFLibEntry();
00559 
00560   KLFLegacyData::KLFLibraryList ll = d->library[d->resources[index]];
00561   // find entry with id 'id'
00562   int k;
00563   for (k = 0; k < ll.size() && ll[k].id != (quint32)id; ++k)
00564     ;
00565   if (k == ll.size()) {
00566     return KLFLibEntry();
00567   }
00568 
00569   return d->toLibEntry(ll[k]);
00570 }
00571 
00572 
00573 
00574 QList<KLFLibResourceEngine::KLFLibEntryWithId>
00575 /* */ KLFLibLegacyEngine::allEntries(const QString& resource, const QList<int>& wantedEntryProperties)
00576 {
00577   KLF_ASSERT_NOT_NULL( d , "d is NULL!" , return QList<KLFLibEntryWithId>() ) ;
00578 
00579   int rindex = d->findResourceName(resource);
00580   if (rindex < 0)
00581     return QList<KLFLibEntryWithId>();
00582 
00583   QList<KLFLibEntryWithId> entryList;
00584   KLFLegacyData::KLFLibraryList ll = d->library[d->resources[rindex]];
00585   int k;
00586   for (k = 0; k < ll.size(); ++k) {
00587     KLFLibEntryWithId e;
00588     e.entry = d->toLibEntry(ll[k]);
00589     e.id = ll[k].id;
00590     entryList << e;
00591   }
00592   return entryList;
00593 }
00594 
00595 
00596 QStringList KLFLibLegacyEngine::subResourceList() const
00597 {
00598   KLF_ASSERT_NOT_NULL( d , "d is NULL!" , return QStringList() ) ;
00599 
00600   QStringList list;
00601   int k;
00602   for (k = 0; k < d->resources.size(); ++k)
00603     list << d->resources[k].name;
00604   return list;
00605 }
00606 
00607 bool KLFLibLegacyEngine::canCreateSubResource() const
00608 {
00609   // canModifyData is not sensitive to thses arguments...
00610   return canModifyData(QString(), ChangeData);
00611 }
00612 bool KLFLibLegacyEngine::canRenameSubResource(const QString& subResource) const
00613 {
00614   return canModifyData(subResource, ChangeData);
00615 }
00616 bool KLFLibLegacyEngine::canDeleteSubResource(const QString& subResource) const
00617 {
00618   return subResource.length() && hasSubResource(subResource) &&
00619     canModifyData(subResource, DeleteData) && subResourceList().size() > 1;
00620 }
00621 
00622 bool KLFLibLegacyEngine::createSubResource(const QString& subResource,
00623                                            const QString& subResourceTitle)
00624 {
00625   KLF_ASSERT_NOT_NULL( d , "d is NULL!" , return false ) ;
00626 
00627   quint32 newId = KLFLegacyData::LibResourceUSERMIN;
00628   bool ok = true;
00629   int k;
00630   while (!ok && newId <= KLFLegacyData::LibResourceUSERMAX) {
00631     for (k = 0; k < d->resources.size() && d->resources[k].id != newId; ++k)
00632       ;
00633     if (k == d->resources.size())
00634       ok = true;
00635     ++newId;
00636   }
00637   if (newId == KLFLegacyData::LibResourceUSERMAX) {
00638     qWarning()<<KLF_FUNC_NAME<<"("<<subResource<<",..): no new ID could be found (!?!)";
00639     return false;
00640   }
00641   KLFLegacyData::KLFLibraryResource res;
00642   res.name = subResource;
00643   res.id = d->getReservedResourceId(subResource, newId);
00644 
00645   d->resources.push_back(res);
00646   d->library[res] = KLFLegacyData::KLFLibraryList();
00647   d->haschanges = true;
00648 
00649   emit subResourceCreated(subResource);
00650 
00651   return true;
00652 }
00653 
00654 bool KLFLibLegacyEngine::renameSubResource(const QString& subResource, const QString& subResourceNewName)
00655 {
00656   KLF_ASSERT_NOT_NULL( d , "d is NULL!" , return false ) ;
00657   int rindex = d->findResourceName(subResource);
00658   if (rindex < 0) {
00659     qWarning()<<KLF_FUNC_NAME<<": can't find sub-resource "<<subResource<<" in our data.";
00660     return false;
00661   }
00662   KLFLegacyData::KLFLibraryResource & resref = d->resources[rindex];
00663   // remove from library lists, keep the list
00664   KLFLegacyData::KLFLibraryList liblist = d->library.take(resref);
00665 
00666   // modify the resource data as requested
00667   resref.name = subResourceNewName;
00668   // see if the name we gave this resource is a 'reserved' name, eg. "History", or "Archive", that
00669   // have specific resource IDs.
00670   int possibleNewId = d->getReservedResourceId(subResource, -1);
00671   if (possibleNewId != -1)
00672     resref.id = possibleNewId;
00673 
00674   // re-insert into library list
00675   d->library[resref] = liblist;
00676 
00677   emit subResourceRenamed(subResource, subResourceNewName);
00678   return true;
00679 }
00680 
00681 bool KLFLibLegacyEngine::deleteSubResource(const QString& subResource)
00682 {
00683   KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00684   klfDbg("sub-resource: "<<subResource) ;
00685 
00686   KLF_ASSERT_NOT_NULL( d , "d is NULL!" , return false ) ;
00687   if (!canDeleteSubResource(subResource)) {
00688     klfDbg("Cannot delete sub-resource "<<subResource) ;
00689     return false;
00690   }
00691   int rindex = d->findResourceName(subResource);
00692   if (rindex < 0) {
00693     qWarning()<<KLF_FUNC_NAME<<": can't find sub-resource "<<subResource<<" in our data.";
00694     return false;
00695   }
00696 
00697   // delete the data from our resource list and library
00698 
00699   KLFLegacyData::KLFLibraryResource res = d->resources.takeAt(rindex);
00700   // remove from library lists, keep the list
00701   d->library.remove(res);
00702 
00703   emit subResourceDeleted(subResource);
00704   return true;
00705 }
00706 
00707 
00708 bool KLFLibLegacyEngine::save()
00709 {
00710   klfDbg( "() our url="<<url()<<"." ) ;
00711   if (isReadOnly()) {
00712     qWarning("KLFLibLegacyEngine::save: resource is read-only!");
00713     return false;
00714   }
00715   KLF_ASSERT_NOT_NULL( d , "d is NULL!" , return false ) ;
00716 
00717   return d->save();
00718 }
00719 
00720 void KLFLibLegacyEngine::setAutoSaveInterval(int intervalms)
00721 {
00722   d->autoSaveTimer->stop();
00723   if (intervalms > 0) {
00724     d->autoSaveTimer->setInterval(intervalms);
00725     d->autoSaveTimer->start();
00726   }
00727 }
00728 
00729 QList<KLFLibResourceEngine::entryId> KLFLibLegacyEngine::insertEntries(const QString& subResource,
00730                                                                        const KLFLibEntryList& entrylist)
00731 {
00732   klfDbg("subResource="<<subResource<<"; entrylist="<<entrylist) ;
00733 
00734   KLF_ASSERT_NOT_NULL( d , "d is NULL!" , return QList<entryId>() ) ;
00735 
00736   if ( entrylist.size() == 0 )
00737      return QList<entryId>();
00738   if (!canModifyData(subResource, InsertData)) {
00739     klfDbg("cannot modify data.") ;
00740     return QList<entryId>();
00741   }
00742 
00743   int index = d->findResourceName(subResource);
00744   if (index < 0) {
00745     klfDbg("cannot find sub-resource: "<<subResource) ;
00746     return QList<entryId>();
00747   }
00748 
00749   QList<entryId> newIds;
00750 
00751   int k;
00752   for (k = 0; k < entrylist.size(); ++k) {
00753     KLFLegacyData::KLFLibraryItem item = d->toLegacyLibItem(entrylist[k]);
00754     d->library[d->resources[index]] << item;
00755     newIds << item.id;
00756   }
00757   d->haschanges = true;
00758 
00759   emit dataChanged(subResource, InsertData, newIds);
00760 
00761   klfDbg("finished inserting items. d="<<d<<"; dumping resources:\n"<<d->resources
00762          <<"\nand library:\n"<<d->library) ;
00763 
00764   return newIds;
00765 }
00766 
00767 bool KLFLibLegacyEngine::changeEntries(const QString& subResource, const QList<entryId>& idlist,
00768                                        const QList<int>& properties, const QList<QVariant>& values)
00769 {
00770   if (idlist.size() == 0)
00771     return true;
00772   if (!canModifyData(subResource, ChangeData))
00773     return false;
00774 
00775   KLF_ASSERT_NOT_NULL( d , "d is NULL!" , return false ) ;
00776 
00777   int index = d->findResourceName(subResource);
00778   if (index < 0)
00779     return false;
00780 
00781   const KLFLegacyData::KLFLibraryList& ll = d->library[d->resources[index]];
00782 
00783   bool success = true;
00784 
00785   int k;
00786   for (k = 0; k < idlist.size(); ++k) {
00787     int libindex;
00788     int j;
00789     // find the entry
00790     for (libindex = 0; libindex < ll.size() && ll[libindex].id != (quint32)idlist[k]; ++libindex)
00791       ;
00792     if (libindex == ll.size()) {
00793       qWarning()<<KLF_FUNC_NAME<<": Can't find entry with id "<<idlist[k];
00794       success = false;
00795       continue;
00796     }
00797     // modify this entry as requested.
00798     for (j = 0; j < properties.size(); ++j) {
00799       switch (properties[j]) {
00800       case KLFLibEntry::Latex:
00801         // remember that entry.latex has redundancy for category+tags in the form "%: ...\n% ...\n<latex>"
00802         { QString curcategory = d->library[d->resources[index]][libindex].category;
00803           QString curtags = d->library[d->resources[index]][libindex].tags;
00804           d->library[d->resources[index]][libindex].latex =
00805             KLFLibEntry::latexAddCategoryTagsComment(values[j].toString(), curcategory, curtags);
00806           break;
00807         }
00808       case KLFLibEntry::DateTime:
00809         d->library[d->resources[index]][libindex].datetime = values[j].toDateTime();
00810         break;
00811       case KLFLibEntry::Preview:
00812         d->library[d->resources[index]][libindex].preview = QPixmap::fromImage(values[j].value<QImage>());
00813         break;
00814       case KLFLibEntry::Category:
00815         // remember that entry.latex has redundancy for category+tags in the form "%: ...\n% ...\n<latex>"
00816         { QString curlatex =
00817             KLFLibEntry::stripCategoryTagsFromLatex(d->library[d->resources[index]][libindex].latex);
00818           QString newcategory = values[j].toString();
00819           QString curtags = d->library[d->resources[index]][libindex].tags;
00820           d->library[d->resources[index]][libindex].latex =
00821             KLFLibEntry::latexAddCategoryTagsComment(curlatex, newcategory, curtags);
00822           d->library[d->resources[index]][libindex].category = newcategory;
00823           break;
00824         }
00825       case KLFLibEntry::Tags:
00826         // remember that entry.latex has redundancy for category+tags in the form "%: ...\n% ...\n<latex>"
00827         { QString curlatex =
00828             KLFLibEntry::stripCategoryTagsFromLatex(d->library[d->resources[index]][libindex].latex);
00829           QString curcategory = d->library[d->resources[index]][libindex].category;
00830           QString newtags = values[j].toString();
00831           d->library[d->resources[index]][libindex].latex =
00832             KLFLibEntry::latexAddCategoryTagsComment(curlatex, curcategory, newtags);
00833           d->library[d->resources[index]][libindex].tags = newtags;
00834           break;
00835         }
00836         break;
00837       case KLFLibEntry::Style:
00838         d->library[d->resources[index]][libindex].style = d->toLegacyStyle(values[j].value<KLFStyle>());
00839         break;
00840       default:
00841         qWarning()<<KLF_FUNC_NAME<<": Cannot set arbitrary property "<<propertyNameForId(properties[j])
00842                   <<"!";
00843         success = false;
00844         break;
00845       }
00846     }
00847   }
00848 
00849 #ifdef KLF_DEBUG
00850   klfDbg( ": Changed entries. Dump:" ) ;
00851   const KLFLegacyData::KLFLibraryList& ll2 = d->library[d->resources[index]];
00852   int kl;
00853   for (kl = 0; kl < ll2.size(); ++kl)
00854     klfDbg( "\t#"<<kl<<": "<<ll2[kl].latex<<" - "<<ll2[kl].category ) ;
00855 #endif
00856 
00857   d->haschanges = true;
00858 
00859   emit dataChanged(subResource, ChangeData, idlist);
00860 
00861   return success;
00862 }
00863 
00864 bool KLFLibLegacyEngine::deleteEntries(const QString& subResource, const QList<entryId>& idlist)
00865 {
00866   KLF_ASSERT_NOT_NULL( d , "d is NULL!" , return false ) ;
00867 
00868   if (idlist.isEmpty())
00869     return true;
00870   if (!canModifyData(subResource, DeleteData))
00871     return false;
00872 
00873   int index = d->findResourceName(subResource);
00874   if (index < 0)
00875     return false;
00876 
00877   // now remove the requested entries
00878 
00879   KLFLegacyData::KLFLibraryList *ll = & d->library[d->resources[index]];
00880   bool success = true;
00881   int k;
00882   for (k = 0; k < idlist.size(); ++k) {
00883     int j;
00884     for (j = 0; j < ll->size() && ll->operator[](j).id != (quint32)idlist[k]; ++j)
00885       ;
00886     if (j == ll->size()) {
00887       qWarning("KLFLibLegacyEngine::deleteEntries: Can't find ID %d in library list in current resource.",
00888                idlist[k]);
00889       success = false;
00890       continue;
00891     }
00892     // remove this entry from list
00893     ll->removeAt(j);
00894   }
00895 
00896   d->haschanges = true;
00897 
00898   emit dataChanged(subResource, DeleteData, idlist);
00899 
00900   return success;
00901 }
00902 
00903 bool KLFLibLegacyEngine::saveTo(const QUrl& newPath)
00904 {
00905   KLF_ASSERT_NOT_NULL( d , "d is NULL!" , return false ) ;
00906 
00907   if (newPath.scheme() == "klf+legacy") {
00908     return d->save(klfUrlLocalFilePath(newPath));
00909   }
00910   return false;
00911 }
00912 
00913 bool KLFLibLegacyEngine::saveResourceProperty(int propId, const QVariant& value)
00914 {
00915   KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00916 
00917   QVariantMap m = d->metadata["ResProps"].toMap();
00918 
00919   QString propName = propertyNameForId(propId);
00920   if ( propName.isEmpty() )
00921     return false;
00922 
00923   if (m.contains(propName) && m[propName] == value)
00924     return true; // nothing to do
00925 
00926   m[propName] = value;
00927 
00928   d->metadata["ResProps"] = QVariant(m);
00929   d->haschanges = true;
00930 
00931   d->emitResourcePropertyChanged(propId);
00932 
00933   return true;
00934 }
00935 
00936 void KLFLibLegacyEngine::updateResourceProperty(int propId)
00937 {
00938   KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00939   klfDbg("property id="<<propId) ;
00940 
00941   // need KLFPropertizedObject:: explicit scopes to disambiguate from QObject's functions
00942 
00943   const QMap<QString,QVariant> resprops = d->metadata["ResProps"].toMap();
00944 
00945   if (propId < 0) {
00946     // read and update all the properties
00947     KLFPropertizedObject::setAllProperties(resprops);
00948     // set some default values for some properties if they have not been set
00949     if (!KLFPropertizedObject::property(PropLocked).isValid())
00950       KLFPropertizedObject::setProperty(PropLocked, QVariant(false));
00951     if (!KLFPropertizedObject::property(PropAccessShared).isValid())
00952       KLFPropertizedObject::setProperty(PropAccessShared, QVariant::fromValue(false));
00953     if (!KLFPropertizedObject::property(PropTitle).isValid())
00954       KLFPropertizedObject::setProperty(PropTitle, QFileInfo(d->fileName()).baseName());
00955   } else {
00956     QString propName = KLFPropertizedObject::propertyNameForId(propId);
00957     KLFPropertizedObject::setProperty(propId, resprops[propName]);
00958   }
00959   emit resourcePropertyChanged(propId);
00960 }
00961 
00962 
00963 // ------------------------------------
00964 
00965 
00966 QString KLFLibLegacyLocalFileSchemeGuesser::guessScheme(const QString& fileName) const
00967 {
00968   klfDbg("file "<<fileName);
00969 
00970   if (fileName.endsWith(".klf")) {
00971     klfDbg("has .klf extension.") ;
00972     return QLatin1String("klf+legacy");
00973   }
00974 
00975   QFile f(fileName);
00976   if ( ! f.open(QIODevice::ReadOnly) ) {
00977     qWarning()<<KLF_FUNC_NAME<<": Can't open file: "<<fileName;
00978     return QString();
00979   }
00980   QDataStream stream(&f);
00981   // Qt3-compatible stream input
00982   stream.setVersion(QDataStream::Qt_3_3);
00983   QString s1;
00984   stream >> s1;
00985   klfDbg("read line: got magic "<<s1);
00986   if (s1 == QLatin1String("KLATEXFORMULA_LIBRARY_EXPORT") ||
00987       s1 == QLatin1String("KLATEXFORMULA_LIBRARY") ||
00988       s1 == QLatin1String("KLATEXFORMULA_HISTORY"))
00989     return QLatin1String("klf+legacy");
00990 
00991   return QString();
00992 }
00993 
00994 // ------------------------------------
00995 
00996 
00997 KLFLibLegacyEngineFactory::KLFLibLegacyEngineFactory(QObject *parent)
00998   : KLFLibEngineFactory(parent)
00999 {
01000   KLFLibBasicWidgetFactory::LocalFileType f;
01001   f.scheme = QLatin1String("klf+legacy");
01002   f.filepattern = QLatin1String("*.klf");
01003   f.filter = QString("%1 (%2)").arg(schemeTitle(f.scheme), f.filepattern);
01004   KLFLibBasicWidgetFactory::addLocalFileType(f);
01005   new KLFLibLegacyLocalFileSchemeGuesser(this);
01006 }
01007 
01008 QStringList KLFLibLegacyEngineFactory::supportedTypes() const
01009 {
01010   return QStringList() << QLatin1String("klf+legacy");
01011 }
01012 
01013 QString KLFLibLegacyEngineFactory::schemeTitle(const QString& scheme) const
01014 {
01015   if (scheme == QLatin1String("klf+legacy"))
01016     return tr("KLatexFormula Library Export File");
01017   return QString();
01018 }
01019 
01020 
01021 uint KLFLibLegacyEngineFactory::schemeFunctions(const QString& scheme) const
01022 {
01023   if (scheme == QLatin1String("klf+legacy"))
01024     return FuncOpen|FuncCreate;
01025   return 0;
01026 }
01027 
01028 QString KLFLibLegacyEngineFactory::correspondingWidgetType(const QString& scheme) const
01029 {
01030   if (scheme == QLatin1String("klf+legacy"))
01031     return QLatin1String("LocalFile");
01032   return 0;
01033 }
01034 
01035 
01036 KLFLibResourceEngine *KLFLibLegacyEngineFactory::openResource(const QUrl& location, QObject *parent)
01037 {
01038   return KLFLibLegacyEngine::openUrl(location, parent);
01039 }
01040 
01041 KLFLibResourceEngine *KLFLibLegacyEngineFactory::createResource(const QString& scheme,
01042                                                                 const Parameters& parameters,
01043                                                                 QObject *parent)
01044 {
01045   QString defsubres = parameters["klfDefaultSubResource"].toString();
01046   if (defsubres.isEmpty())
01047     defsubres = QLatin1String("Table1");
01048 
01049   if (scheme == QLatin1String("klf+legacy")) {
01050     if ( !parameters.contains("Filename") ) {
01051       qWarning()
01052         <<"KLFLibLegacyEngineFactory::createResource: bad parameters. They do not contain `Filename': "
01053         <<parameters;
01054       return NULL;
01055     }
01056     return KLFLibLegacyEngine::createDotKLF(parameters["Filename"].toString(),
01057                                             defsubres, parent);
01058   }
01059   qWarning()<<"KLFLibLegacyEngineFactory::createResource("<<scheme<<","<<parameters<<","<<parent<<"):"
01060             <<"Bad scheme!";
01061   return NULL;
01062 }
01063 
01064 
01065 

Generated by doxygen 1.7.3