00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <QDebug>
00025 #include <QString>
00026 #include <QBuffer>
00027 #include <QByteArray>
00028 #include <QDataStream>
00029 #include <QColor>
00030 #include <QMimeData>
00031
00032 #include <klfutil.h>
00033 #include "klflib_p.h"
00034 #include "klflib.h"
00035
00036
00037
00038
00039
00040 #define KLFLIBRESOURCEENGINE_WARN_NO_DEFAULT_SUBRESOURCE(func) \
00041 if ((pFeatureFlags & FeatureSubResources) && pDefaultSubResource.isNull()) { \
00042 qWarning("KLFLibResourceEngine::" func "(id): sub-resources are supported feature but" \
00043 " no default sub-resource is specified!"); } \
00044
00045
00046
00047
00048
00049
00050 KLFLibEntry::KLFLibEntry(const QString& latex, const QDateTime& dt, const QImage& preview,
00051 const QSize& previewsize, const QString& category, const QString& tags,
00052 const KLFStyle& style)
00053 : KLFPropertizedObject("KLFLibEntry")
00054 {
00055 initRegisteredProperties();
00056 setLatex(latex);
00057 setDateTime(dt);
00058 setPreview(preview);
00059 setPreviewSize(previewsize);
00060 setCategory(category);
00061 setTags(tags);
00062 setStyle(style);
00063 }
00064 KLFLibEntry::KLFLibEntry(const QString& latex, const QDateTime& dt, const QImage& preview,
00065 const KLFStyle& style)
00066 : KLFPropertizedObject("KLFLibEntry")
00067 {
00068 initRegisteredProperties();
00069 QString latexonly = stripCategoryTagsFromLatex(latex);
00070 QString category = categoryFromLatex(latex);
00071 QString tags = tagsFromLatex(latex);
00072 QSize previewsize = preview.size();
00073 setLatex(latexonly);
00074 setDateTime(dt);
00075 setPreview(preview);
00076 setPreviewSize(previewsize);
00077 setCategory(category);
00078 setTags(tags);
00079 setStyle(style);
00080 }
00081 KLFLibEntry::KLFLibEntry(const KLFLibEntry& copy)
00082 : KLFPropertizedObject("KLFLibEntry")
00083 {
00084 initRegisteredProperties();
00085 setAllProperties(copy.allProperties());
00086 }
00087 KLFLibEntry::~KLFLibEntry()
00088 {
00089 }
00090
00091
00092 int KLFLibEntry::setEntryProperty(const QString& propName, const QVariant& value)
00093 {
00094 int propId = propertyIdForName(propName);
00095 if (propId < 0) {
00096
00097 propId = registerProperty(propName);
00098 if (propId < 0)
00099 return -1;
00100 }
00101
00102 setProperty(propId, value);
00103 return propId;
00104 }
00105
00106
00107 void KLFLibEntry::initRegisteredProperties()
00108 {
00109 KLF_FUNC_SINGLE_RUN ;
00110
00111 registerBuiltInProperty(Latex, "Latex");
00112 registerBuiltInProperty(DateTime, "DateTime");
00113 registerBuiltInProperty(Preview, "Preview");
00114 registerBuiltInProperty(PreviewSize, "PreviewSize");
00115 registerBuiltInProperty(Category, "Category");
00116 registerBuiltInProperty(Tags, "Tags");
00117 registerBuiltInProperty(Style, "Style");
00118 }
00119
00120
00121
00122 QString KLFLibEntry::categoryFromLatex(const QString& latex)
00123 {
00124 QString s = latex.section('\n', 0, 0, QString::SectionSkipEmpty);
00125 if (s[0] == '%' && s[1] == ':') {
00126 return s.mid(2).trimmed();
00127 }
00128 return QString::null;
00129 }
00130
00131 QString KLFLibEntry::tagsFromLatex(const QString& latex)
00132 {
00133 QString s = latex.section('\n', 0, 0, QString::SectionSkipEmpty);
00134 if (s[0] == '%' && s[1] == ':') {
00135
00136 s = latex.section('\n', 1, 1, QString::SectionSkipEmpty);
00137 }
00138 if (s[0] == '%') {
00139 return s.mid(1).trimmed();
00140 }
00141 return QString::null;
00142 }
00143
00144
00145 QString KLFLibEntry::stripCategoryTagsFromLatex(const QString& latex)
00146 {
00147 int k = 0;
00148 while (k < latex.length() && latex[k].isSpace())
00149 ++k;
00150 if (k == latex.length()) return "";
00151 if (latex[k] == '%') {
00152 ++k;
00153 if (k == latex.length()) return "";
00154
00155 if (latex[k] == ':') {
00156
00157 while (k < latex.length() && latex[k] != '\n')
00158 ++k;
00159 ++k;
00160 if (k >= latex.length()) return "";
00161 if (latex[k] != '%') {
00162
00163 return latex.mid(k);
00164 }
00165 ++k;
00166 if (k >= latex.length()) return "";
00167 }
00168
00169 while (k < latex.length() && latex[k] != '\n')
00170 ++k;
00171 ++k;
00172 if (k >= latex.length()) return "";
00173 }
00174
00175 return latex.mid(k);
00176 }
00177
00178
00179 QString KLFLibEntry::latexAddCategoryTagsComment(const QString& latex, const QString& category,
00180 const QString& tags)
00181 {
00182 QString s;
00183
00184 if (!category.isEmpty())
00185 s = "%: "+category+"\n";
00186
00187 if (!tags.isEmpty())
00188 s += "% "+tags+"\n";
00189
00190 s += latex;
00191 return s;
00192 }
00193
00194
00195 QString KLFLibEntry::normalizeCategoryPath(const QString& categoryPath)
00196 {
00197 QString c = categoryPath.trimmed().split('/', QString::SkipEmptyParts).join("/");
00198 if (c.endsWith("/"))
00199 c.chop(1);
00200 return c;
00201 }
00202
00203
00204
00205
00206
00207
00208
00209 KLFLibEntrySorter::KLFLibEntrySorter(int propId, Qt::SortOrder order)
00210 : pCloneOf(NULL), pPropId(propId), pOrder(order)
00211 {
00212 }
00213 KLFLibEntrySorter::KLFLibEntrySorter(const KLFLibEntrySorter *clone)
00214 : pCloneOf(clone), pPropId(clone->pPropId), pOrder(clone->pOrder)
00215 {
00216 }
00217
00218 KLFLibEntrySorter::~KLFLibEntrySorter()
00219 {
00220 }
00221
00222 void KLFLibEntrySorter::setPropId(int propId)
00223 {
00224 if (pCloneOf != NULL) {
00225 qWarning()<<"Attempt to setPropId() in entry sorter that is a clone of "<<pCloneOf;
00226 return;
00227 }
00228 pPropId = propId;
00229 }
00230 void KLFLibEntrySorter::setOrder(Qt::SortOrder order)
00231 {
00232 if (pCloneOf != NULL) {
00233 qWarning()<<"Attempt to setOrder() in entry sorter that is a clone of "<<pCloneOf;
00234 return;
00235 }
00236 pOrder = order;
00237 }
00238
00239
00240
00241 QString KLFLibEntrySorter::entryValue(const KLFLibEntry& entry, int propId) const
00242 {
00243 if (pCloneOf != NULL)
00244 return pCloneOf->entryValue(entry, propId);
00245
00246
00247
00248
00249 if (propId == KLFLibEntry::Preview)
00250 propId = KLFLibEntry::DateTime;
00251
00252 if (propId == KLFLibEntry::PreviewSize) {
00253 QSize s = entry.previewSize();
00254
00255 return QString("%1,%2").arg(s.width(), 10, 10, QChar('0')).arg(s.height(), 10, 10, QChar('0'));
00256 }
00257 if (propId == KLFLibEntry::DateTime) {
00258 return entry.property(KLFLibEntry::DateTime).toDateTime().toString("yyyy-MM-dd+hh:mm:ss.zzz");
00259 }
00260 return entry.property(propId).toString();
00261 }
00262
00263 bool KLFLibEntrySorter::compareLessThan(const KLFLibEntry& a, const KLFLibEntry& b,
00264 int propId, Qt::SortOrder order) const
00265 {
00266 if (pCloneOf != NULL)
00267 return pCloneOf->compareLessThan(a, b, propId, order);
00268
00269 QString as = entryValue(a, propId);
00270 QString bs = entryValue(b, propId);
00271 if (order == Qt::AscendingOrder)
00272 return QString::localeAwareCompare(as, bs) < 0;
00273 return QString::localeAwareCompare(as, bs) > 0;
00274 }
00275
00276 bool KLFLibEntrySorter::operator()(const KLFLibEntry& a, const KLFLibEntry& b) const
00277 {
00278 if (pCloneOf != NULL)
00279 return pCloneOf->operator()(a, b);
00280
00281 return compareLessThan(a, b, pPropId, pOrder);
00282 }
00283
00284
00285
00286
00287 KLFAbstractLibEntryMimeEncoder::KLFAbstractLibEntryMimeEncoder()
00288 {
00289 registerEncoder(this);
00290 }
00291 KLFAbstractLibEntryMimeEncoder::~KLFAbstractLibEntryMimeEncoder()
00292 {
00293 }
00294 void KLFAbstractLibEntryMimeEncoder::registerEncoder(KLFAbstractLibEntryMimeEncoder *encoder)
00295 {
00296 staticEncoderList.append(encoder);
00297 }
00298
00299 QList<KLFAbstractLibEntryMimeEncoder*> KLFAbstractLibEntryMimeEncoder::encoderList()
00300 {
00301 return staticEncoderList;
00302 }
00303
00304
00305 QStringList KLFAbstractLibEntryMimeEncoder::allEncodingMimeTypes()
00306 {
00307 QStringList encTypes;
00308 int k;
00309 for (k = 0; k < staticEncoderList.size(); ++k) {
00310 encTypes << staticEncoderList[k]->supportedEncodingMimeTypes();
00311 }
00312 return encTypes;
00313 }
00314
00315 QStringList KLFAbstractLibEntryMimeEncoder::allDecodingMimeTypes()
00316 {
00317 QStringList decTypes;
00318 int k;
00319 for (k = 0; k < staticEncoderList.size(); ++k) {
00320 decTypes << staticEncoderList[k]->supportedDecodingMimeTypes();
00321 }
00322 return decTypes;
00323 }
00324
00325
00326 QMimeData *KLFAbstractLibEntryMimeEncoder::createMimeData(const KLFLibEntryList& entryList,
00327 const QVariantMap& metaData)
00328 {
00329 QMimeData *mime = new QMimeData;
00330 int k, j;
00331 for (k = 0; k < staticEncoderList.size(); ++k) {
00332 QStringList mimeTypeList = staticEncoderList[k]->supportedEncodingMimeTypes();
00333 for (j = 0; j < mimeTypeList.size(); ++j) {
00334 QByteArray data =
00335 staticEncoderList[k]->encodeMime(entryList, metaData, mimeTypeList[j]);
00336 if (data.isEmpty()) {
00337 klfDbg("Skipping mime type "<<mimeTypeList[k]<<" because it did not provide any data.");
00338 } else {
00339 mime->setData(mimeTypeList[j], data);
00340 }
00341 }
00342 }
00343 return mime;
00344 }
00345
00346
00347
00348 bool KLFAbstractLibEntryMimeEncoder::canDecodeMimeData(const QMimeData *mimeData)
00349 {
00350 QStringList fmts = mimeData->formats();
00351 int k;
00352 for (k = 0; k < fmts.size(); ++k) {
00353 if (findDecoderFor(fmts[k], false) != NULL)
00354 return true;
00355 }
00356 return false;
00357 }
00358
00359
00360 bool KLFAbstractLibEntryMimeEncoder::decodeMimeData(const QMimeData *mimeData,
00361 KLFLibEntryList *entryListPtr,
00362 QVariantMap *metaDataPtr)
00363 {
00364 QStringList fmts = mimeData->formats();
00365 int k;
00366 for (k = 0; k < fmts.size(); ++k) {
00367 KLFAbstractLibEntryMimeEncoder *decoder = findDecoderFor(fmts[k], false);
00368 if (decoder == NULL)
00369 continue;
00370 bool result = decoder->decodeMime(mimeData->data(fmts[k]), fmts[k], entryListPtr, metaDataPtr);
00371 if ( result )
00372 return true;
00373
00374 }
00375 return false;
00376 }
00377
00378
00379
00380 KLFAbstractLibEntryMimeEncoder *KLFAbstractLibEntryMimeEncoder::findEncoderFor(const QString& mimeType,
00381 bool warn)
00382 {
00383 int k;
00384 for (k = 0; k < staticEncoderList.size(); ++k)
00385 if (staticEncoderList[k]->supportedEncodingMimeTypes().contains(mimeType))
00386 return staticEncoderList[k];
00387 if (warn)
00388 qWarning()<<KLF_FUNC_NAME<<": Failed to find encoder for mime-type "<<mimeType;
00389 return NULL;
00390 }
00391
00392 KLFAbstractLibEntryMimeEncoder *KLFAbstractLibEntryMimeEncoder::findDecoderFor(const QString& mimeType,
00393 bool warn)
00394 {
00395 int k;
00396 for (k = 0; k < staticEncoderList.size(); ++k)
00397 if (staticEncoderList[k]->supportedDecodingMimeTypes().contains(mimeType))
00398 return staticEncoderList[k];
00399 if (warn)
00400 qWarning()<<KLF_FUNC_NAME<<": Failed to find decoder for mime-type "<<mimeType;
00401 return NULL;
00402 }
00403
00404
00405 QList<KLFAbstractLibEntryMimeEncoder*> KLFAbstractLibEntryMimeEncoder::staticEncoderList;
00406
00407
00408
00409
00410
00411 KLFLibEntryMimeEncoder __klf_lib_mime_encoder;
00412
00413
00414
00415
00416 KLFLibResourceEngine::KLFLibResourceEngine(const QUrl& url, uint featureflags,
00417 QObject *parent)
00418 : QObject(parent), KLFPropertizedObject("KLFLibResourceEngine"), pUrl(url),
00419 pFeatureFlags(featureflags), pReadOnly(false), pDefaultSubResource(QString()),
00420 pProgressBlocked(false), pThisOperationProgressBlockedOnly(false)
00421 {
00422 initRegisteredProperties();
00423
00424
00425
00426
00427 QStringList rdonly = pUrl.allQueryItemValues("klfReadOnly");
00428 if (rdonly.size() && rdonly.last() == "true") {
00429 if (pFeatureFlags & FeatureReadOnly)
00430 pReadOnly = true;
00431 }
00432 pUrl.removeAllQueryItems("klfReadOnly");
00433
00434 if (pFeatureFlags & FeatureSubResources) {
00435 QStringList defaultsubresource = pUrl.allQueryItemValues("klfDefaultSubResource");
00436 if (!defaultsubresource.isEmpty()) {
00437 pUrl.removeAllQueryItems("klfDefaultSubResource");
00438 pDefaultSubResource = defaultsubresource.last();
00439 }
00440 }
00441
00442 }
00443 KLFLibResourceEngine::~KLFLibResourceEngine()
00444 {
00445 }
00446
00447 void KLFLibResourceEngine::initRegisteredProperties()
00448 {
00449 KLF_FUNC_SINGLE_RUN
00450
00451 registerBuiltInProperty(PropTitle, "Title");
00452 registerBuiltInProperty(PropLocked, "Locked");
00453 registerBuiltInProperty(PropViewType, "ViewType");
00454 registerBuiltInProperty(PropAccessShared, "AccessShared");
00455 }
00456
00457 QUrl KLFLibResourceEngine::url(uint flags) const
00458 {
00459 QUrl url = pUrl;
00460 if (flags & WantUrlDefaultSubResource &&
00461 (pFeatureFlags & FeatureSubResources) &&
00462 !pDefaultSubResource.isNull()) {
00463 url.addQueryItem("klfDefaultSubResource", pDefaultSubResource);
00464 }
00465 if (flags & WantUrlReadOnly) {
00466 url.addQueryItem("klfReadOnly", pReadOnly?QString("true"):QString("false"));
00467 }
00468 return url;
00469 }
00470
00471
00472 bool KLFLibResourceEngine::canModifyData(const QString& subResource,
00473 ModifyType ) const
00474 {
00475 return baseCanModifyStatus(true, subResource) == MS_CanModify;
00476 }
00477
00478 bool KLFLibResourceEngine::canModifyData(ModifyType modifytype) const
00479 {
00480 KLFLIBRESOURCEENGINE_WARN_NO_DEFAULT_SUBRESOURCE("canModifyData")
00481 return canModifyData(pDefaultSubResource, modifytype);
00482 }
00483
00484
00485 bool KLFLibResourceEngine::canModifyProp(int propId) const
00486 {
00487 ModifyStatus ms = baseCanModifyStatus(false);
00488 return ms == MS_CanModify ||
00489 (ms == MS_IsLocked && propId == PropLocked);
00490 }
00491 bool KLFLibResourceEngine::canRegisterProperty(const QString& ) const
00492 {
00493 return false;
00494 }
00495
00496 bool KLFLibResourceEngine::hasSubResource(const QString& subResource) const
00497 {
00498 if ( !(pFeatureFlags & FeatureSubResources) )
00499 return false;
00500
00501 return subResourceList().contains(subResource);
00502 }
00503
00504 QString KLFLibResourceEngine::defaultSubResource() const
00505 {
00506 return pDefaultSubResource;
00507 }
00508
00509 bool KLFLibResourceEngine::compareDefaultSubResourceEquals(const QString& subResourceName) const
00510 {
00511 return QString::compare(pDefaultSubResource, subResourceName) == 0;
00512 }
00513
00514 bool KLFLibResourceEngine::canCreateSubResource() const
00515 {
00516 return false;
00517 }
00518
00519 bool KLFLibResourceEngine::canRenameSubResource(const QString& ) const
00520 {
00521 return false;
00522 }
00523 bool KLFLibResourceEngine::canDeleteSubResource(const QString& ) const
00524 {
00525 return false;
00526 }
00527
00528 QVariant KLFLibResourceEngine::subResourceProperty(const QString& , int ) const
00529 {
00530 return QVariant();
00531 }
00532
00533 QString KLFLibResourceEngine::subResourcePropertyName(int propId) const
00534 {
00535 switch (propId) {
00536 case SubResPropTitle:
00537 return QLatin1String("Title");
00538 case SubResPropLocked:
00539 return QLatin1String("Locked");
00540 case SubResPropViewType:
00541 return QLatin1String("ViewType");
00542 default:
00543 ;
00544 }
00545 return QString::number(propId);
00546 }
00547
00548 bool KLFLibResourceEngine::canModifySubResourceProperty(const QString& subResource, int propId) const
00549 {
00550 ModifyStatus ms = baseCanModifyStatus(true, subResource);
00551 return ms == MS_CanModify ||
00552 (ms == MS_SubResLocked && propId == SubResPropLocked);
00553 }
00554
00555 bool KLFLibResourceEngine::setTitle(const QString& title)
00556 {
00557 return setResourceProperty(PropTitle, title);
00558 }
00559 bool KLFLibResourceEngine::setLocked(bool setlocked)
00560 {
00561
00562
00563 if (pFeatureFlags & FeatureLocked) {
00564 return setResourceProperty(PropLocked, setlocked);
00565 }
00566 return false;
00567 }
00568
00569 bool KLFLibResourceEngine::setViewType(const QString& viewType)
00570 {
00571 return setResourceProperty(PropViewType, viewType);
00572 }
00573
00574 bool KLFLibResourceEngine::setReadOnly(bool readonly)
00575 {
00576 if ( !(pFeatureFlags & FeatureReadOnly) )
00577 return false;
00578
00579 pReadOnly = readonly;
00580 return true;
00581 }
00582
00583
00584 void KLFLibResourceEngine::setDefaultSubResource(const QString& subResource)
00585 {
00586 if (pDefaultSubResource == subResource)
00587 return;
00588
00589 pDefaultSubResource = subResource;
00590 emit defaultSubResourceChanged(subResource);
00591 }
00592
00593 bool KLFLibResourceEngine::setSubResourceProperty(const QString& , int ,
00594 const QVariant& )
00595 {
00596 return false;
00597 }
00598
00599 bool KLFLibResourceEngine::createSubResource(const QString& ,
00600 const QString& )
00601 {
00602 return false;
00603 }
00604 bool KLFLibResourceEngine::createSubResource(const QString& subResource)
00605 {
00606 return createSubResource(subResource, QString());
00607 }
00608 bool KLFLibResourceEngine::renameSubResource(const QString& , const QString& )
00609 {
00610 return false;
00611 }
00612 bool KLFLibResourceEngine::deleteSubResource(const QString& )
00613 {
00614 return false;
00615 }
00616
00617
00618 KLFLibEntry KLFLibResourceEngine::entry(entryId id)
00619 {
00620 KLFLIBRESOURCEENGINE_WARN_NO_DEFAULT_SUBRESOURCE("entry");
00621 return entry(pDefaultSubResource, id);
00622 }
00623 bool KLFLibResourceEngine::hasEntry(entryId id)
00624 {
00625 KLFLIBRESOURCEENGINE_WARN_NO_DEFAULT_SUBRESOURCE("hasEntry");
00626 return hasEntry(pDefaultSubResource, id);
00627 }
00628 QList<KLFLibResourceEngine::KLFLibEntryWithId>
00629 KLFLibResourceEngine::entries(const QList<KLFLib::entryId>& idList,
00630 const QList<int>& wantedEntryProperties)
00631 {
00632 KLFLIBRESOURCEENGINE_WARN_NO_DEFAULT_SUBRESOURCE("entries");
00633 return entries(pDefaultSubResource, idList, wantedEntryProperties);
00634 }
00635
00636 QList<KLFLibResourceEngine::KLFLibEntryWithId>
00637 KLFLibResourceEngine::allEntries(const QList<int>& wantedEntryProperties)
00638 {
00639 KLFLIBRESOURCEENGINE_WARN_NO_DEFAULT_SUBRESOURCE("allEntries");
00640 return allEntries(pDefaultSubResource, wantedEntryProperties);
00641 }
00642 QList<KLFLib::entryId> KLFLibResourceEngine::allIds()
00643 {
00644 KLFLIBRESOURCEENGINE_WARN_NO_DEFAULT_SUBRESOURCE("allIds");
00645 return allIds(pDefaultSubResource);
00646 }
00647
00648 void KLFLibResourceEngine::blockProgressReportingForNextOperation()
00649 {
00650 pProgressBlocked = true;
00651 pThisOperationProgressBlockedOnly = true;
00652 }
00653
00654 void KLFLibResourceEngine::blockProgressReporting(bool block)
00655 {
00656 pProgressBlocked = true;
00657 pThisOperationProgressBlockedOnly = false;
00658 }
00659
00660 bool KLFLibResourceEngine::thisOperationProgressBlocked() const
00661 {
00662 bool blocked = pProgressBlocked;
00663 if (pThisOperationProgressBlockedOnly)
00664 pProgressBlocked = false;
00665 return blocked;
00666 }
00667
00668
00669 KLFLibResourceEngine::entryId KLFLibResourceEngine::insertEntry(const QString& subResource,
00670 const KLFLibEntry& entry)
00671 {
00672 QList<entryId> ids = insertEntries(subResource, KLFLibEntryList() << entry);
00673 if (ids.size() == 0)
00674 return -1;
00675
00676 return ids[0];
00677 }
00678 KLFLibResourceEngine::entryId KLFLibResourceEngine::insertEntry(const KLFLibEntry& entry)
00679 {
00680 KLFLIBRESOURCEENGINE_WARN_NO_DEFAULT_SUBRESOURCE("insertEntry");
00681 return insertEntry(pDefaultSubResource, entry);
00682 }
00683 QList<KLFLibResourceEngine::entryId> KLFLibResourceEngine::insertEntries(const KLFLibEntryList& entrylist)
00684 {
00685 KLFLIBRESOURCEENGINE_WARN_NO_DEFAULT_SUBRESOURCE("insertEntries");
00686 return insertEntries(pDefaultSubResource, entrylist);
00687 }
00688
00689 bool KLFLibResourceEngine::changeEntries(const QList<entryId>& idlist, const QList<int>& properties,
00690 const QList<QVariant>& values)
00691 {
00692 KLFLIBRESOURCEENGINE_WARN_NO_DEFAULT_SUBRESOURCE("changeEntries");
00693 return changeEntries(pDefaultSubResource, idlist, properties, values);
00694 }
00695
00696 bool KLFLibResourceEngine::deleteEntries(const QList<entryId>& idList)
00697 {
00698 KLFLIBRESOURCEENGINE_WARN_NO_DEFAULT_SUBRESOURCE("deleteEntries");
00699 return deleteEntries(pDefaultSubResource, idList);
00700 }
00701
00702
00703
00704 bool KLFLibResourceEngine::saveTo(const QUrl&)
00705 {
00706
00707
00708 return false;
00709 }
00710
00711 QVariant KLFLibResourceEngine::resourceProperty(const QString& name) const
00712 {
00713 return KLFPropertizedObject::property(name);
00714 }
00715
00716 bool KLFLibResourceEngine::loadResourceProperty(const QString& propName, const QVariant& value)
00717 {
00718 int propId = propertyIdForName(propName);
00719 if (propId < 0) {
00720 if (!canRegisterProperty(propName))
00721 return false;
00722
00723 propId = registerProperty(propName);
00724 if (propId < 0)
00725 return false;
00726 }
00727
00728 return setResourceProperty(propId, value);
00729 }
00730
00731 bool KLFLibResourceEngine::setResourceProperty(int propId, const QVariant& value)
00732 {
00733 if ( ! KLFPropertizedObject::propertyIdRegistered(propId) )
00734 return false;
00735
00736 if ( !canModifyProp(propId) ) {
00737 return false;
00738 }
00739
00740 bool result = saveResourceProperty(propId, value);
00741 if (!result)
00742 return false;
00743
00744
00745 KLFPropertizedObject::setProperty(propId, value);
00746 emit resourcePropertyChanged(propId);
00747 return true;
00748 }
00749
00750
00751 KLFLibResourceEngine::ModifyStatus
00752 KLFLibResourceEngine::baseCanModifyStatus(bool inSubResource, const QString& subResource) const
00753 {
00754 if (pFeatureFlags & FeatureLocked) {
00755 if (locked())
00756 return MS_IsLocked;
00757 if (inSubResource &&
00758 (pFeatureFlags & FeatureSubResources) &&
00759 (pFeatureFlags & FeatureSubResourceProps)) {
00760 if (subResourceProperty(subResource, SubResPropLocked).toBool())
00761 return MS_SubResLocked;
00762 }
00763 }
00764
00765 if (pFeatureFlags & FeatureReadOnly) {
00766 if (isReadOnly())
00767 return MS_NotModifiable;
00768 }
00769
00770 return MS_CanModify;
00771 }
00772
00773
00774
00775
00776 KLFLib::EntryMatchCondition KLFLib::EntryMatchCondition::mkMatchAll()
00777 {
00778 return EntryMatchCondition(MatchAllType);
00779 }
00780
00781 KLFLib::EntryMatchCondition KLFLib::EntryMatchCondition::mkPropertyMatch(PropertyMatch pmatch)
00782 {
00783 EntryMatchCondition c(PropertyMatchType);
00784 c.mPropertyMatch = pmatch;
00785 return c;
00786 }
00787
00788 KLFLib::EntryMatchCondition KLFLib::EntryMatchCondition::mkNegateMatch(const EntryMatchCondition& condition)
00789 {
00790 EntryMatchCondition c(NegateMatchType);
00791 c.mConditionList = QList<EntryMatchCondition>() << condition;
00792 return c;
00793 }
00794
00795 KLFLib::EntryMatchCondition KLFLib::EntryMatchCondition::mkOrMatch(QList<EntryMatchCondition> conditions)
00796 {
00797 EntryMatchCondition c(OrMatchType);
00798 c.mConditionList = conditions;
00799 return c;
00800 }
00801
00802 KLFLib::EntryMatchCondition KLFLib::EntryMatchCondition::mkAndMatch(QList<EntryMatchCondition> conditions)
00803 {
00804 EntryMatchCondition c(AndMatchType);
00805 c.mConditionList = conditions;
00806 return c;
00807 }
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817 KLF_EXPORT QDataStream& operator<<(QDataStream& stream, const KLFLibResourceEngine::KLFLibEntryWithId& entrywid)
00818 {
00819 return stream << entrywid.id << entrywid.entry;
00820 }
00821 KLF_EXPORT QDataStream& operator>>(QDataStream& stream, KLFLibResourceEngine::KLFLibEntryWithId& entrywid)
00822 {
00823 return stream >> entrywid.id >> entrywid.entry;
00824 }
00825
00826
00827 KLF_EXPORT QDebug& operator<<(QDebug& dbg, const KLFLib::StringMatch& smatch)
00828 {
00829 return dbg << "StringMatch[ref="<<smatch.matchValueString()<<";flags="<<smatch.matchFlags()<<"]";
00830 }
00831 KLF_EXPORT QDebug& operator<<(QDebug& dbg, const KLFLib::PropertyMatch& pmatch)
00832 {
00833 return dbg << "PropertyMatch[prop-id="<<pmatch.propertyId()<<"; ref="<<pmatch.matchValueString()
00834 <<"; flags="<<pmatch.matchFlags()<<"]";
00835 }
00836 KLF_EXPORT QDebug& operator<<(QDebug& dbg, const KLFLib::EntryMatchCondition& c)
00837 {
00838 #ifdef Q_WS_MAC
00839 return dbg<<"EntryMatchCondition{...}";
00840 #endif
00841 dbg << "EntryMatchCondition{type=";
00842 if (c.type() == KLFLib::EntryMatchCondition::MatchAllType)
00843 return dbg << "match-all}";
00844 if (c.type() == KLFLib::EntryMatchCondition::PropertyMatchType)
00845 return dbg << "property-match; "<<c.propertyMatch()<<"}";
00846 if (c.type() != KLFLib::EntryMatchCondition::NegateMatchType &&
00847 c.type() != KLFLib::EntryMatchCondition::AndMatchType &&
00848 c.type() != KLFLib::EntryMatchCondition::OrMatchType)
00849 return dbg << "unknown-type}";
00850
00851 static const char *w_and = " AND ";
00852 static const char *w_or = " OR ";
00853 static const char *w_not = " NOT ";
00854 const char * word = (c.type()==KLFLib::EntryMatchCondition::NegateMatchType)? w_not :
00855 ((c.type()==KLFLib::EntryMatchCondition::AndMatchType) ? w_and : w_or) ;
00856 dbg << (word+1) << "; list: ";
00857 QList<KLFLib::EntryMatchCondition> conditions = c.conditionList();
00858 int k;
00859 for (k = 0; k < conditions.size(); ++k) {
00860 if (k > 0)
00861 dbg << word;
00862 dbg << conditions[k];
00863 }
00864 dbg << ".}";
00865 return dbg;
00866 }
00867 KLF_EXPORT QDebug& operator<<(QDebug& dbg, const KLFLibResourceEngine::KLFLibEntryWithId& e)
00868 {
00869 return dbg <<"KLFLibEntryWithId(id="<<e.id<<";"<<e.entry.category()<<","<<e.entry.tags()<<","
00870 <<e.entry.latex()<<")";
00871 }
00872 KLF_EXPORT QDebug& operator<<(QDebug& dbg, const KLFLibResourceEngine::Query& q)
00873 {
00874 return dbg << "Query(cond.="<<q.matchCondition<<"; skip="<<q.skip<<",limit="<<q.limit
00875 <<"; orderpropid="<<q.orderPropId<<"/"<<(q.orderDirection==Qt::AscendingOrder ? "Asc":"Desc")
00876 <<"; wanted props="<<q.wantedEntryProperties<<")" ;
00877 }
00878
00879
00880
00881
00882
00883
00884 QList<KLFLib::entryId> KLFLibResourceSimpleEngine::allIds(const QString& subResource)
00885 {
00886 QList<KLFLib::entryId> idList;
00887 QList<KLFLibResourceEngine::KLFLibEntryWithId> elist = allEntries(subResource);
00888 int k;
00889 for (k = 0; k < idList.size(); ++k)
00890 idList << elist[k].id;
00891 return idList;
00892 }
00893
00894 bool KLFLibResourceSimpleEngine::hasEntry(const QString& subResource, entryId id)
00895 {
00897 return entry(subResource, id).latex().size();
00898 }
00899
00900 QList<KLFLibResourceEngine::KLFLibEntryWithId>
00901 KLFLibResourceSimpleEngine::entries(const QString& subResource, const QList<KLFLib::entryId>& idList,
00902 const QList<int>& )
00903 {
00904 QList<KLFLibEntryWithId> elist;
00905 int k;
00906 for (k = 0; k < idList.size(); ++k)
00907 elist << KLFLibEntryWithId(idList[k], entry(subResource, idList[k]));
00908 return elist;
00909 }
00910
00911
00912 int KLFLibResourceSimpleEngine::query(const QString& subResource,
00913 const Query& query,
00914 QueryResult *result)
00915 {
00916 return queryImpl(this, subResource, query, result);
00917 }
00918
00919 QList<QVariant> KLFLibResourceSimpleEngine::queryValues(const QString& subResource, int entryPropId)
00920 {
00921 return queryValuesImpl(this, subResource, entryPropId);
00922 }
00923
00924
00925 template<class T>
00926 static void qlist_skip_and_limit(QList<T> *list, int skip, int limit)
00927 {
00928 KLF_ASSERT_NOT_NULL( list, "list is NULL!", return; ) ;
00929
00930
00931
00932 if (skip <= 0) {
00933
00934 } else if (list->size() <= skip) {
00935 list->clear();
00936 } else {
00937 *list = list->mid(skip);
00938 }
00939
00940
00941 if (limit < 0)
00942 return;
00943
00944 if (list->size() > limit)
00945 *list = list->mid(0, limit);
00946
00947 return;
00948 }
00949
00950
00951 int KLFLibResourceSimpleEngine::queryImpl(KLFLibResourceEngine *resource, const QString& subResource,
00952 const Query& query, QueryResult *result)
00953 {
00955
00956 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
00957 klfDbgSt("Query: "<<query);
00958
00959 if (result == NULL) {
00960 qWarning()<<KLF_FUNC_NAME<<": expected valid `result' pointer";
00961 return -1;
00962 }
00963
00964 QList<KLFLibEntryWithId> allEList = resource->allEntries(subResource);
00965
00966 KLFLibEntrySorter sorter(query.orderPropId, query.orderDirection);
00967 QueryResultListSorter lsorter(&sorter, result);
00968
00969
00970
00971 int k;
00972 for (k = 0; k < allEList.size(); ++k) {
00973
00974 const KLFLibEntryWithId& ewid = allEList[k];
00975 if (testEntryMatchConditionImpl(query.matchCondition, ewid.entry)) {
00976 lsorter.insertIntoOrderedResult(ewid);
00977 }
00978 }
00979
00980 klfDbgSt("queried ordered list. result->entryWithIdList: \n"<<result->entryWithIdList) ;
00981
00982
00983
00984
00985 qlist_skip_and_limit(&result->entryIdList, query.skip, query.limit);
00986 qlist_skip_and_limit(&result->rawEntryList, query.skip, query.limit);
00987 qlist_skip_and_limit(&result->entryWithIdList, query.skip, query.limit);
00988
00989 klfDbgSt("About to return. Number of entries in TEE VALUE.") ;
00990
00991 return KLF_DEBUG_TEE( lsorter.numberOfEntries() );
00992 }
00993
00994
00995 QList<QVariant> KLFLibResourceSimpleEngine::queryValuesImpl(KLFLibResourceEngine *resource,
00996 const QString& subResource, int entryPropId)
00997 {
00998 QList<KLFLibEntryWithId> allEList = resource->allEntries(subResource);
00999 QList<QVariant> values;
01000 int k;
01001 for (k = 0; k < allEList.size(); ++k) {
01002 QVariant p = allEList[k].entry.property(entryPropId);
01003 if (!values.contains(p))
01004 values << p;
01005 }
01006 return values;
01007 }
01008
01009
01010
01011 bool KLFLibResourceSimpleEngine::testEntryMatchConditionImpl(const KLFLib::EntryMatchCondition& condition,
01012 const KLFLibEntry& libentry)
01013 {
01014 int k;
01015 KLFLib::PropertyMatch pmatch;
01016 QList<KLFLib::EntryMatchCondition> condlist;
01017
01018 switch (condition.type()) {
01019 case KLFLib::EntryMatchCondition::MatchAllType:
01020 return true;
01021 case KLFLib::EntryMatchCondition::PropertyMatchType:
01022 pmatch = condition.propertyMatch();
01023 return klfMatch(libentry.property(pmatch.propertyId()),
01024 pmatch.matchValue(),
01025 pmatch.matchFlags(),
01026 pmatch.matchValueString());
01027 case KLFLib::EntryMatchCondition::NegateMatchType:
01028 condlist = condition.conditionList();
01029 if (condlist.isEmpty()) {
01030 qWarning()<<KLF_FUNC_NAME<<": NOT condition with no arguments!";
01031 return false;
01032 }
01033 return ! testEntryMatchConditionImpl(condlist[0], libentry);
01034 case KLFLib::EntryMatchCondition::OrMatchType:
01035 condlist = condition.conditionList();
01036 if (condlist.isEmpty())
01037 return true;
01038 for (k = 0; k < condlist.size(); ++k) {
01039 if (testEntryMatchConditionImpl(condlist[k], libentry))
01040 return true;
01041 }
01042 return false;
01043 case KLFLib::EntryMatchCondition::AndMatchType:
01044 condlist = condition.conditionList();
01045 if (condlist.isEmpty())
01046 return true;
01047 for (k = 0; k < condlist.size(); ++k) {
01048 if ( ! testEntryMatchConditionImpl(condlist[k], libentry) )
01049 return false;
01050 }
01051 return true;
01052 default:
01053 qWarning()<<KLF_FUNC_NAME<<": KLFLib::EntryMatchCondition type "<<condition.type()<<" not known!";
01054 }
01055 return false;
01056 }
01057
01058
01059 KLFLibResourceSimpleEngine::QueryResultListSorter::QueryResultListSorter(KLFLibEntrySorter *sorter,
01060 QueryResult *result)
01061 : mSorter(sorter), mResult(result)
01062 {
01063 KLF_ASSERT_NOT_NULL( result, "result ptr is NULL!", return ) ;
01064
01065 fillflags = result->fillFlags;
01066
01067 if (fillflags & QueryResult::FillRawEntryList) {
01068 reference_is_rawentrylist = true;
01069 } else if (fillflags & QueryResult::FillEntryWithIdList) {
01070 reference_is_rawentrylist = false;
01071 } else {
01072
01073 fillflags |= QueryResult::FillRawEntryList;
01074 reference_is_rawentrylist = true;
01075 }
01076 }
01077 int KLFLibResourceSimpleEngine::QueryResultListSorter::numberOfEntries()
01078 {
01079 if (reference_is_rawentrylist)
01080 return mResult->rawEntryList.size();
01081 else
01082 return mResult->entryWithIdList.size();
01083 }
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094 #define klf_lower_bound_entry \
01095 qLowerBound<KLFLibEntryList::iterator,KLFLibEntry,const KLFLibEntrySorter&>
01096 #define klf_lower_bound_ewid \
01097 qLowerBound<QList<KLFLibEntryWithId>::iterator,KLFLibEntryWithId,const QueryResultListSorter&>
01098
01099 void KLFLibResourceSimpleEngine::QueryResultListSorter::insertIntoOrderedResult(const KLFLibEntryWithId& ewid)
01100 {
01101 int pos;
01102
01103 if (mSorter->propId() == -1) {
01104
01105 if (reference_is_rawentrylist)
01106 pos = mResult->rawEntryList.size();
01107 else
01108 pos = mResult->entryWithIdList.size();
01109 } else {
01110
01111 if (reference_is_rawentrylist) {
01112 KLFLibEntryList::iterator it =
01113 klf_lower_bound_entry(mResult->rawEntryList.begin(), mResult->rawEntryList.end(), ewid.entry, *mSorter);
01114 pos = it - mResult->rawEntryList.begin();
01115 } else {
01116 QList<KLFLibEntryWithId>::iterator it =
01117 klf_lower_bound_ewid(mResult->entryWithIdList.begin(), mResult->entryWithIdList.end(), ewid, *this);
01118 pos = it - mResult->entryWithIdList.begin();
01119 }
01120 }
01121
01122 if (fillflags & QueryResult::FillEntryIdList)
01123 mResult->entryIdList.insert(pos, ewid.id);
01124 if (fillflags & QueryResult::FillRawEntryList)
01125 mResult->rawEntryList.insert(pos, ewid.entry);
01126 if (fillflags & QueryResult::FillEntryWithIdList)
01127 mResult->entryWithIdList.insert(pos, ewid);
01128 }
01129
01130
01131
01132
01133
01134 KLFFactoryManager KLFLibEngineFactory::pFactoryManager;
01135
01136
01137 KLFLibEngineFactory::KLFLibEngineFactory(QObject *parent)
01138 : QObject(parent), KLFFactoryBase(&pFactoryManager)
01139 {
01140 }
01141 KLFLibEngineFactory::~KLFLibEngineFactory()
01142 {
01143 }
01144
01145 uint KLFLibEngineFactory::schemeFunctions(const QString& ) const
01146 {
01147 return FuncOpen;
01148 }
01149
01150 KLFLibEngineFactory *KLFLibEngineFactory::findFactoryFor(const QUrl& url)
01151 {
01152 return findFactoryFor(url.scheme());
01153 }
01154
01155 KLFLibEngineFactory *KLFLibEngineFactory::findFactoryFor(const QString& urlscheme)
01156 {
01157 return dynamic_cast<KLFLibEngineFactory*>(pFactoryManager.findFactoryFor(urlscheme));
01158 }
01159
01160 QStringList KLFLibEngineFactory::allSupportedSchemes()
01161 {
01162 return pFactoryManager.allSupportedTypes();
01163 }
01164
01165 KLFLibResourceEngine *KLFLibEngineFactory::createResource(const QString& ,
01166 const Parameters& ,
01167 QObject *)
01168 {
01169 return NULL;
01170 }
01171
01172 bool KLFLibEngineFactory::saveResourceTo(KLFLibResourceEngine *, const QUrl& )
01173 {
01174 return false;
01175 }
01176
01177
01178 KLFLibResourceEngine *KLFLibEngineFactory::openURL(const QUrl& url, QObject *parent)
01179 {
01180 KLFLibEngineFactory *factory = findFactoryFor(url.scheme());
01181 if ( factory == NULL ) {
01182 qWarning()<<"KLFLibEngineFactory::openURL("<<url<<"): No suitable factory found!";
01183 return NULL;
01184 }
01185 return factory->openResource(url, parent);
01186 }
01187
01188
01189 QMap<QString,QString> KLFLibEngineFactory::listSubResourcesWithTitles(const QUrl& urlbase)
01190 {
01191 QUrl url = urlbase;
01192 url.addQueryItem("klfReadOnly", "true");
01193 KLFLibResourceEngine *resource = openURL(url, NULL);
01194 if ( resource == NULL ) {
01195 qWarning()<<"KLFLibEngineFactory::listSubResources("<<url<<"): Unable to open resource!";
01196 return QMap<QString,QString>();
01197 }
01198 if ( !(resource->supportedFeatureFlags() & KLFLibResourceEngine::FeatureSubResources) ) {
01199 qWarning()<<"KLFLibEngineFactory::listSubResources("<<url<<"): Resource does not support sub-resources!";
01200 return QMap<QString,QString>();
01201 }
01202 QStringList subreslist = resource->subResourceList();
01203 int k;
01204 QMap<QString,QString> subresmap;
01205 for (k = 0; k < subreslist.size(); ++k) {
01206 if (resource->supportedFeatureFlags() & KLFLibResourceEngine::FeatureSubResourceProps)
01207 subresmap[subreslist[k]]
01208 = resource->subResourceProperty(subreslist[k],
01209 KLFLibResourceEngine::SubResPropTitle).toString();
01210 else
01211 subresmap[subreslist[k]] = QString();
01212 }
01213 delete resource;
01214 return subresmap;
01215 }
01216
01217
01218 QStringList KLFLibEngineFactory::listSubResources(const QUrl& urlbase)
01219 {
01220 return listSubResourcesWithTitles(urlbase).keys();
01221 }
01222