~scottydelicious666/brewtarget/brewtarget

« back to all changes in this revision

Viewing changes to src/database.cpp

  • Committer: Philip Greggory Lee
  • Date: 2009-08-23 16:53:43 UTC
  • Revision ID: git-v1:f8d1a25135bd92f06c46c562293800e4faa42c61
Made a src/ and ui/ directory and moved everything.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * database.cpp is part of Brewtarget, and is Copyright Philip G. Lee
 
3
 * (rocketman768@gmail.com), 2009.
 
4
 *
 
5
 * Brewtarget is free software: you can redistribute it and/or modify
 
6
 * it under the terms of the GNU General Public License as published by
 
7
 * the Free Software Foundation, either version 3 of the License, or
 
8
 * (at your option) any later version.
 
9
 
 
10
 * Brewtarget is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 
 
15
 * You should have received a copy of the GNU General Public License
 
16
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
17
 */
 
18
 
 
19
#include "database.h"
 
20
 
 
21
#include <list>
 
22
#include <iostream>
 
23
#include <fstream>
 
24
#include <QDomDocument>
 
25
#include <QIODevice>
 
26
#include <QDomNodeList>
 
27
#include <QDomNode>
 
28
#include <QTextStream>
 
29
 
 
30
#include "equipment.h"
 
31
#include "fermentable.h"
 
32
#include "hop.h"
 
33
#include "mash.h"
 
34
#include "mashstep.h"
 
35
#include "misc.h"
 
36
#include "recipe.h"
 
37
#include "style.h"
 
38
#include "water.h"
 
39
#include "yeast.h"
 
40
 
 
41
#include "xmlnode.h"
 
42
#include "xmltree.h"
 
43
#include "config.h"
 
44
#include "brewtarget.h"
 
45
 
 
46
// Grrr... stupid C++. Have to define these outside the class AGAIN.
 
47
std::list<Equipment*> Database::equipments;
 
48
std::list<Fermentable*> Database::fermentables;
 
49
std::list<Hop*> Database::hops;
 
50
std::list<Mash*> Database::mashs;
 
51
std::list<MashStep*> Database::mashSteps;
 
52
std::list<Misc*> Database::miscs;
 
53
std::list<Recipe*> Database::recipes;
 
54
std::list<Style*> Database::styles;
 
55
std::list<Water*> Database::waters;
 
56
std::list<Yeast*> Database::yeasts;
 
57
bool Database::initialized = false;
 
58
Database* Database::internalDBInstance = 0;
 
59
QFile Database::dbFile;
 
60
QString Database::dbFileName;
 
61
QFile Database::recipeFile;
 
62
QString Database::recipeFileName;
 
63
QFile Database::mashFile;
 
64
QString Database::mashFileName;
 
65
 
 
66
Database::Database()
 
67
{
 
68
   // Don't EVER use this method to get the database!!!
 
69
}
 
70
 
 
71
Database* Database::getDatabase()
 
72
{
 
73
   if( initialized )
 
74
      return internalDBInstance;
 
75
   else
 
76
      return 0;
 
77
}
 
78
 
 
79
bool Database::isInitialized()
 
80
{
 
81
   return initialized;
 
82
}
 
83
 
 
84
void Database::initialize()
 
