2 * Copyright (C) 2008 David Greaves <david@dgreaves.com>
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
21 #include "CategoryDialog.h"
22 #include "shopper.h" // automake, i8n, gettext
24 #include "shopperList.h"
25 #include "LabelEntry.h"
27 #include <QDesktopWidget>
28 #include <QToolButton>
29 #include <QPushButton>
30 #include <QVBoxLayout>
31 #include <QDialogButtonBox>
32 #include <QScrollArea>
37 #include <QApplication>
41 struct CategoryDialog::Private
{
43 Shopper::List
*mylist
;
44 Shopper::Category
*mycat
;
47 QFingerScrollArea
*areaS
;
52 ////////////////////////////////////////////////////////////////
54 CategoryManage::CategoryManage(QWidget
* parent
, Shopper::List
* l
) :
55 CategoryDialog(parent
, l
, 0)
58 ////////////////////////////////////////////////////////////////
59 // Private class CategoryDialog : public QDialog
60 CategoryDialog::CategoryDialog(QWidget
* parent
, Shopper::List
* l
, Shopper::Category
* cat
) :
68 // Make the dialog tall and not too wide.
69 resize(qApp
->desktop()->screenGeometry().width()*70/100,
70 qApp
->desktop()->screenGeometry().height()*90/100);
73 QDialogButtonBox
* bbox
= new QDialogButtonBox(Qt::Horizontal
, this);
74 bbox
->addButton(tr("Done"), QDialogButtonBox::AcceptRole
);
75 connect(bbox
, SIGNAL(accepted()), this, SLOT(accept()));
77 connect(bbox
->addButton(tr("Add Category"), QDialogButtonBox::ActionRole
),
79 this, SLOT(add_category()));
81 // Scroll area with category views
82 p
->areaS
= new QFingerScrollArea(this);
83 p
->areaS
->setWidgetResizable(true);
86 p
->area
= new QWidget
;
87 p
->areaL
= new QVBoxLayout(p
->area
);
88 p
->area
->setLayout(p
->areaL
); // set the layout and take parentage of all children
89 p
->areaS
->setWidget(p
->area
); // add area to the scroller
92 QVBoxLayout
* vbox
= new QVBoxLayout
;
93 vbox
->addWidget(p
->areaS
);
94 vbox
->addWidget(bbox
);
97 // add the categories to the area.
100 // Now connect the List's category_list_changed() signal to this object's updater
101 connect (l
, SIGNAL(category_list_changed()),
102 this, SLOT(update_area()));
104 // When a category is added make sure the scroll area is in the right place
105 // and the CatView is focused. This needs to be a queued connection.
106 connect (this, SIGNAL(categoryAdded(CatView
*)),
107 this, SLOT(highlightCategory(CatView
*)), Qt::QueuedConnection
);
110 CategoryDialog::~CategoryDialog()
115 void CategoryDialog::update_area()
118 // Clean up our old widgets
121 foreach (child
, p
->area
->children()){
122 if (child
->isWidgetType()) {
123 wChild
= static_cast<QWidget
*>(child
);
124 DEBUG("Kill a child " << child
->metaObject()->className() );
125 p
->areaL
->removeWidget(wChild
);
126 wChild
->deleteLater();
133 Shopper::List::pCategoryIter begin
=p
->mylist
->categoriesI(),
134 end
= p
->mylist
->categoriesEnd();
135 Shopper::List::pCategoryIter catI
;
136 for(catI
= begin
, pos
=0; catI
!= end
; ++catI
,++pos
)
138 cv
= new CatView(**catI
, *(p
->mylist
), p
->area
);
139 p
->areaL
->addWidget(cv
); // add CatView to the layout
140 connect(cv
, SIGNAL(move_up()),
141 this, SLOT(move_up()));
142 connect(cv
, SIGNAL(move_down()),
143 this, SLOT(move_down()));
144 if (catI
== begin
) cv
->set_pos(pos
,-1); // size of -1 won't be reached
146 cv
->set_pos(pos
-1,pos
-1); // Now we know the end
149 void CategoryDialog::add_category()
152 // Create a new category
153 p
->mycat
= new Shopper::Category("New Category");
154 p
->mylist
->add(*p
->mycat
);
155 p
->mylist
->make_category_active(*p
->mycat
);
157 // Give the scrollbar chance to update with all the new widgets
158 qApp
->processEvents();
160 // Adding the category should update the area to include the new cv...
161 // so find it and emit a change which will be scheduled to occur from
164 foreach (child
, p
->area
->children()){
165 if (child
->isWidgetType()) {
167 cv
= dynamic_cast<CatView
*>(child
);
168 if (cv
&& cv
->get_cat() == p
->mycat
) {
169 emit
categoryAdded(cv
);
176 void CategoryDialog::highlightCategory(CatView
*cv
)
179 p
->areaS
->ensureWidgetVisible(cv
);
182 #define DOWN_SCREEN 1
184 void CategoryDialog::move_up()
187 CatView
*src
= static_cast<CatView
*>(this->sender());
188 move(src
, UP_SCREEN
);
190 void CategoryDialog::move_down()
193 CatView
*src
= static_cast<CatView
*>(this->sender());
194 move(src
, DOWN_SCREEN
);
196 void CategoryDialog::move(CatView
* src
, int direction
)
199 int pos
= p
->areaL
->indexOf(src
);
200 int max
= p
->areaL
->count()-1;
201 DEBUG("src at pos=" << pos
<< "/"<<max
<<" direction=" << direction
);
203 if (direction
== DOWN_SCREEN
and pos
== max
) return; // moving 'down' the screen
204 if (direction
== UP_SCREEN
and pos
== 0) return;
206 QLayoutItem
*li
= p
->areaL
->itemAt(pos
+direction
);
208 DEBUG("No item found at pos=" << pos
<< " direction=" << direction
);
211 CatView
*that
= static_cast<CatView
*>(p
->areaL
->itemAt(pos
+direction
)->widget());
214 p
->areaL
->removeWidget(src
);
215 p
->areaL
->insertWidget(pos
+direction
, src
);
216 p
->mylist
->swap_categories(src
->get_cat(), that
->get_cat());
217 src
->set_pos(pos
+direction
,max
);
218 that
->set_pos(pos
,max
);
222 ////////////////////////////////////////////////////////////////
223 ////////////////////////////////////////////////////////////////
224 ////////////////////////////////////////////////////////////////
226 // The widget shows the state of a category
227 // it can move up or down and edits the relevant category.
228 struct CatView::Private
{
239 CatView::CatView(Category
&cat
, List
&lst
, QWidget
*parent
) :
247 p
->name
= new LabelEntry(cat
.get_name(), this);
248 p
->up_b
= new QToolButton(this);
249 p
->up_b
->setArrowType(Qt::UpArrow
);
250 p
->down_b
= new QToolButton(this);
251 p
->down_b
->setArrowType(Qt::DownArrow
);
252 QToolButton
*del_b
= new QToolButton(this);
253 del_b
->setIcon(style()->standardIcon(QStyle::SP_TrashIcon
));
254 QHBoxLayout
*box
= new QHBoxLayout(this);
256 box
->addWidget(del_b
);
257 box
->addWidget(p
->name
,1);
258 box
->addWidget(p
->up_b
);
259 box
->addWidget(p
->down_b
);
262 // Respond to changing the label
263 connect(p
->name
, SIGNAL(changed()),
264 this, SLOT(name_changed()));
266 connect(del_b
, SIGNAL(clicked()),
267 this, SLOT(delete_category()));
269 connect(p
->up_b
, SIGNAL(clicked()),
270 this, SIGNAL(move_up()));
272 connect(p
->down_b
, SIGNAL(clicked()),
273 this, SIGNAL(move_down()));
275 // Make the container visible according to visibility logic
276 DEBUG("CatView created for " <<cat
.get_name());
284 void CatView::delete_category()
286 DEBUG("Delete Category");
290 int s
= p
->mycat
->get_size();
292 l
= "Category '" + p
->mycat
->get_name()
293 + "' has " + QString::number(s
)
294 + " items. Delete them all? ";
296 l
= "Delete empty category '" + p
->mycat
->get_name() + "'?";
300 dia
.setWindowTitle("Are you sure?");
302 QVBoxLayout
vbox(&dia
);
303 QDialogButtonBox
bbox(QDialogButtonBox::Yes
| QDialogButtonBox::No
, Qt::Horizontal
, &dia
);
304 connect(&bbox
, SIGNAL(accepted()), &dia
, SLOT(accept()));
305 connect(&bbox
, SIGNAL(rejected()), &dia
, SLOT(reject()));
306 vbox
.addWidget(new QLabel(l
, &dia
));
307 vbox
.addWidget(&bbox
);
308 dia
.setLayout(&vbox
);
310 if (dia
.exec() == QDialog::Accepted
)
312 //FIX Hildon::Banner::show_information(*this, "Deleted category " + p->mycat->get_name());
313 p
->mylist
->rm(*p
->mycat
);
317 void CatView::name_changed()
319 p
->mycat
->set_name(p
->name
->getText());
321 void CatView::set_pos(int pos
, int size
)
324 if (pos
== 0) p
->up_b
->hide(); else p
->up_b
->show();
325 if (pos
== size
) p
->down_b
->hide(); else p
->down_b
->show();
329 void CatView::activate()
332 p
->name
->label_clicked();
335 Category
* CatView::get_cat()