summaryrefslogtreecommitdiffstats
path: root/src/collection.h
blob: e3ea284b71b50ff15b10301f4b70dbac3411a051 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
/***************************************************************************
    copyright            : (C) 2001-2006 by Robby Stephenson
    email                : [email protected]
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of version 2 of the GNU General Public License as  *
 *   published by the Free Software Foundation;                            *
 *                                                                         *
 ***************************************************************************/

#ifndef COLLECTION_H
#define COLLECTION_H

#include "field.h"
#include "entry.h"
#include "filter.h"
#include "borrower.h"
#include "datavectors.h"

#include <ksharedptr.h>

#include <tqstringlist.h>
#include <tqptrlist.h>
#include <tqstring.h>
#include <tqdict.h>
#include <tqintdict.h>
#include <tqobject.h>

namespace Tellico {
  namespace Data {
    class EntryGroup;
    typedef TQDict<EntryGroup> EntryGroupDict;

/**
 * The Collection class is the primary data object, holding a
 * list of fields and entries.
 *
 * A collection holds entries of a single type, whether it be books, CDs, or whatever.
 * It has a list of attributes which apply for the whole collection. A unique id value
 * identifies each collection object.
 *
 * @see Entry
 * @see Field
 *
 * @author Robby Stephenson
 */
class Collection : public TQObject, public TDEShared {
Q_OBJECT
  

public:
  enum Type {
    Base = 1,
    Book = 2,
    Video = 3,
    Album = 4,
    Bibtex = 5,
    ComicBook = 6,
    Wine = 7,
    Coin = 8,
    Stamp = 9,
    Card = 10,
    Game = 11,
    File = 12,
    BoardGame = 13
    // if you want to add custom collection types, use a number sure to be unique like 101
  };

  /**
   * The constructor is only used to create custom collections. It adds a title field,
   * in the "General" group. The iconName is set to be the typeName;
   *
   * @param title The title of the collection itself
   * @param entryTitle The title of the entries, which can be translated
   */
  explicit Collection(const TQString& title);
  /**
   */
  virtual ~Collection();

  /**
   * Returns the type of the collection.
   *
   * @return The type
   */
  virtual Type type() const { return Base; }
  /**
   * Returns the id of the collection.
   *
   * @return The id
   */
  long id() const { return m_id; }
  /**
   * Returns the name of the collection.
   *
   * @return The name
   */
  const TQString& title() const { return m_title; }
  /**
   * Sets the title of the collection.
   *
   * @param title The new collection title
   */
  void setTitle(const TQString& title) { m_title = title; }
  /**
   * Returns the name of the entries in the collection, e.g. "book".
   * Not translated.
   *
   * @return The type name
   */
  TQString typeName() const;
  /**
   * Returns a reference to the list of all the entries in the collection.
   *
   * @return The list of entries
   */
  const EntryVec& entries() const { return m_entries; }
  /**
   * Returns a reference to the list of the collection attributes.
   *
   * @return The list of fields
   */
  const FieldVec& fields() const { return m_fields; }
  EntryPtr entryById(long id);
  /**
   * Returns a reference to the list of the collection's people fields.
   *
   * @return The list of fields
   */
  const FieldVec& peopleFields() const { return m_peopleFields; }
  /**
   * Returns a reference to the list of the collection's image fields.
   *
   * @return The list of fields
   */
  const FieldVec& imageFields() const { return m_imageFields; }
  /**
   * Returns a reference to the list of field groups. This value is cached rather
   * than generated with each call, so the method should be fairly fast.
   *
   * @return The list of group names
   */
  const TQStringList& fieldCategories() const { return m_fieldCategories; }
  /**
   * Returns the name of the field used to group the entries by default.
   *
   * @return The field name
   */
  const TQString& defaultGroupField() const { return m_defaultGroupField; }
  /**
   * Sets the name of the default field used to group the entries.
   *
   * @param name The name of the field
   */
  void setDefaultGroupField(const TQString& name) { m_defaultGroupField = name; }
  /**
   * Returns the number of entries in the collection.
   *
   * @return The number of entries
   */
  size_t entryCount() const { return m_entries.count(); }
  /**
   * Adds a entry to the collection. The collection takes ownership of the entry object.
   *
   * @param entry A pointer to the entry
   */
  void addEntries(EntryVec entries);
  /**
   * Updates the dicts that include the entry.
   *
   * @param entry A pointer to the entry
   */
  void updateDicts(EntryVec entries);
  /**
   * Deletes a entry from the collection.
   *
   * @param entry The pointer to the entry
   * @return A boolean indicating if the entry was in the collection and was deleted
   */
  bool removeEntries(EntryVec entries);
  /**
   * Adds a whole list of attributes. It's gotta be virtual since it calls
   * @ref addField, which is virtual.
   *
   * @param list List of attributes to add
   * @return A boolean indicating if the field was added or not
   */
  virtual bool addFields(FieldVec list);
  /**
   * Adds an field to the collection, unless an field with that name
   * already exists. The collection takes ownership of the field object.
   *
   * @param field A pointer to the field
   * @return A boolean indicating if the field was added or not
   */
  virtual bool addField(FieldPtr field);
  virtual bool mergeField(FieldPtr field);
  virtual bool modifyField(FieldPtr field);
  virtual bool removeField(FieldPtr field, bool force=false);
  virtual bool removeField(const TQString& name, bool force=false);
  void reorderFields(const FieldVec& list);

  // the reason this is not static is so I can call it from a collection pointer
  // it also gets virtualized for different collection types
  // the return values should be compared against the GOOD and PERFECT
  // static match constants in this class
  virtual int sameEntry(Data::EntryPtr, Data::EntryPtr) const;