85
{
 
86
   QDomDocument dbDoc, recDoc, mashDoc;
 
87
   QDomNodeList list;
 
88
   QString err;
 
89
   int line;
 
90
   int col;
 
91
   unsigned int i, size;
 
92
 
 
93
   dbFileName = (Brewtarget::getDataDir() + "database.xml");
 
94
   recipeFileName = (Brewtarget::getDataDir() + "recipes.xml");
 
95
   mashFileName = (Brewtarget::getDataDir() + "mashs.xml");
 
96
 
 
97
   dbFile.setFileName(dbFileName);
 
98
   recipeFile.setFileName(recipeFileName);
 
99
   mashFile.setFileName(mashFileName);
 
100
 
 
101
   // Try to open the files.
 
102
   if( ! dbFile.open(QIODevice::ReadOnly) )
 
103
   {
 
104
      Brewtarget::log(Brewtarget::ERROR, "Could not open " + dbFile.fileName().toStdString() + " for reading.");
 
105
      return;
 
106
   }
 
107
   if( ! recipeFile.open(QIODevice::ReadOnly) )
 
108
   {
 
109
      Brewtarget::log(Brewtarget::ERROR, "Could not open " + recipeFile.fileName().toStdString() + " for reading.");
 
110
      return;
 
111
   }
 
112
   if( ! mashFile.open(QIODevice::ReadOnly) )
 
113
   {
 
114
      Brewtarget::log(Brewtarget::ERROR, "Could not open " + recipeFile.fileName().toStdString() + " for reading.");
 
115
      return;
 
116
   }
 
117
 
 
118
   // Parse the xml documents.
 
119
   if( ! dbDoc.setContent(&dbFile, false, &err, &line, &col) )
 
120
      Brewtarget::log(Brewtarget::WARNING, QString("Bad document formatting in %1 %2:%3. %4").arg(dbFile.fileName()).arg(line).arg(col).arg(err) );
 
121
   if( ! recDoc.setContent(&recipeFile, false, &err, &line, &col) )
 
122
      Brewtarget::log(Brewtarget::WARNING, QString("Bad document formatting in %1 %2:%3. %4").arg(recipeFile.fileName()).arg(line).arg(col).arg(err) );
 
123
   if( ! mashDoc.setContent(&mashFile, false, &err, &line, &col) )
 
124
      Brewtarget::log(Brewtarget::WARNING, QString("Bad document formatting in %1 %2:%3. %4").arg(mashFile.fileName()).arg(line).arg(col).arg(err) );
 
125
 
 
126
   /*** Items in dbDoc ***/
 
127
   list = dbDoc.elementsByTagName("EQUIPMENT");
 
128
   size = list.size();
 
129
   for( i = 0; i < size; ++i )
 
130
      equipments.push_back(new Equipment( list.at(i) ));
 
131
   list = dbDoc.elementsByTagName("FERMENTABLE");
 
132
   size = list.size();
 
133
   for( i = 0; i < size; ++i )
 
134
      fermentables.push_back( new Fermentable( list.at(i) ) );
 
135
   list = dbDoc.elementsByTagName("HOP");
 
136
   size = list.size();
 
137
   for( i = 0; i < size; ++i )
 
138
      hops.push_back(new Hop( list.at(i) ));
 
139
   list = dbDoc.elementsByTagName("MASH_STEP");
 
140
   size = list.size();
 
141
   for( i = 0; i < size; ++i )
 
142
      mashSteps.push_back(new MashStep( list.at(i) ));
 
143
   list = dbDoc.elementsByTagName("MISC");
 
144
   size = list.size();
 
145
   for( i = 0; i < size; ++i )
 
146
      miscs.push_back(new Misc( list.at(i) ));
 
147
   list = dbDoc.elementsByTagName("STYLE");
 
148
   size = list.size();
 
149
   for( i = 0; i < size; ++i )
 
150
      styles.push_back(new Style(list.at(i)));
 
151
   list = dbDoc.elementsByTagName("WATER");
 
152
   size = list.size();
 
153
   for( i = 0; i < size; ++i )
 
154
      waters.push_back(new Water(list.at(i)));
 
155
   list = dbDoc.elementsByTagName("YEAST");
 
156
   size = list.size();
 
157
   for( i = 0; i < size; ++i )
 
158
      yeasts.push_back(new Yeast(list.at(i)));
 
159
 
 
160
   /*** Items in mashDoc ***/
 
161
   list = mashDoc.elementsByTagName("MASH");
 
162
   size = list.size();
 
163
   for( i = 0; i < size; ++i )
 
164
      mashs.push_back(new Mash(list.at(i)));
 
165
 
 
166
   /*** Items in recDoc ***/
 
167
   list = recDoc.elementsByTagName("RECIPE");
 
168
   size = list.size();
 
169
   for( i = 0; i < size; ++i )
 
170
      recipes.push_back(new Recipe(list.at(i)));
 
171
 
 
172
   // Sort everything by name.
 
173
   equipments.sort(Equipment_ptr_cmp());
 
174
   fermentables.sort(Fermentable_ptr_cmp());
 
175
   hops.sort(Hop_ptr_cmp());
 
176
   mashs.sort(Mash_ptr_cmp());
 
177
   mashSteps.sort(MashStep_ptr_cmp());
 
178
   miscs.sort(Misc_ptr_cmp());
 
179
   recipes.sort(Recipe_ptr_cmp());
 
180
   styles.sort(Style_ptr_cmp());
 
181
   waters.sort(Water_ptr_cmp());
 
182
   yeasts.sort(Yeast_ptr_cmp());
 
183
 
 
184
   dbFile.close();
 
185
   recipeFile.close();
 
186
   mashFile.close();
 
187
 
 
188
   internalDBInstance = new Database();
 
189
   Database::initialized = true;
 
190
   
 
191
   /*
 
192
   dbFile.open(dbFileName.toStdString().c_str());
 
193
   recipeFile.open(recipeFileName.toStdString().c_str()); // Why are these separate from the dbFile? To prevent duplicates.
 
194
   mashFile.open(mashFileName.toStdString().c_str()); // Why are these separate from the dbFile? To prevent duplicates.
 
195
   
 
196
   unsigned int i, size;
 
197
   std::vector<XmlNode*> nodes;
 
198
   XmlTree* tree = new XmlTree(dbFile);
 
199
 
 
200
   size = tree->getNodesWithTag(nodes, "EQUIPMENT");
 
201
   for( i = 0; i < size; ++i )
 
202
      equipments.push_back(new Equipment(nodes[i]));
 
203
   size = tree->getNodesWithTag(nodes, "FERMENTABLE");
 
204
   for( i = 0; i < size; ++i )
 
205
      fermentables.push_back(new Fermentable(nodes[i]));
 
206
   size = tree->getNodesWithTag(nodes, "HOP");
 
207
   for( i = 0; i < size; ++i )
 
208
      hops.push_back(new Hop(nodes[i]));
 
209
   size = tree->getNodesWithTag(nodes, "MASH_STEP");
 
210
   for( i = 0; i < size; ++i )
 
211
      mashSteps.push_back(new MashStep(nodes[i]));
 
212
   size = tree->getNodesWithTag(nodes, "MISC");
 
213
   for( i = 0; i < size; ++i )
 
214
      miscs.push_back(new Misc(nodes[i]));
 
215
   size = tree->getNodesWithTag(nodes, "STYLE");
 
216
   for( i = 0; i < size; ++i )
 
217
      styles.push_back(new Style(nodes[i]));
 
218
   size = tree->getNodesWithTag(nodes, "WATER");
 
219
   for( i = 0; i < size; ++i )
 
220
      waters.push_back(new Water(nodes[i]));
 
221
   size = tree->getNodesWithTag(nodes, "YEAST");
 
222
   for( i = 0; i < size; ++i )
 
223
      yeasts.push_back(new Yeast(nodes[i]));
 
224
 
 
225
   delete tree;
 
226
 
 
227
   tree = new XmlTree(mashFile);
 
228
 
 
229
   size = tree->getNodesWithTag(nodes, "MASH");
 
230
   for( i = 0; i < size; ++i )
 
231
      mashs.push_back(new Mash(nodes[i]));
 
232
 
 
233
   delete tree;
 
234
 
 
235
   tree = new XmlTree(recipeFile);
 
236
 
 
237
   size = tree->getNodesWithTag(nodes, "RECIPE");
 
238
   for( i = 0; i < size; ++i )
 
239
      recipes.push_back(new Recipe(nodes[i]));
 
240
 
 
241
   delete tree;
 
242
   dbFile.close();
 
243
   recipeFile.close();
 
244
   mashFile.close();
 
245
 
 
246
   // Sort everything by name.
 
247
   equipments.sort(Equipment_ptr_cmp());
 
248
   fermentables.sort(Fermentable_ptr_cmp());
 
249
   hops.sort(Hop_ptr_cmp());
 
250
   mashs.sort(Mash_ptr_cmp());
 
251
   mashSteps.sort(MashStep_ptr_cmp());
 
252
   miscs.sort(Misc_ptr_cmp());
 
253
   recipes.sort(Recipe_ptr_cmp());
 
254
   styles.sort(Style_ptr_cmp());
 
255
   waters.sort(Water_ptr_cmp());
 
256
   yeasts.sort(Yeast_ptr_cmp());
 
257
 
 
258
    */
 
259
}
 
