1 #include "reading_list_model.h"
2 
3 #include "reading_list_item.h"
4 
5 #include "data_base_management.h"
6 #include "qnaturalsorting.h"
7 #include "db_helper.h"
8 
9 #include "QsLog.h"
10 
11 #include <typeinfo>
12 
ReadingListModel(QObject * parent)13 ReadingListModel::ReadingListModel(QObject *parent)
14     : QAbstractItemModel(parent), rootItem(0)
15 {
16     separator1 = new ReadingListSeparatorItem;
17     separator2 = new ReadingListSeparatorItem;
18 }
19 
rowCount(const QModelIndex & parent) const20 int ReadingListModel::rowCount(const QModelIndex &parent) const
21 {
22     if (!parent.isValid()) //TOP
23     {
24         int separatorsCount = 2; //labels.isEmpty()?1:2;
25         return specialLists.count() + labels.count() + rootItem->childCount() + separatorsCount;
26     } else {
27         auto item = static_cast<ListItem *>(parent.internalPointer());
28 
29         if (typeid(*item) == typeid(ReadingListItem)) {
30             auto item = static_cast<ReadingListItem *>(parent.internalPointer());
31             return item->childCount();
32         }
33     }
34 
35     return 0;
36 }
37 
columnCount(const QModelIndex & parent) const38 int ReadingListModel::columnCount(const QModelIndex &parent) const
39 {
40     if (parent.isValid()) {
41         auto item = static_cast<ListItem *>(parent.internalPointer());
42         if (typeid(*item) == typeid(ReadingListSeparatorItem))
43             return 0;
44     }
45     return 1;
46     /*if (parent.isValid())
47         return static_cast<ListItem*>(parent.internalPointer())->columnCount();
48     else
49         return rootItem->columnCount();*/
50 }
51 
data(const QModelIndex & index,int role) const52 QVariant ReadingListModel::data(const QModelIndex &index, int role) const
53 {
54     if (!index.isValid())
55         return QVariant();
56 
57     auto item = static_cast<ListItem *>(index.internalPointer());
58 
59     if (role == ReadingListModel::TypeListsRole) {
60         if (typeid(*item) == typeid(SpecialListItem))
61             return QVariant(ReadingListModel::SpecialList);
62 
63         if (typeid(*item) == typeid(LabelItem))
64             return QVariant(ReadingListModel::Label);
65 
66         if (typeid(*item) == typeid(ReadingListItem))
67             return QVariant(ReadingListModel::ReadingList);
68 
69         if (typeid(*item) == typeid(ReadingListSeparatorItem))
70             return QVariant(ReadingListModel::Separator);
71     }
72 
73     if (role == ReadingListModel::LabelColorRole && typeid(*item) == typeid(LabelItem)) {
74         auto labelItem = static_cast<LabelItem *>(item);
75         return QVariant(labelItem->colorid());
76     }
77 
78     if (role == ReadingListModel::IDRole) {
79         QLOG_DEBUG() << "getting role";
80         return item->getId();
81     }
82 
83     if (role == ReadingListModel::SpecialListTypeRole && typeid(*item) == typeid(SpecialListItem)) {
84         auto specialListItem = static_cast<SpecialListItem *>(item);
85         return QVariant(specialListItem->getType());
86     }
87 
88     if (typeid(*item) == typeid(ReadingListSeparatorItem))
89         return QVariant();
90 
91     if (role == Qt::DecorationRole) {
92         return QVariant(item->getIcon());
93     }
94 
95     if (role != Qt::DisplayRole)
96         return QVariant();
97 
98     return item->data(index.column());
99 }
100 
flags(const QModelIndex & index) const101 Qt::ItemFlags ReadingListModel::flags(const QModelIndex &index) const
102 {
103     if (!index.isValid())
104         return {};
105 
106     auto item = static_cast<ListItem *>(index.internalPointer());
107     if (typeid(*item) == typeid(ReadingListSeparatorItem))
108         return {};
109 
110     if (typeid(*item) == typeid(ReadingListItem) && static_cast<ReadingListItem *>(item)->parent->getId() != 0)
111         return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDropEnabled | Qt::ItemIsDragEnabled; //only sublists are dragable
112 
113     return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDropEnabled;
114 }
115 
headerData(int section,Qt::Orientation orientation,int role) const116 QVariant ReadingListModel::headerData(int section, Qt::Orientation orientation, int role) const
117 {
118     if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
119         return rootItem->data(section);
120 
121     return QVariant();
122 }
123 
index(int row,int column,const QModelIndex & parent) const124 QModelIndex ReadingListModel::index(int row, int column, const QModelIndex &parent) const
125 {
126     if (!hasIndex(row, column, parent))
127         return QModelIndex();
128 
129     if (!parent.isValid()) {
130         int separatorsCount = 2; //labels.isEmpty()?1:2;
131 
132         if (rowIsSpecialList(row, parent))
133             return createIndex(row, column, specialLists.at(row));
134 
135         if (row == specialLists.count())
136             return createIndex(row, column, separator1);
137 
138         if (rowIsLabel(row, parent))
139             return createIndex(row, column, labels.at(row - specialLists.count() - 1));
140 
141         if (separatorsCount == 2)
142             if (row == specialLists.count() + labels.count() + 1)
143                 return createIndex(row, column, separator2);
144 
145         if (rowIsReadingList(row, parent))
146             return createIndex(row, column, rootItem->child(row - (specialLists.count() + labels.count() + separatorsCount)));
147 
148     } else //sublist
149     {
150         ReadingListItem *parentItem;
151 
152         if (!parent.isValid())
153             parentItem = rootItem; //this should be impossible
154         else
155             parentItem = static_cast<ReadingListItem *>(parent.internalPointer());
156 
157         ReadingListItem *childItem = parentItem->child(row);
158         return createIndex(row, column, childItem);
159     }
160     /*FolderItem *childItem = parentItem->child(row);
161     if (childItem)
162         return createIndex(row, column, childItem);
163     else*/
164     return QModelIndex();
165 }
166 
parent(const QModelIndex & index) const167 QModelIndex ReadingListModel::parent(const QModelIndex &index) const
168 {
169 
170     if (!index.isValid())
171         return QModelIndex();
172 
173     auto item = static_cast<ListItem *>(index.internalPointer());
174 
175     if (typeid(*item) == typeid(ReadingListItem)) {
176         auto childItem = static_cast<ReadingListItem *>(index.internalPointer());
177         ReadingListItem *parent = childItem->parent;
178         if (parent->getId() != 0)
179             return createIndex(parent->row() + specialLists.count() + labels.count() + 2, 0, parent);
180     }
181 
182     return QModelIndex();
183 }
184 
canDropMimeData(const QMimeData * data,Qt::DropAction action,int row,int column,const QModelIndex & parent) const185 bool ReadingListModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const
186 {
187     Q_UNUSED(action);
188 
189     QLOG_DEBUG() << "trying to drop into row = " << row << "column column = " << column << "parent" << parent;
190 
191     if (row == -1)
192         return false;
193 
194     if (!parent.isValid()) //top level items
195     {
196         if (row == -1) //no list
197             return false;
198 
199         if (row == 1) //reading is just an smart list
200             return false;
201 
202         if (rowIsSeparator(row, parent))
203             return false;
204     }
205 
206     if (data->formats().contains(YACReader::YACReaderLibrarComiscSelectionMimeDataFormat))
207         return true;
208 
209     if (rowIsReadingList(row, parent)) // TODO avoid droping in a different parent
210     {
211         if (!parent.isValid())
212             return false;
213         else {
214             QList<QPair<int, int>> sublistsRows;
215             QByteArray rawData = data->data(YACReader::YACReaderLibrarSubReadingListMimeDataFormat);
216             QDataStream in(&rawData, QIODevice::ReadOnly);
217             in >> sublistsRows; //deserialize the list of indentifiers
218             if (parent.row() != sublistsRows.at(0).second)
219                 return false;
220             return data->formats().contains(YACReader::YACReaderLibrarSubReadingListMimeDataFormat);
221         }
222     }
223 
224     return false;
225 }
226 
dropMimeData(const QMimeData * data,Qt::DropAction action,int row,int column,const QModelIndex & parent)227 bool ReadingListModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
228 {
229     QLOG_DEBUG() << "drop mimedata into row = " << row << " column = " << column << "parent" << parent;
230     if (data->formats().contains(YACReader::YACReaderLibrarComiscSelectionMimeDataFormat))
231         return dropComics(data, action, row, column, parent);
232 
233     if (data->formats().contains(YACReader::YACReaderLibrarSubReadingListMimeDataFormat))
234         return dropSublist(data, action, row, column, parent);
235 
236     return false;
237 }
238 
dropComics(const QMimeData * data,Qt::DropAction action,int row,int column,const QModelIndex & parent)239 bool ReadingListModel::dropComics(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
240 {
241     Q_UNUSED(action);
242 
243     QList<qulonglong> comicIds = YACReader::mimeDataToComicsIds(data);
244 
245     QLOG_DEBUG() << "dropped : " << comicIds;
246 
247     QModelIndex dest;
248     QModelIndex parentDest;
249 
250     if (row == -1) {
251         dest = parent;
252     } else
253         dest = index(row, column, parent);
254 
255     parentDest = dest.parent();
256 
257     if (rowIsSpecialList(dest.row(), parentDest)) {
258         if (dest.row() == 0) //add to favorites
259         {
260             QLOG_DEBUG() << "-------addComicsToFavorites : " << comicIds << " to " << dest.data(IDRole).toULongLong();
261             emit addComicsToFavorites(comicIds);
262             return true;
263         }
264     }
265 
266     if (rowIsLabel(dest.row(), parentDest)) {
267         QLOG_DEBUG() << "+++++++++++addComicsToLabel : " << comicIds << " to " << dest.data(IDRole).toULongLong();
268         emit addComicsToLabel(comicIds, dest.data(IDRole).toULongLong());
269         return true;
270     }
271 
272     if (rowIsReadingList(dest.row(), parentDest)) {
273         QLOG_DEBUG() << "///////////addComicsToReadingList : " << comicIds << " to " << dest.data(IDRole).toULongLong();
274         emit addComicsToReadingList(comicIds, dest.data(IDRole).toULongLong());
275         return true;
276     }
277 
278     return false;
279 }
280 
dropSublist(const QMimeData * data,Qt::DropAction action,int row,int column,const QModelIndex & parent)281 bool ReadingListModel::dropSublist(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
282 {
283     Q_UNUSED(action);
284     Q_UNUSED(column);
285 
286     QList<QPair<int, int>> sublistsRows;
287     QByteArray rawData = data->data(YACReader::YACReaderLibrarSubReadingListMimeDataFormat);
288     QDataStream in(&rawData, QIODevice::ReadOnly);
289     in >> sublistsRows; //deserialize the list of indentifiers
290 
291     QLOG_DEBUG() << "dropped : " << sublistsRows;
292 
293     int sourceRow = sublistsRows.at(0).first;
294     int destRow = row;
295     QModelIndex destParent = parent;
296     if (row == -1) {
297         QLOG_DEBUG() << "droping inside parent";
298         destRow = parent.row();
299         destParent = parent.parent();
300     }
301     QLOG_DEBUG() << "move " << sourceRow << "-" << destRow;
302 
303     if (sourceRow == destRow)
304         return false;
305 
306     //beginMoveRows(destParent,sourceRow,sourceRow,destParent,destRow);
307 
308     auto parentItem = static_cast<ReadingListItem *>(destParent.internalPointer());
309     ReadingListItem *child = parentItem->child(sourceRow);
310     parentItem->removeChild(child);
311     parentItem->appendChild(child, destRow);
312 
313     reorderingChildren(parentItem->children());
314     //endMoveRows();
315 
316     return true;
317 }
318 
mimeData(const QModelIndexList & indexes) const319 QMimeData *ReadingListModel::mimeData(const QModelIndexList &indexes) const
320 {
321     QLOG_DEBUG() << "mimeData requested" << indexes;
322 
323     if (indexes.length() == 0) {
324         QLOG_ERROR() << "mimeData requested: indexes is empty";
325         return new QMimeData(); //TODO what happens if 0 is returned?
326     }
327 
328     if (indexes.length() > 1) {
329         QLOG_DEBUG() << "mimeData requested for more than one index, this shouldn't be possible";
330     }
331 
332     QModelIndex modelIndex = indexes.at(0);
333 
334     QList<QPair<int, int>> rows;
335     rows << QPair<int, int>(modelIndex.row(), modelIndex.parent().row());
336     QLOG_DEBUG() << "mimeData requested for row : " << modelIndex.row();
337 
338     QByteArray data;
339     QDataStream out(&data, QIODevice::WriteOnly);
340     out << rows; //serialize the list of identifiers
341 
342     auto mimeData = new QMimeData();
343     mimeData->setData(YACReader::YACReaderLibrarSubReadingListMimeDataFormat, data);
344 
345     return mimeData;
346 }
347 
setupReadingListsData(QString path)348 void ReadingListModel::setupReadingListsData(QString path)
349 {
350     beginResetModel();
351 
352     cleanAll();
353 
354     _databasePath = path;
355     QSqlDatabase db = DataBaseManagement::loadDatabase(path);
356 
357     //setup special lists
358     specialLists = setupSpecialLists(db);
359 
360     //separator--------------------------------------------
361 
362     //setup labels
363     setupLabels(db);
364 
365     //separator--------------------------------------------
366 
367     //setup reading list
368     setupReadingLists(db);
369 
370     endResetModel();
371 }
372 
addNewLabel(const QString & name,YACReader::LabelColors color)373 void ReadingListModel::addNewLabel(const QString &name, YACReader::LabelColors color)
374 {
375     QString connectionName = "";
376     {
377         QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath);
378         qulonglong id = DBHelper::insertLabel(name, color, db);
379 
380         int newPos = addLabelIntoList(new LabelItem(QList<QVariant>() << name << YACReader::colorToName(color) << id << color));
381         beginInsertRows(QModelIndex(), specialLists.count() + 1 + newPos + 1, specialLists.count() + 1 + newPos + 1);
382 
383         endInsertRows();
384         connectionName = db.connectionName();
385     }
386     QSqlDatabase::removeDatabase(connectionName);
387 }
388 
addReadingList(const QString & name)389 void ReadingListModel::addReadingList(const QString &name)
390 {
391     QString connectionName = "";
392     {
393         QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath);
394         beginInsertRows(QModelIndex(), 0, 0); //TODO calculate the right coordinates before inserting
395 
396         qulonglong id = DBHelper::insertReadingList(name, db);
397         ReadingListItem *newItem;
398         rootItem->appendChild(newItem = new ReadingListItem(QList<QVariant>()
399                                                             << name
400                                                             << id
401                                                             << false
402                                                             << true
403                                                             << 0));
404 
405         items.insert(id, newItem);
406 
407         endInsertRows();
408         connectionName = db.connectionName();
409     }
410     QSqlDatabase::removeDatabase(connectionName);
411 }
412 
addReadingListAt(const QString & name,const QModelIndex & mi)413 void ReadingListModel::addReadingListAt(const QString &name, const QModelIndex &mi)
414 {
415     QString connectionName = "";
416     {
417         QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath);
418 
419         beginInsertRows(mi, 0, 0); //TODO calculate the right coordinates before inserting
420 
421         auto readingListParent = static_cast<ReadingListItem *>(mi.internalPointer());
422         qulonglong id = DBHelper::insertReadingSubList(name, mi.data(IDRole).toULongLong(), readingListParent->childCount(), db);
423         ReadingListItem *newItem;
424 
425         readingListParent->appendChild(newItem = new ReadingListItem(QList<QVariant>()
426                                                                      << name
427                                                                      << id
428                                                                      << false
429                                                                      << true
430                                                                      << readingListParent->childCount()));
431 
432         items.insert(id, newItem);
433         endInsertRows();
434         connectionName = db.connectionName();
435     }
436     QSqlDatabase::removeDatabase(connectionName);
437 }
438 
isEditable(const QModelIndex & mi)439 bool ReadingListModel::isEditable(const QModelIndex &mi)
440 {
441     if (!mi.isValid())
442         return false;
443     auto item = static_cast<ListItem *>(mi.internalPointer());
444     return typeid(*item) != typeid(SpecialListItem);
445 }
446 
isReadingList(const QModelIndex & mi)447 bool ReadingListModel::isReadingList(const QModelIndex &mi)
448 {
449     if (!mi.isValid())
450         return false;
451     auto item = static_cast<ListItem *>(mi.internalPointer());
452     return typeid(*item) == typeid(ReadingListItem);
453 }
454 
isReadingSubList(const QModelIndex & mi)455 bool ReadingListModel::isReadingSubList(const QModelIndex &mi)
456 {
457     if (!mi.isValid())
458         return false;
459     auto item = static_cast<ListItem *>(mi.internalPointer());
460     if (typeid(*item) == typeid(ReadingListItem)) {
461         auto readingListItem = static_cast<ReadingListItem *>(item);
462         if (readingListItem->parent == rootItem)
463             return false;
464         else
465             return true;
466     } else
467         return false;
468 }
469 
name(const QModelIndex & mi)470 QString ReadingListModel::name(const QModelIndex &mi)
471 {
472     return data(mi, Qt::DisplayRole).toString();
473 }
474 
rename(const QModelIndex & mi,const QString & name)475 void ReadingListModel::rename(const QModelIndex &mi, const QString &name)
476 {
477     if (!isEditable(mi))
478         return;
479     QString connectionName = "";
480     {
481         QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath);
482 
483         auto item = static_cast<ListItem *>(mi.internalPointer());
484 
485         if (typeid(*item) == typeid(ReadingListItem)) {
486             auto rli = static_cast<ReadingListItem *>(item);
487             rli->setName(name);
488             DBHelper::renameList(item->getId(), name, db);
489 
490             if (rli->parent->getId() != 0) {
491                 //TODO
492                 //move row depending on the name
493             } else
494                 emit dataChanged(index(mi.row(), 0), index(mi.row(), 0));
495         } else if (typeid(*item) == typeid(LabelItem)) {
496             auto li = static_cast<LabelItem *>(item);
497             li->setName(name);
498             DBHelper::renameLabel(item->getId(), name, db);
499             emit dataChanged(index(mi.row(), 0), index(mi.row(), 0));
500         }
501         connectionName = db.connectionName();
502     }
503     QSqlDatabase::removeDatabase(connectionName);
504 }
505 
deleteItem(const QModelIndex & mi)506 void ReadingListModel::deleteItem(const QModelIndex &mi)
507 {
508     if (isEditable(mi)) {
509         QLOG_DEBUG() << "parent row :" << mi.parent().data() << "-" << mi.row();
510         beginRemoveRows(mi.parent(), mi.row(), mi.row());
511         QString connectionName = "";
512         {
513             QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath);
514 
515             auto item = static_cast<ListItem *>(mi.internalPointer());
516 
517             if (typeid(*item) == typeid(ReadingListItem)) {
518                 auto rli = static_cast<ReadingListItem *>(item);
519                 QLOG_DEBUG() << "num children : " << rli->parent->childCount();
520                 rli->parent->removeChild(rli);
521                 QLOG_DEBUG() << "num children : " << rli->parent->childCount();
522                 DBHelper::removeListFromDB(item->getId(), db);
523                 if (rli->parent->getId() != 0) {
524                     reorderingChildren(rli->parent->children());
525                 }
526                 QLOG_DEBUG() << "num children : " << rli->parent->childCount();
527             } else if (typeid(*item) == typeid(LabelItem)) {
528                 auto li = static_cast<LabelItem *>(item);
529                 labels.removeOne(li);
530                 DBHelper::removeLabelFromDB(item->getId(), db);
531             }
532             connectionName = db.connectionName();
533         }
534         QSqlDatabase::removeDatabase(connectionName);
535 
536         endRemoveRows();
537     }
538 }
539 
getLabels()540 const QList<LabelItem *> ReadingListModel::getLabels()
541 {
542     return labels;
543 }
544 
cleanAll()545 void ReadingListModel::cleanAll()
546 {
547     if (rootItem != 0) {
548         delete rootItem;
549 
550         qDeleteAll(specialLists);
551         qDeleteAll(labels);
552 
553         specialLists.clear();
554         labels.clear();
555 
556         items.clear();
557     }
558 
559     rootItem = 0;
560 }
561 
setupReadingListsData(QSqlQuery & sqlquery,ReadingListItem * parent)562 void ReadingListModel::setupReadingListsData(QSqlQuery &sqlquery, ReadingListItem *parent)
563 {
564     items.insert(parent->getId(), parent);
565 
566     QSqlRecord record = sqlquery.record();
567 
568     int name = record.indexOf("name");
569     int id = record.indexOf("id");
570     int finished = record.indexOf("finished");
571     int completed = record.indexOf("completed");
572     int ordering = record.indexOf("ordering");
573     int parentId = record.indexOf("parentId");
574 
575     while (sqlquery.next()) {
576         ReadingListItem *rli = new ReadingListItem(QList<QVariant>()
577                                                    << sqlquery.value(name)
578                                                    << sqlquery.value(id)
579                                                    << sqlquery.value(finished)
580                                                    << sqlquery.value(completed)
581                                                    << sqlquery.value(ordering));
582 
583         ReadingListItem *currentParent;
584         if (sqlquery.value(parentId).isNull())
585             currentParent = rootItem;
586         else
587             currentParent = items.value(sqlquery.value(parentId).toULongLong());
588 
589         currentParent->appendChild(rli);
590 
591         items.insert(rli->getId(), rli);
592     }
593 }
594 
setupSpecialLists(QSqlDatabase & db)595 QList<SpecialListItem *> ReadingListModel::setupSpecialLists(QSqlDatabase &db)
596 {
597     QList<SpecialListItem *> list;
598 
599     QSqlQuery selectQuery("SELECT * FROM default_reading_list ORDER BY id,name", db);
600 
601     QSqlRecord record = selectQuery.record();
602 
603     int name = record.indexOf("name");
604     int id = record.indexOf("id");
605 
606     while (selectQuery.next()) {
607         list << new SpecialListItem(QList<QVariant>()
608                                     << selectQuery.value(name)
609                                     << selectQuery.value(id));
610     }
611 
612     //Reading after Favorites, Why? Because I want to :P
613     list.insert(1, new SpecialListItem(QList<QVariant>() << "Reading" << 0));
614 
615     return list;
616 }
617 
setupLabels(QSqlDatabase & db)618 void ReadingListModel::setupLabels(QSqlDatabase &db)
619 {
620     QSqlQuery selectQuery("SELECT * FROM label ORDER BY ordering,name", db);
621 
622     QSqlRecord record = selectQuery.record();
623 
624     int name = record.indexOf("name");
625     int color = record.indexOf("color");
626     int id = record.indexOf("id");
627     int ordering = record.indexOf("ordering");
628 
629     while (selectQuery.next()) {
630         addLabelIntoList(new LabelItem(QList<QVariant>()
631                                        << selectQuery.value(name)
632                                        << selectQuery.value(color)
633                                        << selectQuery.value(id)
634                                        << selectQuery.value(ordering)));
635     }
636 
637     //TEST
638 
639     //    INSERT INTO label (name, color, ordering) VALUES ("Oh Oh", "red", 1);
640     //    INSERT INTO label (name, color, ordering) VALUES ("lalala", "orange", 2);
641     //    INSERT INTO label (name, color, ordering) VALUES ("we are not sorry", "yellow", 3);
642     //    INSERT INTO label (name, color, ordering) VALUES ("there we go", "green", 4);
643     //    INSERT INTO label (name, color, ordering) VALUES ("oklabunga", "cyan", 5);
644     //    INSERT INTO label (name, color, ordering) VALUES ("hailer mailer", "blue", 6);
645     //    INSERT INTO label (name, color, ordering) VALUES ("lol", "violet", 7);
646     //    INSERT INTO label (name, color, ordering) VALUES ("problems", "purple", 8);
647     //    INSERT INTO label (name, color, ordering) VALUES ("me gussssta", "pink", 9);
648     //    INSERT INTO label (name, color, ordering) VALUES (":D", "white", 10);
649     //    INSERT INTO label (name, color, ordering) VALUES ("ainsss", "light", 11);
650     //    INSERT INTO label (name, color, ordering) VALUES ("put a smile on my face", "dark", 12);
651 }
652 
setupReadingLists(QSqlDatabase & db)653 void ReadingListModel::setupReadingLists(QSqlDatabase &db)
654 {
655     //setup root item
656     rootItem = new ReadingListItem(QList<QVariant>() << "ROOT" << 0 << true << false);
657 
658     QSqlQuery selectQuery("select * from reading_list order by parentId IS NULL DESC", db);
659 
660     //setup reading lists
661     setupReadingListsData(selectQuery, rootItem);
662 
663     //TEST
664     //    ReadingListItem * node1;
665     //    rootItem->appendChild(node1 = new ReadingListItem(QList<QVariant>() /*<< 0*/ << "My reading list" << "atr"));
666     //    rootItem->appendChild(new ReadingListItem(QList<QVariant>() /*<< 0*/ << "X timeline" << "atr"));
667 
668     //    node1->appendChild(new ReadingListItem(QList<QVariant>() /*<< 0*/ << "sublist" << "atr",node1));
669 }
670 
addLabelIntoList(LabelItem * item)671 int ReadingListModel::addLabelIntoList(LabelItem *item)
672 {
673     if (labels.isEmpty())
674         labels << item;
675     else {
676         int i = 0;
677 
678         while (i < labels.count() && (labels.at(i)->colorid() < item->colorid()))
679             i++;
680 
681         if (i < labels.count()) {
682             if (labels.at(i)->colorid() == item->colorid()) //sort by name
683             {
684                 while (i < labels.count() && labels.at(i)->colorid() == item->colorid() && naturalSortLessThanCI(labels.at(i)->name(), item->name()))
685                     i++;
686             }
687         }
688 
689         if (i >= labels.count()) {
690             QLOG_DEBUG() << "insertando label al final " << item->name();
691             labels << item;
692         } else {
693             QLOG_DEBUG() << "insertando label en  " << i << "-" << item->name();
694             labels.insert(i, item);
695         }
696 
697         return i;
698     }
699 
700     return 0;
701 }
702 
reorderingChildren(QList<ReadingListItem * > children)703 void ReadingListModel::reorderingChildren(QList<ReadingListItem *> children)
704 {
705     QList<qulonglong> childrenIds;
706     int i = 0;
707     foreach (ReadingListItem *item, children) {
708         item->setOrdering(i++);
709         childrenIds << item->getId();
710     }
711     QString connectionName = "";
712     {
713         QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath);
714         DBHelper::reasignOrderToSublists(childrenIds, db);
715         connectionName = db.connectionName();
716     }
717     QSqlDatabase::removeDatabase(connectionName);
718 }
719 
rowIsSpecialList(int row,const QModelIndex & parent) const720 bool ReadingListModel::rowIsSpecialList(int row, const QModelIndex &parent) const
721 {
722     if (parent.isValid())
723         return false; //by now no sublists in special list
724 
725     if (row >= 0 && row < specialLists.count())
726         return true;
727 
728     return false;
729 }
730 
rowIsLabel(int row,const QModelIndex & parent) const731 bool ReadingListModel::rowIsLabel(int row, const QModelIndex &parent) const
732 {
733     if (parent.isValid())
734         return false; //by now no sublists in labels
735 
736     if (row > specialLists.count() && row <= specialLists.count() + labels.count())
737         return true;
738 
739     return false;
740 }
741 
rowIsReadingList(int row,const QModelIndex & parent) const742 bool ReadingListModel::rowIsReadingList(int row, const QModelIndex &parent) const
743 {
744     if (parent.isValid())
745         return true; //only lists with sublists
746 
747     int separatorsCount = labels.isEmpty() ? 1 : 2;
748 
749     if (row >= specialLists.count() + labels.count() + separatorsCount)
750         return true;
751 
752     return false;
753 }
754 
rowIsSeparator(int row,const QModelIndex & parent) const755 bool ReadingListModel::rowIsSeparator(int row, const QModelIndex &parent) const
756 {
757     if (parent.isValid())
758         return false; //only separators at top level
759 
760     if (row == specialLists.count())
761         return true;
762 
763     int separatorsCount = labels.isEmpty() ? 1 : 2;
764     if (separatorsCount == 2 && row == specialLists.count() + labels.count() + 1)
765         return true;
766 
767     return false;
768 }
769 
ReadingListModelProxy(QObject * parent)770 ReadingListModelProxy::ReadingListModelProxy(QObject *parent)
771     : QSortFilterProxyModel(parent)
772 {
773 }
774