1 /***************************************************************************
2  *   file klflib.h
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.h 881 2014-06-15 21:23:43Z phfaist $ */
23 
24 #ifndef KLFLIB_H
25 #define KLFLIB_H
26 
27 #include <QImage>
28 #include <QMap>
29 #include <QUrl>
30 #include <QDataStream>
31 #include <QDateTime>
32 #include <QFileInfo>
33 
34 #include <klfdefs.h>
35 #include <klfbackend.h>
36 
37 #include <klfpobj.h>
38 #include <klffactory.h>
39 #include <klfstyle.h>
40 
41 
42 
43 class KLFProgressReporter;
44 
45 
46 
47 /** \brief An entry (single formula) in the library
48  *
49  * Stores Latex code, Date/Time of evaluation, A preview image, A Category String,
50  * A Tags String, and a Style in a KLFPropertizedObject-based object.
51  *
52  * This object can be used as a normal value (ie. it has copy constructor, assignment
53  * operator and default constructor).
54  */
55 class KLF_EXPORT KLFLibEntry : public KLFPropertizedObject {
56 public:
57   /** \note The numeric IDs don't have to be preserved from one version of KLF to
58    * another, since they are nowhere stored. Properties are always stored by name
59    * when dealing in scopes larger than the running application (saved files, etc.).
60    */
61   enum PropertyId {
62     Latex = 0, //!< The Latex Code of the equation
63     DateTime, //!< The Date/Time at which the equation was evaluated
64     Preview, //!< An Image Preview of equation (scaled down QImage)
65     PreviewSize, //!< A cached value of the size of value in \c Preview
66     Category, //!< The Category to which eq. belongs (path-style string)
67     Tags, //!< Tags about the equation (string)
68     Style //!< KLFStyle style used
69   };
70 
71   KLFLibEntry(const QString& latex = QString(), const QDateTime& dt = QDateTime(),
72 	      const QImage& preview = QImage(),	const QSize& previewsize = QSize(),
73 	      const QString& category = QString(), const QString& tags = QString(),
74 	      const KLFStyle& style = KLFStyle());
75   /** This constructor extracts the legacy-style category and tags from latex, and
76    * stores latex with those tags stripped. */
77   KLFLibEntry(const QString& latex, const QDateTime& dt, const QImage& preview,
78 	      const KLFStyle& style);
79   KLFLibEntry(const KLFLibEntry& copy);
80   virtual ~KLFLibEntry();
81 
latex()82   inline QString latex() const { return property(Latex).toString(); }
dateTime()83   inline QDateTime dateTime() const { return property(DateTime).toDateTime(); }
preview()84   inline QImage preview() const { return property(Preview).value<QImage>(); }
previewSize()85   inline QSize previewSize() const { return property(PreviewSize).value<QSize>(); }
category()86   inline QString category() const { return property(Category).toString(); }
tags()87   inline QString tags() const { return property(Tags).toString(); }
style()88   inline KLFStyle style() const { return property(Style).value<KLFStyle>(); }
89 
latexWithCategoryTagsComments()90   inline QString latexWithCategoryTagsComments() const
91   { return latexAddCategoryTagsComment(latex(), category(), tags()); }
92 
setLatex(const QString & latex)93   inline void setLatex(const QString& latex) { setProperty(Latex, latex); }
setDateTime(const QDateTime & dt)94   inline void setDateTime(const QDateTime& dt) { setProperty(DateTime, dt); }
setPreview(const QImage & img)95   inline void setPreview(const QImage& img) { setProperty(Preview, img); }
setPreviewSize(const QSize & sz)96   inline void setPreviewSize(const QSize& sz) { setProperty(PreviewSize, sz); }
97   /** \note this function normalizes category to remove any double-'/' to avoid empty sections.
98    *    Equality between categories can be compared stringwise.
99    *
100    * See also \ref normalizeCategoryPath(). */
setCategory(const QString & s)101   inline void setCategory(const QString& s) { setProperty(Category, normalizeCategoryPath(s)); }
setTags(const QString & s)102   inline void setTags(const QString& s) { setProperty(Tags, s); }
setStyle(const KLFStyle & style)103   inline void setStyle(const KLFStyle& style) { setProperty(Style, QVariant::fromValue(style)); }
104 
105   /** Set the property named \c name to value \c value. If the property does not
106    * yet exist in the registered properties, it is registered.
107    *
108    * \returns -1 for error, or the property ID that was successfully (maybe registered
109    * and) set.
110    */
111   int setEntryProperty(const QString& propName, const QVariant& value);
112 
113 
114   /** Parses and returns legacy-style category comment string from latex string
115    * in the form <pre>%: Category</pre> */
116   static QString categoryFromLatex(const QString& latex);
117   /** Parses and returns legacy-style tags comment string from latex string */
118   static QString tagsFromLatex(const QString& latex);
119   /** Removes legacy-style category and tags comment from latex string */
120   static QString stripCategoryTagsFromLatex(const QString& latex);
121   /** Creates a latex with category and tags comments */
122   static QString latexAddCategoryTagsComment(const QString& latex, const QString& category,
123 					     const QString& tags);
124   /** Renders a category-path "pretty" by removing any double-slashes to single slashes.
125    * Trailing slashes are removed. The root category is an empty string.
126    *
127    * When a category is set to a lib-entry with \c setCategory(), it is automatically
128    * normalized.
129    *
130    * Returned paths may be compared string-wise for equality.
131    */
132   static QString normalizeCategoryPath(const QString& categoryPath);
133 
134 private:
135 
136   void initRegisteredProperties();
137 };
138 
139 Q_DECLARE_METATYPE(KLFLibEntry)
140   ;
141 
142 typedef QList<KLFLibEntry> KLFLibEntryList;
143 
144 
145 //! Contains general definitions to be used anywhere in the KLFLib* framework
146 namespace KLFLib {
147   //! An entry ID
148   /** The type of the ID of an entry in a library resource (see \ref KLFLibResourceEngine)
149    *
150    * \note This type is signed, and may be assigned a negative value. Negative values
151    *   should only indicate invalid IDs. Valid IDs are always positive.
152    *
153    * \note \ref KLFLibResourceEngine::entryId is a typedef of \ref KLFLib::entryId.
154    *
155    * */
156   typedef qint32 entryId;
157 
158 
159   /** Describes a matching criterion for a string
160    *
161    * Note: The Qt::MatchWrap and Qt::MatchRecursive flags are ignored.
162    */
163   struct StringMatch {
164     StringMatch(const QVariant& value = QVariant(), Qt::MatchFlags flags = Qt::MatchExactly)
mFlagsStringMatch165       : mFlags(flags), mValue(value), mValueString(value.toString()) { }
StringMatchStringMatch166     StringMatch(const StringMatch& m) : mFlags(m.mFlags), mValue(m.mValue), mValueString(m.mValueString) { }
167 
168     /** How the match should be tested (exact match, regex, contains, etc.), this is
169      * a binary-OR'ed value of Qt::MatchFlag enum values.
170      *
171      * the Qt::MatchCaseSensitive may be set to match case sensitive.
172      */
matchFlagsStringMatch173     inline const Qt::MatchFlags matchFlags() const { return mFlags; }
174     /** The value that will be matched to. */
matchValueStringMatch175     inline const QVariant matchValue() const { return mValue; }
176     /** equivalent to <tt>matchValue().toString()</tt>, however the conversion is
177      * performed once and cached. */
matchValueStringStringMatch178     inline const QString matchValueString() const { return mValueString; }
179 
180   protected:
181     Qt::MatchFlags mFlags;
182     QVariant mValue;
183     QString mValueString;
184   };
185 
186   /** Discribes a matching criterion for the value of a property ID. Although not assumed
187    * in this definition, property IDs will eventually refer to KLFPropertizedObject property
188    * IDs, more specifically \ref KLFLibEntry property IDs.
189    */
190   struct PropertyMatch : public StringMatch {
191     /** propId is the ID of the property which will have to match as given by \c match */
192     PropertyMatch(int propId = -1, const StringMatch& match = StringMatch())
StringMatchPropertyMatch193       : StringMatch(match), mPropertyId(propId) { }
194     /** copy constructor */
PropertyMatchPropertyMatch195     PropertyMatch(const PropertyMatch& other) : StringMatch(other), mPropertyId(other.mPropertyId) { }
196 
197     /** Returns the propery ID set in the constructor. */
propertyIdPropertyMatch198     inline int propertyId() const { return mPropertyId; }
199 
200   protected:
201     int mPropertyId;
202   };
203 
204   /** This is a generalized condition. It can be one of several types.
205    *
206    * In the future, more match condition types may be added. For now, the following
207    * matching condition types are supported.
208    *  - property string matching (see \ref PropertyMatch)
209    *  - AND of N conditions
210    *  - OR of N conditions
211    *
212    * This class is meant for use with findEntries().
213    */
214   struct EntryMatchCondition
215   {
216     enum Type {
217       MatchAllType = 0, //!< Matches all entries
218       PropertyMatchType, //!< Matches a property ID with a string (with a \ref StringMatch)
219       NegateMatchType, //!< Matches entries that don't match a condition
220       OrMatchType, //!< entries have to match with one of a list of conditions
221       AndMatchType //!< entries have to match with all given conditions
222     };
223 
224     //! Get which type of condition this is
typeEntryMatchCondition225     inline Type type() const { return mType; }
226     //! Relevant for type PropertyMatchType
propertyMatchEntryMatchCondition227     inline PropertyMatch propertyMatch() const { return mPropertyMatch; }
228     //! Relevant for types OrMatchType and AndMatchType
conditionListEntryMatchCondition229     inline QList<EntryMatchCondition> conditionList() const { return mConditionList; }
230 
231     static EntryMatchCondition mkMatchAll();
232     static EntryMatchCondition mkPropertyMatch(PropertyMatch pmatch);
233     /** Stores \c condition in first element of conditionList(). */
234     static EntryMatchCondition mkNegateMatch(const EntryMatchCondition& condition);
235     static EntryMatchCondition mkOrMatch(QList<EntryMatchCondition> conditions);
236     static EntryMatchCondition mkAndMatch(QList<EntryMatchCondition> conditions);
237 
238   protected:
EntryMatchConditionEntryMatchCondition239     EntryMatchCondition(Type type) : mType(type) { }
240 
241     Type mType;
242 
243     PropertyMatch mPropertyMatch;
244     QList<EntryMatchCondition> mConditionList;
245   };
246 
247 }
248 
249 //! Utility class for sorting library entry items
250 /**
251  * This class can be used as a sorter to sort entry items.
252  *
253  * This class functions as follows:
254  * - operator()() calls compareLessThan() with the stored propId() and order().
255  * - \ref compareLessThan() in turns calls entryValue() to get string representations of the
256  *   values of the property to compare for each entry, and compares the strings with
257  *   \ref QString::localeAwareCompare().
258  * - \ref entryValue() provides sensible string representations for the given property in the
259  *   given entry.
260  *
261  * \note The column number may be set to be equal \c -1, to indicate an invalid sorter (maybe
262  *   to indicate that a list should not be sorted). However, the functions \ref entryValue(),
263  *   \ref compareLessThan() and operator()() are NOT meant to be used with an invalid \c propId.
264  *   In other words, if isValid() is false (or equivalently, if \ref propId() is negative), don't
265  *   attempt any sorting or comparisions.
266  *
267  * To customize the behaviour of this class, you may subclass it and reimplement any level
268  * of its behavior, eg. you may want to just reimplement entryValue() to alter the string
269  * representation of the values of some properties, or you could reimplement compareLessThan()
270  * to do more sophisticated comparisions.
271  *
272  * \note There is no copy constructor. If there was, there would be no way of customizing the sort
273  *   behavior. To use the entry sorter in contexts where you need to copy an object, use the
274  *   clone mechanism with the clone constructor. (Although this should scarcely be needed ...).
275  */
276 class KLF_EXPORT KLFLibEntrySorter
277 {
278 public:
279   KLFLibEntrySorter(int propId = -1, Qt::SortOrder order = Qt::AscendingOrder);
280   /** Used to "circumvent" the copy-constructor issues of reimplemented functions.
281    * If an object is constructed using this constructor all calls to entryValue(),
282    * compareLessThan(), and operator()() are redirected to clone's.
283    *
284    * Calls to setPropId() and setOrder() will fail and emit a warning.
285    *
286    * In particular, never pass 'this' nor 'NULL' as clone!
287    */
288   KLFLibEntrySorter(const KLFLibEntrySorter *clone);
289   virtual ~KLFLibEntrySorter();
290 
isValid()291   inline bool isValid() const { return (pPropId >= 0); }
292 
293   //! The currently set property that will be queried in the items we're sorting
propId()294   inline int propId() const { return pPropId; }
295   //! The currently set sorting order
order()296   inline Qt::SortOrder order() const { return pOrder; }
297 
298   //! Set the KLFLibEntry property id the sort will take into account
299   virtual void setPropId(int propId);
300   //! Set the sort order
301   virtual void setOrder(Qt::SortOrder order);
302 
303   //! Returns a string representation of the given property in the given entry
304   virtual QString entryValue(const KLFLibEntry& entry, int propId) const;
305 
306   //! Compares entries two entries according to the given property and order
307   /** Compares the given property of entries \c a and \c b.
308    *
309    * When \c order is \c Qt::Ascending, if \c a is found to be less than (and not equal) to
310    * \c b, then TRUE is returned, otherwise FALSE is returned.
311    *
312    * If the \c order is \c Qt::Descending, if \c b is found to be less than (and not equal) to
313    * \c a, then TRUE is returned, otherwise FALSE is returned.
314    */
315   virtual bool compareLessThan(const KLFLibEntry& a, const KLFLibEntry& b,
316 			       int propId, Qt::SortOrder order) const;
317 
318   /** This is a wrapper that calls \ref compareLessThan() with the previously set
319    * propId() and order().
320    */
321   virtual bool operator()(const KLFLibEntry& a, const KLFLibEntry& b) const;
322 
323 
324 private:
325   const KLFLibEntrySorter * pCloneOf;
326 
327   int pPropId;
328   Qt::SortOrder pOrder;
329 };
330 
331 
332 
333 /** \brief An abstract resource engine
334  *
335  * This class is the base of all resource types. Subclasses (e.g. KLFLibDBEngine) implement
336  * the actual access to the data, while this class defines the base API that will be used
337  * by e.g. the library browser (through a KLFAbstractLibView subclass) to access the data.
338  *
339  * Subclasses may choose to implement various features specified by the \ref ResourceFeature
340  * enum. The supported features must be passed (binary OR-ed) to the constructor.
341  *
342  * Library resources provide entries without any particular order.
343  *
344  * Library entries are communicated with KLFLibEntry objects. Each entry in the resource must
345  * be attributed a numerical ID, which is unique within the resource, in particular not
346  * necessarily globally unique among all open resources. For engines implementing the
347  * \ref FeatureSubResources feature, the attributed IDs have only to be unique within the
348  * sub-resource the entry lives in.
349  *
350  * Entries are queried by calling for example the functions: \ref allEntries(), \ref entries(),
351  * \ref entry(). See the individual function documentation for more details.
352  *
353  * The API in this class for accessing data is pretty elaborate. You may consider to subclass
354  * \ref KLFLibResourceSimpleEngine, which requires you to implement a simpler API, but at the
355  * price of not being able to take profit of the optimization opportunities given by the
356  * more complicated API.
357  *
358  * <b>Resource Properties</b>. Resources have properties (stored in a
359  * KLFPropertizedObject structure, NOT in regular QObject
360  * properties) that ARE STORED IN THE RESOURCE DATA ITSELF. Built-in properties are listed
361  * in the \ref ResourceProperty enum. Some properties may be implemented read-only
362  * (eg. \ref PropAccessShared) in which case saveResourceProperty() should return FALSE.
363  *
364  * The view used to display this resource is stored in the "ViewType" resource property (and
365  * thus should be stored in the backend data like other properties).
366  *
367  * <b>Note on URL</b>. The URL is not a resource property as it is not stored in the resource
368  * itself. However the resource engine instance knows about the url it is manipulating
369  * (because subclasses pass the relevant url as parameter in the constructor). However, the
370  * URL itself blindly stored and reprovided when requested; it is not used by
371  * KLFLibResourceEngine itself. Small exception: in the constructor, some query items are
372  * recognized and stripped from the URL. See below.
373  *
374  * <b>Read-Only Mode</b>. The read-only mode differs from the locked property in that the
375  * mode is activated by the accessor only and is NOT stored in the resource data eg. on disk
376  * (in contrast to the locked property). It is up to SUBCLASSES to enforce this flag and
377  * prevent data from being modified if isReadOnly() is TRUE.<br>
378  * Subclasses may prevent read-only mode by not specifying
379  * the FeatureReadOnly in the constructor. In this case the default implementation of
380  * \ref setReadOnly() will return FALSE without doing anything. Also in this case, any
381  * occurrence of the query item "klfReadOnly" in the URL is stripped and ignored.
382  *
383  * <b>Sub-Resources</b>. Sub-resources are a way of logically separating the contents of
384  * a resource into separate so-called "sub-resources", like for example a library could
385  * contain a sub-resource "History", "Archive" etc. Derived subclasses don't have to
386  * implement subresources, they can specify if subresources are available using the
387  * FeatureSubResources flag in the constructor. In classes implementing sub-resources,
388  * the <i>default sub-resource</i> (queried by \ref defaultSubResource() and set by
389  * \ref setDefaultSubResource()) is the resource that the \ref insertEntry(),
390  * \ref changeEntries(), etc.
391  * family functions will access when the variant of the function without sub-resource
392  * argument is called.
393  *
394  * <b>Sub-Resource Properties</b>. Sub-resources, when implemented by the subclass, may
395  * each have properties (the API would suggest subclasses to store these property values
396  * into \ref KLFPropertizedObject's). The properties (structure+values) are NOT stored
397  * by KLFLibResourceEngine itself, all the work must be done by the subclass, in particular
398  * reimplementing \ref subResourceProperty() and \ref setSubResourceProperty(). Again this
399  * feature is implemented by the subclass if and only if the subclass specified
400  * \ref FeatureSubResourceProps in the constructor argument. In this case note also that views
401  * may for example expect the resource to provide values for the sub-resource properties defined
402  * by \ref SubResourceProperty.
403  *
404  * <b>query Items in URL</b>. The URL may contain query items e.g.
405  * <tt>scheme://klf.server.dom/path/to/location<b>?klfReadOnly=true</b></tt>. Here is a
406  * list of recognized (universal) query items. Subclasses may choose to recognize more query
407  * items, but these listed here are detected in the KLFLibResourceEngine constructor and
408  * the appropriate flags are set (eg. \ref isReadOnly()):
409  * - <tt>klfReadOnly=</tt>{<tt>true</tt>|<tt>false</tt>} If provided, sets the read-only
410  *   flag to the given value. If not provided, the flag defaults to false (flag is directly
411  *   set, bypassing the setReadOnly() function).
412  * - <tt>klfDefaultSubResource=<i>sub-resource name</i></tt> If provided, specifies which
413  *   sub-resource (which has to be present in the given location) should be opened by default.
414  *   See \ref setDefaultSubResource().
415  * .
416  * Note that recognized query items (and <i>only</i> the query items recognized at the
417  * KLFLibResourceEngine level) are stripped from the \ref url() as they are parsed. Subclasses
418  * may choose to (independently) recognize and strip other query items from URL if it is relevant
419  * to do so.
420  *
421  * <b>NOTES FOR SUBCLASSES</b><br>
422  * - Subclasses must deal with the properties and implement them as they are meant to, and
423  *   as they have been documented in their respective functions (see \ref locked(), \ref title()).
424  *   For example, if a resource is \ref locked(), then \ref canModifyData() and \ref canModifyProp()
425  *   must return FALSE and any attempt to modify the resource must fail.
426  * - Subclasses must reimplement \ref saveResourceProperty() to save the new property value
427  *   to the backend data, or return FALSE to cancel the resource change. Calls to
428  *   \ref setLocked(), \ref setTitle() or setViewType() all call in turn \ref setResourceProperty(),
429  *   the default implementation of which is usually sufficient, which calls in turn
430  *   \ref saveResourceProperty().
431  * - See also docs for \ref setResourceProperty() and \ref saveResourceProperty().
432  * - The \ref resourcePropertyChanged() is emitted in the default implementation of
433  *   \ref setResourceProperty().
434  * - lengthy operations should emit the signal \ref operationStartReportingProgress() with a suitable
435  *   KLFProgressReporter as necessary to inform callers of progress of operations that can take some
436  *   time. This is recommended, but subclasses aren't forced to comply (for laziness' sake for ex...).
437  *   However, subclasses should test ONCE per operation whether \ref thisOperationProgressBlocked() and
438  *   should not emit progress in that case.
439  */
440 class KLF_EXPORT KLFLibResourceEngine : public QObject, public KLFPropertizedObject
441 {
442   Q_OBJECT
443 public:
444   typedef KLFLib::entryId entryId;
445 
446   //! A KLFLibEntry in combination with a KLFLib::entryId
447   struct KLFLibEntryWithId {
448     KLFLibEntryWithId(entryId i = -1, const KLFLibEntry& e = KLFLibEntry())
idKLFLibEntryWithId449       : id(i), entry(e) { }
450     entryId id;
451     KLFLibEntry entry;
452   };
453 
454   /** List of built-in KLFPropertizedObject-properties. See
455    * \ref KLFLibResourceEngine "class documentation" and \ref setResourceProperty(). */
456   enum ResourceProperty {
457     PropTitle = 0,
458     PropLocked,
459     PropViewType,
460     PropAccessShared
461   };
462 
463   /** List of pre-defined properties that can be applied to sub-resources when the features
464    * \ref FeatureSubResources and \ref FeatureSubResourceProps are implemented. See also
465    * \ref setSubResourceProperty().
466    *
467    * \note These properties, by contrast to resource properties, have fixed numerical IDs, since
468    *   sub-resource properties are not backed by a KLFPropertizedObject object. */
469   enum SubResourceProperty {
470     SubResPropTitle    = 0,
471     SubResPropLocked   = 1,
472     SubResPropViewType = 2
473   };
474 
475   //! Features that may or may not be implemented by subclasses
476   /** These binary codes specify features that a subclass may or may not implement.
477    *
478    * The subclass provides the binary combination of the exact features it supports in the
479    * constructor argument in \ref KLFLibResourceEngine().
480    *
481    * The flags can be accessed with a call to \ref supportedFeatureFlags(). They cannot be
482    * modified after the constructor call.
483    *
484    * See this \ref KLFLibResourceEngine "class documentation" for more details.
485    */
486   enum ResourceFeature {
487     //! Open in Read-Only mode
488     /** Flag indicating that this resource engine supports opening a location in read-only mode.
489      * This resource explicitely checks that we're not \ref isReadOnly() before modifying the
490      * resource contents. */
491     FeatureReadOnly		= 0x0001,
492     //! Lock the resource
493     /** Flag indicating that this resource engine supports the resource property \ref PropLocked,
494      * can modify that property and checks that we're not \ref locked() before modifying the
495      * resource contents.
496      *
497      * Resources supporting feature \ref FeatureSubResourceProps, in combination with this feature
498      * (FeatureLocked) are also expected to treat properly locked sub-resources (ie. sub-resource
499      * property \ref SubResPropLocked). */
500     FeatureLocked		= 0x0002,
501     //! Implements the \ref saveTo() function
502     /** Flag indicating that this resource engine implements the saveTo() function, ie. that
503      * calling it has a chance that it will not fail */
504     FeatureSaveTo		= 0x0004,
505     //! Data can be stored in separate sub-resources
506     /** Flag indicating that this resource engine supports saving and reading data into different
507      * "sub-resources". See \ref KLFLibResourceEngine "class documentation" for details. */
508     FeatureSubResources		= 0x0008,
509     //! Sub-Resources may be assigned properties and values
510     /** Flag indicating that this resource engine supports saving and reading sub-resource
511      * property values. This flag makes sense only in combination with \c FeatureSubResources.
512      * Note that views may assume that implementing sub-resource properties means also providing
513      * sensible values and/or loaded/stored values for the built-in sub-resource properties
514      * described in the \ref SubResourceProperty enum. */
515     FeatureSubResourceProps	= 0x0010
516   };
517 
518   /**
519    *
520    * \note If the URL \c url needs to be normalized in some way (eg. convert some query item
521    * values to lower case, ...), then you need to implement a static function, eg.
522    * \code
523    * static KLFMyEngine * openURL(const QUrl& url) {
524    *   QUrl normalized = url;
525    *   // ... normalize URL ...
526    *   return new KLFMyEngine(normalized, ...);
527    * }
528    * KLFMyEngine::KLFMyEngine(const QUrl& url, ...) : KLFLibResourceEngine(url,...)
529    * {
530    *   // ...
531    * }
532    * \endcode
533    * which will pass the normalized URL here. You cannot change the URL once it has been
534    * passed to the constructor. Note however that the stored URL has some elements stripped,
535    * as described in the class documentation \ref KLFLibResourceEngine, which you can
536    * change via the API (eg. setDefaultSubResource()).
537    */
538   KLFLibResourceEngine(const QUrl& url, uint supportedfeatureflags, QObject *parent = NULL);
539 
540   virtual ~KLFLibResourceEngine();
541 
542   //! List of features supported by this resource engine
543   /** Use this function to probe whether this resource instance supports a specific
544    * feature. For example a property editor widget might want to know if this resource
545    * supportes the \ref FeatureLocked feature, to enable or disable the corresponding
546    * check box.
547    *
548    * Do not reimplement in subclasses, simply pass the feature flags to the constructor.
549    * */
supportedFeatureFlags()550   virtual uint supportedFeatureFlags() const { return pFeatureFlags; }
551 
552   //! Format options one can give to \ref url()
553   enum WantUrlFormatFlag {
554     //! Add a query item for default sub-res. as \c "klfDefaultSubResource"
555     WantUrlDefaultSubResource = 0x01,
556     //! Add a query item for read-only status, as \c "klfReadOnly"
557     WantUrlReadOnly = 0x02
558   };
559   //! query URL
560   /** Returns the identifying URL of this resource.
561    *
562    * \note This is not quite the URL passed to the constructor. Some query items are recognized
563    *   and stripped. See the \ref KLFLibResourceEngine "Class Documentation" for more information.
564    *
565    * Flags may be specified as to which query items we would like to add to URL (eg. default
566    * sub-resource, read-only status). see \ref WantUrlFormatFlag.
567    *
568    * See also \ref KLFAbstractLibView::url(). That function gives also information on what part
569    * of the resource it displays.
570    */
571   virtual QUrl url(uint flags = 0x0) const;
572 
573   //! Compare this resource's URL with another's
574   /** Compares the URL of this resource with \c other, and returns a binary OR'ed value of
575    * KlfUrlCompareFlag enum values of tests that have proved true (see KlfUrlCompareFlag
576    * for a list of URL-comparision tests in klfutil.h in klftools).
577    *
578    * This function should return the following flag, if its corresponding tests turn out
579    * to be true. This function should NOT return any other flag that is not listed here.
580    * - \c KLFUrlComapreBaseEqual should be set if this resource shares its data with the resource
581    *   given by URL \c other. Default sub-resources are to be ignored.
582    *
583    * The \c interestFlags is a binary OR'ed value of KlfUrlCompareFlag values of tests
584    * to be performed. Any flag that is set in \c interestFlags indicates that the return
585    * value of this function, when binary-AND'ed with that flag, is the result (T or F)
586    * of the test the flag stands for. However, if a flag is not set in \c interestFlags,
587    * its state in the return value by this function is undefined.
588    *
589    * See also klfUrlCompare().
590    */
591   virtual uint compareUrlTo(const QUrl& other, uint interestFlags = 0xfffffff) const = 0;
592 
593   //! query read-only state
594   /** See \ref KLFLibResourceEngine "Class Documentation" for more details. */
isReadOnly()595   virtual bool isReadOnly() const { return pReadOnly; }
596 
597   //! The human-set title of this resource
598   /** See \ref setTitle(). */
title()599   virtual QString title() const { return KLFPropertizedObject::property(PropTitle).toString(); }
600 
601   //! Is this resource is locked?
602   /** If the resource is locked (property \ref PropLocked), no changes can be in principle made,
603    * except <tt>setLocked(false)</tt> (of course...).
604    *
605    * Note: the subclass is responsible to check in functions such as insertEntry(), that the
606    * resource is not locked and not read-only etc. (checked all-in-one with \ref canModifyData()).
607    *
608    * The default implementation has some limited support for the locked property: see
609    * \ref setLocked(). */
locked()610   virtual bool locked() const { return KLFPropertizedObject::property(PropLocked).toBool(); }
611 
612   //! The (last) View Type used to display this resource
viewType()613   virtual QString viewType() const
614   { return KLFPropertizedObject::property(PropViewType).toString(); }
615 
616   //! If the resource is accessed by many clients
617   /** Whether the resource is meant to be shared by many clients (eg. a remote database access)
618    * or if it is local and we're the only one to use it (eg. a local sqlite file).
619    *
620    * This property may be used by views to decide if they can store meta-information about the
621    * view state in the resource itself (icon positions in icon view mode for example). */
accessShared()622   virtual bool accessShared() const
623   { return KLFPropertizedObject::property(PropAccessShared).toBool(); }
624 
625   //! Get the value of a resource property
626   /** Returns the value of the given resource property. If the property is not registered,
627    * returns an invalid QVariant with a warning.
628    *
629    * For built-in resource properties, consider using the simpler \ref locked(), \ref title()
630    * and \ref viewType() methods (for example). */
631   virtual QVariant resourceProperty(const QString& name) const;
632 
633   enum ModifyType {
634     AllActionsData = 0,
635     UnknownModification = 0,
636     InsertData,
637     ChangeData,
638     DeleteData
639   };
640 
641   /** Returns TRUE here if it is possible to modify the resource's data in the way described
642    * by \c modifytype (see \ref ModifyType enum).
643    *
644    * Engines supporting feature \ref FeatureSubResources should return TRUE or FALSE whether
645    * it is possible to perform the requested action in the given sub-resource \c subResource.
646    * Other engines should ignore the \c subResource parameter.
647    *
648    * For engines supporting all of \ref FeatureSubResources, \ref FeatureSubResourceProps, and
649    * \ref FeatureLocked the default implementation checks whether the sub-resource is locked
650    * by querying \ref subResourceProperty(\ref SubResPropLocked).
651    *
652    * \c modifytype must be one of AllActionsData, InsertData, ChangeData, DeleteData.
653    *
654    * The base implementation returns TRUE only if the current resource is not read-only (see
655    * \ref isReadOnly()) and is not locked (see \ref locked()). Subclasses should reimplement
656    * this function to add more sophisticated behaviour, eg. checking that an open file is not
657    * read-only, or that a DB user was granted the correct rights, etc.
658    *
659    * \warning subclasses should call the base implementation to e.g. take into account
660    * eg. the \ref locked() property. If the base implementation returns FALSE, then the
661    * subclasses should also return FALSE. */
662   virtual bool canModifyData(const QString& subResource, ModifyType modifytype) const;
663 
664   /** This function is provided for convenience for resource not implementing
665    * \ref FeatureSubResources, or Views relying on the default sub-resource.
666    *
667    * \warning Subclasses should normally not reimplement this function, but rather the
668    *   canModifyData(const QString&, ModifyType) function, even if they do not support
669    *   sub-resources!
670    *
671    * The default implementation of this function (which should be sufficient in a vast majority
672    * of cases) calls
673    * \code
674    *  canModifyData(defaultSubResource(), modifytype)
675    * \endcode
676    * as one would expect.
677    */
678   virtual bool canModifyData(ModifyType modifytype) const;
679 
680   /** Subclasses should return TRUE here if it is possible to modify the resource's property
681    * identified by \c propId. Return for ex. false when opening a read-only file.
682    *
683    * \warning subclasses should call the base implementation to e.g. take into account
684    * the \ref locked() property and \ref isReadOnly() state. If the base implementation
685    * returns FALSE, then the subclasses should also return FALSE.
686    *
687    * If \c propId is negative, then a more general "Can we generally speaking modify properties
688    * right now?" is returned.
689    *
690    * \note The base implementation returns TRUE if the resource is locked but if \c propId is
691    * \ref PropLocked (to be able to un-lock the resource!) */
692   virtual bool canModifyProp(int propId) const;
693 
694   /** Subclasses should return TRUE if they can handle a new resource property that they
695    * (maybe) haven't yet heard of, and if they can handle saving and loading the property
696    * as a \ref QVariant to and from the backend data.
697    *
698    * Call \ref loadResourceProperty() to actually register the property and save a value
699    * to it. */
700   virtual bool canRegisterProperty(const QString& propName) const;
701 
702   /** Suggested library view widget to view this resource with optimal user experience :-) .
703    * Return QString() for default view. */
suggestedViewTypeIdentifier()704   virtual QString suggestedViewTypeIdentifier() const { return QString(); }
705 
706   /** Returns TRUE if this resource supports sub-resources and contains a sub-resource
707    * named \c subResource.
708    *
709    * The default implementation checks that the \ref FeatureSubResources is supported, and
710    * that \ref subResourceList() contains \c subResource (with exact string match).
711    *
712    * If subclasses have a more optimized method to check this, they may (but need not
713    * necessarily) reimplement this function to optimize it.
714    *
715    * Engines that have case-insensitive resource names (eg. SQL tables) must reimplement
716    * this function to do a case-insensitive test.
717    */
718   virtual bool hasSubResource(const QString& subResource) const;
719 
720   /** Returns a list of sub-resources in this resource. This function is relevant only
721    * if the \ref FeatureSubResources is implemented. */
subResourceList()722   virtual QStringList subResourceList() const { return QStringList(); }
723 
724   /** Returns the default sub-resource, ie. the sub-resource to access if eg. the variant
725    * of insertEntry() without the sub-resource argument is called.
726    *
727    * This is relevant only if the engine supports feature \ref FeatureSubResources.
728    */
729   virtual QString defaultSubResource() const;
730 
731   /** \brief Compare our sub-resource name to another
732    *
733    * Returns TRUE if our default sub-resource name equals \c subResource, FALSE otherwise.
734    *
735    * The default implementation tests for string equality (case sensitive). If sub-resources
736    * in the reimplemented engine are case-insensitive, then reimplement this function to
737    * compare string case-insensitive.
738    */
739   virtual bool compareDefaultSubResourceEquals(const QString& subResourceName) const;
740 
741   /** Returns TRUE if we can create a new sub-resource in this resource.
742    *
743    * This function can be reimplemented if the resource supports feature \ref FeatureSubResources.
744    *
745    * The default implementation returns FALSE.
746    */
747   virtual bool canCreateSubResource() const;
748 
749   /** Returns TRUE if we can give the sub-resource \c subResource a new name. More specifically,
750    * returns TRUE if \ref renameSubResource() on that sub-resource has chances to succeed.
751    *
752    * This function can be reimplemented if the resource supports feature \ref FeatureSubResources.
753    *
754    * The default implementation returns FALSE.
755    */
756   virtual bool canRenameSubResource(const QString& subResource) const;
757 
758   /** Returns TRUE if we can completely delete sub-resource \c subResource from the resource.
759    *
760    * If this function returns FALSE, a subsequent call to deleteSubResoruce() is certain
761    * to fail.
762    *
763    * The default implementation returns FALSE.
764    */
765   virtual bool canDeleteSubResource(const QString& subResource) const;
766 
767   /** Queries properties of sub-resources. The default implementation returns an empty
768    * QVariant(). Test the \ref supportedFeatureFlags() for \ref FeatureSubResourceProps to
769    * see if this feature is implemented. In particular, subclasses should specify whether
770    * they implement this feature by passing the correct feature flags. */
771   virtual QVariant subResourceProperty(const QString& subResource, int propId) const;
772 
773   /** Returns a list of sub-resource properties that are supported by this resource.
774    *
775    * This function makes sense to be reimplemented and called only if this resource supports
776    * features \ref FeatureSubResources and \ref FeatureSubResourceProps.
777    *
778    * The default implementation returns an empty list.
779    */
subResourcePropertyIdList()780   virtual QList<int> subResourcePropertyIdList() const { return QList<int>(); }
781 
782   /** Returns a property name for the sub-resource property \c propId.
783    *
784    * The name should be significant but machine-compatible (in particular, NOT translated) as
785    * it could be used to identify the property for example to save it possibly...
786    *
787    * the default implementation returns reasonable names for \c SubResPropTitle,
788    * \c SubResPropLocked, and \c SubResPropViewType, and returns the \c propId in a string
789    * for other IDs (\ref QString::number()).
790    *
791    * This function makes sense to be called only for engines supporting
792    * \ref FeatureSubResourceProps.
793    */
794   virtual QString subResourcePropertyName(int propId) const;
795 
796   /** Returns TRUE if the property \c propId in sub-resource \c subResource can be modified.
797    *
798    * This function should not be called or reimplemented for classes not supporting feature
799    * \ref FeatureSubResourceProps.
800    *
801    * The default implementation provides a basic functionality based on \ref baseCanModifyStatus().
802    * If the modifiable status of the sub-resource \c subResource is \ref MS_CanModify, or if the
803    * status is \ref MS_IsLocked but the \c propId we want to modify is \ref SubResPropLocked, this
804    * function returns TRUE. In other cases it returns FALSE.
805    *
806    * In short, it behaves as you would expect it to: protect against modifications but allow
807    * un-locking of a locked sub-resource.
808    */
809   virtual bool canModifySubResourceProperty(const QString& subResource, int propId) const;
810 
811   //! query an entry in this resource
812   /** Returns the entry (in the sub-resource \c subResource) corresponding to ID \c id, or an
813    * empty KLFLibEntry() if the \c id is not valid.
814    *
815    * \note Subclasses must reimplement this function to behave as described here.
816    *
817    * For resources implementing \ref FeatureSubResources, the \c subResource argument specifies
818    * the sub-resource in which the entry should be fetched. Classes not implementing this feature
819    * should ignore this parameter.
820    *  */
821   virtual KLFLibEntry entry(const QString& subResource, entryId id) = 0;
822 
823   //! query an entry in this resource
824   /** Returns the entry (for classes implementing the \ref FeatureSubResources, queries the default
825    * sub-resource) corresponding to ID \c id, or an empty KLFLibEntry() if the \c id is not valid.
826    *
827    * The default implementation calls \ref entry(const QString& subResource, entryId id) with
828    * the default subresource as argument. See \ref setDefaultSubResource().
829    */
830   virtual KLFLibEntry entry(entryId id);
831 
832   //! query the existence of an entry in this resource
833   /** Returns TRUE if an entry with entry ID \c id exists in this resource, in the sub-resource
834    * \c subResource, or FALSE otherwise.
835    *
836    * \note Subclasses must reimplement this function to behave as described here.
837    */
838   virtual bool hasEntry(const QString& subResource, entryId id) = 0;
839 
840   //! query the existence of an entry in this resource
841   /** Returns TRUE if an entry with entry ID \c id exists in this resource or FALSE otherwise.
842    * Classes implementing the \ref FeatureSubResources will query the default sub-resource, see
843    * \ref setDefaultSubResource().
844    *
845    * The default implementation calls \ref hasEntry(const QString& subResource, entryId id) with
846    * the default subresource as argument. See \ref setDefaultSubResource().
847    */
848   virtual bool hasEntry(entryId id);
849 
850   //! query multiple entries in this resource
851   /** Returns a list of \ref KLFLibResourceEngine::KLFLibEntryWithId "KLFLibEntryWithId" s, that
852    * is a list of KLFLibEntry-ies with their corresponding IDs, exactly corresponding to the
853    * requested entries given in idList. The same order of entries in the returned list as in the
854    * specified \c idList is garanteed. For classes implementing sub-resources
855    * (\ref FeatureSubResources), the sub-resource \c subResource is queried.
856    *
857    * The KLFLibEntry objects are populated only of the required \c wantedEntryProperties, which is
858    * a list of IDs of KLFLibEntry properties (the KLFPropertizedObject-kind properties) that are
859    * set in the KLFLibEntry object. The other fields are left undefined. If the property
860    * list is empty (by default), then all properties are fetched and set.
861    *
862    * If in the list an ID is given which does not exist in the resource, a corresponding
863    * KLFLibEntryWithId entry is returned in which the \c entry is set to an empty \c KLFLibEntry()
864    * and the \c id is set to \c -1.
865    *
866    * If \c idList is empty, then this function returns an empty list.
867    *
868    * \note Subclasses must reimplement this function to behave as described here.
869    * */
870   virtual QList<KLFLibEntryWithId> entries(const QString& subResource,
871 					   const QList<KLFLib::entryId>& idList,
872 					   const QList<int>& wantedEntryProperties = QList<int>()) = 0;
873 
874   //! query multiple entries in this resource
875   /** Returns a list of \ref KLFLibEntryWithId's, that is a list of KLFLibEntry-ies with their
876    * corresponding IDs, exactly corresponding to the requested entries given in idList. The same
877    * order of entries in the returned list as in the specified \c idList is garanteed. For classes
878    * implementing sub-resources (\ref FeatureSubResources), the default sub-resource is
879    * queried, see \ref setDefaultSubResource().
880    *
881    * The KLFLibEntry objects are populated only of the required \c wantedEntryProperties, which is
882    * a list of IDs of KLFLibEntry properties (the KLFPropertizedObject-kind properties) that are
883    * set in the KLFLibEntry object. The other fields are left undefined. If the property
884    * list is empty (by default), then all properties are fetched and set.
885    *
886    * If in the list an ID is given which does not exist in the resource, a corresponding
887    * KLFLibEntryWithId entry is returned in which the \c entry is set to an empty \c KLFLibEntry()
888    * and the \c id is set to \c -1.
889    *
890    * If \c idList is empty, then this function returns an empty list.
891    *
892    * The default implementation calls
893    * \ref entries(const QString& subResource, const QList<KLFLib::entryId>& idList, const QList<int>&)
894    * with the default subresource as argument. See \ref setDefaultSubResource().
895    */
896   virtual QList<KLFLibEntryWithId> entries(const QList<KLFLib::entryId>& idList,
897 					   const QList<int>& wantedEntryProperties = QList<int>());
898 
899 
900   /** \brief A structure that describes a query for query()
901    *
902    * The following properties should be adjusted (by direct access) before calling query().
903    *
904    * \c matchcondition is an \ref KLFLib::EntryMatchCondition struct that tells which properties have to be
905    * matched, how, and to what value. Only entries that match the match condition set in \c query will
906    * be returned by query(). Note that the match condition itself may be a complex condition, like an OR
907    * and AND tree of property matching conditions with strings or regexps. See \ref KLFLib::EntryMatchCondition,
908    * and \ref KLFLib::PropertyMatch for more info. The idea is that engines can translate such conditions into,
909    * eg. a SQL WHERE condition for optimized entry queries.
910    *
911    * The default match condition (set automatically in constructor) matches all entries.
912    *
913    * The first \c skip results will be ignored, and the first returned result will be the <tt>skip</tt>'th
914    * entry (that is counting from 0; or the <tt>skip+1</tt>'th, counting more intuitively from 1). By default,
915    * \c skip is zero, so no entries are skipped. The entries must be skipped \a after they have been sorted.
916    * The query() function's return value (entry count) does not include the skipped entries.
917    *
918    * A \c limit may be set to limit the number of returned results (default is \c -1, meaning no limit).
919    *
920    * \c orderPropId specifies along which KLFLibEntry property ID the items should be ordered. This
921    * can be \c -1 to specify that elements should not be ordered; their order will then be undefined.
922    * Default value: \c -1.
923    *
924    * \c orderDirection specifies in which direction the elements should be ordered. This can be
925    * Qt::AscendingOrder or Qt::DescendingOrder (lesser value first or greater value first).
926    *
927    * \c wantedEntryProperties is a list of properties the lists should be filled with. Elements in the
928    * entryWithIdList and rawEntryList lists will only have those properties listed in
929    * \c wantedEntryProperties set. The other properties are undefined (some implementations may decide
930    * to ignore this optimization). An empty list (which is the default) indicates that all entry
931    * properties have to be set.
932    */
933   struct Query
934   {
935     /** Default constructor. sets reasonable default values as documented in class doc. */
QueryQuery936     Query()
937       : matchCondition(KLFLib::EntryMatchCondition::mkMatchAll()),
938 	skip(0),
939 	limit(-1),
940 	orderPropId(-1),
941 	orderDirection(Qt::AscendingOrder),
942 	wantedEntryProperties(QList<int>())
943     {
944     }
945 
946     KLFLib::EntryMatchCondition matchCondition;
947     int skip;
948     int limit;
949     int orderPropId;
950     Qt::SortOrder orderDirection;
951     QList<int> wantedEntryProperties;
952   };
953 
954   /** \brief A structure that will hold the result of a query() query.
955    *
956    * This class will contain the entry ID list, the raw entry list and the entry-with-id
957    * list of the entries that matched the query() query this object was given to.
958    *
959    * \c fillFlags may specify which of the aforementioned lists are to be filled (those that are
960    * not needed by the caller don't have to be filled, this saves time). You may pass those flags
961    * to the constructor.
962    *
963    * Once the \c fillFlags adjusted, pass a pointer to this object to the query() function to
964    * retrieve results.
965    *
966    * \warning The lists in this object are not garanteed to be cleared at the beginning of
967    *   query(). If you recycle this object to call query() a second time, be sure to clean this
968    *   object first.
969    */
970   struct QueryResult
971   {
972     enum Flags { FillEntryIdList = 0x01, FillRawEntryList = 0x02, FillEntryWithIdList = 0x04 };
973 
974     /** Constructor. Sets \c fillFlags as given, and sets reasonable default values for the other
975      * members. */
fillFlagsQueryResult976     QueryResult(uint fill_flags = 0x00)  : fillFlags(fill_flags)   {  }
977     uint fillFlags;
978 
979     QList<KLFLib::entryId> entryIdList;
980     KLFLibEntryList rawEntryList;
981     QList<KLFLibEntryWithId> entryWithIdList;
982   };
983 
984 
985   //! query entries in this resource with specified property values
986   /** Returns a list of all entries in this resource (and in sub-resource \c subResource
987    * for the engines supporting this feature) that match all the required matches specifed
988    * in \c matchcondition.
989    *
990    * \note the subclass is responsible for providing a functional implementation of this function.
991    *   Subclasses that don't want to pass much time to implement this feature can resort to calling
992    *   the static method \ref KLFLibResourceSimpleEngine::queryImpl() that provides a functional
993    *   (but not very optimized) default implementation; the
994    *   KLFLibResourceSimpleEngine::testMatchConditionImpl() function may prove useful for testing match
995    *   conditions; and the utilities KLFLibEntrySorter and KLFLibResourceSimpleEngine::QueryResultListSorter
996    *   might prove useful for sorting entries in conjuction with qLowerBound().
997    *
998    * \c query is a \ref Query object that describes the query. See \ref Query for details.
999    *
1000    * \c result is a \ref QueryResult structure that will be filled with the queried data. See
1001    * \ref QueryResult for details.
1002    *
1003    * The matches are returned in the following way into the \c result structure:
1004    *   - if the appropriate flag in \c result is set, then <tt>result.entryIdList</tt> is set to a list
1005    *     of all entry IDs that matched
1006    *   - if the appropriate flag in \c result is set, then <tt>result.rawEntryList</tt> is set to a list
1007    *     of all entries that matched, stored as KLFLibEntry objects. Only the requested properties
1008    *     are populated (specified by <tt>query.wantedEntryProperties</tt>)
1009    *   - if the appropriate flag in \c result is set, then <tt>result.entryWithIdList</tt> is set
1010    *     to a list of all entries, with their corresponding entry ID, that matched (similar to the
1011    *     return value of allEntries()). Only the requested properties are populated (as specified
1012    *     by <tt>result.wantedEntryProperties</tt>.)
1013    *
1014    * If the \c orderPropId member in \c query is not \c -1, then the returned results (in all
1015    * to-be-filled lists) are ordered according to the entry property ID \c orderPropId, in the order
1016    * specified by \c orderDirection.
1017    *
1018    * \returns the number of items in the resource that matched. If a \c limit was set in \c query,
1019    *   then at most that many results are returned. \c 0 is returned if no match was found. \c -1
1020    *   can be returned to signify an error (eg. invalid regexp, i/o error, etc.).
1021    *
1022    * The KLFLibEntry objects are populated only of the required \c wantedEntryProperties as set in
1023    * \c query (see \ref Query), which is a list of IDs of KLFLibEntry properties (the
1024    * KLFPropertizedObject-kind properties) that are set in the KLFLibEntry object. If the property
1025    * list is empty (by default), then all properties are fetched and set. Note that if this list
1026    * is not empty, then the properties not in the list are undefined: they may be uninitialized,
1027    * set to null/invalid, or filled eg. by an implementation that ignores \c wantedEntryProperties.
1028    *
1029    * \note it is possible to specify a property ID in the match condition that isn't given in
1030    *   \c wantedEntryProperties, and reimplementations must handle this. <i>Reason: even if
1031    *   this may seem inconsistent, it can be easily implemented in some examples of engines (SQL
1032    *   condition, ...) and can easily be worked around in other engines by adding the requested
1033    *   property to the wanted property list. Example: listing entries by date/time order, without
1034    *   necessarily displaying the date/time.</i>
1035    */
1036   virtual int query(const QString& subResource, const Query& query, QueryResult *result) = 0;
1037 
1038 
1039   /** \brief List all distinct values that a property takes in all entries
1040    *
1041    * \return A list of all (distinct) values that a given property in all the entries of sub-resource
1042    *   \c subResource takes.
1043    *
1044    * For example, KLFLibModel uses this function in category tree mode to get the category tree,
1045    * by passing \ref KLFLibEntry::Category as \c entryPropId.
1046    *
1047    * The order of the elements within the returned list is not defined.
1048    *
1049    * In mathematical terms, if $f_{pid}(entry)$ is the value of property ID \c pid of the entry \c entry,
1050    * then this function returns the \a range (=set of all reached values) of $f_{pid}$.
1051    *
1052    * KLFLibResourceSimpleEngine::queryValuesImpl() offers a very simple non-optimized implementation
1053    * of this function that you can use in your resource engine subclass if you don't want to do this
1054    * yourself. That function is automatically re-implemented if you subclass KLFLibResourceSimpleEngine.
1055    */
1056   virtual QList<QVariant> queryValues(const QString& subResource, int entryPropId) = 0;
1057 
1058 
1059   //! Returns all IDs in this resource (and this sub-resource)
1060   /** Returns a list of the ID of each entry in this resource.
1061    *
1062    * If sub-resources are supported, then returns only IDs in the given \c subResource.
1063    * Otherwise, the \c subResource parameter should be ignored.
1064    */
1065   virtual QList<KLFLib::entryId> allIds(const QString& subResource) = 0;
1066 
1067   //! Returns all IDs in this resource (and the default sub-resource)
1068   /** Returns a list of the ID of each entry in this resource.
1069    *
1070    * If sub-resources are supported, then returns only IDs in the default sub-resource
1071    * given by \ref defaultSubResource().
1072    *
1073    * The base implementation calls \ref allIds(const QString&) with the default sub-resource
1074    * as parameter. Subclasses need not reimplement this function, but rather
1075    * \ref allIds(const QString&) instead.
1076    */
1077   virtual QList<KLFLib::entryId> allIds();
1078 
1079   //! query all entries in this resource
1080   /** Returns all the entries in this library resource (in sub-resource \c subResource if
1081    * \ref FeatureSubResources is supported) with their corresponding IDs.
1082    *
1083    * \note Subclasses must reimplement this function to behave as described here.
1084    */
1085   virtual QList<KLFLibEntryWithId> allEntries(const QString& subResource,
1086 					      const QList<int>& wantedEntryProperties = QList<int>()) = 0;
1087 
1088   //! query all entries in this resource
1089   /** Returns all the entries in this library resource (in default sub-resource if
1090    * \ref FeatureSubResources is supported) with their corresponding IDs.
1091    *
1092    * The default implementation calls
1093    * \ref allEntries(const QString& subResource, const QList<int>&) with the default subresource
1094    * as argument. See \ref setDefaultSubResource().
1095    */
1096   virtual QList<KLFLibEntryWithId> allEntries(const QList<int>& wantedEntryProperties = QList<int>());
1097 
1098 
1099   //! Specifies that the next operation (only) should not report progress
1100   void blockProgressReportingForNextOperation();
1101 
1102   //! (Un)Blocks generally progress reporting
1103   void blockProgressReporting(bool block);
1104 
1105 signals:
1106   //! Emitted when data has changed
1107   /** This signal is emitted whenever data changes in the model (eg. due to an \ref insertEntries()
1108    * function call).
1109    *
1110    * The parameter \c subResource is the sub-resource in which the change was observed.
1111    *
1112    * The parameter \c modificationType is the type of modification that occured. It is one
1113    * of \ref InsertData, \ref ChangeData, \ref DeleteData, or \ref UnknownModification. (In
1114    * particular, sub-classes should not emit other modification types). The \c int type is
1115    * used for compatibility in Qt's SIGNAL-SLOT mechanism.
1116    *
1117    * An \c UnknownModification change means either the library resource changed completely,
1118    * or simply the backend does not wish to privide any information on which entries changed.
1119    * In any case, the receiver should consider all previously read data from the resource as
1120    * out of date and refresh all.
1121    *
1122    * The entries that were changed are given in the argument \c entryIdList.
1123    */
1124   void dataChanged(const QString& subResource, int modificationType,
1125 		   const QList<KLFLib::entryId>& entryIdList);
1126 
1127   //! Emitted when the default sub-resource changes.
1128   void defaultSubResourceChanged(const QString& newDefaultSubResource);
1129 
1130   //! Emitted when a resource property changes.
1131   /** \param propId the ID of the property that changed. */
1132   void resourcePropertyChanged(int propId);
1133 
1134   //! Emitted when a sub-resource property changes.
1135   /** This signal should only be emitted by engines supporting feature \ref FeatureSubResourceProps
1136    * as well as \ref FeatureSubResources.
1137    *
1138    * \param subResource the affected sub-resource name
1139    * \param propId the ID of the property that changed
1140    */
1141   void subResourcePropertyChanged(const QString& subResource, int propId);
1142 
1143   //! Emitted when a sub-resource is created
1144   /** This signal should be emitted by engines supporting feature \ref FeatureSubResources, at
1145    * the end of a (successful) \ref createSubResource() call.\
1146    */
1147   void subResourceCreated(const QString& newSubResource);
1148 
1149   //! Emitted when a sub-resource is renamed
1150   /** This signal should be emitted by engines supporting feature \ref FeatureSubResources, at
1151    * the end of a (successful) \ref renameSubResource() call.\
1152    */
1153   void subResourceRenamed(const QString& oldSubResourceName,
1154 			  const QString& newSubResourceName);
1155 
1156   //! Emitted when a sub-resource is deleted
1157   /** This signal should be emitted by engines supporting feature \ref FeatureSubResources, at
1158    * the end of a (successful) \ref deleteSubResource() call.
1159    */
1160   void subResourceDeleted(const QString& subResource);
1161 
1162 
1163   /** Emitted at the beginning of a long operation during which progress will be reported
1164    * by emission of KLFProgressReporter::progress() of the given object \c progressReporter.
1165    *
1166    * \param progressReporter is the object that will emit its progress() at regular intervals
1167    *   to inform caller of operation progress.
1168    * \param descriptiveText is some text describing the nature of the operation in progress
1169    *
1170    * Subclasses have to use KLFProgressReporter directly. It's very simple to use, example:
1171    * \code
1172    * int do_some_long_computations(...) {
1173    *   int num_of_steps = ... ;
1174    *   KLFProgressReporter progressReporter(0, num_of_steps, this);
1175    *   // ...
1176    *   int current_step = 0;
1177    *   for ( ... many iterations ... ) {
1178    *     progressReporter.doReportProgress(current_step++);
1179    *
1180    *     .... // perform a long computation iteration
1181    *
1182    *   }
1183    *   // finally emit the last progress value
1184    *   progressReporter.doReportProgress(num_of_steps);
1185    *   ...
1186    *   return some_result;
1187    * }
1188    * \endcode
1189    *
1190    * The signal operationStartReportingProgress() is suitable to use in conjunction with
1191    * a KLFProgressDialog.
1192    */
1193   void operationStartReportingProgress(KLFProgressReporter *progressReporter,
1194 				       const QString& descriptiveText);
1195 
1196 
1197 
1198 public slots:
1199 
1200   //! set a new resource title for this library resource
1201   /** Stores the new resource title. The title is a human string to display eg. in the
1202    * tabs of the KLFLibBrowser library browser. [KLFLibBrowser:  see klfapp library]
1203    *
1204    * This function calls directly \ref setResourceProperty().
1205    *
1206    * The default implementation should suffice; subclass \ref saveResourceProperty()
1207    * for actually saving the new value into the resource backend data, and for more control
1208    * over setting properties, or possibly subclass \ref setResourceProperty() for even more
1209    * control.
1210    *  */
1211   virtual bool setTitle(const QString& title);
1212 
1213   //! Set the resource to be locked
1214   /** See \ref locked() for more doc.
1215    *
1216    * If the feature flags do not contain \ref FeatureLocked, then this function returns
1217    * immediately FALSE. Otherwise, this function calls \ref setResourceProperty() with
1218    * arguments \ref PropLocked and the new value.
1219    *
1220    *
1221    * The default implementation should suffice; subclass \ref saveResourceProperty()
1222    * for actually saving the new value into the resource backend data, and for more control
1223    * over setting properties, or possibly subclass \ref setResourceProperty() for even more
1224    * control.
1225    */
1226   virtual bool setLocked(bool locked);
1227 
1228   /** Store the given view type in the ViewType property.
1229    *
1230    * Calls directly \ref setResourceProperty().
1231    *
1232    * The default implementation should suffice; subclass \ref saveResourceProperty()
1233    * for actually saving the new value into the resource backend data, and for more control
1234    * over setting properties, or possibly subclass \ref setResourceProperty() for even more
1235    * control.
1236    * */
1237   virtual bool setViewType(const QString& viewType);
1238 
1239   //! Set the resource to be read-only or not
1240   /** If the \ref FeatureReadOnly was given to the constructor, The base implementation sets
1241    * the read-only flag to \c readonly (this is then returned by \ref isReadOnly()). The
1242    * base implementation does nothing and returns FALSE if the feature \ref FeatureReadOnly is
1243    * not supported.
1244    */
1245   virtual bool setReadOnly(bool readonly);
1246 
1247   //! Set the default sub-resource
1248   /** When calling the variants of insertEntry(), changeEntry(), etc. that do not take a
1249    * sub-resource argument, and when this resource implements \ref FeatureSubResources, then
1250    * calls to those functions will access the <i>default sub-resource</i>, which can be
1251    * set with this function.
1252    *
1253    * This function should be used only with subclasses implementing \ref FeatureSubResources.
1254    *
1255    * The default implementation remembers \c subResource to be the new \ref defaultSubResource() and
1256    * emits \ref defaultSubResourceChanged(). It does nothing if \c subResource is already the default
1257    * sub-resource.
1258    *
1259    * \warning Reimplementing this function has a drawback: it will not be called with the argument
1260    * given in the constructor (impossible to call reimplemented virtual methods in base constructor).
1261    * Instead, the sub-class has to explicitely call its own implementation in its own constructor
1262    * to ensure full proper initialization.
1263    */
1264   virtual void setDefaultSubResource(const QString& subResource);
1265 
1266   //! Create a new sub-resource
1267   /** If they implement the feature \ref FeatureSubResources, subclasses may reimplement this
1268    * function to create a new sub-resource named \c subResource, with human title \c subResourceTitle.
1269    *
1270    * \c subResourceTitle should be ignored for resources not implementing the \ref FeatureSubResourceProps
1271    * feature.
1272    *
1273    * \returns TRUE for success or FALSE for failure.
1274    *
1275    * Subclasses should reimplement this function to provide functionality if they wish. The default
1276    * implementation does nothing and returns FALSE.
1277    *
1278    * \note engines not implementing sub-resource properties should also subclass this function and
1279    *   not the other one, without the \c subResourceTitle parameter. This is because internally this
1280    *   function is ultimately called in all cases.
1281    */
1282   virtual bool createSubResource(const QString& subResource, const QString& subResourceTitle);
1283 
1284   //! Create a new sub-resource
1285   /** This function is provided for convenience. It calls
1286    * \code
1287    *  createSubResource(subResource, QString());
1288    * \endcode
1289    * and returns the same result.
1290    *
1291    * In other words, call this function if you don't want to provide a resource title, but subclasses
1292    * should re-implement the _other_ function to make sure full functionality is achieved (in particular
1293    * also engines not implementing sub-resource properties, which will then simply ignore the title
1294    * argument). This is because internally the other function is ultimately called in all cases.
1295    *
1296    * Again, the default implementation of this function sould be largely sufficient in most cases
1297    * and thus in principle needs not be reimplemented.
1298    */
1299   virtual bool createSubResource(const QString& subResource);
1300 
1301   /** Rename the sub-resource \c oldSubResourceName to \c newSubResourceName.
1302    *
1303    * \note we are talking about the resource <i>name</i> (eg. the table name in the database),
1304    *   not the <i>title</i> (stored as a sub-resource property, for engines supporting
1305    *   \ref FeatureSubResourceProps).
1306    *
1307    * Returns TRUE for success and FALSE for failure.
1308    *
1309    * Subclasses may reimplement this function to provide functionality. The default implementation
1310    * does nothing and returns FALSE.
1311    *
1312    * Subclasses should not forget to emit \ref subResourceRenamed() after a successful sub-resource
1313    * rename.
1314    *
1315    * \note Subclasses should also adjust the current defaultSubResource() if that is the one that
1316    *   was precisely renamed. Use a call to \ref setDefaultSubResource().
1317    */
1318   virtual bool renameSubResource(const QString& oldSubResourceName, const QString& newSubResourceName);
1319 
1320   /** Delete the given sub-resource
1321    *
1322    * Returns TRUE for success and FALSE for failure.
1323    *
1324    * Subclasses may reimplement this function to provide functionality. The default implementation
1325    * does nothing and returns FALSE.
1326    *
1327    * Subclasses should not forget to emit \ref subResourceDeleted() after the sub-resource
1328    * has been deleted (ie. upon a successful execution).
1329    *
1330    * \note Subclasses should also change the current defaultSubResource() if that is the one that
1331    *   was precisely deleted. Use a call to \ref setDefaultSubResource().
1332    */
1333   virtual bool deleteSubResource(const QString& subResource);
1334 
1335 
1336   /** Sets the given sub-resource property of sub-resource \c subResource to the value \c value,
1337    * if the operation is possible and legal.
1338    *
1339    * \returns TRUE for success, FALSE for failure.
1340    *
1341    * The default implementation does nothing and returns FALSE.
1342    */
1343   virtual bool setSubResourceProperty(const QString& subResource, int propId, const QVariant& value);
1344 
1345 
1346   //! Insert an entry into this resource
1347   /** This function is provided for convenience. Inserts the entry \c entry into the
1348    * subresource \c subResource of this resource. Resources not implementing the sub-resources
1349    * feature (\ref FeatureSubResources) should ignore the subResource parameter.
1350    *
1351    * API users should use the version of \ref insertEntry(const KLFLibEntry& entry) when dealing
1352    * with resources that do not implement the \ref FeatureSubResources feature.
1353    *
1354    * This function is already implemented as shortcut for calling the list version. Subclasses
1355    * need in principle NOT reimplement this function. */
1356   virtual entryId insertEntry(const QString& subResource, const KLFLibEntry& entry);
1357 
1358   //! Insert an entry into this resource
1359   /** This function is provided for convenience. Inserts the entry \c entry into this resource.
1360    *
1361    * Use this function for resources not supporting sub-resources (but subclasses still need
1362    * to reimplement the other function, ignoring the sub-resources argument), or use this
1363    * function when you explicitely want to use the default sub-resource.
1364    *
1365    * A reasonable default implementation is provided. Subclasses are not required to reimplement
1366    * this function.
1367    */
1368   virtual entryId insertEntry(const KLFLibEntry& entry);
1369 
1370   //! Insert new entries in this resource
1371   /** Inserts the given library entries (given as a \ref KLFLibEntry list) into this resource
1372    * and returns a list of the IDs that were attributed to the new entries (in the same
1373    * order as the given list). An individual ID of -1 means failure for that specific entry;
1374    * an empty list returned means a general failure, except if \c entrylist is empty.
1375    *
1376    * The entries are inserted into sub-resource \c subResource, if sub-resources are supported
1377    * (\ref FeatureSubResources). Otherwise the \c subResource parameter should be ignored
1378    * by subclasses.
1379    *
1380    * This function should be reimplemented by subclasses to actually save the new entries.
1381    * The reimplementation should make sure that the operation is permitted (eg. by checking
1382    * that \ref canModifyData() "canModifyData(InsertData)" is true, and should behave as
1383    * described above.
1384    *
1385    * Subclasses should then emit the \ref dataChanged() signal, and return a success/failure
1386    * code.
1387    */
1388   virtual QList<entryId> insertEntries(const QString& subResource, const KLFLibEntryList& entrylist) = 0;
1389 
1390   //! Insert new entries in this resource
1391   /** This function is provided for convenience. Inserts the entries \c entrylist into this resource.
1392    *
1393    * Use this function for resources not supporting sub-resources (but subclasses still need
1394    * to reimplement the other function, ignoring the sub-resources argument), or use this
1395    * function when you explicitely want to use the default sub-resource.
1396    *
1397    * A reasonable default implementation is provided. Subclasses are not required to reimplement
1398    * this function.
1399    */
1400   virtual QList<entryId> insertEntries(const KLFLibEntryList& entrylist);
1401 
1402   //! Change some entries in this resource.
1403   /** The entries specified by the ids \c idlist are modified. The properties given
1404    * in \c properties (which should be KLFLibEntry property IDs) are to be set to the respective
1405    * value in \c values for all the given entries in \c idlist. \c properties and \c values must
1406    * obviously be of same size.
1407    *
1408    * This function affects entries in sub-resource \c subResource for engines supporting feature
1409    * \ref FeatureSubResources.
1410    *
1411    * A return value of TRUE indicates general success and FALSE indicates a failure.
1412    *
1413    * This function should be reimplemented by subclasses to actually save the modified entries.
1414    * The reimplementation should make sure that the operation is permitted (eg. by checking
1415    * that \ref canModifyData() "canModifyData(ChangeData)" is true, and should behave as described
1416    * above.
1417    *
1418    * Subclasses should then emit the \ref dataChanged() signal, and return a success/failure
1419    * code.
1420    */
1421   virtual bool changeEntries(const QString& subResource, const QList<entryId>& idlist,
1422 			     const QList<int>& properties, const QList<QVariant>& values) = 0;
1423 
1424   //! Change some entries in this resource
1425   /** This function is provided for convenience. The default implementation, which should largely
1426    * suffice in most cases, calls the other changeEntries() function, with the default sub-resource
1427    * \c defaultSubResource() as first argument.
1428    *
1429    * Use this function for resources not supporting sub-resources (but subclasses still need
1430    * to reimplement the other function, ignoring the sub-resources argument), or use this
1431    * function when you explicitely want to use the default sub-resource.
1432    */
1433   virtual bool changeEntries(const QList<entryId>& idlist, const QList<int>& properties,
1434 			     const QList<QVariant>& values);
1435 
1436   //! Delete some entries in this resource.
1437   /** The entries specified by the ids \c idlist are deleted.
1438    *
1439    * A return value of TRUE indicates general success and FALSE indicates a failure.
1440    *
1441    * This function affects entries in sub-resource \c subResource for engines supporting feature
1442    * \ref FeatureSubResources.
1443    *
1444    * This function should be reimplemented by subclasses to actually delete the entries.
1445    * The reimplementation should make sure that the operation is permitted (eg. by checking
1446    * that \ref canModifyData() "canModifyData(DeleteData)" is true, and should behave as described
1447    * above.
1448    *
1449    * Subclasses should then emit the \ref dataChanged() signal, and return a success/failure
1450    * code.
1451    */
1452   virtual bool deleteEntries(const QString& subResource, const QList<entryId>& idlist) = 0;
1453 
1454   //! Delete some entries in this resource
1455   /** This function is provided for convenience. The default implementation, which should largely
1456    * suffice in most cases, calls the other deleteEntries() function, with the default sub-resource
1457    * \c defaultSubResource() as first argument.
1458    *
1459    * Use this function for resources not supporting sub-resources (but subclasses still need
1460    * to reimplement the other function, ignoring the sub-resources argument), or use this
1461    * function when you explicitely want to use the default sub-resource.
1462    */
1463   virtual bool deleteEntries(const QList<entryId>& idList);
1464 
1465   /** If the \ref FeatureSaveTo is supported (passed to the constructor), reimplement this
1466    * function to save the resource data in the new path specified by \c newPath.
1467    *
1468    * The \c newPath must be garanteed to have same schema as the previous url.
1469    *
1470    * \bug ........ THIS FUNCTION IS NOT COMPLETELY SUPPORTED IN KLFLibBrowser. ....... It also
1471    *   needs a "concept clarification", ie. what this is supposed to do exactly and how it is
1472    *   supposed to be used.
1473    */
1474   virtual bool saveTo(const QUrl& newPath);
1475 
1476   //! Set a resource property to the given value
1477   /** This function calls in turn:
1478    * - \ref canModifyProp() to check whether the property can be modified
1479    * - \ref saveResourceProperty() to check whether the operation is permitted (the value
1480    *   is acceptable, or any other check the subclass would want to perform) and to save
1481    *   the given value to the backend data;
1482    * - \ref KLFPropertizedObject::setProperty() to save the property locally;
1483    * - emits \ref resourcePropertyChanged() to notify other classes of the property change.
1484    *
1485    * \note This function fails immediately if \c propId is not a valid registered
1486    *   property ID, or if canModifyProp() returns FALSE.
1487    * */
1488   virtual bool setResourceProperty(int propId, const QVariant& value);
1489 
1490   //! Set the given property to the given value
1491   /** Very similar to calling \ref setResourceProperty() with the respective property
1492    * ID (see \ref KLFPropertizedObject::propertyIdForName()), except the property is
1493    * registered if it does't exist.
1494    *
1495    * The property is registered if it doesn't exist yet and the \ref canRegisterProperty()
1496    * returns TRUE.
1497    *
1498    * Once the property has been possibly registered, setResourceProperty() is called.
1499    */
1500   virtual bool loadResourceProperty(const QString& propName, const QVariant& value);
1501 
1502 
1503 protected:
1504 
1505   //! Save a resource property to the backend resource data.
1506   /** Subclasses should reimplement this function to save the value of the given resource
1507    * property to the knew given value.
1508    *
1509    * If the new value is inacceptable, or if the operation is not permitted, the subclass
1510    * should return FALSE, in which case the resource property will not be changed.
1511    *
1512    */
1513   virtual bool saveResourceProperty(int propId, const QVariant& value) = 0;
1514 
1515   /** Whether it's possible to modify \a something (data, property value, etc.)
1516    */
1517   enum ModifyStatus {
1518     MS_CanModify = 0, //!< It's possible to modify that \a something
1519     MS_IsLocked = 1, //!< That \a something is resource-locked (ie., the only possible action is to unlock it)
1520     MS_SubResLocked = 2, //!< That \a something is sub-resource-locked
1521     MS_NotModifiable = 3 //!< That \a something is read-only or not modifiable for another reason
1522   };
1523 
1524   //! can modify data in resource (base common tests only)
1525   /** External classes: Don't call this function directly, use \ref canModifyData(), \ref canModifyProp(),
1526    * and \ref canModifySubResourceProperty() instead.
1527    *
1528    * Internal classes: this is useful for reimplementations of canModifyData(), canModifyProp(), etc.
1529    *
1530    * The latter and their reimplementations may call this function.
1531    *
1532    * This function can be reimplemented to take into account more factors (eg. a file being writable).
1533    *
1534    * \returns one value of the \ref ModifyStatus enum. See that documentation for more info.
1535    *
1536    * All supporting-feature checks are made correspondingly as needed. If nothing is supported
1537    * (read-only, locked, sub-resource properties) by default data is modifiable.
1538    */
1539   virtual ModifyStatus baseCanModifyStatus(bool inSubResource,
1540 					   const QString& subResource = QString()) const;
1541 
1542   bool thisOperationProgressBlocked() const;
1543 
1544 private:
1545   void initRegisteredProperties();
1546 
1547   QUrl pUrl;
1548   uint pFeatureFlags;
1549   bool pReadOnly;
1550 
1551   QString pDefaultSubResource;
1552 
1553   mutable bool pProgressBlocked;
1554   bool pThisOperationProgressBlockedOnly;
1555 
1556   KLF_DEBUG_DECLARE_REF_INSTANCE( QFileInfo(url().path()).fileName()+":"+defaultSubResource()  ) ;
1557 };
1558 
1559 
1560 Q_DECLARE_METATYPE(KLFLibResourceEngine::KLFLibEntryWithId)
1561   ;
1562 
1563 
1564 KLF_EXPORT QDataStream& operator<<(QDataStream& stream,
1565 				   const KLFLibResourceEngine::KLFLibEntryWithId& entrywid);
1566 KLF_EXPORT QDataStream& operator>>(QDataStream& stream,
1567 				   KLFLibResourceEngine::KLFLibEntryWithId& entrywid);
1568 
1569 
1570 /** \brief Provides a simple API for reading library resources.
1571  *
1572  * This class provides default implementations of some pure virtual methods of
1573  * \ref KLFLibResourceEngine, which call other member functions. The goal is to make life
1574  * simpler to create a resource engine, where access speed is not a major concern.
1575  *
1576  * For example, KLFLibResourceEngine::allIds() is pure virtual. Normally it can be implemented
1577  * to be faster than allEntries(), depending on the engine backend. However the functionality
1578  * can as well easily be achieved by calling KLFLibResourceEngine::allEntries() and returning
1579  * just a list with all the IDs, at the price of losing optimization.
1580  *
1581  * This class provides non-optimized default implementations for allIds() (as given above),
1582  * hasEntry(), entries(), and query(), based on the data returned by allEntries() and
1583  * entry()
1584  *
1585  * Bear in mind that optimizing one or more of those functions is still possible, by
1586  * reimplementing them (!)
1587  */
1588 class KLF_EXPORT KLFLibResourceSimpleEngine : public KLFLibResourceEngine
1589 {
1590   Q_OBJECT
1591 public:
1592   KLFLibResourceSimpleEngine(const QUrl& url, uint supportedfeatureflags, QObject *parent = NULL)
KLFLibResourceEngine(url,supportedfeatureflags,parent)1593     : KLFLibResourceEngine(url, supportedfeatureflags, parent)
1594   {
1595   }
~KLFLibResourceSimpleEngine()1596   virtual ~KLFLibResourceSimpleEngine() { }
1597 
1598   // these functions are implemented using the other base functions.
1599 
1600   virtual QList<KLFLib::entryId> allIds(const QString& subResource);
1601   virtual bool hasEntry(const QString&, entryId id);
1602   virtual QList<KLFLibEntryWithId> entries(const QString&, const QList<KLFLib::entryId>& idList,
1603 					   const QList<int>& wantedEntryProperties = QList<int>());
1604 
1605   /** \brief Helper class to sort entries into a \ref KLFLibResourceEngine::QueryResult.
1606    */
1607   class QueryResultListSorter
1608   {
1609     KLFLibEntrySorter *mSorter;
1610     QueryResult *mResult;
1611     uint fillflags;
1612     bool reference_is_rawentrylist;
1613   public:
1614     /** Build an QueryResultListSorter object, that should sort entries according to
1615      * \c sorter. See also \ref KLFLibEntrySorter.
1616      *
1617      * \c sorter must not be NULL.
1618      */
1619     QueryResultListSorter(KLFLibEntrySorter *sorter, QueryResult *result);
1620 
1621     /*    QueryResultListSorter(const QueryResultListSorter& other); */
1622 
1623     /** \brief Compares \ref KLFLibEntry'ies */
operator()1624     inline bool operator()(const KLFLibEntry& a, const KLFLibEntry& b)
1625     { return mSorter->operator()(a, b); }
1626 
1627     /** \brief Compares \ref KLFLibResourceEngine::KLFLibEntryWithId's */
operator()1628     inline bool operator()(const KLFLibEntryWithId& a, const KLFLibEntryWithId& b)
1629     { return mSorter->operator()(a.entry, b.entry); }
1630 
1631     /** Returns the number of entries there are in the lists (ignoring those lists left empty, of
1632      * course). */
1633     int numberOfEntries();
1634 
1635     /** Inserts the entry-with-id \c entrywid, into the appropriate lists in the \c result that
1636      * was given to the constructor, such that the lists are ordered according to the sorter set
1637      * in the constructor.
1638      *
1639      * By \a appropriate we mean the lists for which the fill flags are set in the QueryResult object.
1640      *
1641      * If the set sorter's sorting property ID is \c -1, then the elements are simply
1642      * appended to the appropriate lists; sorting is disabled in this case.
1643      *
1644      * When sorting is enabled, this function assumes that the lists in \c result are sorted
1645      * appropriately. This is naturally the case if you only use this function to build the lists.
1646      * In other terms, don't call this function if you already added non-sorted items into the
1647      * list(s).
1648      *
1649      * \note if the fill flags include neither the raw entry list, nor the entry-with-id list,
1650      *   then the raw entry list is also filled, as it is not possible to just compare bare entry
1651      *   IDs (!)
1652      */
1653     void insertIntoOrderedResult(const KLFLibEntryWithId& entry);
1654   };
1655 
1656   virtual int query(const QString& subResource, const Query& query, QueryResult *result);
1657 
1658   virtual QList<QVariant> queryValues(const QString& subResource, int entryPropId);
1659 
1660 
1661   /** A basic implementation of query() based on matching the results of
1662    * <tt>resource->allEntries()</tt>. */
1663   static int queryImpl(KLFLibResourceEngine *resource, const QString& subResource,
1664 		       const Query& query, QueryResult *result);
1665 
1666   /** A basic implementation of queryValues() based on looking at the results of
1667    * <tt>resource->allEntries()</tt> */
1668   static QList<QVariant> queryValuesImpl(KLFLibResourceEngine *resource, const QString& subResource,
1669 					 int entryPropId);
1670 
1671 
1672   /** A simple entry condition tester. */
1673   static bool testEntryMatchConditionImpl(const KLFLib::EntryMatchCondition& condition,
1674 					  const KLFLibEntry& libentry);
1675 };
1676 
1677 
1678 
1679 /** An abstract factory class for opening resources identified by their URL, and creating
1680  * objects of the currect subclass of KLFLibResourceEngine.
1681  *
1682  * See also \ref KLFLibResourceEngine, \ref KLFLibDBEngine, \ref KLFLibLegacyEngine.
1683  * More about factory common functions in \ref KLFFactoryManager documentation.
1684  */
1685 class KLF_EXPORT KLFLibEngineFactory : public QObject, public KLFFactoryBase
1686 {
1687   Q_OBJECT
1688 public:
1689   /** A generalized way of passing arbitrary parameters for creating
1690    * new resources or saving resources to new locations.
1691    *
1692    */
1693   typedef QMap<QString,QVariant> Parameters;
1694 
1695   enum SchemeFunctions {
1696     FuncOpen   = 0x01, //!< Open Resources
1697     FuncCreate = 0x02, //!< Create New Resources
1698     FuncSaveTo = 0x04  //!< Save Resources to new locations
1699   };
1700 
1701   /** Constructs an engine factory and automatically regisers it. */
1702   KLFLibEngineFactory(QObject *parent = NULL);
1703   /** Destroys this engine factory and unregisters it. */
1704   virtual ~KLFLibEngineFactory();
1705 
1706   /** \brief A list of supported URL schemes this factory can open.
1707    *
1708    * If two factories provide a common scheme name, only the last instantiated is used;
1709    * the consequent ones will be ignored for that scheme name. See
1710    * \ref KLFFactoryBase::supportedTypes() and \ref KLFFactoryManager::findFactoryFor() */
1711   virtual QStringList supportedTypes() const = 0;
1712 
1713   /** \brief What this factory is capable of doing
1714    *
1715    * Informs the caller of what functionality this factory provides for the given \c scheme.
1716    *
1717    * The \c FuncOpen must be provided in every factory.
1718    *
1719    * \returns a bitwise-OR of flags defined in the \ref SchemeFunctions enum.
1720    *
1721    * The default implementation returns \c FuncOpen. */
1722   virtual uint schemeFunctions(const QString& scheme) const;
1723 
1724   /** Should return a human (short) description of the given scheme (which is one
1725    * returned by \ref supportedTypes()) */
1726   virtual QString schemeTitle(const QString& scheme) const = 0;
1727 
1728   /** Returns the widget type that should be used to present to user to "open" or "create" or
1729    * "save" a resource of the given \c scheme.
1730    *
1731    * For example, both \c "klf+sqlite" and \c "klf+legacy" schemes could return a "LocalFile"
1732    * widget that prompts to open/create/save-as a file. */
1733   virtual QString correspondingWidgetType(const QString& scheme) const = 0;
1734 
1735   /** Instantiate a library engine that opens resource stored at \c location. The resource
1736    * engine should be constructed as a child of object \c parent.
1737    */
1738   virtual KLFLibResourceEngine *openResource(const QUrl& location, QObject *parent = NULL) = 0;
1739 
1740   //! Create a new resource of given type and parameters
1741   /** Create the new resource, with the given settings. This function opens the resource and
1742    * returns the KLFLibResourceEngine object, which is instantiated as child of \c parent.
1743    *
1744    * The parameters' structure are defined for each widget type. That is, if the
1745    * \ref correspondingWidgetType() for a given scheme is eg. \c "LocalFile", then the
1746    * parameters are defined by whatever the \c "LocalFile" widget sets. For example
1747    * \c "LocalFile" documents its parameters in
1748    * \ref KLFLibBasicWidgetFactory::retrieveCreateParametersFromWidget(), eg. parameter
1749    * \c "Filename" contains a QString with the entered local file name.
1750    *
1751    * Additional parameters may also be set by KLFLibCreateResourceDlg itself (eg.
1752    * default sub-resource name/title, .........TODO............)
1753    *
1754    * The default implementation of this function does nothing and returns \c NULL. To enable
1755    * creating resources, reimplement \ref schemeFunctions() to return also \ref FuncCreate
1756    * and reimplement this function.
1757    */
1758   virtual KLFLibResourceEngine *createResource(const QString& scheme, const Parameters& parameters,
1759 					       QObject *parent = NULL);
1760 
1761   //! Save the given resource to a new location
1762   /** Save the resource \c resource to the new location given by \c newLocation.
1763    *
1764    * The caller should garantee that \c resource is a resource engine of a scheme supported by
1765    * this factory.
1766    *
1767    * \note The resource a the new location is not opened. \c resource will still continue pointing
1768    *   to the previous location.
1769    *
1770    * For example, an \c "klf+sqlite" Sqlite database may choose to simply copy the database file
1771    * to the new location. This example is implemented in \ref KLFLibDBEngine::saveTo().
1772    *
1773    * \returns TRUE for success or FALSE for failure.
1774    *
1775    * The default implementation of this function does nothing and returns false. To enable
1776    * creating resources, reimplement \ref schemeFunctions() to return also \ref FuncCreate
1777    * and reimplement this function.
1778    */
1779   virtual bool saveResourceTo(KLFLibResourceEngine *resource, const QUrl& newLocation);
1780 
1781 
1782 
1783 
1784   /** Finds the last registered factory that should be able to open URL \c url (determined by
1785    * the URL's scheme) and returns a pointer to that factory.
1786    *
1787    * This function is provided for convenience; it is equivalent to
1788    * \code findFactoryFor(url.scheme()) \endcode
1789    */
1790   static KLFLibEngineFactory *findFactoryFor(const QUrl& url);
1791 
1792   /** Finds the last registered factory that should be able to open URLs with scheme \c urlScheme
1793    * and returns a pointer to that factory. */
1794   static KLFLibEngineFactory *findFactoryFor(const QString& urlScheme);
1795 
1796   /** Returns a concatenated list of all schemes that all registered factories support */
1797   static QStringList allSupportedSchemes();
1798 
1799   /** Finds the good factory for URL \c location, and opens the resource using that factory.
1800    * The created resource will be a child of \c parent. */
1801   static KLFLibResourceEngine *openURL(const QUrl& location, QObject *parent = NULL);
1802 
1803   /** Opens resource designated by \c url, and then lists the subresources. An empty list
1804    * is returned if the resource cannot be opened, or if the resource does not support
1805    * sub-resources.
1806    *
1807    * The resource is immedately closed after reading the list of sub-resources.
1808    *
1809    * This function:
1810    * - Finds the relevant factory with \ref findFactoryFor()
1811    * - Opens the resource with \ref openResource() using that factory
1812    * - fails if the resource does not support \ref KLFLibResourceEngine::FeatureSubResources
1813    * - lists the sub-resources
1814    * - closes the resource
1815    */
1816   static QStringList listSubResources(const QUrl& url);
1817 
1818   /** Opens resource designated by \c url, and then lists the subresources with as key
1819    * the resource name and as value the sub-resource title (if sub-resource properties
1820    * are supported, or an empty string if not). An empty map is returned if the resource
1821    * cannot be opened, or if the resource does not support sub-resources.
1822    *
1823    * This function works in a very similar way to \ref listSubResources().
1824    *
1825    * The resource is immedately closed after reading the list of sub-resources.
1826    */
1827   static QMap<QString,QString> listSubResourcesWithTitles(const QUrl& url);
1828 
1829 private:
1830   static KLFFactoryManager pFactoryManager;
1831 };
1832 
1833 
1834 
1835 // -------------------------
1836 
1837 
1838 class QMimeData;
1839 
1840 //! Helper class to encode an entry list as mime data (abstract interface)
1841 class KLF_EXPORT KLFAbstractLibEntryMimeEncoder
1842 {
1843 public:
1844   KLFAbstractLibEntryMimeEncoder();
1845   virtual ~KLFAbstractLibEntryMimeEncoder();
1846 
1847   //! A list of mime types this class can encode
1848   virtual QStringList supportedEncodingMimeTypes() const = 0;
1849   //! A list of mime types this class can decode
1850   virtual QStringList supportedDecodingMimeTypes() const = 0;
1851 
1852   virtual QByteArray encodeMime(const KLFLibEntryList& entryList, const QVariantMap& metaData,
1853 				const QString& mimeType) const = 0;
1854 
1855   virtual bool decodeMime(const QByteArray& data, const QString& mimeType,
1856 			  KLFLibEntryList *entryList, QVariantMap *metaData) const = 0;
1857 
1858 
1859   static QStringList allEncodingMimeTypes();
1860   static QStringList allDecodingMimeTypes();
1861   //! Creates a QMetaData with all known registered encoding mime types
1862   static QMimeData *createMimeData(const KLFLibEntryList& entryList, const QVariantMap& metaData);
1863   static bool canDecodeMimeData(const QMimeData *mimeData);
1864   static bool decodeMimeData(const QMimeData *mimeData, KLFLibEntryList *entryList,
1865 			     QVariantMap *metaData);
1866 
1867   static KLFAbstractLibEntryMimeEncoder *findEncoderFor(const QString& mimeType,
1868 							bool warnIfNotFound = true);
1869   static KLFAbstractLibEntryMimeEncoder *findDecoderFor(const QString& mimeType,
1870 							bool warnIfNotFound = true);
1871   static QList<KLFAbstractLibEntryMimeEncoder*> encoderList();
1872 private:
1873 
1874   static void registerEncoder(KLFAbstractLibEntryMimeEncoder *encoder);
1875 
1876   static QList<KLFAbstractLibEntryMimeEncoder*> staticEncoderList;
1877 };
1878 
1879 
1880 
1881 
1882 
1883 #ifdef KLF_DEBUG
1884 #include <QDebug>
1885 KLF_EXPORT QDebug& operator<<(QDebug& dbg, const KLFLib::StringMatch& smatch);
1886 KLF_EXPORT QDebug& operator<<(QDebug& dbg, const KLFLib::PropertyMatch& pmatch);
1887 KLF_EXPORT QDebug& operator<<(QDebug& dbg, const KLFLib::EntryMatchCondition& c);
1888 KLF_EXPORT QDebug& operator<<(QDebug& dbg, const KLFLibResourceEngine::Query& q);
1889 KLF_EXPORT QDebug& operator<<(QDebug& dbg, const KLFLibResourceEngine::KLFLibEntryWithId& ewid);
1890 #endif
1891 
1892 
1893 
1894 
1895 #endif
1896 
1897