260
 
 
261
void Database::resortAll()
 
262
{
 
263
   // Sort everything by name.
 
264
   equipments.sort(Equipment_ptr_cmp());
 
265
   fermentables.sort(Fermentable_ptr_cmp());
 
266
   hops.sort(Hop_ptr_cmp());
 
267
   mashs.sort(Mash_ptr_cmp());
 
268
   mashSteps.sort(MashStep_ptr_cmp());
 
269
   miscs.sort(Misc_ptr_cmp());
 
270
   recipes.sort(Recipe_ptr_cmp());
 
271
   styles.sort(Style_ptr_cmp());
 
272
   waters.sort(Water_ptr_cmp());
 
273
   yeasts.sort(Yeast_ptr_cmp());
 
274
 
 
275
   hasChanged(QVariant(DBALL));
 
276
}
 
277
 
 
278
void Database::resortEquipments()
 
279
{
 
280
   equipments.sort(Equipment_ptr_cmp());
 
281
   hasChanged(QVariant(DBEQUIP));
 
282
}
 
283
 
 
284
void Database::resortFermentables()
 
285
{
 
286
   fermentables.sort(Fermentable_ptr_cmp());
 
287
   hasChanged(QVariant(DBFERM));
 
288
}
 
289
 
 
290
void Database::resortHops()
 
291
{
 
292
   hops.sort(Hop_ptr_cmp());
 
293
   hasChanged(QVariant(DBHOP));
 
294
}
 
295
 
 
296
void Database::resortMiscs()
 
297
{
 
298
   miscs.sort(Misc_ptr_cmp());
 
299
   hasChanged(QVariant(DBMISC));
 
300
}
 
301
 
 
302
void Database::resortStyles()
 
303
{
 
304
   styles.sort(Style_ptr_cmp());
 
305
   hasChanged(QVariant(DBSTYLE));
 
306
}
 
307
 
 
308
void Database::resortYeasts()
 
309
{
 
310
   yeasts.sort(Yeast_ptr_cmp());
 
311
   hasChanged(QVariant(DBYEAST));
 
312
}
 
313
 
 
314
void Database::savePersistent()
 
