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
48 Category::Category() :
49 id (Category::id_master
++)
52 Category::Category(const Category
&src
)
54 DEBUG("\n\n\nCategory copy SCREAMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\n\n\n");
57 Category::Category(QString name
) :
58 id (Category::id_master
++),
66 void Category::dbg() {
67 DEBUG("\nCat name : " << name
<<
73 bool operator< (const Category
&a
, const Category
&b
)
77 bool cat_cmp (const Category
*a
, const Category
*b
)
79 return (a
->id
< b
->id
);
82 // bool user_cmp (const Category &a, const Category &b)
84 // return (a.pos < b.pos);
88 QString
Category::print_id()
92 int Category::get_id() { return id
; }
93 void Category::set_id(int i
)
98 void Category::set_name(QString n
)
103 QString
Category::get_name() { return name
; }
104 int Category::get_size() {
105 DEBUG("Category size is " << items
.size() << "\n");
109 void Category::add(Item
&it
)
111 DEBUG("Category add item " << it
.get_desc() << "\n");
112 items
.push_back(&it
);
114 void Category::rm(Item
&it
)
116 DEBUG("Category remove item " << it
.get_desc() << "\n");
121 Category::pItemIter
Category::itemsI() {return items
.begin();}
122 Category::pItemIter
Category::itemsEnd(){return items
.end();}
123 ////////////////////////////////////////////////////////////////
125 int Item::id_master
= 0;
127 Item::Item(sparseItem dummy
) : // SPARSE constructor for ListParser
128 id (Item::id_master
++),
132 id (Item::id_master
++),
136 Item::Item(Category
&c
, QString d
, QString n
, bool w
, bool b
) :
137 id (Item::id_master
++),
144 DEBUG("Created an item from parts\n");
154 "\nItem desc : " << desc
<<
156 "\n note : " << note
<<
157 "\n bought : " << (bought
? "true":"false") <<
158 "\n wanted : " << (wanted
? "true":"false") <<
159 "\n category : " << category
->get_name() <<
163 QString
Item::print_id(){return "id";}
164 int Item::get_id(){return id
;}
165 void Item::set_id(int i
){id
=i
;}
166 void Item::set_desc(QString d
){
170 QString
Item::get_desc(){return desc
;}
172 void Item::set_note(QString n
)
177 QString
Item::get_note(){return note
;}
178 void Item::set_wanted(bool w
)
186 bool Item::get_wanted(){return wanted
;}
187 void Item::set_bought(bool b
)
195 bool Item::get_bought(){return bought
;}
196 void Item::set_category(Category
*c
){
200 Category
* Item::get_category(){return category
;}
202 ////////////////////////////////////////////////////////////////
208 active_category(NULL
)
210 // No items, no categories
211 DEBUG("\n\n\nMAKING NEW LIST\n\n\n");
213 List::List(QString dump
)
215 DEBUG("\n\n\nMAKING NEW LIST FROM STRING\n\n\n");
216 ListParser
parse(this);
217 parse
.from_string(dump
);
218 } // initiate from a dump
221 for(list
<Category
*>::iterator catI
= categories
.begin();
222 catI
!= categories
.end(); ++catI
) {
225 for(list
<Item
*>::iterator itI
= items
.begin();
226 itI
!= items
.end(); ++itI
) {
232 List
* List::from_file(QString filename
)
235 std::ifstream
file(filename
.toAscii());
239 // Read xml as a stream
240 std::stringstream xml
;
242 std::string
sxml(xml
.str());
243 QString
qxml(sxml
.c_str());
244 // Create new list and return it
245 return new Shopper::List(qxml
); // FIXME: may not succeed.
248 void List::to_file(QString filename
)
250 std::ofstream
outf(filename
.toAscii());
252 DEBUG("Couldn't open " << filename
<< " for writing\n");
258 List::operator QString() {return QString("XML here");} // a ustring representation of a List (XML)
260 // an ostream representation of a List (XML)
261 std::ostream
& operator <<(std::ostream
&out
, const List
&l
)
263 DEBUG("in << operator\n");
265 // DEBUG(w.write(cerr));
266 DEBUG("written XML\n");
267 // return w.write(out);
270 void List::add(Item
&it
)
272 if (categories
.empty()) {
273 cerr
<< "Adding an item but there are no categories\n";
274 exit(1); // FIXME - is this a no-op or an exception or...
276 DEBUG("Add item " << it
.get_desc() << "\n");
277 items
.push_back(&it
);
278 it
.get_category()->add(it
);
279 emit
item_list_changed();
281 void List::rm(Item
&it
)
283 DEBUG("Remove item " << it
.get_desc() << "\n");
285 it
.get_category()->rm(it
);
286 emit
item_list_changed();
290 void List::add(Category
&cat
)
292 DEBUG("Add category " << cat
.get_name());
293 if (categories
.empty())
295 DEBUG(" made active\n");
296 categories
.push_back(&cat
);
297 make_category_active(cat
);
299 list
<Category
*>::iterator low
= lower_bound(categories
.begin(),categories
.end(), &cat
, &cat_cmp
);
300 categories
.insert(low
, &cat
);
304 emit
category_list_changed();
306 void List::rm(Category
&cat
)
308 if (categories
.size() == 1) return;
309 DEBUG("Removing category\n");
310 if (is_category_active(cat
)) cycle_active_category(true);
311 for(list
<Item
*>::iterator itemI
= cat
.items
.begin();
312 itemI
!= cat
.items
.end(); itemI
=cat
.items
.erase(itemI
)) {
314 DEBUG("Removing an item from list");
317 categories
.remove(&cat
);
319 emit
category_list_changed();
324 QString
List::get_name(){return name
;}
325 void List::set_name(QString
)
329 sState
List::get_state(){
332 void List::set_state(sState s
)
336 emit
state_changed();
340 // Category filtering
341 Category
* List::get_active_category()
343 return(active_category
);
345 bool List::is_category_active(Category
&c
) // empty set = all active
347 return (active_category
== NULL
|| active_category
== &c
);
348 // If using a set for multiple active categories
349 // return (active_categories.empty() || ( active_categories.find(c) != active_categories.end() ));;
351 void List::cycle_active_category(bool f
)
353 List::pCategoryIter begin
= categories
.begin();
354 List::pCategoryIter end
= categories
.end();
355 if (active_category
== NULL
) { // use first or last element as 'next'
356 active_category
= f
? *(begin
) : *(categories
.rbegin());
358 List::pCategoryIter c
=
359 find(begin
, end
, active_category
);
361 DEBUG("Not found - shouldn't happen\n");
365 active_category
= (++c
== end
)?NULL
:*c
;
367 active_category
= (c
== begin
)?NULL
:*--c
;
372 void List::make_next_category_active()
374 cycle_active_category(true);
375 emit
active_category_changed();
377 void List::make_prev_category_active()
379 cycle_active_category(false);
380 emit
active_category_changed();
382 void List::make_category_active(Category
&c
)
384 if (active_category
!= &c
) {
385 active_category
= &c
;
386 // If using a set for multiple active categories
387 // active_categories.insert(c);
388 emit
active_category_changed();
391 void List::make_category_inactive(Category
&c
)
393 if (active_category
!= NULL
) {
394 active_category
= NULL
;
395 // If using a set for multiple active categories
396 // active_categories.erase(c);
397 emit
active_category_changed();
400 void List::no_category_active()
402 if (active_category
!= NULL
) {
403 active_category
= NULL
;
404 emit
active_category_changed();
408 void List::resequence()
411 for(list
<Category
*>::iterator catI
= categories
.begin();
412 catI
!= categories
.end(); ++catI
) {
413 (*catI
)->set_id(id
++);
418 categories
.sort(&cat_cmp
);
421 void List::swap_categories(Category
*a
, Category
*b
)
423 int a_id
= a
->get_id();
424 DEBUG("a id is : " << a
->get_id()
425 << " b id is : " << b
->get_id()
427 a
->set_id(b
->get_id());
428 DEBUG("Now set b\n");
430 DEBUG("a id is : " << a
->get_id()
431 << " b id is : " << b
->get_id()
434 DEBUG("Reorder done\n");
436 void List::swap_categories(int a
, int b
)
438 /*Category *c1 = cat_by_id[a];
439 Category *c2 = cat_by_id[b];
447 QString
List::modeText()
449 return modeText(state
);
451 QString
List::modeText(sState s
)
455 return(QString("What's Left"));
457 return(QString("Full List"));
459 return(QString("Making List"));
461 return(QString("BAD State"));
464 List::pItemIter
List::itemsI() { return items
.begin(); }
465 List::pCategoryIter
List::categoriesI(){ return categories
.begin(); }
466 List::pItemIter
List::itemsEnd() { return items
.end(); }
467 List::pCategoryIter
List::categoriesEnd(){ return categories
.end(); }
469 void List::boughtNothing(){} // marks all items as not bought
470 void List::newList(){} // marks all items as not wanted