1 /***************************************************************************
2 miscmodel.cpp
3 -------------------
4 Misc model
5 -------------------
6 Copyright 2006-2008, David Johnson
7 Please see the header file for copyright and license information
8 ***************************************************************************/
9
10 #include <QApplication>
11 #include <QMessageBox>
12 #include <QPair>
13
14 #include "data.h"
15 #include "miscmodel.h"
16
17 using namespace Resource;
18
19 //////////////////////////////////////////////////////////////////////////////
20 // MiscModel()
21 // ------------
22 // Constructor
23
MiscModel(QObject * parent,MiscList * list)24 MiscModel::MiscModel(QObject *parent, MiscList *list)
25 : QAbstractTableModel(parent), list_(list)
26 {}
27
~MiscModel()28 MiscModel::~MiscModel() {}
29
30 //////////////////////////////////////////////////////////////////////////////
31 // flush()
32 // -------
33 // Reset the model
34
flush()35 void MiscModel::flush()
36 {
37 beginResetModel();
38 endResetModel();
39 }
40
41 //////////////////////////////////////////////////////////////////////////////
42 // data()
43 // ------
44 // Return data at index
45
data(const QModelIndex & index,int role) const46 QVariant MiscModel::data(const QModelIndex &index, int role) const
47 {
48 if (!index.isValid()) return QVariant();
49 if (index.row() >= list_->count()) return QVariant();
50
51 // row is the entry in the QList
52 const Misc &misc = list_->at(index.row());
53
54 // column is the ingredient "field"
55 if (role == Qt::DisplayRole) {
56 switch (index.column()) {
57 case NAME:
58 return misc.name();
59 case QUANTITY:
60 return misc.quantity().toString(3);
61 case TYPE:
62 return misc.type();
63 case NOTES:
64 return misc.notes();
65 default:
66 return QVariant();
67 }
68 } else if (role == Qt::EditRole) {
69 switch (index.column()) {
70 case NAME:
71 return misc.name();
72 case QUANTITY: {
73 // return converted quantity
74 Quantity quantity = misc.quantity();
75 quantity.convert(Data::instance()->defaultMiscUnit());
76 return quantity.amount();
77 }
78 case TYPE:
79 return misc.type();
80 case NOTES:
81 return misc.notes();
82 default:
83 return QVariant();
84 }
85 } else if (role == Qt::TextAlignmentRole) {
86 switch (index.column()) {
87 case NAME:
88 case TYPE:
89 case NOTES:
90 return Qt::AlignLeft;
91 case QUANTITY:
92 default:
93 return Qt::AlignRight;
94 }
95 } else {
96 return QVariant();
97 }
98 }
99
100 //////////////////////////////////////////////////////////////////////////////
101 // setData()
102 // ---------
103 // Set data at index
104
setData(const QModelIndex & index,const QVariant & value,int role)105 bool MiscModel::setData(const QModelIndex &index,
106 const QVariant &value, int role)
107 {
108 static bool deleting = false;
109
110 Misc misc;
111 QString name;
112 int row = index.row();
113 int column = index.column();
114
115 if (!index.isValid()) return false;
116 if (role != Qt::EditRole) return false;
117 if (row >= list_->count()) return false;
118
119 // grab existing misc
120 if (row < list_->count()) misc = list_->value(row);
121
122 switch (column) {
123 case NAME:
124 // editing name as several special cases
125 name = value.toString();
126
127 // deleting name deletes ingredient
128 if (name.isEmpty()) {
129 if (row >= list_->count()) return false; // empty
130
131 // TODO: for some reason this gets entered recursively...
132 if (deleting) return false;
133 deleting = true;
134
135 int status = QMessageBox::question(QApplication::activeWindow(),
136 TITLE + tr(" - Delete?"),
137 tr("Do you wish to remove this entry?"),
138 QMessageBox::Yes | QMessageBox::Cancel);
139 if (status == QMessageBox::Yes) {
140 // remove misc
141 beginRemoveRows(index.parent(), row, row);
142
143 list_->removeAt(row);
144 emit modified();
145 endRemoveRows();
146
147 deleting = false;
148 return true;
149 } else {
150 // ignore
151 deleting = false;
152 return false;
153 }
154 }
155
156 // no change, nothing to do
157 if (name == list_->at(row).name()) {
158 return false;
159 }
160
161 // changed name
162 misc.setName(name);
163 if (Data::instance()->hasMisc(name)) {
164 Misc newmisc = Data::instance()->misc(name);
165 // we don't override weight
166 misc.setType(newmisc.type());
167 misc.setNotes(newmisc.notes());
168 }
169 break;
170
171 case QUANTITY:
172 misc.setQuantity(Quantity(value.toDouble(),
173 Data::instance()->defaultMiscUnit()));
174 break;
175
176 case TYPE:
177 misc.setType(value.toString());
178 break;
179
180 case NOTES:
181 misc.setNotes(value.toString());
182 break;
183
184 default:
185 return false;
186 }
187
188 list_->replace(row, misc);
189 emit modified();
190
191 // whole row may have changed
192 emit dataChanged(index.sibling(row, NAME),
193 index.sibling(row, NOTES));
194
195 return true;
196 }
197
198 //////////////////////////////////////////////////////////////////////////////
199 // insertRows()
200 // ------------
201 // Insert rows into table
202
insertRows(int row,int count,const QModelIndex &)203 bool MiscModel::insertRows(int row, int count, const QModelIndex&)
204 {
205 if (count != 1) return false; // only insert one row at a time
206 if ((row < 0) || (row >= list_->count())) row = list_->count();
207
208 Misc misc = Data::instance()->misc(tr("Generic"));
209
210 beginInsertRows(QModelIndex(), row, row);
211 list_->insert(row, misc);
212 emit modified();
213 endInsertRows();
214 return true;
215 }
216
217 //////////////////////////////////////////////////////////////////////////////
218 // removeRows()
219 // ------------
220 // Remove rows from table
221
removeRows(int row,int count,const QModelIndex &)222 bool MiscModel::removeRows(int row, int count, const QModelIndex&)
223 {
224 if (count != 1) return false; // only remove one row at a time
225 if ((row < 0) || (row >= list_->count())) return false;
226
227 int status = QMessageBox::question(QApplication::activeWindow(),
228 TITLE + tr(" - Delete?"),
229 tr("Do you wish to remove this entry?"),
230 QMessageBox::Yes | QMessageBox::Cancel);
231 if (status == QMessageBox::Cancel) {
232 return false;
233 }
234
235 beginRemoveRows(QModelIndex(), row, row);
236 list_->removeAt(row);
237 emit modified();
238 endRemoveRows();
239 return true;
240 }
241
242 //////////////////////////////////////////////////////////////////////////////
243 // headerData()
244 // ------------
245 // Return header information
246
headerData(int section,Qt::Orientation orientation,int role) const247 QVariant MiscModel::headerData(int section, Qt::Orientation orientation,
248 int role) const
249 {
250 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
251 switch (section) {
252 case NAME:
253 return tr("Misc");
254 case QUANTITY:
255 return tr("Quantity");
256 case TYPE:
257 return tr("Type");
258 case NOTES:
259 return tr("Notes");
260 default:
261 return QVariant();
262 }
263 }
264
265 return QVariant();
266 }
267
268 //////////////////////////////////////////////////////////////////////////////
269 // flags()
270 // -------
271 // Return flags at index
272
flags(const QModelIndex & index) const273 Qt::ItemFlags MiscModel::flags(const QModelIndex &index) const
274 {
275 if (!index.isValid()) return Qt::ItemIsEnabled;
276
277 return QAbstractTableModel::flags(index) | Qt::ItemIsEditable;
278 }
279
280 //////////////////////////////////////////////////////////////////////////////
281 // rowCount()
282 // ----------
283 // Return number of rows of data
284
rowCount(const QModelIndex &) const285 int MiscModel::rowCount(const QModelIndex &) const
286 {
287 return list_->count();
288 }
289
290 //////////////////////////////////////////////////////////////////////////////
291 // columnCount()
292 // -------------
293 // Return number of columns of data
294
columnCount(const QModelIndex &) const295 int MiscModel::columnCount(const QModelIndex &) const
296 {
297 return COUNT;
298 }
299
300 //////////////////////////////////////////////////////////////////////////////
301 // sort()
302 // ------
303 // Sort by column
304
sort(int column,Qt::SortOrder order)305 void MiscModel::sort(int column, Qt::SortOrder order)
306 {
307 QList<QPair<QString,Misc> > sortlist;
308
309 foreach(Misc misc, *list_) {
310 QString field;
311 switch (column) {
312 case NAME:
313 field = misc.name();
314 break;
315 case QUANTITY:
316 field = QString::number(misc.quantity().amount()).rightJustified(8,'0');
317 break;
318 case TYPE:
319 field = misc.type();
320 break;
321 case NOTES:
322 default:
323 field = misc.notes();
324 break;
325 }
326 sortlist.append(QPair<QString,Misc>(field, misc));
327 }
328
329 // sort list
330 qSort(sortlist.begin(), sortlist.end());
331
332 emit layoutAboutToBeChanged();
333
334 // create new list
335 list_->clear();
336 QPair<QString,Misc> pair;
337 foreach(pair, sortlist) {
338 if (order == Qt::AscendingOrder)
339 list_->append(pair.second);
340 else
341 list_->prepend(pair.second);
342 }
343
344 emit layoutChanged();
345 }
346