315
{
 
316
   QDomDocument dbDoc, recDoc, mashDoc;
 
317
   QDomElement dbRoot, recRoot, mashRoot;
 
318
   
 
319
   if( ! dbFile.open( QIODevice::Truncate | QIODevice::WriteOnly ) )
 
320
   {
 
321
      Brewtarget::log(Brewtarget::ERROR, "Could not open " + dbFile.fileName().toStdString() + " for writing.");
 
322
      return;
 
323
   }
 
324
   if( ! recipeFile.open( QIODevice::Truncate | QIODevice::WriteOnly ) )
 
325
   {
 
326
      Brewtarget::log(Brewtarget::ERROR, "Could not open " + recipeFile.fileName().toStdString() + " for writing.");
 
327
      return;
 
328
   }
 
329
   if( ! mashFile.open( QIODevice::Truncate | QIODevice::WriteOnly ) )
 
330
   {
 
331
      Brewtarget::log(Brewtarget::ERROR, "Could not open " + mashFile.fileName().toStdString() + " for writing.");
 
332
      return;
 
333
   }
 
334
 
 
335
   QTextStream dbOut(&dbFile);
 
336
   QTextStream recipeOut(&recipeFile);
 
337
   QTextStream mashOut(&mashFile);
 
338
 
 
339
   /*** dbDoc ***/
 
340
   dbRoot = dbDoc.createElement("DATABASE");
 
341
   
 
342
   std::list<Equipment*>::iterator eqit, eqend;
 
343
   eqend = equipments.end();
 
344
   for( eqit = equipments.begin(); eqit != eqend; ++eqit )
 
345
      (*eqit)->toXml(dbDoc, dbRoot);
 
346
   
 
347
   std::list<Fermentable*>::iterator fit, fend;
 
348
   fend = fermentables.end();
 
349
   for( fit = fermentables.begin(); fit != fend; ++fit )
 
350
      (*fit)->toXml(dbDoc, dbRoot);
 
351
   
 
352
   std::list<Hop*>::iterator hit, hend;
 
353
   hend = hops.end();
 
354
   for( hit = hops.begin(); hit != hend; ++hit )
 
355
      (*hit)->toXml(dbDoc, dbRoot);
 
356
   
 
357
   std::list<MashStep*>::iterator msit, msend;
 
358
   msend = mashSteps.end();
 
359
   for( msit = mashSteps.begin(); msit != msend; ++msit )
 
360
      (*msit)->toXml(dbDoc, dbRoot);
 
361
   
 
362
   std::list<Misc*>::iterator miscit, miscend;
 
363
   miscend = miscs.end();
 
364
   for( miscit = miscs.begin(); miscit != miscend; ++miscit )
 
365
      (*miscit)->toXml(dbDoc, dbRoot);
 
366
   
 
367
   std::list<Style*>::iterator sit, send;
 
368
   send = styles.end();
 
369
   for( sit = styles.begin(); sit != send; ++sit )
 
370
      (*sit)->toXml(dbDoc, dbRoot);
 
371
   
 
372
   std::list<Water*>::iterator wit, wend;
 
373
   wend = waters.end();
 
374
   for( wit = waters.begin(); wit != wend; ++wit )
 
375
      (*wit)->toXml(dbDoc, dbRoot);
 
376
   
 
377
   std::list<Yeast*>::iterator yit, yend;
 
378
   yend = yeasts.end();
 
379
   for( yit = yeasts.begin(); yit != yend; ++yit )
 
380
      (*yit)->toXml(dbDoc, dbRoot);
 
381
   
 
382
   dbDoc.appendChild(dbRoot);
 
383
   dbOut << dbDoc.toString();
 
384
   /*** END dbDoc ***/
 
385
   
 
386
   /*** recDoc ***/
 
387
   recRoot = recDoc.createElement("RECIPES");
 
388
   
 
389
   std::list<Recipe*>::iterator rit, rend;
 
390
   rend = recipes.end();
 
391
   for( rit = recipes.begin(); rit != rend; ++rit )
 
392
      (*rit)->toXml(recDoc, recRoot);
 
393
   
 
394
   recDoc.appendChild(recRoot);
 
395
   recipeOut << recDoc.toString();
 
396
   /*** END recDoc ***/
 
397
   
 
398
   /*** mashDoc ***/
 
399
   mashRoot = mashDoc.createElement("MASHS");
 
400
   
 
401
   std::list<Mash*>::iterator mait, maend;
 
402
   maend = mashs.end();
 
403
   for( mait = mashs.begin(); mait != maend; ++mait )
 
404
      (*mait)->toXml(mashDoc, mashRoot);
 
405
   
 
406
   mashDoc.appendChild(mashRoot);
 
407
   mashOut << mashDoc.toString();
 
408
   /*** END mashDoc ***/
 
409
   
 
410
   /*
 
411
   dbOut << QString("<?xml version=\"1.0\"?>\n");
 
412
   recipeOut << QString("<?xml version=\"1.0\"?>\n");
 
413
   mashOut << QString("<?xml version=\"1.0\"?>\n");
 
414
 
 
415
   //=====================dbOut entries=============================
 
416
 
 
417
   std::list<Equipment*>::iterator eqit, eqend;
 
418
   eqend = equipments.end();
 
419
   dbOut << QString("<EQUIPMENTS>\n");
 
420
   for( eqit = equipments.begin(); eqit != eqend; ++eqit )
 
421
      dbOut << QString((*eqit)->toXml().c_str());
 
422
   dbOut << QString("</EQUIPMENTS>\n");
 
423
 
 
424
   std::list<Fermentable*>::iterator fit, fend;
 
425
   fend = fermentables.end();
 
426
   dbOut << QString("<FERMENTABLES>\n");
 
427
   for( fit = fermentables.begin(); fit != fend; ++fit )
 
428
      dbOut << QString((*fit)->toXml().c_str());
 
429
   dbOut << QString("</FERMENTABLES>\n");
 
430
 
 
431
   std::list<Hop*>::iterator hit, hend;
 
432
   hend = hops.end();
 
433
   dbOut << QString("<HOPS>\n");
 
434
   for( hit = hops.begin(); hit != hend; ++hit )
 
435
      dbOut << QString((*hit)->toXml().c_str());
 
436
   dbOut << QString("</HOPS>\n");
 
437
 
 
438
   std::list<MashStep*>::iterator msit, msend;
 
439
   msend = mashSteps.end();
 
440
   dbOut << QString("<MASH_STEPS>\n");
 
441
   for( msit = mashSteps.begin(); msit != msend; ++msit )
 
442
      dbOut << QString((*msit)->toXml().c_str());
 
443
   dbOut << QString("</MASH_STEPS>\n");
 
444
 
 
445
   std::list<Misc*>::iterator miscit, miscend;
 
446
   miscend = miscs.end();
 
447
   dbOut << QString("<MISCS>\n");
 
448
   for( miscit = miscs.begin(); miscit != miscend; ++miscit )
 
449
      dbOut << QString((*miscit)->toXml().c_str());
 
450
   dbOut << QString("</MISCS>\n");
 
451
 
 
452
   std::list<Style*>::iterator sit, send;
 
453
   send = styles.end();
 
454
   dbOut << QString("<STYLES>\n");
 
455
   for( sit = styles.begin(); sit != send; ++sit )
 
456
      dbOut << QString((*sit)->toXml().c_str());
 
457
   dbOut << QString("</STYLES>\n");
 
458
 
 
459
   std::list<Water*>::iterator wit, wend;
 
460
   wend = waters.end();
 
461
   dbOut << QString("<WATERS>\n");
 
462
   for( wit = waters.begin(); wit != wend; ++wit )
 
463
      dbOut << QString((*wit)->toXml().c_str());
 
464
   dbOut << QString("</WATERS>\n");
 
465
 
 
466
   std::list<Yeast*>::iterator yit, yend;
 
467
   yend = yeasts.end();
 
468
   dbOut << QString("<YEASTS>\n");
 
469
   for( yit = yeasts.begin(); yit != yend; ++yit )
 
470
      dbOut << QString((*yit)->toXml().c_str());
 
471
   dbOut << QString("</YEASTS>\n");
 
472
 
 
473
   //============================mashOut entries===============================
 
474
   std::list<Mash*>::iterator mait, maend;
 
475
   maend = mashs.end();
 
476
   mashOut << QString("<MASHS>\n");
 
477
   for( mait = mashs.begin(); mait != maend; ++mait )
 
478
      mashOut << QString((*mait)->toXml().c_str());
 
479
   mashOut << QString("</MASHS>\n");
 
480
 
 
481
   //==========================recipeOut entries===============================
 
482
   std::list<Recipe*>::iterator rit, rend;
 
483
   rend = recipes.end();
 
484
   recipeOut << QString("<RECIPES>\n");
 
485
   for( rit = recipes.begin(); rit != rend; ++rit )
 
486
      recipeOut << QString((*rit)->toXml().c_str());
 
487
   recipeOut << QString("</RECIPES>\n");
 
488
 
 
489
   */
 
490
   
 
491
   dbFile.close();
 
492
   recipeFile.close();
 
493
   mashFile.close();
 
494
}
 
