1 /***************************************************************************
2  *   file klflib.cpp
3  *   This file is part of the KLatexFormula Project.
4  *   Copyright (C) 2011 by Philippe Faist
5  *   philippe.faist at bluewin.ch
6  *                                                                         *
7  *   This program is free software; you can redistribute it and/or modify  *
8  *   it under the terms of the GNU General Public License as published by  *
9  *   the Free Software Foundation; either version 2 of the License, or     *
10  *   (at your option) any later version.                                   *
11  *                                                                         *
12  *   This program is distributed in the hope that it will be useful,       *
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
15  *   GNU General Public License for more details.                          *
16  *                                                                         *
17  *   You should have received a copy of the GNU General Public License     *
18  *   along with this program; if not, write to the                         *
19  *   Free Software Foundation, Inc.,                                       *
20  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
21  ***************************************************************************/
22 /* $Id: klflib.cpp 953 2016-12-27 00:13:10Z phfaist $ */
23 
24 #include <QDebug>
25 #include <QString>
26 #include <QUrl>
27 #include <QUrlQuery>
28 #include <QBuffer>
29 #include <QByteArray>
30 #include <QDataStream>
31 #include <QColor>
32 #include <QMimeData>
33 
34 #include <klfutil.h>
35 #include "klflib_p.h"
36 #include "klflib.h"
37 
38 
39 
40 
41 // issue a warning if no default sub-resource is set
42 #define KLFLIBRESOURCEENGINE_WARN_NO_DEFAULT_SUBRESOURCE(func)		\
43   if ((pFeatureFlags & FeatureSubResources) && pDefaultSubResource.isNull()) { \
44     qWarning("KLFLibResourceEngine::" func "(id): sub-resources are supported feature but" \
45 	     " no default sub-resource is specified!"); }		\
46 
47 
48 
49 // ----------------------
50 
51 
KLFLibEntry(const QString & latex,const QDateTime & dt,const QImage & preview,const QSize & previewsize,const QString & category,const QString & tags,const KLFStyle & style)52 KLFLibEntry::KLFLibEntry(const QString& latex, const QDateTime& dt, const QImage& preview,
53 			 const QSize& previewsize, const QString& category, const QString& tags,
54 			 const KLFStyle& style)
55   : KLFPropertizedObject("KLFLibEntry")
56 {
57   initRegisteredProperties();
58   setLatex(latex);
59   setDateTime(dt);
60   setPreview(preview);
61   setPreviewSize(previewsize);
62   setCategory(category);
63   setTags(tags);
64   setStyle(style);
65 }
KLFLibEntry(const QString & latex,const QDateTime & dt,const QImage & preview,const KLFStyle & style)66 KLFLibEntry::KLFLibEntry(const QString& latex, const QDateTime& dt, const QImage& preview,
67 			 const KLFStyle& style)
68   : KLFPropertizedObject("KLFLibEntry")
69 {
70   initRegisteredProperties();
71   QString latexonly = stripCategoryTagsFromLatex(latex);
72   QString category = categoryFromLatex(latex);
73   QString tags = tagsFromLatex(latex);
74   QSize previewsize = preview.size();
75   setLatex(latexonly);
76   setDateTime(dt);
77   setPreview(preview);
78   setPreviewSize(previewsize);
79   setCategory(category);
80   setTags(tags);
81   setStyle(style);
82 }
KLFLibEntry(const KLFLibEntry & copy)83 KLFLibEntry::KLFLibEntry(const KLFLibEntry& copy)
84   : KLFPropertizedObject("KLFLibEntry")
85 {
86   initRegisteredProperties();
87   setAllProperties(copy.allProperties());
88 }
~KLFLibEntry()89 KLFLibEntry::~KLFLibEntry()
90 {
91 }
92 
93 
setEntryProperty(const QString & propName,const QVariant & value)94 int KLFLibEntry::setEntryProperty(const QString& propName, const QVariant& value)
95 {
96   //   int propId = propertyIdForName(propName);
97   //   if (propId < 0) {
98   //     // register the property
99   //     propId = registerProperty(propName);
100   //     if (propId < 0)
101   //       return -1;
102   //   }
103   //   // and set the property
104   //   setProperty(propId, value);
105   //   return propId;
106   // call KLFPropertizedObject's setProperty() to do the job for us
107   bool ok = setProperty(propName, value);
108   if (!ok)
109     return -1;
110   return propertyIdForName(propName);
111 }
112 
113 // private, static
initRegisteredProperties()114 void KLFLibEntry::initRegisteredProperties()
115 {
116   KLF_FUNC_SINGLE_RUN ;
117 
118   registerBuiltInProperty(Latex, "Latex");
119   registerBuiltInProperty(DateTime, "DateTime");
120   registerBuiltInProperty(Preview, "Preview");
121   registerBuiltInProperty(PreviewSize, "PreviewSize");
122   registerBuiltInProperty(Category, "Category");
123   registerBuiltInProperty(Tags, "Tags");
124   registerBuiltInProperty(Style, "Style");
125 }
126 
127 
128 // static
categoryFromLatex(const QString & latex)129 QString KLFLibEntry::categoryFromLatex(const QString& latex)
130 {
131   QString s = latex.section('\n', 0, 0, QString::SectionSkipEmpty);
132   if (s[0] == '%' && s[1] == ':') {
133     return s.mid(2).trimmed();
134   }
135   return QString::null;
136 }
137 // static
tagsFromLatex(const QString & latex)138 QString KLFLibEntry::tagsFromLatex(const QString& latex)
139 {
140   QString s = latex.section('\n', 0, 0, QString::SectionSkipEmpty);
141   if (s[0] == '%' && s[1] == ':') {
142     // category is s.mid(2);
143     s = latex.section('\n', 1, 1, QString::SectionSkipEmpty);
144   }
145   if (s[0] == '%') {
146     return s.mid(1).trimmed();
147   }
148   return QString::null;
149 }
150 
151 // static
stripCategoryTagsFromLatex(const QString & latex)152 QString KLFLibEntry::stripCategoryTagsFromLatex(const QString& latex)
153 {
154   int k = 0;
155   while (k < latex.length() && latex[k].isSpace())
156     ++k;
157   if (k == latex.length()) return "";
158   if (latex[k] == '%') {
159     ++k;
160     if (k == latex.length()) return "";
161     //strip category and/or tag:
162     if (latex[k] == ':') {
163       // strip category
164       while (k < latex.length() && latex[k] != '\n')
165 	++k;
166       ++k;
167       if (k >= latex.length()) return "";
168       if (latex[k] != '%') {
169 	// there isn't any tags, just category; return rest of string
170 	return latex.mid(k);
171       }
172       ++k;
173       if (k >= latex.length()) return "";
174     }
175     // strip tag:
176     while (k < latex.length() && latex[k] != '\n')
177       ++k;
178     ++k;
179     if (k >= latex.length()) return "";
180   }
181   // k is the beginnnig of the latex string
182   return latex.mid(k);
183 }
184 
185 // static
latexAddCategoryTagsComment(const QString & latex,const QString & category,const QString & tags)186 QString KLFLibEntry::latexAddCategoryTagsComment(const QString& latex, const QString& category,
187 						 const QString& tags)
188 {
189   QString s;
190 
191   if (!category.isEmpty())
192     s = "%: "+category+"\n";
193 
194   if (!tags.isEmpty())
195     s += "% "+tags+"\n";
196 
197   s += latex;
198   return s;
199 }
200 
201 // static
normalizeCategoryPath(const QString & categoryPath)202 QString KLFLibEntry::normalizeCategoryPath(const QString& categoryPath)
203 {
204   QString c = categoryPath.trimmed().split('/', QString::SkipEmptyParts).join("/");
205   if (c.endsWith("/"))
206     c.chop(1);
207   return c;
208 }
209 
210 
211 
212 // ------------------------------------------------------------
213 
214 
215 
KLFLibEntrySorter(int propId,Qt::SortOrder order)216 KLFLibEntrySorter::KLFLibEntrySorter(int propId, Qt::SortOrder order)
217   : pCloneOf(NULL), pPropId(propId), pOrder(order)
218 {
219 }
KLFLibEntrySorter(const KLFLibEntrySorter * clone)220 KLFLibEntrySorter::KLFLibEntrySorter(const KLFLibEntrySorter *clone)
221   : pCloneOf(clone), pPropId(clone->pPropId), pOrder(clone->pOrder)
222 {
223 }
224 
~KLFLibEntrySorter()225 KLFLibEntrySorter::~KLFLibEntrySorter()
226 {
227 }
228 
setPropId(int propId)229 void KLFLibEntrySorter::setPropId(int propId)
230 {
231   if (pCloneOf != NULL) {
232     qWarning()<<"Attempt to setPropId() in entry sorter that is a clone of "<<pCloneOf;
233     return;
234   }
235   pPropId = propId;
236 }
setOrder(Qt::SortOrder order)237 void KLFLibEntrySorter::setOrder(Qt::SortOrder order)
238 {
239   if (pCloneOf != NULL) {
240     qWarning()<<"Attempt to setOrder() in entry sorter that is a clone of "<<pCloneOf;
241     return;
242   }
243   pOrder = order;
244 }
245 
246 
247 
entryValue(const KLFLibEntry & entry,int propId) const248 QString KLFLibEntrySorter::entryValue(const KLFLibEntry& entry, int propId) const
249 {
250   if (pCloneOf != NULL)
251     return pCloneOf->entryValue(entry, propId);
252 
253   // return an internal string representation of the value of the property 'propId' in libentry 'entry'
254 
255   // user friendliness. sort by date when selecting preview.
256   if (propId == KLFLibEntry::Preview)
257     propId = KLFLibEntry::DateTime;
258 
259   if (propId == KLFLibEntry::PreviewSize) {
260     QSize s = entry.previewSize();
261     // eg. "0000000280,0000000180" for 280x180
262     return QString("%1,%2").arg(s.width(), 10, 10, QChar('0')).arg(s.height(), 10, 10, QChar('0'));
263   }
264   if (propId == KLFLibEntry::DateTime) {
265     return entry.property(KLFLibEntry::DateTime).toDateTime().toString("yyyy-MM-dd+hh:mm:ss.zzz");
266   }
267   return entry.property(propId).toString();
268 }
269 
compareLessThan(const KLFLibEntry & a,const KLFLibEntry & b,int propId,Qt::SortOrder order) const270 bool KLFLibEntrySorter::compareLessThan(const KLFLibEntry& a, const KLFLibEntry& b,
271 					int propId, Qt::SortOrder order) const
272 {
273   if (pCloneOf != NULL)
274     return pCloneOf->compareLessThan(a, b, propId, order);
275 
276   QString as = entryValue(a, propId);
277   QString bs = entryValue(b, propId);
278   if (order == Qt::AscendingOrder)
279     return QString::localeAwareCompare(as, bs) < 0;
280   return QString::localeAwareCompare(as, bs) > 0;
281 }
282 
operator ()(const KLFLibEntry & a,const KLFLibEntry & b) const283 bool KLFLibEntrySorter::operator()(const KLFLibEntry& a, const KLFLibEntry& b) const
284 {
285   if (pCloneOf != NULL)
286     return pCloneOf->operator()(a, b);
287 
288   return compareLessThan(a, b, pPropId, pOrder);
289 }
290 
291 
292 // ---------------------------------------------------
293 
KLFAbstractLibEntryMimeEncoder()294 KLFAbstractLibEntryMimeEncoder::KLFAbstractLibEntryMimeEncoder()
295 {
296   registerEncoder(this);
297 }
~KLFAbstractLibEntryMimeEncoder()298 KLFAbstractLibEntryMimeEncoder::~KLFAbstractLibEntryMimeEncoder()
299 {
300 }
registerEncoder(KLFAbstractLibEntryMimeEncoder * encoder)301 void KLFAbstractLibEntryMimeEncoder::registerEncoder(KLFAbstractLibEntryMimeEncoder *encoder)
302 {
303   staticEncoderList.append(encoder);
304 }
305 
encoderList()306 QList<KLFAbstractLibEntryMimeEncoder*> KLFAbstractLibEntryMimeEncoder::encoderList()
307 {
308   return staticEncoderList;
309 }
310 
311 // static
allEncodingMimeTypes()312 QStringList KLFAbstractLibEntryMimeEncoder::allEncodingMimeTypes()
313 {
314   QStringList encTypes;
315   int k;
316   for (k = 0; k < staticEncoderList.size(); ++k) {
317     encTypes << staticEncoderList[k]->supportedEncodingMimeTypes();
318   }
319   return encTypes;
320 }
321 // static
allDecodingMimeTypes()322 QStringList KLFAbstractLibEntryMimeEncoder::allDecodingMimeTypes()
323 {
324   QStringList decTypes;
325   int k;
326   for (k = 0; k < staticEncoderList.size(); ++k) {
327     decTypes << staticEncoderList[k]->supportedDecodingMimeTypes();
328   }
329   return decTypes;
330 }
331 
332 // static
createMimeData(const KLFLibEntryList & entryList,const QVariantMap & metaData)333 QMimeData *KLFAbstractLibEntryMimeEncoder::createMimeData(const KLFLibEntryList& entryList,
334 							  const QVariantMap& metaData)
335 {
336   QMimeData *mime = new QMimeData;
337   int k, j;
338   for (k = 0; k < staticEncoderList.size(); ++k) {
339     QStringList mimeTypeList = staticEncoderList[k]->supportedEncodingMimeTypes();
340     for (j = 0; j < mimeTypeList.size(); ++j) {
341       QByteArray data =
342 	staticEncoderList[k]->encodeMime(entryList, metaData, mimeTypeList[j]);
343       if (data.isEmpty()) {
344 	klfDbg("Skipping mime type "<<mimeTypeList[k]<<" because it did not provide any data.");
345       } else {
346 	mime->setData(mimeTypeList[j], data);
347       }
348     }
349   }
350   return mime;
351 }
352 
353 
354 // static
canDecodeMimeData(const QMimeData * mimeData)355 bool KLFAbstractLibEntryMimeEncoder::canDecodeMimeData(const QMimeData *mimeData)
356 {
357   QStringList fmts = mimeData->formats();
358   int k;
359   for (k = 0; k < fmts.size(); ++k) {
360     if (findDecoderFor(fmts[k], false) != NULL)
361       return true;
362   }
363   return false;
364 }
365 
366 // static
decodeMimeData(const QMimeData * mimeData,KLFLibEntryList * entryListPtr,QVariantMap * metaDataPtr)367 bool KLFAbstractLibEntryMimeEncoder::decodeMimeData(const QMimeData *mimeData,
368 						    KLFLibEntryList *entryListPtr,
369 						    QVariantMap *metaDataPtr)
370 {
371   QStringList fmts = mimeData->formats();
372   int k;
373   for (k = 0; k < fmts.size(); ++k) {
374     KLFAbstractLibEntryMimeEncoder *decoder = findDecoderFor(fmts[k], false);
375     if (decoder == NULL)
376       continue;
377     bool result = decoder->decodeMime(mimeData->data(fmts[k]), fmts[k], entryListPtr, metaDataPtr);
378     if ( result )
379       return true;
380     // else continue trying
381   }
382   return false;
383 }
384 
385 
386 
findEncoderFor(const QString & mimeType,bool warn)387 KLFAbstractLibEntryMimeEncoder *KLFAbstractLibEntryMimeEncoder::findEncoderFor(const QString& mimeType,
388 									       bool warn)
389 {
390   int k;
391   for (k = 0; k < staticEncoderList.size(); ++k)
392     if (staticEncoderList[k]->supportedEncodingMimeTypes().contains(mimeType))
393       return staticEncoderList[k];
394   if (warn)
395     qWarning()<<KLF_FUNC_NAME<<": Failed to find encoder for mime-type "<<mimeType;
396   return NULL;
397 }
398 
findDecoderFor(const QString & mimeType,bool warn)399 KLFAbstractLibEntryMimeEncoder *KLFAbstractLibEntryMimeEncoder::findDecoderFor(const QString& mimeType,
400 									       bool warn)
401 {
402   int k;
403   for (k = 0; k < staticEncoderList.size(); ++k)
404     if (staticEncoderList[k]->supportedDecodingMimeTypes().contains(mimeType))
405       return staticEncoderList[k];
406   if (warn)
407     qWarning()<<KLF_FUNC_NAME<<": Failed to find decoder for mime-type "<<mimeType;
408   return NULL;
409 }
410 
411 
412 QList<KLFAbstractLibEntryMimeEncoder*> KLFAbstractLibEntryMimeEncoder::staticEncoderList;
413 
414 
415 
416 
417 // The instance of the basic encoder, that will auto-register itself
418 KLFLibEntryMimeEncoder __klf_lib_mime_encoder;
419 
420 
421 // ---------------------------------------------------
422 
KLFLibResourceEngine(const QUrl & url,uint featureflags,QObject * parent)423 KLFLibResourceEngine::KLFLibResourceEngine(const QUrl& url, uint featureflags,
424 					   QObject *parent)
425   : QObject(parent), KLFPropertizedObject("KLFLibResourceEngine"), pUrl(url),
426     pFeatureFlags(featureflags), pReadOnly(false), pDefaultSubResource(QString()),
427     pProgressBlocked(false), pThisOperationProgressBlockedOnly(false)
428 {
429   initRegisteredProperties();
430 
431   //  klfDbg( "KLFLibResourceEngine::KLFLibResourceEngine("<<url<<","<<pFeatureFlags<<","
432   //	  <<parent<<")" ) ;
433 
434   QUrlQuery urlq(pUrl);
435 
436   QStringList rdonly = urlq.allQueryItemValues("klfReadOnly");
437   if (rdonly.size() && rdonly.last() == "true") {
438     if (pFeatureFlags & FeatureReadOnly)
439       pReadOnly = true;
440   }
441   urlq.removeAllQueryItems("klfReadOnly");
442   pUrl.setQuery(urlq);
443 
444   if (pFeatureFlags & FeatureSubResources) {
445     QStringList defaultsubresource = urlq.allQueryItemValues("klfDefaultSubResource");
446     if (!defaultsubresource.isEmpty()) {
447       urlq.removeAllQueryItems("klfDefaultSubResource");
448       pUrl.setQuery(urlq);
449       pDefaultSubResource = defaultsubresource.last();
450     }
451   }
452 
453 }
~KLFLibResourceEngine()454 KLFLibResourceEngine::~KLFLibResourceEngine()
455 {
456 }
457 
initRegisteredProperties()458 void KLFLibResourceEngine::initRegisteredProperties()
459 {
460   KLF_FUNC_SINGLE_RUN
461 
462   registerBuiltInProperty(PropTitle, "Title");
463   registerBuiltInProperty(PropLocked, "Locked");
464   registerBuiltInProperty(PropViewType, "ViewType");
465   registerBuiltInProperty(PropAccessShared, "AccessShared");
466 }
467 
url(uint flags) const468 QUrl KLFLibResourceEngine::url(uint flags) const
469 {
470   QUrlQuery urlq(pUrl);
471   if (flags & WantUrlDefaultSubResource &&
472       (pFeatureFlags & FeatureSubResources) &&
473       !pDefaultSubResource.isNull()) {
474     urlq.addQueryItem("klfDefaultSubResource", pDefaultSubResource);
475   }
476   if (flags & WantUrlReadOnly) {
477     urlq.addQueryItem("klfReadOnly", pReadOnly?QString("true"):QString("false"));
478   }
479   QUrl url = pUrl;
480   url.setQuery(urlq);
481   return url;
482 }
483 
484 
canModifyData(const QString & subResource,ModifyType) const485 bool KLFLibResourceEngine::canModifyData(const QString& subResource,
486 					 ModifyType /*modifytype*/) const
487 {
488   return baseCanModifyStatus(true, subResource) == MS_CanModify;
489 }
490 
canModifyData(ModifyType modifytype) const491 bool KLFLibResourceEngine::canModifyData(ModifyType modifytype) const
492 {
493   KLFLIBRESOURCEENGINE_WARN_NO_DEFAULT_SUBRESOURCE("canModifyData")
494   return canModifyData(pDefaultSubResource, modifytype);
495 }
496 
497 
canModifyProp(int propId) const498 bool KLFLibResourceEngine::canModifyProp(int propId) const
499 {
500   ModifyStatus ms = baseCanModifyStatus(false);
501   return ms == MS_CanModify ||
502     (ms == MS_IsLocked && propId == PropLocked); // allow un-locking (!)
503 }
canRegisterProperty(const QString &) const504 bool KLFLibResourceEngine::canRegisterProperty(const QString& /*propName*/) const
505 {
506   return false;
507 }
508 
hasSubResource(const QString & subResource) const509 bool KLFLibResourceEngine::hasSubResource(const QString& subResource) const
510 {
511   if ( !(pFeatureFlags & FeatureSubResources) )
512     return false;
513 
514   return subResourceList().contains(subResource);
515 }
516 
defaultSubResource() const517 QString KLFLibResourceEngine::defaultSubResource() const
518 {
519   return pDefaultSubResource;
520 }
521 
compareDefaultSubResourceEquals(const QString & subResourceName) const522 bool KLFLibResourceEngine::compareDefaultSubResourceEquals(const QString& subResourceName) const
523 {
524   return QString::compare(pDefaultSubResource, subResourceName) == 0;
525 }
526 
canCreateSubResource() const527 bool KLFLibResourceEngine::canCreateSubResource() const
528 {
529   return false;
530 }
531 
canRenameSubResource(const QString &) const532 bool KLFLibResourceEngine::canRenameSubResource(const QString& /*subResource*/) const
533 {
534   return false;
535 }
canDeleteSubResource(const QString &) const536 bool KLFLibResourceEngine::canDeleteSubResource(const QString& /*subResource*/) const
537 {
538   return false;
539 }
540 
subResourceProperty(const QString &,int) const541 QVariant KLFLibResourceEngine::subResourceProperty(const QString& /*subResource*/, int /*propId*/) const
542 {
543   return QVariant();
544 }
545 
subResourcePropertyName(int propId) const546 QString KLFLibResourceEngine::subResourcePropertyName(int propId) const
547 {
548   switch (propId) {
549   case SubResPropTitle:
550     return QLatin1String("Title");
551   case SubResPropLocked:
552     return QLatin1String("Locked");
553   case SubResPropViewType:
554     return QLatin1String("ViewType");
555   default:
556     ;
557   }
558   return QString::number(propId);
559 }
560 
canModifySubResourceProperty(const QString & subResource,int propId) const561 bool KLFLibResourceEngine::canModifySubResourceProperty(const QString& subResource, int propId) const
562 {
563   ModifyStatus ms = baseCanModifyStatus(true, subResource);
564   return ms == MS_CanModify ||
565     (ms == MS_SubResLocked && propId == SubResPropLocked); // allow sub-resource un-locking
566 }
567 
setTitle(const QString & title)568 bool KLFLibResourceEngine::setTitle(const QString& title)
569 {
570   return setResourceProperty(PropTitle, title);
571 }
setLocked(bool setlocked)572 bool KLFLibResourceEngine::setLocked(bool setlocked)
573 {
574   // if locked feature is supported, setResourceProperty().
575   // immediately return FALSE otherwise.
576   if (pFeatureFlags & FeatureLocked) {
577     return setResourceProperty(PropLocked, setlocked);
578   }
579   return false;
580 }
581 
setViewType(const QString & viewType)582 bool KLFLibResourceEngine::setViewType(const QString& viewType)
583 {
584   return setResourceProperty(PropViewType, viewType);
585 }
586 
setReadOnly(bool readonly)587 bool KLFLibResourceEngine::setReadOnly(bool readonly)
588 {
589   if ( !(pFeatureFlags & FeatureReadOnly) )
590     return false;
591 
592   pReadOnly = readonly;
593   return true;
594 }
595 
596 
setDefaultSubResource(const QString & subResource)597 void KLFLibResourceEngine::setDefaultSubResource(const QString& subResource)
598 {
599   if (pDefaultSubResource == subResource)
600     return;
601 
602   pDefaultSubResource = subResource;
603   emit defaultSubResourceChanged(subResource);
604 }
605 
setSubResourceProperty(const QString &,int,const QVariant &)606 bool KLFLibResourceEngine::setSubResourceProperty(const QString& /*subResource*/, int /*propId*/,
607 						  const QVariant& /*value*/)
608 {
609   return false;
610 }
611 
createSubResource(const QString &,const QString &)612 bool KLFLibResourceEngine::createSubResource(const QString& /*subResource*/,
613 					     const QString& /*subResourceTitle*/)
614 {
615   return false;
616 }
createSubResource(const QString & subResource)617 bool KLFLibResourceEngine::createSubResource(const QString& subResource)
618 {
619   return createSubResource(subResource, QString());
620 }
renameSubResource(const QString &,const QString &)621 bool KLFLibResourceEngine::renameSubResource(const QString& /*old*/, const QString& /*new*/)
622 {
623   return false;
624 }
deleteSubResource(const QString &)625 bool KLFLibResourceEngine::deleteSubResource(const QString& /*subResource*/)
626 {
627   return false;
628 }
629 
630 
entry(entryId id)631 KLFLibEntry KLFLibResourceEngine::entry(entryId id)
632 {
633   KLFLIBRESOURCEENGINE_WARN_NO_DEFAULT_SUBRESOURCE("entry");
634   return entry(pDefaultSubResource, id);
635 }
hasEntry(entryId id)636 bool KLFLibResourceEngine::hasEntry(entryId id)
637 {
638   KLFLIBRESOURCEENGINE_WARN_NO_DEFAULT_SUBRESOURCE("hasEntry");
639   return hasEntry(pDefaultSubResource, id);
640 }
641 QList<KLFLibResourceEngine::KLFLibEntryWithId>
entries(const QList<KLFLib::entryId> & idList,const QList<int> & wantedEntryProperties)642 /* */ KLFLibResourceEngine::entries(const QList<KLFLib::entryId>& idList,
643 				    const QList<int>& wantedEntryProperties)
644 {
645   KLFLIBRESOURCEENGINE_WARN_NO_DEFAULT_SUBRESOURCE("entries");
646   return entries(pDefaultSubResource, idList, wantedEntryProperties);
647 }
648 
649 QList<KLFLibResourceEngine::KLFLibEntryWithId>
allEntries(const QList<int> & wantedEntryProperties)650 /* */ KLFLibResourceEngine::allEntries(const QList<int>& wantedEntryProperties)
651 {
652   KLFLIBRESOURCEENGINE_WARN_NO_DEFAULT_SUBRESOURCE("allEntries");
653   return allEntries(pDefaultSubResource, wantedEntryProperties);
654 }
allIds()655 QList<KLFLib::entryId> KLFLibResourceEngine::allIds()
656 {
657   KLFLIBRESOURCEENGINE_WARN_NO_DEFAULT_SUBRESOURCE("allIds");
658   return allIds(pDefaultSubResource);
659 }
660 
blockProgressReportingForNextOperation()661 void KLFLibResourceEngine::blockProgressReportingForNextOperation()
662 {
663   pProgressBlocked = true;
664   pThisOperationProgressBlockedOnly = true;
665 }
666 
blockProgressReporting(bool block)667 void KLFLibResourceEngine::blockProgressReporting(bool block)
668 {
669   pProgressBlocked = block;
670   pThisOperationProgressBlockedOnly = false;
671 }
672 
thisOperationProgressBlocked() const673 bool KLFLibResourceEngine::thisOperationProgressBlocked() const
674 {
675   bool blocked = pProgressBlocked;
676   if (pThisOperationProgressBlockedOnly)
677     pProgressBlocked = false; // reset for next operation
678   return blocked;
679 }
680 
681 
insertEntry(const QString & subResource,const KLFLibEntry & entry)682 KLFLibResourceEngine::entryId KLFLibResourceEngine::insertEntry(const QString& subResource,
683 								const KLFLibEntry& entry)
684 {
685   QList<entryId> ids = insertEntries(subResource, KLFLibEntryList() << entry);
686   if (ids.size() == 0)
687     return -1;
688 
689   return ids[0];
690 }
insertEntry(const KLFLibEntry & entry)691 KLFLibResourceEngine::entryId KLFLibResourceEngine::insertEntry(const KLFLibEntry& entry)
692 {
693   KLFLIBRESOURCEENGINE_WARN_NO_DEFAULT_SUBRESOURCE("insertEntry");
694   return insertEntry(pDefaultSubResource, entry);
695 }
insertEntries(const KLFLibEntryList & entrylist)696 QList<KLFLibResourceEngine::entryId> KLFLibResourceEngine::insertEntries(const KLFLibEntryList& entrylist)
697 {
698   KLFLIBRESOURCEENGINE_WARN_NO_DEFAULT_SUBRESOURCE("insertEntries");
699   return insertEntries(pDefaultSubResource, entrylist);
700 }
701 
changeEntries(const QList<entryId> & idlist,const QList<int> & properties,const QList<QVariant> & values)702 bool KLFLibResourceEngine::changeEntries(const QList<entryId>& idlist, const QList<int>& properties,
703 					 const QList<QVariant>& values)
704 {
705   KLFLIBRESOURCEENGINE_WARN_NO_DEFAULT_SUBRESOURCE("changeEntries");
706   return changeEntries(pDefaultSubResource, idlist, properties, values);
707 }
708 
deleteEntries(const QList<entryId> & idList)709 bool KLFLibResourceEngine::deleteEntries(const QList<entryId>& idList)
710 {
711   KLFLIBRESOURCEENGINE_WARN_NO_DEFAULT_SUBRESOURCE("deleteEntries");
712   return deleteEntries(pDefaultSubResource, idList);
713 }
714 
715 
716 
saveTo(const QUrl &)717 bool KLFLibResourceEngine::saveTo(const QUrl&)
718 {
719   // not implemented by default. Subclasses must reimplement
720   // to support this feature.
721   return false;
722 }
723 
resourceProperty(const QString & name) const724 QVariant KLFLibResourceEngine::resourceProperty(const QString& name) const
725 {
726   return KLFPropertizedObject::property(name);
727 }
728 
loadResourceProperty(const QString & propName,const QVariant & value)729 bool KLFLibResourceEngine::loadResourceProperty(const QString& propName, const QVariant& value)
730 {
731   int propId = propertyIdForName(propName);
732   if (propId < 0) {
733     if (!canRegisterProperty(propName))
734       return false;
735     // register the property
736     propId = registerProperty(propName);
737     if (propId < 0)
738       return false;
739   }
740   // finally set the property
741   return setResourceProperty(propId, value);
742 }
743 
setResourceProperty(int propId,const QVariant & value)744 bool KLFLibResourceEngine::setResourceProperty(int propId, const QVariant& value)
745 {
746   if ( ! KLFPropertizedObject::propertyIdRegistered(propId) )
747     return false;
748 
749   if ( !canModifyProp(propId) ) {
750     return false;
751   }
752 
753   bool result = saveResourceProperty(propId, value);
754   if (!result) // operation not permitted or failed
755     return false;
756 
757   // operation succeeded: set KLFPropertizedObject-based property.
758   KLFPropertizedObject::doSetProperty(propId, value);
759   emit resourcePropertyChanged(propId);
760   return true;
761 }
762 
763 
764 KLFLibResourceEngine::ModifyStatus
baseCanModifyStatus(bool inSubResource,const QString & subResource) const765 /* */ KLFLibResourceEngine::baseCanModifyStatus(bool inSubResource, const QString& subResource) const
766 {
767   if (pFeatureFlags & FeatureLocked) {
768     if (locked())
769       return MS_IsLocked;
770     if (inSubResource &&
771 	(pFeatureFlags & FeatureSubResources) &&
772 	(pFeatureFlags & FeatureSubResourceProps)) {
773       if (subResourceProperty(subResource, SubResPropLocked).toBool())
774 	return MS_SubResLocked;
775     }
776   }
777 
778   if (pFeatureFlags & FeatureReadOnly) {
779     if (isReadOnly())
780       return MS_NotModifiable;
781   }
782 
783   return MS_CanModify;
784 }
785 
786 
787 
788 // static
mkMatchAll()789 KLFLib::EntryMatchCondition KLFLib::EntryMatchCondition::mkMatchAll()
790 {
791   return EntryMatchCondition(MatchAllType);
792 }
793 // static
mkPropertyMatch(PropertyMatch pmatch)794 KLFLib::EntryMatchCondition KLFLib::EntryMatchCondition::mkPropertyMatch(PropertyMatch pmatch)
795 {
796   EntryMatchCondition c(PropertyMatchType);
797   c.mPropertyMatch = pmatch;
798   return c;
799 }
800 // static
mkNegateMatch(const EntryMatchCondition & condition)801 KLFLib::EntryMatchCondition KLFLib::EntryMatchCondition::mkNegateMatch(const EntryMatchCondition& condition)
802 {
803   EntryMatchCondition c(NegateMatchType);
804   c.mConditionList = QList<EntryMatchCondition>() << condition;
805   return c;
806 }
807 // static
mkOrMatch(QList<EntryMatchCondition> conditions)808 KLFLib::EntryMatchCondition KLFLib::EntryMatchCondition::mkOrMatch(QList<EntryMatchCondition> conditions)
809 {
810   EntryMatchCondition c(OrMatchType);
811   c.mConditionList = conditions;
812   return c;
813 }
814 // static
mkAndMatch(QList<EntryMatchCondition> conditions)815 KLFLib::EntryMatchCondition KLFLib::EntryMatchCondition::mkAndMatch(QList<EntryMatchCondition> conditions)
816 {
817   EntryMatchCondition c(AndMatchType);
818   c.mConditionList = conditions;
819   return c;
820 }
821 
822 
823 
824 
825 
826 
827 // -----
828 
829 // DATA STREAM OPERATORS
operator <<(QDataStream & stream,const KLFLibResourceEngine::KLFLibEntryWithId & entrywid)830 KLF_EXPORT QDataStream& operator<<(QDataStream& stream, const KLFLibResourceEngine::KLFLibEntryWithId& entrywid)
831 {
832   return stream << entrywid.id << entrywid.entry;
833 }
operator >>(QDataStream & stream,KLFLibResourceEngine::KLFLibEntryWithId & entrywid)834 KLF_EXPORT QDataStream& operator>>(QDataStream& stream, KLFLibResourceEngine::KLFLibEntryWithId& entrywid)
835 {
836   return stream >> entrywid.id >> entrywid.entry;
837 }
838 
839 // DEBUG OPERATOR<<'S
operator <<(QDebug & dbg,const KLFLib::StringMatch & smatch)840 KLF_EXPORT  QDebug& operator<<(QDebug& dbg, const KLFLib::StringMatch& smatch)
841 {
842   return dbg << "StringMatch[ref="<<smatch.matchValueString()<<";flags="<<smatch.matchFlags()<<"]";
843 }
operator <<(QDebug & dbg,const KLFLib::PropertyMatch & pmatch)844 KLF_EXPORT  QDebug& operator<<(QDebug& dbg, const KLFLib::PropertyMatch& pmatch)
845 {
846   //  KLF_DEBUG_BLOCK("operator<<(QDebug, KLFLib::PropertyMatch)") ;
847   //  klfDbg("prop-id="<<pmatch.propertyId());
848   return dbg << "PropertyMatch[prop-id="<<pmatch.propertyId()<<"; ref="<<pmatch.matchValueString()
849 	     <<"; flags="<<pmatch.matchFlags()<<"]";
850 }
operator <<(QDebug & dbg,const KLFLib::EntryMatchCondition & c)851 KLF_EXPORT  QDebug& operator<<(QDebug& dbg, const KLFLib::EntryMatchCondition& c)
852 {
853   //  KLF_DEBUG_BLOCK("operator<<(QDebug, KLFLib::EntryMatchCondition)") ;
854   klfDbg("type="<<c.type()) ;
855 #ifdef KLF_WS_MAC
856   return dbg<<"EntryMatchCondition{...}";
857 #endif
858   dbg << "EntryMatchCondition{type=";
859   if (c.type() == KLFLib::EntryMatchCondition::MatchAllType) {
860     return dbg << "match-all}";
861   }
862   if (c.type() == KLFLib::EntryMatchCondition::PropertyMatchType) {
863     //    KLF_DEBUG_BLOCK("if-block...") ;
864     dbg << "property-match; "<<c.propertyMatch();
865     //    klfDbg("printed into dbg...") ;
866     dbg <<"}";
867     //    klfDbg("printed into dbg...") ;
868     return dbg;
869   }
870   if (c.type() != KLFLib::EntryMatchCondition::NegateMatchType &&
871       c.type() != KLFLib::EntryMatchCondition::AndMatchType &&
872       c.type() != KLFLib::EntryMatchCondition::OrMatchType) {
873     return dbg << "unknown-type}";
874   }
875   // NOT, AND or OR type:
876   static const char *w_and = " AND ";
877   static const char *w_or  = " OR ";
878   static const char *w_not = " NOT ";
879   const char * word =  (c.type()==KLFLib::EntryMatchCondition::NegateMatchType)? w_not :
880 			((c.type()==KLFLib::EntryMatchCondition::AndMatchType) ? w_and : w_or) ;
881   dbg << (word+1/*nospace*/) << "; list: ";
882   QList<KLFLib::EntryMatchCondition> conditions = c.conditionList();
883   int k;
884   for (k = 0; k < conditions.size(); ++k) {
885     if (k > 0)
886       dbg << word;
887     dbg << conditions[k];
888   }
889   dbg << ".}";
890   return dbg;
891 }
operator <<(QDebug & dbg,const KLFLibResourceEngine::KLFLibEntryWithId & e)892 KLF_EXPORT  QDebug& operator<<(QDebug& dbg, const KLFLibResourceEngine::KLFLibEntryWithId& e)
893 {
894   return dbg <<"KLFLibEntryWithId(id="<<e.id<<";"<<e.entry.category()<<","<<e.entry.tags()<<","
895 	     <<e.entry.latex()<<")";
896 }
operator <<(QDebug & dbg,const KLFLibResourceEngine::Query & q)897 KLF_EXPORT  QDebug& operator<<(QDebug& dbg, const KLFLibResourceEngine::Query& q)
898 {
899   //  KLF_DEBUG_BLOCK("operator<<(QDebug, KLFLibRes.Eng.::Query)") ;
900   return dbg << "Query(cond.="<<q.matchCondition<<"; skip="<<q.skip<<",limit="<<q.limit
901 	     <<"; orderpropid="<<q.orderPropId<<"/"<<(q.orderDirection==Qt::AscendingOrder ? "Asc":"Desc")
902 	     <<"; wanted props="<<q.wantedEntryProperties<<")" ;
903 }
904 
905 
906 
907 
908 // ---------------------------------------------------
909 
allIds(const QString & subResource)910 QList<KLFLib::entryId> KLFLibResourceSimpleEngine::allIds(const QString& subResource)
911 {
912   QList<KLFLib::entryId> idList;
913   QList<KLFLibResourceEngine::KLFLibEntryWithId> elist = allEntries(subResource);
914   int k;
915   for (k = 0; k < idList.size(); ++k)
916     idList << elist[k].id;
917   return idList;
918 }
919 
hasEntry(const QString & subResource,entryId id)920 bool KLFLibResourceSimpleEngine::hasEntry(const QString& subResource, entryId id)
921 {
922   /** \bug ............... BUG/TODO .......... concept problem here */
923   return entry(subResource, id).latex().size();
924 }
925 
926 QList<KLFLibResourceEngine::KLFLibEntryWithId>
entries(const QString & subResource,const QList<KLFLib::entryId> & idList,const QList<int> &)927 /* */ KLFLibResourceSimpleEngine::entries(const QString& subResource, const QList<KLFLib::entryId>& idList,
928 					  const QList<int>& /*wantedEntryProperties*/)
929 {
930   QList<KLFLibEntryWithId> elist;
931   int k;
932   for (k = 0; k < idList.size(); ++k)
933     elist << KLFLibEntryWithId(idList[k], entry(subResource, idList[k]));
934   return elist;
935 }
936 
937 
query(const QString & subResource,const Query & query,QueryResult * result)938 int KLFLibResourceSimpleEngine::query(const QString& subResource,
939 				      const Query& query,
940 				      QueryResult *result)
941 {
942   return queryImpl(this, subResource, query, result);
943 }
944 
queryValues(const QString & subResource,int entryPropId)945 QList<QVariant> KLFLibResourceSimpleEngine::queryValues(const QString& subResource, int entryPropId)
946 {
947   return queryValuesImpl(this, subResource, entryPropId);
948 }
949 
950 
951 template<class T>
qlist_skip_and_limit(QList<T> * list,int skip,int limit)952 static void qlist_skip_and_limit(QList<T> *list, int skip, int limit)
953 {
954   KLF_ASSERT_NOT_NULL( list, "list is NULL!", return; ) ;
955 
956   // skip `skip' first entries
957 
958   if (skip <= 0) {
959     // nothing to do
960   } else if (list->size() <= skip) {
961     list->clear();
962   } else {
963     *list = list->mid(skip);
964   }
965 
966   // and limit to `limit'
967   if (limit < 0)
968     return; // no limit
969 
970   if (list->size() > limit)
971     *list = list->mid(0, limit);
972 
973   return;
974 }
975 
976 // static
queryImpl(KLFLibResourceEngine * resource,const QString & subResource,const Query & query,QueryResult * result)977 int KLFLibResourceSimpleEngine::queryImpl(KLFLibResourceEngine *resource, const QString& subResource,
978 					  const Query& query, QueryResult *result)
979 {
980   /// \bug ............ some features UNTESTED (match conditions....) ......................
981 
982   KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
983   klfDbgSt("Query: "<<query);
984 
985   if (result == NULL) {
986     qWarning()<<KLF_FUNC_NAME<<": expected valid `result' pointer";
987     return -1;
988   }
989 
990   QList<KLFLibEntryWithId> allEList = resource->allEntries(subResource);
991 
992   KLFLibEntrySorter sorter(query.orderPropId, query.orderDirection);
993   QueryResultListSorter lsorter(&sorter, result);
994 
995   // we first need to order _all_ the entries (yes, since the order of allEntries()
996   // is undefined ... and limit/skip refer to _ordered_ entry list...)
997   int k;
998   for (k = 0; k < allEList.size(); ++k) {
999     // test match condition
1000     const KLFLibEntryWithId& ewid = allEList[k];
1001     if (testEntryMatchConditionImpl(query.matchCondition, ewid.entry)) {
1002       lsorter.insertIntoOrderedResult(ewid);
1003     }
1004   }
1005 
1006   klfDbgSt("queried ordered list. result->entryWithIdList: \n"<<result->entryWithIdList) ;
1007 
1008   // now we need to remove the first 'query.skip' number of results.
1009   // we can't do this while inserting because the order counts.
1010 
1011   qlist_skip_and_limit(&result->entryIdList, query.skip, query.limit);
1012   qlist_skip_and_limit(&result->rawEntryList, query.skip, query.limit);
1013   qlist_skip_and_limit(&result->entryWithIdList, query.skip, query.limit);
1014 
1015   klfDbgSt("About to return. Number of entries in TEE VALUE.") ;
1016 
1017   return KLF_DEBUG_TEE( lsorter.numberOfEntries() );
1018 }
1019 
1020 // static
queryValuesImpl(KLFLibResourceEngine * resource,const QString & subResource,int entryPropId)1021 QList<QVariant> KLFLibResourceSimpleEngine::queryValuesImpl(KLFLibResourceEngine *resource,
1022 							    const QString& subResource, int entryPropId)
1023 {
1024   QList<KLFLibEntryWithId> allEList = resource->allEntries(subResource);
1025   QList<QVariant> values;
1026   int k;
1027   for (k = 0; k < allEList.size(); ++k) {
1028     QVariant p = allEList[k].entry.property(entryPropId);
1029     if (!values.contains(p))
1030       values << p;
1031   }
1032   return values;
1033 }
1034 
1035 
1036 // static
testEntryMatchConditionImpl(const KLFLib::EntryMatchCondition & condition,const KLFLibEntry & libentry)1037 bool KLFLibResourceSimpleEngine::testEntryMatchConditionImpl(const KLFLib::EntryMatchCondition& condition,
1038 							     const KLFLibEntry& libentry)
1039 {
1040   int k;
1041   KLFLib::PropertyMatch pmatch;
1042   QList<KLFLib::EntryMatchCondition> condlist;
1043 
1044   switch (condition.type()) {
1045   case KLFLib::EntryMatchCondition::MatchAllType:
1046     return true;
1047   case KLFLib::EntryMatchCondition::PropertyMatchType:
1048     pmatch = condition.propertyMatch();
1049     return klfMatch(libentry.property(pmatch.propertyId()), // test value
1050 		    pmatch.matchValue(), // match value
1051 		    pmatch.matchFlags(), // flags
1052 		    pmatch.matchValueString()); // variant converted to string, cached
1053   case KLFLib::EntryMatchCondition::NegateMatchType:
1054     condlist = condition.conditionList(); // only first item is used
1055     if (condlist.isEmpty()) {
1056       qWarning()<<KLF_FUNC_NAME<<": NOT condition with no arguments!";
1057       return false;
1058     }
1059     return  ! testEntryMatchConditionImpl(condlist[0], libentry); // negate test
1060   case KLFLib::EntryMatchCondition::OrMatchType:
1061     condlist = condition.conditionList();
1062     if (condlist.isEmpty())
1063       return true;
1064     for (k = 0; k < condlist.size(); ++k) {
1065       if (testEntryMatchConditionImpl(condlist[k], libentry)) // recurse
1066 	return true; // 'OR' -> find one that's OK and the condition is OK
1067     }
1068     return false; // but if none is OK then we're not OK
1069   case KLFLib::EntryMatchCondition::AndMatchType:
1070     condlist = condition.conditionList();
1071     if (condlist.isEmpty())
1072       return true;
1073     for (k = 0; k < condlist.size(); ++k) {
1074       if ( ! testEntryMatchConditionImpl(condlist[k], libentry) ) // recurse
1075 	return false; // 'AND' -> find one that's not OK and the condition is globally false
1076     }
1077     return true; // but if all are OK then we're OK
1078   default:
1079     qWarning()<<KLF_FUNC_NAME<<": KLFLib::EntryMatchCondition type "<<condition.type()<<" not known!";
1080   }
1081   return false;
1082 }
1083 
1084 
QueryResultListSorter(KLFLibEntrySorter * sorter,QueryResult * result)1085 KLFLibResourceSimpleEngine::QueryResultListSorter::QueryResultListSorter(KLFLibEntrySorter *sorter,
1086 									 QueryResult *result)
1087   : mSorter(sorter), mResult(result)
1088 {
1089   KLF_ASSERT_NOT_NULL( result, "result ptr is NULL!", return ) ;
1090 
1091   fillflags = result->fillFlags;
1092 
1093   if (fillflags & QueryResult::FillRawEntryList) {
1094     reference_is_rawentrylist = true;
1095   } else if (fillflags & QueryResult::FillEntryWithIdList) {
1096     reference_is_rawentrylist = false;
1097   } else {
1098     // fill also the raw entry list to have a reference (!)
1099     fillflags |= QueryResult::FillRawEntryList;
1100     reference_is_rawentrylist = true;
1101   }
1102 }
numberOfEntries()1103 int KLFLibResourceSimpleEngine::QueryResultListSorter::numberOfEntries()
1104 {
1105   if (reference_is_rawentrylist)
1106     return mResult->rawEntryList.size();
1107   else
1108     return mResult->entryWithIdList.size();
1109 }
1110 
1111 
1112 /*
1113 KLFLibResourceSimpleEngine::QueryResultListSorter::QueryResultListSorter(const QueryResultListSorter& other)
1114   : mSorter(other.mSorter), mResult(other.mResult), fillflags(other.fillflags),
1115     reference_is_rawentrylist(other.reference_is_rawentrylist)
1116 {
1117 }
1118 */
1119 
1120 #define klf_lower_bound_entry						\
1121   qLowerBound<KLFLibEntryList::iterator,KLFLibEntry,const KLFLibEntrySorter&>
1122 #define klf_lower_bound_ewid						\
1123   qLowerBound<QList<KLFLibEntryWithId>::iterator,KLFLibEntryWithId,const QueryResultListSorter&>
1124 
insertIntoOrderedResult(const KLFLibEntryWithId & ewid)1125 void KLFLibResourceSimpleEngine::QueryResultListSorter::insertIntoOrderedResult(const KLFLibEntryWithId& ewid)
1126 {
1127   int pos;
1128 
1129   if (mSorter->propId() == -1) {
1130     // just append
1131     if (reference_is_rawentrylist)
1132       pos = mResult->rawEntryList.size();
1133     else
1134       pos = mResult->entryWithIdList.size();
1135   } else {
1136     // insert at right place
1137     if (reference_is_rawentrylist) {
1138       KLFLibEntryList::iterator it =
1139 	klf_lower_bound_entry(mResult->rawEntryList.begin(), mResult->rawEntryList.end(), ewid.entry, *mSorter);
1140       pos = it - mResult->rawEntryList.begin();
1141     } else {
1142       QList<KLFLibEntryWithId>::iterator it =
1143 	klf_lower_bound_ewid(mResult->entryWithIdList.begin(), mResult->entryWithIdList.end(), ewid, *this);
1144       pos = it - mResult->entryWithIdList.begin();
1145     }
1146   }
1147   // actually insert the items into appropriate lists
1148   if (fillflags & QueryResult::FillEntryIdList)
1149     mResult->entryIdList.insert(pos, ewid.id);
1150   if (fillflags & QueryResult::FillRawEntryList)
1151     mResult->rawEntryList.insert(pos, ewid.entry);
1152   if (fillflags & QueryResult::FillEntryWithIdList)
1153     mResult->entryWithIdList.insert(pos, ewid);
1154 }
1155 
1156 
1157 // ---------------------------------------------------
1158 
1159 // static
1160 KLFFactoryManager KLFLibEngineFactory::pFactoryManager;
1161 
1162 
KLFLibEngineFactory(QObject * parent)1163 KLFLibEngineFactory::KLFLibEngineFactory(QObject *parent)
1164   : QObject(parent), KLFFactoryBase(&pFactoryManager)
1165 {
1166 }
~KLFLibEngineFactory()1167 KLFLibEngineFactory::~KLFLibEngineFactory()
1168 {
1169 }
1170 
schemeFunctions(const QString &) const1171 uint KLFLibEngineFactory::schemeFunctions(const QString& /*scheme*/) const
1172 {
1173   return FuncOpen;
1174 }
1175 
findFactoryFor(const QUrl & url)1176 KLFLibEngineFactory *KLFLibEngineFactory::findFactoryFor(const QUrl& url)
1177 {
1178   return findFactoryFor(url.scheme());
1179 }
1180 
findFactoryFor(const QString & urlscheme)1181 KLFLibEngineFactory *KLFLibEngineFactory::findFactoryFor(const QString& urlscheme)
1182 {
1183   return dynamic_cast<KLFLibEngineFactory*>(pFactoryManager.findFactoryFor(urlscheme));
1184 }
1185 
allSupportedSchemes()1186 QStringList KLFLibEngineFactory::allSupportedSchemes()
1187 {
1188   return pFactoryManager.allSupportedTypes();
1189 }
1190 
createResource(const QString &,const Parameters &,QObject *)1191 KLFLibResourceEngine *KLFLibEngineFactory::createResource(const QString& /*scheme*/,
1192 							  const Parameters& /*param*/,
1193 							  QObject */*parent*/)
1194 {
1195   return NULL;
1196 }
1197 
saveResourceTo(KLFLibResourceEngine *,const QUrl &)1198 bool KLFLibEngineFactory::saveResourceTo(KLFLibResourceEngine */*resource*/, const QUrl& /*newLocation*/)
1199 {
1200   return false;
1201 }
1202 
1203 
openURL(const QUrl & url,QObject * parent)1204 KLFLibResourceEngine *KLFLibEngineFactory::openURL(const QUrl& url, QObject *parent)
1205 {
1206   KLFLibEngineFactory *factory = findFactoryFor(url.scheme());
1207   if ( factory == NULL ) {
1208     qWarning()<<"KLFLibEngineFactory::openURL("<<url<<"): No suitable factory found!";
1209     return NULL;
1210   }
1211   return factory->openResource(url, parent);
1212 }
1213 
1214 // static
listSubResourcesWithTitles(const QUrl & urlbase)1215 QMap<QString,QString> KLFLibEngineFactory::listSubResourcesWithTitles(const QUrl& urlbase)
1216 {
1217   QUrl url = urlbase;
1218   QUrlQuery urlq(url);
1219   urlq.addQueryItem("klfReadOnly", "true");
1220   url.setQuery(urlq);
1221   KLFLibResourceEngine *resource = openURL(url, NULL); // NULL parent
1222   if ( resource == NULL ) {
1223     qWarning()<<"KLFLibEngineFactory::listSubResources("<<url<<"): Unable to open resource!";
1224     return QMap<QString,QString>();
1225   }
1226   if ( !(resource->supportedFeatureFlags() & KLFLibResourceEngine::FeatureSubResources) ) {
1227     qWarning()<<"KLFLibEngineFactory::listSubResources("<<url<<"): Resource does not support sub-resources!";
1228     return QMap<QString,QString>();
1229   }
1230   QStringList subreslist = resource->subResourceList();
1231   int k;
1232   QMap<QString,QString> subresmap;
1233   for (k = 0; k < subreslist.size(); ++k) {
1234     if (resource->supportedFeatureFlags() & KLFLibResourceEngine::FeatureSubResourceProps)
1235       subresmap[subreslist[k]]
1236 	= resource->subResourceProperty(subreslist[k],
1237 					KLFLibResourceEngine::SubResPropTitle).toString();
1238     else
1239       subresmap[subreslist[k]] = QString();
1240   }
1241   delete resource;
1242   return subresmap;
1243 }
1244 
1245 // static
listSubResources(const QUrl & urlbase)1246 QStringList KLFLibEngineFactory::listSubResources(const QUrl& urlbase)
1247 {
1248   return listSubResourcesWithTitles(urlbase).keys();
1249 }
1250 
1251