  /**
   * Determines whether or not a certain value is allowed for an field.
   *
   * @param key The name of the field
   * @param value The desired value
   * @return A boolean indicating if the value is an allowed value for that field
   */
  bool isAllowed(const TQString& key, const TQString& value) const;
  /**
   * Returns a list of all the field names.
   *
   * @return The list of names
   */
  const TQStringList& fieldNames() const { return m_fieldNames; }
  /**
   * Returns a list of all the field titles.
   *
   * @return The list of titles
   */
  const TQStringList& fieldTitles() const { return m_fieldTitles; }
  /**
   * Returns the title of an field, given its name.
   *
   * @param name The field name
   * @return The field title
   */
  const TQString& fieldTitleByName(const TQString& name) const;
  /**
   * Returns the name of an field, given its title.
   *
   * @param title The field title
   * @return The field name
   */
  const TQString& fieldNameByTitle(const TQString& title) const;
  /**
   * Returns a list of the values of a given field for every entry
   * in the collection. The values in the list are not repeated. Attribute
   * values which contain ";" are split into separate values. Since this method
   * iterates over all the entries, for large collections, it is expensive.
   *
   * @param name The name of the field
   * @return The list of values
   */
  TQStringList valuesByFieldName(const TQString& name) const;
  /**
   * Returns a list of all the fields in a given category.
   *
   * @param category The name of the category
   * @return The field list
   */
  FieldVec fieldsByCategory(const TQString& category);
  /**
   * Returns a pointer to an field given its name. If none is found, a NULL pointer
   * is returned.
   *
   * @param name The field name
   * @return The field pointer
   */
  FieldPtr fieldByName(const TQString& name) const;
  /**
   * Returns a pointer to an field given its title. If none is found, a NULL pointer
   * is returned. This lookup is slower than by name.
   *
   * @param title The field title
   * @return The field pointer
   */
  FieldPtr fieldByTitle(const TQString& title) const;
  /**
   * Returns @p true if the collection contains a field named @ref name;
   */
  bool hasField(const TQString& name) const;
  /**
   * Returns a list of all the possible entry groups. This value is cached rather
   * than generated with each call, so the method should be fairly fast.
   *
   * @return The list of groups
   */
  const TQStringList& entryGroups() const { return m_entryGroups; }
  /**
   * Returns a pointer to a dict of all the entries grouped by
   * a certain field
   *
   * @param name The name of the field by which the entries are grouped
   * @return The list of group names
   */
  EntryGroupDict* entryGroupDictByName(const TQString& name);
  /**
   * Invalidates all group names in the collection.
   */
  void invalidateGroups();
  /**
   * Returns true if the collection contains at least one Image field.
   *
   * @return Returns true if the collection contains at least one Image field;
   */
  bool hasImages() const { return !m_imageFields.isEmpty(); }

  void setTrackGroups(bool b) { m_trackGroups = b; }

  void addBorrower(Data::BorrowerPtr borrower);
  const BorrowerVec& borrowers() const { return m_borrowers; }
  /**
   * Clears all vectors which contain shared ptrs
   */
  void clear();

  void addFilter(FilterPtr filter);
  bool removeFilter(FilterPtr filter);
  const FilterVec& filters() const { return m_filters; }

  static bool mergeEntry(EntryPtr entry1, EntryPtr entry2, bool overwrite, bool askUser=false);
  /**
   * The string used for empty values. This forces consistency.
   */
  static const char* s_emptyGroupTitle;
  /**
   * The string used for the people pseudo-group. This forces consistency.
   */
  static const TQString s_peopleGroupName;

  // these are the values that should be compared against
  // the result from sameEntry()
  static const int ENTRY_GOOD_MATCH = 10;
  static const int ENTRY_PERFECT_MATCH = 20;

signals:
  void signalGroupsModified(Tellico::Data::CollPtr coll, PtrVector<Tellico::Data::EntryGroup> groups);
  void signalRefreshField(Tellico::Data::FieldPtr field);

private:
  TQStringList entryGroupNamesByField(EntryPtr entry, const TQString& fieldName);
  void removeEntriesFromDicts(EntryVec entries);
  void populateDict(EntryGroupDict* dict, const TQString& fieldName, EntryVec entries);
  void populateCurrentDicts(EntryVec entries);
  void cleanGroups();
  bool dependentFieldHasRecursion(FieldPtr field);

  /*
   * Gets the preferred ID of the collection. Currently, it just gets incremented as
   * new collections are created.
   */
  static long getID();

  /**
   * The copy constructor is private, to ensure that it's never used.
   */
  Collection(const Collection& coll);
  /**
   * The assignment operator is private, to ensure that it's never used.
   */
  Collection operator=(const Collection& coll);

  long m_id;
  long m_nextEntryId;
  TQString m_title;
  TQString m_typeName;
  TQString m_iconName;
  TQString m_defaultGroupField;

  FieldVec m_fields;
  FieldVec m_peopleFields; // keep separate list of people fields
  FieldVec m_imageFields; // keep track of image fields
  TQDict<Field> m_fieldNameDict;
  TQDict<Field> m_fieldTitleDict;
  TQStringList m_fieldCategories;
  TQStringList m_fieldNames;
  TQStringList m_fieldTitles;

  EntryVec m_entries;
  TQIntDict<Entry> m_entryIdDict;

  TQDict<EntryGroupDict> m_entryGroupDicts;
  TQStringList m_entryGroups;
  PtrVector<EntryGroup> m_groupsToDelete;

  FilterVec m_filters;
  BorrowerVec m_borrowers;

  bool m_trackGroups : 1;
};

  } // end namespace
} //end namespace
#endif