495
 
 
496
//=========================accessor methods=====================================
 
497
 
 
498
// TODO: restructure the database to use maps so that this process is fast.
 
499
void Database::addEquipment(Equipment* equip)
 
500
{
 
501
   if( equip != 0 )
 
502
   {
 
503
      equipments.push_back(equip);
 
504
      equipments.sort(Equipment_ptr_cmp());
 
505
      equipments.unique(Equipment_ptr_equals()); // No dups.
 
506
      hasChanged(QVariant(DBEQUIP));
 
507
   }
 
508
}
 
509
 
 
510
void Database::addFermentable(Fermentable* ferm)
 
511
{
 
512
   if( ferm != 0 )
 
513
   {
 
514
      fermentables.push_back(ferm);
 
515
      fermentables.sort(Fermentable_ptr_cmp());
 
516
      fermentables.unique(Fermentable_ptr_equals());
 
517
      hasChanged(QVariant(DBFERM));
 
518
   }
 
519
}
 
520
 
 
521
void Database::addHop(Hop* hop)
 
522
{
 
523
   if( hop != 0 )
 
524
   {
 
525
      hops.push_back(hop);
 
526
      hops.sort(Hop_ptr_cmp());
 
527
      hops.unique(Hop_ptr_equals());
 
528
      hasChanged(QVariant(DBHOP));
 
529
   }
 
530
}
 
