File indexing completed on 2024-04-28 16:31:51

0001 /***************************************************************************
0002     Copyright (C) 2001-2009 Robby Stephenson <robby@periapsis.org>
0003  ***************************************************************************/
0004 
0005 /***************************************************************************
0006  *                                                                         *
0007  *   This program is free software; you can redistribute it and/or         *
0008  *   modify it under the terms of the GNU General Public License as        *
0009  *   published by the Free Software Foundation; either version 2 of        *
0010  *   the License or (at your option) version 3 or any later version        *
0011  *   accepted by the membership of KDE e.V. (or its successor approved     *
0012  *   by the membership of KDE e.V.), which shall act as a proxy            *
0013  *   defined in Section 14 of version 3 of the license.                    *
0014  *                                                                         *
0015  *   This program is distributed in the hope that it will be useful,       *
0016  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0017  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0018  *   GNU General Public License for more details.                          *
0019  *                                                                         *
0020  *   You should have received a copy of the GNU General Public License     *
0021  *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
0022  *                                                                         *
0023  ***************************************************************************/
0024 
0025 #ifndef TELLICO_COLLECTION_H
0026 #define TELLICO_COLLECTION_H
0027 
0028 #include "field.h"
0029 #include "entry.h"
0030 #include "filter.h"
0031 #include "borrower.h"
0032 #include "datavectors.h"
0033 
0034 #include <QStringList>
0035 #include <QHash>
0036 #include <QObject>
0037 
0038 namespace Tellico {
0039   namespace Data {
0040     class EntryGroup;
0041     typedef QHash<QString, EntryGroup*> EntryGroupDict;
0042 
0043 /**
0044  * The Collection class is the primary data object, holding a
0045  * list of fields and entries.
0046  *
0047  * A collection holds entries of a single type, whether it be books, CDs, or whatever.
0048  * It has a list of attributes which apply for the whole collection. A unique id value
0049  * identifies each collection object.
0050  *
0051  * @see Entry
0052  * @see Field
0053  *
0054  * @author Robby Stephenson
0055  */
0056 class Collection : public QObject, public QSharedData {
0057 Q_OBJECT
0058 
0059 public:
0060   enum Type {
0061     Base = 1,
0062     Book = 2,
0063     Video = 3,
0064     Album = 4,
0065     Bibtex = 5,
0066     ComicBook = 6,
0067     Wine = 7,
0068     Coin = 8,
0069     Stamp = 9,
0070     Card = 10,
0071     Game = 11,
0072     File = 12,
0073     BoardGame = 13
0074     // if you want to add custom collection types, use a number sure to be unique like 101
0075     // don't forget to update macros in core/tellico_config_addons.cpp
0076   };
0077 
0078   /**
0079    * The constructor is only used to create custom collections.
0080    *
0081    * @param addDefaultFields whether to add default fields or not
0082    * @param title The title of the collection itself
0083    */
0084   explicit Collection(bool addDefaultFields, const QString& title=QString());
0085   /**
0086    */
0087   virtual ~Collection();
0088 
0089   /**
0090    * Returns the type of the collection.
0091    *
0092    * @return The type
0093    */
0094   virtual Type type() const { return Base; }
0095   /**
0096    * Returns the id of the collection.
0097    *
0098    * @return The id
0099    */
0100   ID id() const { return m_id; }
0101   /**
0102    * Returns the name of the collection.
0103    *
0104    * @return The name
0105    */
0106   const QString& title() const { return m_title; }
0107   /**
0108    * Sets the title of the collection.
0109    *
0110    * @param title The new collection title
0111    */
0112   void setTitle(const QString& title) { m_title = title; }
0113   /**
0114    * Returns a reference to the list of all the entries in the collection.
0115    *
0116    * @return The list of entries
0117    */
0118   const EntryList& entries() const { return m_entries; }
0119   /**
0120    * Returns a reference to the list of the collection attributes.
0121    *
0122    * @return The list of fields
0123    */
0124   const FieldList& fields() const { return m_fields; }
0125   EntryPtr entryById(ID id);
0126   /**
0127    * Returns a reference to the list of the collection's people fields.
0128    *
0129    * @return The list of fields
0130    */
0131   const FieldList& peopleFields() const { return m_peopleFields; }
0132   /**
0133    * Returns a reference to the list of the collection's image fields.
0134    *
0135    * @return The list of fields
0136    */
0137   const FieldList& imageFields() const { return m_imageFields; }
0138   /**
0139    * Return the primary image field, which is used for icons for the entry.
0140    * By default, the first image field is returned.
0141    *
0142    * @return The primary image field
0143    */
0144   FieldPtr primaryImageField() const;
0145   /**
0146    * Returns a reference to the list of field groups. This value is cached rather
0147    * than generated with each call, so the method should be fairly fast.
0148    *
0149    * @return The list of group names
0150    */
0151   const QStringList& fieldCategories() const { return m_fieldCategories; }
0152   /**
0153    * Returns the name of the field used to group the entries by default.
0154    *
0155    * @return The field name
0156    */
0157   const QString& defaultGroupField() const { return m_defaultGroupField; }
0158   /**
0159    * Sets the name of the default field used to group the entries.
0160    *
0161    * @param name The name of the field
0162    */
0163   void setDefaultGroupField(const QString& name) { m_defaultGroupField = name; }
0164   /**
0165    * Returns the number of entries in the collection.
0166    *
0167    * @return The number of entries
0168    */
0169   int entryCount() const { return m_entries.count(); }
0170   /**
0171    * Adds a entry to the collection. The collection takes ownership of the entry object.
0172    *
0173    * @param entry A pointer to the entry
0174    */
0175   void addEntries(const EntryList& entries);
0176   void addEntries(EntryPtr entry) { addEntries(EntryList() << entry); }
0177   /**
0178    * Updates the dicts that include the entry.
0179    *
0180    * @param entry A pointer to the entry
0181    */
0182   void updateDicts(const EntryList& entries, const QStringList& fields);
0183   /**
0184    * Deletes a entry from the collection.
0185    *
0186    * @param entry The pointer to the entry
0187    * @return A boolean indicating if the entry was in the collection and was deleted
0188    */
0189   bool removeEntries(const EntryList& entries);
0190   QList<int> entryIdList() const { return m_entryById.keys(); }
0191   /**
0192    * Adds a whole list of fields. It calls
0193    * @ref addField, which is virtual.
0194    *
0195    * @param list List of fields to add
0196    * @return A boolean indicating if the fields were successfully added or not
0197    */
0198   bool addFields(FieldList list);
0199   /**
0200    * Adds an field to the collection, unless an field with that name
0201    * already exists. The collection takes ownership of the field object.
0202    *
0203    * @param field A pointer to the field
0204    * @return A boolean indicating if the field was added or not
0205    */
0206   virtual bool addField(FieldPtr field);
0207   virtual bool modifyField(FieldPtr field);
0208   virtual bool removeField(FieldPtr field, bool force=false);
0209   virtual bool removeField(const QString& name, bool force=false);
0210   void reorderFields(const FieldList& list);
0211   /**
0212    * Merges a field into a collection
0213    *
0214    * @param field A pointer to the field
0215    * @return A boolean indicating if structural changes were made to the collection
0216    */
0217   bool mergeField(FieldPtr field);
0218 
0219   // the reason this is not static is so I can call it from a collection pointer
0220   // it also gets overridden for different collection types
0221   // the return values should be compared against the GOOD and PERFECT
0222   // static match constants
0223   virtual int sameEntry(Data::EntryPtr, Data::EntryPtr) const;
0224 
0225   /**
0226    * Determines whether or not a certain value is allowed for an field.
0227    *
0228    * @param field The name of the field
0229    * @param value The desired value
0230    * @return A boolean indicating if the value is an allowed value for that field
0231    */
0232   bool isAllowed(const QString& field, const QString& value) const;
0233   /**
0234    * Returns a list of all the field names.
0235    *
0236    * @return The list of names
0237    */
0238   QStringList fieldNames() const;
0239   /**
0240    * Returns a list of all the field titles.
0241    *
0242    * @return The list of titles
0243    */
0244   QStringList fieldTitles() const;
0245   /**
0246    * Returns the title of an field, given its name.
0247    *
0248    * @param name The field name
0249    * @return The field title
0250    */
0251   QString fieldTitleByName(const QString& name) const;
0252   /**
0253    * Returns the name of an field, given its title.
0254    *
0255    * @param title The field title
0256    * @return The field name
0257    */
0258   QString fieldNameByTitle(const QString& title) const;
0259   /**
0260    * Returns a list of the values of a given field for every entry
0261    * in the collection. The values in the list are not repeated. Attribute
0262    * values which contain ";" are split into separate values. Since this method
0263    * iterates over all the entries, for large collections, it is expensive.
0264    *
0265    * @param name The name of the field
0266    * @return The list of values
0267    */
0268   QStringList valuesByFieldName(const QString& name) const;
0269   /**
0270    * Returns a list of all the fields in a given category.
0271    *
0272    * @param category The name of the category
0273    * @return The field list
0274    */
0275   FieldList fieldsByCategory(const QString& category);
0276   /**
0277    * Returns a pointer to an field given its name. If none is found, a NULL pointer
0278    * is returned.
0279    *
0280    * @param name The field name
0281    * @return The field pointer
0282    */
0283   FieldPtr fieldByName(const QString& name) const;
0284   /**
0285    * Returns a pointer to an field given its title. If none is found, a NULL pointer
0286    * is returned. This lookup is slower than by name.
0287    *
0288    * @param title The field title
0289    * @return The field pointer
0290    */
0291   FieldPtr fieldByTitle(const QString& title) const;
0292   /**
0293    * Returns @p true if the collection contains a field named @ref name;
0294    */
0295   bool hasField(const QString& name) const;
0296   /**
0297    * Returns a list of all the possible entry groups. This value is cached rather
0298    * than generated with each call, so the method should be fairly fast.
0299    *
0300    * @return The list of groups
0301    */
0302   const QStringList& entryGroups() const { return m_entryGroups; }
0303   /**
0304    * Returns a pointer to a dict of all the entries grouped by
0305    * a certain field
0306    *
0307    * @param name The name of the field by which the entries are grouped
0308    * @return The list of group names
0309    */
0310   EntryGroupDict* entryGroupDictByName(const QString& name);
0311   /**
0312    * Invalidates all group names in the collection.
0313    */
0314   void invalidateGroups();
0315   /**
0316    * Returns true if the collection contains at least one Image field.
0317    *
0318    * @return Returns true if the collection contains at least one Image field;
0319    */
0320   bool hasImages() const { return !m_imageFields.isEmpty(); }
0321 
0322   void setTrackGroups(bool b) { m_trackGroups = b; }
0323 
0324   void addBorrower(Data::BorrowerPtr borrower);
0325   const BorrowerList& borrowers() const { return m_borrowers; }
0326   /**
0327    * Clears all vectors which contain shared ptrs
0328    */
0329   void clear();
0330 
0331   void addFilter(FilterPtr filter);
0332   bool removeFilter(FilterPtr filter);
0333   const FilterList& filters() const { return m_filters; }
0334 
0335   /**
0336    * Prepare text for formatting
0337    *
0338    * Useful only for BibtexCollection to strip bibtex strings
0339    */
0340   virtual QString prepareText(const QString& text) const;
0341 
0342   /**
0343    * The string used for the people pseudo-group. This forces consistency.
0344    */
0345   static const QString s_peopleGroupName;
0346 
0347 Q_SIGNALS:
0348   void signalGroupsModified(Tellico::Data::CollPtr coll, QList<Tellico::Data::EntryGroup*> groups);
0349   void signalRefreshField(Tellico::Data::FieldPtr field);
0350   void mergeAddedField(Tellico::Data::CollPtr coll, Tellico::Data::FieldPtr field);
0351 
0352 protected:
0353   Collection(const QString& title);
0354 
0355 private:
0356   QStringList entryGroupNamesByField(EntryPtr entry, const QString& fieldName);
0357   void removeEntriesFromDicts(const EntryList& entries, const QStringList& fields);
0358   void populateDict(EntryGroupDict* dict, const QString& fieldName, const EntryList& entries);
0359   void populateCurrentDicts(const EntryList& entries, const QStringList& fields);
0360   void cleanGroups();
0361 
0362   /*
0363    * Gets the preferred ID of the collection. Currently, it just gets incremented as
0364    * new collections are created.
0365    */
0366   static int getID();
0367 
0368   Q_DISABLE_COPY(Collection)
0369 
0370   ID m_id;
0371   ID m_nextEntryId;
0372   QString m_title;
0373   QString m_defaultGroupField;
0374   QString m_lastGroupField;
0375 
0376   FieldList m_fields;
0377   FieldList m_peopleFields; // keep separate list of people fields
0378   FieldList m_imageFields; // keep track of image fields
0379   QHash<QString, Field*> m_fieldByName;
0380   QHash<QString, Field*> m_fieldByTitle;
0381   QStringList m_fieldCategories;
0382 
0383   EntryList m_entries;
0384   QHash<int, Entry*> m_entryById;
0385 
0386   QHash<QString, EntryGroupDict*> m_entryGroupDicts;
0387   QStringList m_entryGroups;
0388   QList<EntryGroup*> m_groupsToDelete;
0389 
0390   FilterList m_filters;
0391   BorrowerList m_borrowers;
0392 
0393   bool m_trackGroups;
0394 };
0395 
0396   } // end namespace
0397 } //end namespace
0398 #endif