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"
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
) :
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);
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);
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()");
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
)
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);
118 if ((mylist
->get_state() == WHATS_LEFT
) && myitem
->get_bought()) {
119 DEBUG(" what's left+bought, hide\n");
120 QWidget::setVisible(false);
124 QWidget::setVisible(true);
128 void ItemView::note_changed()
130 myitem
->set_note(note
->getText()); // Setting the data
132 // update on the note
134 void ItemView::edit_item()
136 ItemEdit
itemD(this, mylist
, myitem
);
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
156 DEBUG("Tick " << t
<<"\n");
157 switch (mylist
->get_state()) {
161 DEBUG("what's left\n");
162 myitem
->set_bought(t
);
165 DEBUG("Making list\n");
166 myitem
->set_wanted(t
);
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())))
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
) :
204 // setBackgroundRole(QPalette::Light);
205 setWidgetResizable(true);
206 QSizePolicy
sizePolicy(QSizePolicy::Ignored
, QSizePolicy::Preferred
);
207 sizePolicy
.setHorizontalStretch(1);
208 setSizePolicy(sizePolicy
);
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()
245 DEBUG("Notified of a list_change");
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
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++)
272 // it->second->deleteLater();
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");
291 DEBUG(" ... not selected");
295 QSizePolicy
sizePolicy(QSizePolicy::Ignored
, QSizePolicy::Preferred
);
296 sizePolicy
.setHorizontalStretch(1);
297 contents
->setSizePolicy(sizePolicy
);