531
 
 
532
void Database::addMash(Mash* mash)
 
533
{
 
534
   if( mash != 0 )
 
535
   {
 
536
      mashs.push_back(mash);
 
537
      mashs.sort(Mash_ptr_cmp());
 
538
      mashs.unique(Mash_ptr_equals());
 
539
      hasChanged(QVariant(DBMASH));
 
540
   }
 
541
}
 
542
 
 
543
void Database::addMashStep(MashStep* mashStep)
 
544
{
 
545
   if( mashStep != 0 )
 
546
   {
 
547
      mashSteps.push_back(mashStep);
 
548
      mashSteps.sort(MashStep_ptr_cmp());
 
549
      mashSteps.unique(MashStep_ptr_equals());
 
550
      hasChanged(QVariant(DBMASHSTEP));
 
551
   }
 
552
}
 
553
 
 
554
void Database::addMisc(Misc* misc)
 
555
{
 
556
   if( misc != 0 )
 
557
   {
 
558
      miscs.push_back(misc);
 
559
      miscs.sort(Misc_ptr_cmp());
 
560
      miscs.unique(Misc_ptr_equals());
 
561
      hasChanged(QVariant(DBMISC));
 
562
   }
 
563
}
 
564
 
 
565
void Database::addRecipe(Recipe* rec, bool copySubelements)
 
566
{
 
567
   if( rec == 0 )
 
568
      return;
 
569
 
 
570
   recipes.push_back(rec);
 
571
   recipes.sort(Recipe_ptr_cmp());
 
572
   recipes.unique(Recipe_ptr_equals());
 
573
 
 
574
   if( copySubelements )
 
575
   {
 
576
      unsigned int i, size;
 
577
      addEquipment(rec->getEquipment());
 
578
      addMash(rec->getMash());
 
579
      addStyle(rec->getStyle());
 
580
 
 
581
      size = rec->getNumFermentables();
 
582
      for( i = 0; i < size; ++i )
 
583
         addFermentable( rec->getFermentable(i) );
 
584
      size = rec->getNumHops();
 
585
      for( i = 0; i < size; ++i )
 
586
         addHop( rec->getHop(i) );
 
587
      size = rec->getNumMiscs();
 
588
      for( i = 0; i < size; ++i )
 
589
         addMisc( rec->getMisc(i) );
 
590
      size = rec->getNumWaters();
 
591
      for( i = 0; i < size; ++i )
 
592
         addWater( rec->getWater(i) );
 
593
      size = rec->getNumYeasts();
 
594
      for( i = 0; i < size; ++i )
 
595
         addYeast( rec->getYeast(i) );
 
596
   }
 
597
 
 
598
   hasChanged(DBRECIPE);
 
599
 
 
600
}
 
601
 
 
602
void Database::addStyle(Style* style)
 
603
{
 
604
   if( style != 0 )
 
605
   {
 
606
      styles.push_back(style);
 
607
      styles.sort(Style_ptr_cmp());
 
608
      styles.unique(Style_ptr_equals());
 
609
      hasChanged(QVariant(DBSTYLE));
 
610
   }
 
611
}
 
612
 
 
613
void Database::removeEquipment(Equipment* equip)
 
614
{
 
615
   equipments.remove(equip);
 
616
   hasChanged(QVariant(DBEQUIP));
 
617
}
 
618
 
 
619
void Database::removeFermentable(Fermentable* ferm)
 
620
{
 
621
   fermentables.remove(ferm);
 
622
   hasChanged(QVariant(DBFERM));
 
623
}
 
624
 
 
625
void Database::removeHop(Hop* hop)
 
626
{
 
627
   hops.remove(hop);
 
628
   hasChanged(QVariant(DBHOP));
 
629
}
 
630
 
 
631
void Database::removeMash(Mash* mash)
 
632
{
 
633
   mashs.remove(mash);
 
634
   hasChanged(QVariant(DBMASH));
 
635
}
 
636
 
 
637
void Database::removeMashStep(MashStep* mashStep)
 
638
{
 
639
   mashSteps.remove(mashStep);
 
640
   hasChanged(QVariant(DBMASHSTEP));
 
641
}
 
642
 
 
643
void Database::removeMisc(Misc* misc)
 
644
{
 
645
   miscs.remove(misc);
 
646
   hasChanged(QVariant(DBMISC));
 
647
}
 
648
 
 
649
void Database::removeRecipe(Recipe* rec)
 
650
{
 
651
   recipes.remove(rec);
 
652
   hasChanged(QVariant(DBRECIPE));
 
653
}
 
654
 
 
655
void Database::removeStyle(Style* style)
 
