2 * Copyright (C) 2008 David Greaves
4 * This software is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public License
6 * as published by the Free Software Foundation; either version 2.1 of
7 * the License, or (at your option) any later version.
9 * This software is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this software; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 #define DEBUG_SHOPPER 1
32 #include "shopperList.h"
36 std::basic_ostream
<char>& operator<<(std::basic_ostream
<char>& os
, const
38 return os
<< qPrintable(str
);
43 ////////////////////////////////////////////////////////////////
45 int Category::id_master
= 0;
46 Category::Category(sparseCategory dummy
) : // SPARSE constructor for ListParser
50 Category::Category() :
51 id (Category::id_master
++),
56 Category::Category(QString name
) :
57 id (Category::id_master
++),
67 void Category::dbg() {
68 DEBUG("\nCat name : " << name
<<
70 "\n wanted : " << _wanted
<<
71 "\n bought : " << _bought
<<
76 bool operator< (const Category
&a
, const Category
&b
){
79 bool cat_cmp (const Category
*a
, const Category
*b
) {
80 return (a
->id
< b
->id
);
83 // bool user_cmp (const Category &a, const Category &b)
85 // return (a.pos < b.pos);
89 int Category::get_id() { return id
; }
90 void Category::set_id(int i
) {
94 void Category::set_name(QString n
) {
98 QString
Category::get_name() { return name
; }
99 int Category::get_size() { return items
.size(); }
101 void Category::setWanted(bool b
) { b
?_wanted
++:_wanted
--; emit
changed(); }
102 void Category::setBought(bool b
) { b
?_bought
++:_bought
--; emit
changed(); }
103 int Category::wanted() { return _wanted
; }
104 int Category::bought() { return _bought
; }
107 void Category::add(Item
&it
)
109 DEBUG("Category add item " << it
.get_desc() << "\n");
110 items
.push_back(&it
);
112 void Category::rm(Item
&it
)
114 DEBUG("Category remove item " << it
.get_desc() << "\n");
118 Category::pItemIter
Category::itemsI() {return items
.begin();}
119 Category::pItemIter
Category::itemsEnd(){return items
.end();}
120 int Category::size(){return items
.size();}
122 ////////////////////////////////////////////////////////////////
124 int Item::id_master
= 0;
126 Item::Item(sparseItem dummy
) : // SPARSE constructor for ListParser
127 id (Item::id_master
++),
133 id (Item::id_master
++),
138 Item::Item(Category
&c
, QString d
, QString n
, bool w
, bool b
) :
139 id (Item::id_master
++),
149 DEBUG("Created an item from parts\n");
159 "\nItem desc : " << desc
<<
161 "\n note : " << note
<<
162 "\n bought : " << (bought
? "true":"false") <<
163 "\n wanted : " << (wanted
? "true":"false") <<
164 "\n category : " << category
->get_name() <<
168 int Item::get_id(){ return id
; }
169 void Item::set_id(int i
){ id
= i
; }
170 void Item::set_desc(QString d
){
174 QString
Item::get_desc(){ return desc
; }
176 void Item::set_note(QString n
) {
180 QString
Item::get_note(){ return note
; }
181 void Item::set_wanted(bool w
) {
185 category
->setWanted(wanted
);
189 bool Item::get_wanted(){ return wanted
; }
190 void Item::set_bought(bool b
)
195 category
->setBought(bought
);
199 bool Item::get_bought(){ return bought
; }
200 void Item::set_category(Category
*c
){
204 Category
* Item::get_category(){ return category
; }
206 ////////////////////////////////////////////////////////////////
212 active_category(NULL
)
214 // No items, no categories
215 DEBUG("\n\n\nMAKING NEW LIST\n\n\n");
217 List::List(QString dump
)
219 DEBUG("\n\n\nMAKING NEW LIST FROM STRING\n\n\n");
220 ListParser
parse(this);
221 parse
.from_string(dump
);
222 } // initiate from a dump
225 for(list
<Category
*>::iterator catI
= categories
.begin();
226 catI
!= categories
.end(); ++catI
) {
229 for(list
<Item
*>::iterator itI
= items
.begin();
230 itI
!= items
.end(); ++itI
) {
236 List
* List::from_file(QString filename
)
239 std::ifstream
file(filename
.toAscii());
243 // Read xml as a stream
244 std::stringstream xml
;
246 std::string
sxml(xml
.str());
247 QString
qxml(sxml
.c_str());
248 DEBUG("read from : " <<filename
<<"\n"<<qxml
);
249 // Create new list and return it
250 return new Shopper::List(qxml
); // FIXME: may not succeed.
253 void List::to_file(QString filename
)
255 std::ofstream
outf(filename
.toAscii());
257 DEBUG("Couldn't open " << filename
<< " for writing\n");
263 List::operator QString() {return QString("XML here");} // a ustring representation of a List (XML)
265 // an ostream representation of a List (XML)
266 std::ostream
& operator <<(std::ostream
&out
, const List
&l
)
268 DEBUG("in << operator\n");
270 DEBUG("written XML\n");
274 void List::add(Item
&it
)
276 if (categories
.empty()) {
277 cerr
<< "Adding an item but there are no categories\n";
278 exit(1); // FIXME - is this a no-op or an exception or...
280 DEBUG("Add item " << it
.get_desc() << "\n");
281 items
.push_back(&it
);
282 it
.get_category()->add(it
);
283 emit
item_list_changed();
285 void List::rm(Item
&it
)
287 DEBUG("Remove item " << it
.get_desc() << "\n");
289 it
.get_category()->rm(it
);
290 emit
item_list_changed();
294 void List::add(Category
&cat
)
296 DEBUG("Add category " << cat
.get_name());
297 if (categories
.empty())
299 DEBUG(" made active\n");
300 categories
.push_back(&cat
);
301 make_category_active(cat
);
303 list
<Category
*>::iterator low
= lower_bound(categories
.begin(),categories
.end(), &cat
, &cat_cmp
);
304 categories
.insert(low
, &cat
);
307 emit
category_list_changed();
309 void List::rm(Category
&cat
)
311 if (categories
.size() == 1) return;
312 DEBUG("Removing category\n");
313 if (is_category_active(cat
)) cycle_active_category(true);
314 for(list
<Item
*>::iterator itemI
= cat
.items
.begin();
315 itemI
!= cat
.items
.end(); itemI
=cat
.items
.erase(itemI
)) {
317 DEBUG("Removing an item from list");
320 categories
.remove(&cat
);
322 emit
category_list_changed();
327 QString
List::get_name(){return name
;}
328 void List::set_name(QString
)
332 sState
List::get_state(){
335 void List::set_state(sState s
)
339 emit
state_changed();
343 // Category filtering
344 Category
* List::get_active_category()
346 return(active_category
);
348 bool List::is_category_active(Category
&c
) // empty set = all active
350 return (active_category
== NULL
|| active_category
== &c
);
351 // If using a set for multiple active categories
352 // return (active_categories.empty() || ( active_categories.find(c) != active_categories.end() ));;
354 void List::cycle_active_category(bool f
)
356 List::pCategoryIter begin
= categories
.begin();
357 List::pCategoryIter end
= categories
.end();
358 if (active_category
== NULL
) { // use first or last element as 'next'
359 active_category
= f
? *(begin
) : *(categories
.rbegin());
361 List::pCategoryIter c
=
362 find(begin
, end
, active_category
);
364 DEBUG("Not found - shouldn't happen\n");
368 active_category
= (++c
== end
)?NULL
:*c
;
370 active_category
= (c
== begin
)?NULL
:*--c
;
375 void List::make_next_category_active()
377 cycle_active_category(true);
378 emit
active_category_changed();
380 void List::make_prev_category_active()
382 cycle_active_category(false);
383 emit
active_category_changed();
385 void List::make_category_active(Category
&c
)
387 if (active_category
!= &c
) {
388 active_category
= &c
;
389 // If using a set for multiple active categories
390 // active_categories.insert(c);
391 emit
active_category_changed();
394 void List::make_category_inactive(Category
&c
)
396 if (active_category
!= NULL
) {
397 active_category
= NULL
;
398 // If using a set for multiple active categories
399 // active_categories.erase(c);
400 emit
active_category_changed();
403 void List::no_category_active()
405 if (active_category
!= NULL
) {
406 active_category
= NULL
;
407 emit
active_category_changed();
411 void List::resequence()
414 for(list
<Category
*>::iterator catI
= categories
.begin();
415 catI
!= categories
.end(); ++catI
) {
416 (*catI
)->set_id(id
++);
421 categories
.sort(&cat_cmp
);
424 void List::swap_categories(Category
*a
, Category
*b
)
426 int a_id
= a
->get_id();
427 DEBUG("a id is : " << a
->get_id()
428 << " b id is : " << b
->get_id()
430 a
->set_id(b
->get_id());
431 DEBUG("Now set b\n");
433 DEBUG("a id is : " << a
->get_id()
434 << " b id is : " << b
->get_id()
437 DEBUG("Reorder done\n");
439 void List::swap_categories(int a
, int b
)
441 /*Category *c1 = cat_by_id[a];
442 Category *c2 = cat_by_id[b];
450 QString
List::modeText()
452 return modeText(state
);
454 QString
List::modeText(sState s
)
458 return(QString("What's Left"));
460 return(QString("Full List"));
462 return(QString("Making List"));
464 return(QString("BAD State"));
467 List::pItemIter
List::itemsI() { return items
.begin(); }
468 List::pCategoryIter
List::categoriesI(){ return categories
.begin(); }
469 List::pItemIter
List::itemsEnd() { return items
.end(); }
470 List::pCategoryIter
List::categoriesEnd(){ return categories
.end(); }
472 void List::boughtNothing(){} // marks all items as not bought
473 void List::newList(){} // marks all items as not wanted