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