656
{
 
657
   styles.remove(style); // Wow, that was easy.
 
658
   hasChanged(QVariant(DBSTYLE));
 
659
}
 
660
 
 
661
void Database::removeWater(Water* water)
 
662
{
 
663
   waters.remove(water);
 
664
   hasChanged(QVariant(DBWATER));
 
665
}
 
666
 
 
667
void Database::removeYeast(Yeast* yeast)
 
668
{
 
669
   yeasts.remove(yeast);
 
670
   hasChanged(QVariant(DBYEAST));
 
671
}
 
672
 
 
673
void Database::addWater(Water* water)
 
674
{
 
675
   if( water != 0 )
 
676
   {
 
677
      waters.push_back(water);
 
678
      waters.sort(Water_ptr_cmp());
 
679
      waters.unique(Water_ptr_equals());
 
680
      hasChanged(QVariant(DBWATER));
 
681
   }
 
682
}
 
683
 
 
684
void Database::addYeast(Yeast* yeast)
 
685
{
 
686
   if( yeast != 0 )
 
687
   {
 
688
      yeasts.push_back(yeast);
 
689
      yeasts.sort(Yeast_ptr_cmp());
 
690
      yeasts.unique(Yeast_ptr_equals());
 
691
      hasChanged(QVariant(DBYEAST));
 
692
   }
 
693
}
 
694
 
 
695
 
 
696
unsigned int Database::getNumEquipments()
 
697
{
 
698
   return equipments.size();
 
699
}
 
700
 
 
701
unsigned int Database::getNumFermentables()
 
702
{
 
703
   return fermentables.size();
 
704
}
 
705
 
 
706
unsigned int Database::getNumHops()
 
707
{
 
708
   return hops.size();
 
709
}
 
710
 
 
711
unsigned int Database::getNumMashs()
 
712
{
 
713
   return mashs.size();
 
714
}
 
715
 
 
716
unsigned int Database::getNumMashSteps()
 
717
{
 
718
   return mashSteps.size();
 
719
}
 
720
 
 
721
unsigned int Database::getNumMiscs()
 
722
{
 
723
   return miscs.size();
 
724
}
 
725
 
 
726
unsigned int Database::getNumRecipes()
 
727
{
 
728
   return recipes.size();
 
729
}
 
730
 
 
731
unsigned int Database::getNumStyles()
 
732
{
 
733
   return styles.size();
 
734
}
 
735
 
 
736
unsigned int Database::getNumWaters()
 
737
{
 
738
   return waters.size();
 
739
}
 
740
 
 
741
unsigned int Database::getNumYeasts()
 
742
{
 
743
   return yeasts.size();
 
744
}
 
745
 
 
746
 
 
747
std::list<Equipment*>::iterator Database::getEquipmentBegin()
 
748
{
 
749
   return equipments.begin();
 
750
}
 
751
 
 
752
std::list<Equipment*>::iterator Database::getEquipmentEnd()
 
753
{
 
754
   return equipments.end();
 
755
}
 
756
 
 
757
std::list<Fermentable*>::iterator Database::getFermentableBegin()
 
758
{
 
759
   return fermentables.begin();
 
760
}
 
761
 
 
762
std::list<Fermentable*>::iterator Database::getFermentableEnd()
 
763
{
 
764
   return fermentables.end();
 
765
}
 
766
 
 
767
std::list<Hop*>::iterator Database::getHopBegin()
 
768
{
 
769
   return hops.begin();
 
770
}
 
771
 
 
772
std::list<Hop*>::iterator Database::getHopEnd()
 
773
{
 
774
   return hops.end();
 
775
}
 
776
 
 
777
std::list<Mash*>::iterator Database::getMashBegin()
 
778
{
 
779
   return mashs.begin();
 
780
}
 
781
 
 
782
std::list<Mash*>::iterator Database::getMashEnd()
 
783
{
 
784
   return mashs.end();
 
785
}
 
786
 
 
787
std::list<MashStep*>::iterator Database::getMashStepBegin()
 
788
{
 
789
   return mashSteps.begin();
 
790
}
 
791
 
 
792
std::list<MashStep*>::iterator Database::getMashStepEnd()
 
793
{
 
794
   return mashSteps.end();
 
795
}
 
796
 
 
797
std::list<Misc*>::iterator Database::getMiscBegin()
 
798
{
 
799
   return miscs.begin();
 
800
}
 
801
 
 
802
std::list<Misc*>::iterator Database::getMiscEnd()
 
803
{
 
804
   return miscs.end();
 
805
}
 
806
 
 
807
std::list<Recipe*>::iterator Database::getRecipeBegin()
 
808
{
 
809
   return recipes.begin();
 
810
}
 
811
 
 
812
std::list<Recipe*>::iterator Database::getRecipeEnd()
 
813
{
 
814
   return recipes.end();
 
815
}
 
816
 
 
817
std::list<Style*>::iterator Database::getStyleBegin()
 
818
{
 
819
   return styles.begin();
 
820
}
 
