Added a Notify class
[shopper.git] / src / ui / shopperView.cc
blob2e897b79c30d52ab52311e748ffe2c2aaa9094f9
1 /* Shopper
2 * Copyright (C) 2008 David Greaves
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
19 //#define DEBUG_SHOPPER 1
20 #include "shopper.h" // automake, i8n, gettext
21 #include "shopperList.h"
22 #include "ItemDialog.h"
23 #include "LabelEntry.h"
24 #include "shopperView.h"
25 #include <QtGui>
26 #include <iostream>
28 using namespace std;
30 namespace Shopper
32 // The widget shows the state of an item.
33 // Items are watched and when they emit a change signal, the display
34 // is updated (an old Tk/TCL idea)
35 // class ItemView: public QWidget
36 ItemView::ItemView(Item &it, List &l) :
37 myitem(&it),
38 mylist(&l),
39 outer_b(),
40 inner_b()
42 QSizePolicy sizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
43 sizePolicy.setHorizontalStretch(1);
44 sizePolicy.setVerticalStretch(0);
45 setSizePolicy(sizePolicy);
46 // setFrameStyle(QFrame::Panel|QFrame::Sunken);
47 tick = new QCheckBox(this);
48 // The tick represents either wanted or bought
49 tick->setChecked((l.get_state() == MAKING_LIST) ?
50 it.get_wanted() : it.get_bought());
51 desc = new SLabel(it.get_desc(), this);
52 desc->setAlignment(Qt::AlignLeft);
53 desc->setSizePolicy(sizePolicy);
54 // desc->setFrameStyle(QFrame::Panel|QFrame::Sunken);
55 note = new LabelEntry(it.get_note(),this);
56 note->setAlignment(Qt::AlignRight);
57 note->setSizePolicy(sizePolicy);
58 // note->setFrameStyle(QFrame::Panel|QFrame::Sunken);
59 // Lay them out
60 outer_b.addWidget(tick);
61 outer_b.addLayout(&inner_b,1);
62 inner_b.addWidget(desc, 1);
63 inner_b.addWidget(note, 1);
65 outer_b.setContentsMargins(0, 0, 0, 0);
66 inner_b.setContentsMargins(0, 0, 0, 0);
67 // and apply
68 setLayout(&outer_b);
70 // Respond to user clicking the checkbox.
71 connect(tick, SIGNAL(stateChanged(int)),
72 this, SLOT(tick_changed(int)));
73 // And clicking the description is the same.
74 connect(desc, SIGNAL(pressed()),
75 this, SLOT(desc_clicked()));
76 // Respond to clicking the note
77 connect(note, SIGNAL(changed()),
78 this, SLOT(note_changed()));
80 // Now connect the item's changed signal to this object's updater
81 connect(&it, SIGNAL(changed()),
82 this, SLOT(item_changed()));
83 connect(&it, SIGNAL(deleted()),
84 this, SLOT(item_deleted()));
86 // And the watch the list so we can change visibility if needed
87 // [if the list state changes then the list update will ensure 'show']
88 // connect(&l, SIGNAL(state_changed()),
89 // this, SLOT(state_changed()) );
90 DEBUG("About to show()");
91 show();
92 // Make the container visible according to visibility logic
93 DEBUG("ItemView created for " <<it.get_desc());
96 // Prepare menu actions at time of popup
97 void ItemView::contextMenuEvent( QContextMenuEvent * event )
99 QMenu menu(this);
100 connect(menu.addAction(tr("Edit")),
101 SIGNAL(triggered()), this, SLOT(edit_item()));
102 connect(menu.addAction(tr("Delete")),
103 SIGNAL(triggered()), this, SLOT(delete_item()));
104 menu.exec(event->globalPos());
107 // Only shows if matching item should be seen.
108 void ItemView::setVisible(bool vis)
110 // Hide if not wanted
111 if (((mylist->get_state() == WHATS_LEFT) || (mylist->get_state() == OUT_SHOPPING))
112 && ! myitem->get_wanted()) {
113 DEBUG(" shopping, not wanted, hide\n");
114 QWidget::setVisible(false);
115 return;
118 if ((mylist->get_state() == WHATS_LEFT) && myitem->get_bought()) {
119 DEBUG(" what's left+bought, hide\n");
120 QWidget::setVisible(false);
121 return;
123 DEBUG(" show\n");
124 QWidget::setVisible(true);
125 return;
128 void ItemView::note_changed()
130 myitem->set_note(note->getText()); // Setting the data
131 // will call an
132 // update on the note
134 void ItemView::edit_item()
136 ItemEdit itemD(this, mylist, myitem);
137 itemD.exec();
139 void ItemView::delete_item()
141 DEBUG("Delete Item\n");
142 mylist->rm(*(this->myitem));
144 void ItemView::desc_clicked()
146 // Make the tick tock
147 DEBUG("Desc pressed\n");
148 tick->toggle(); // Invokes tick_changed
149 tick->setFocus(Qt::MouseFocusReason);
151 void ItemView::tick_changed(int s)
153 bool t = (s == Qt::Checked);
154 // Suspend our data watch - we're making the change and don't need
155 // to be notified
156 DEBUG("Tick " << t <<"\n");
157 switch (mylist->get_state()) {
158 case OUT_SHOPPING:
159 DEBUG("shopping ");
160 case WHATS_LEFT:
161 DEBUG("what's left\n");
162 myitem->set_bought(t);
163 break;
164 case MAKING_LIST:
165 DEBUG("Making list\n");
166 myitem->set_wanted(t);
167 break;
168 default:
169 DEBUG("State invalid\n");
173 // When the underlying data changes,
174 void ItemView::item_changed()
176 DEBUG("Notified of item change: updating view\n");
177 tick->setChecked((mylist->get_state() == MAKING_LIST) ?
178 myitem->get_wanted() : myitem->get_bought());
179 desc->setText(myitem->get_desc());
180 note->setText(myitem->get_note());
181 if (! mylist->is_category_active(*(myitem->get_category())))
182 hide();
183 else
184 show();
187 void ItemView::item_deleted()
189 DEBUG("Item deleted, thanks for letting me know but this is BAD");
192 // This class displays and manages a list.
194 // It creates ItemViews dynamically
195 // When the mode changes it updates the display
196 // When the active category changes, it updates the display
198 // class ListView: public QScrollArea
200 ListView::ListView(List &l) :
201 mylist(&l),
202 contents(NULL)
204 // setBackgroundRole(QPalette::Light);
205 setWidgetResizable(true);
206 QSizePolicy sizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred);
207 sizePolicy.setHorizontalStretch(1);
208 setSizePolicy(sizePolicy);
210 update();
213 // Now connect the List's state changed signal to this object's updater
214 connect(&l, SIGNAL(state_changed()),
215 this, SLOT(list_changed()));
216 connect(&l, SIGNAL(category_list_changed()),
217 this, SLOT(list_changed()));
218 connect(&l, SIGNAL(item_list_changed()),
219 this, SLOT(list_changed()));
220 connect(&l, SIGNAL(active_category_changed()),
221 this, SLOT(list_changed()));
222 connect(&l, SIGNAL(changed()),
223 this, SLOT(list_changed()));
226 ListView::~ListView()
228 std::map<int, ItemView*>::iterator itemVsI;
230 for(itemVsI = shownItemVs.begin();
231 itemVsI != shownItemVs.end(); ++itemVsI)
233 delete itemVsI->second;
237 void ListView::filter_by(Category &c) // Only view certain categories
239 mylist->make_category_active(c);
242 void ListView::list_changed()
244 _ENTER;
245 DEBUG("Notified of a list_change");
246 update();
249 void ListView::update()
251 if (contents!=NULL) contents->deleteLater();
253 contents = new QFrame;
254 vbox = new QVBoxLayout;
255 contents->setLayout(vbox);
256 // contents->setFrameStyle(QFrame::Panel|QFrame::Raised);
257 contents->setLineWidth(3);
259 // Scans all the items in the Shopper::List and creates or
260 // removes them from the items map
261 ItemView *w;
262 DEBUG("Updating: active category is \n");
263 for(Shopper::List::pCategoryIter catI = mylist->categoriesI();
264 catI != mylist->categoriesEnd(); ++catI)
266 DEBUG(" " << (*catI)->get_name() << " " << (mylist->is_category_active(**catI))?" *");
268 // Delete all the existing itemviews and then clear the map
269 // FIXME: do we even need a map now?
270 // for(std::map<const int, ItemView*>::iterator it = shownItemVs.begin() ; it!= shownItemVs.end(); it++)
271 // {
272 // it->second->deleteLater();
273 // }
274 // shownItemVs.clear();
276 for(Shopper::List::pItemIter itemI = mylist->itemsI();
277 itemI != mylist->itemsEnd(); ++itemI)
279 DEBUG("checking " << (*itemI)->get_desc());
280 if (mylist->is_category_active(*(*itemI)->get_category()))
282 DEBUG(" ... active");
283 w = new ItemView(**itemI, *mylist);
284 // Keep track of our child widgets
285 // shownItemVs.insert(pair<int,ItemView*>((*itemI)->get_id(), w));
286 // Pack from the start...
287 vbox->addWidget(w, 1);
288 DEBUG(" ... made new itemView");
289 // }
290 } else {
291 DEBUG(" ... not selected");
294 vbox->addStretch(1);
295 QSizePolicy sizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred);
296 sizePolicy.setHorizontalStretch(1);
297 contents->setSizePolicy(sizePolicy);
298 setWidget(contents);