821
 
 
822
std::list<Style*>::iterator Database::getStyleEnd()
 
823
{
 
824
   return styles.end();
 
825
}
 
826
 
 
827
std::list<Water*>::iterator Database::getWaterBegin()
 
828
{
 
829
   return waters.begin();
 
830
}
 
831
 
 
832
std::list<Water*>::iterator Database::getWaterEnd()
 
833
{
 
834
   return waters.end();
 
835
}
 
836
 
 
837
std::list<Yeast*>::iterator Database::getYeastBegin()
 
838
{
 
839
   return yeasts.begin();
 
840
}
 
841
 
 
842
std::list<Yeast*>::iterator Database::getYeastEnd()
 
843
{
 
844
   return yeasts.end();
 
845
}
 
846
 
 
847
Equipment* Database::findEquipmentByName(std::string name)
 
848
{
 
849
   std::list<Equipment*>::iterator it, end;
 
850
   end = equipments.end();
 
851
 
 
852
   for( it = equipments.begin(); it != end; it++ )
 
853
   {
 
854
      if( (*it)->getName() == name )
 
855
         return *it;
 
856
   }
 
857
   
 
858
   return 0;
 
859
}
 
860
 
 
861
Fermentable* Database::findFermentableByName(std::string name)
 
862
{
 
863
   std::list<Fermentable*>::iterator it, end;
 
864
   end = fermentables.end();
 
865
 
 
866
   for( it = fermentables.begin(); it != end; it++ )
 
867
   {
 
868
      if( (*it)->getName() == name )
 
869
         return *it;
 
870
   }
 
871
 
 
872
   return 0;
 
873
}
 
874
 
 
875
Hop* Database::findHopByName(std::string name)
 
876
{
 
877
   std::list<Hop*>::iterator it, end;
 
878
   end = hops.end();
 
879
 
 
880
   for( it = hops.begin(); it != end; it++ )
 
881
   {
 
882
      if( (*it)->getName() == name )
 
883
         return *it;
 
884
   }
 
885
 
 
886
   return 0;
 
887
}
 
888
 
 
889
Mash* Database::findMashByName(std::string name)
 
890
{
 
891
   std::list<Mash*>::iterator it, end;
 
892
   end = mashs.end();
 
893
 
 
894
   for( it = mashs.begin(); it != end; it++ )
 
895
   {
 
896
      if( (*it)->getName() == name )
 
897
         return *it;
 
898
   }
 
899
 
 
900
   return 0;
 
901
}
 
902
 
 
903
MashStep* Database::findMashStepByName(std::string name)
 
904
{
 
905
   std::list<MashStep*>::iterator it, end;
 
906
   end = mashSteps.end();
 
907
 
 
908
   for( it = mashSteps.begin(); it != end; it++ )
 
909
   {
 
910
      if( (*it)->getName() == name )
 
911
         return *it;
 
912
   }
 
913
 
 
914
   return 0;
 
915
}
 
916
 
 
917
Misc* Database::findMiscByName(std::string name)
 
918
{
 
919
   std::list<Misc*>::iterator it, end;
 
920
   end = miscs.end();
 
921
 
 
922
   for( it = miscs.begin(); it != end; it++ )
 
923
   {
 
924
      if( (*it)->getName() == name )
 
925
         return *it;
 
926
   }
 
927
 
 
928
   return 0;
 
929
}
 
930
 
 
931
Recipe* Database::findRecipeByName(std::string name)
 
932
{
 
933
   std::list<Recipe*>::iterator it, end;
 
934
   end = recipes.end();
 
935
 
 
936
   for( it = recipes.begin(); it != end; it++ )
 
937
   {
 
938
      if( (*it)->getName() == name )
 
939
         return *it;
 
940
   }
 
941
 
 
942
   return 0;
 
943
}
 
944
 
 
945
Style* Database::findStyleByName(std::string name)
 
946
{
 
947
   std::list<Style*>::iterator it, end;
 
948
   end = styles.end();
 
949
 
 
950
   for( it = styles.begin(); it != end; it++ )
 
951
   {
 
952
      if( (*it)->getName() == name )
 
953
         return *it;
 
954
   }
 
955
 
 
956
   return 0;
 
957
}
 
958
 
 
959
Water* Database::findWaterByName(std::string name)
 
960
{
 
961
   std::list<Water*>::iterator it, end;
 
962
   end = waters.end();
 
963
 
 
964
   for( it = waters.begin(); it != end; it++ )
 
965
   {
 
966
      if( (*it)->getName() == name )
 
967
         return *it;
 
968
   }
 
969
 
 
970
   return 0;
 
971
}
 
972
 
 
973
Yeast* Database::findYeastByName(std::string name)
 
974
{
 
975
   std::list<Yeast*>::iterator it, end;
 
976
   end = yeasts.end();
 
977
 
 
978
   for( it = yeasts.begin(); it != end; it++ )
 
979
   {
 
980
      if( (*it)->getName() == name )
 
981
         return *it;
 
982
   }
 
983
 
 
984
   return 0;
 
985
}