mirror of
https://github.com/YACReader/yacreader
synced 2025-05-28 03:10:27 -04:00
Implement support for updating ComicModel without resetting the whole model
TODO: Favorites, Label, ReadingList still fallback to full reload because we need a way of comparing old vs new results. SearchResult does nothing because we don't have access to the search query.
This commit is contained in:
parent
2e9ec030ad
commit
3a0e8db189
@ -10,24 +10,29 @@
|
|||||||
#include "qnaturalsorting.h"
|
#include "qnaturalsorting.h"
|
||||||
#include "comic_db.h"
|
#include "comic_db.h"
|
||||||
#include "db_helper.h"
|
#include "db_helper.h"
|
||||||
#include "query_parser.h"
|
|
||||||
#include "reading_list_model.h"
|
#include "reading_list_model.h"
|
||||||
|
|
||||||
// ci.number,ci.title,c.fileName,ci.numPages,c.id,c.parentId,c.path,ci.hash,ci.read
|
// ci.number,ci.title,c.fileName,ci.numPages,c.id,c.parentId,c.path,ci.hash,ci.read
|
||||||
#include "QsLog.h"
|
#include "QsLog.h"
|
||||||
|
|
||||||
|
auto defaultFolderContentSortFunction = [](const ComicItem *c1, const ComicItem *c2) {
|
||||||
|
if (c1->data(ComicModel::Number).isNull() && c2->data(ComicModel::Number).isNull()) {
|
||||||
|
return naturalSortLessThanCI(c1->data(ComicModel::FileName).toString(), c2->data(ComicModel::FileName).toString());
|
||||||
|
} else {
|
||||||
|
if (c1->data(ComicModel::Number).isNull() == false && c2->data(ComicModel::Number).isNull() == false) {
|
||||||
|
return naturalSortLessThanCI(c1->data(ComicModel::Number).toString(), c2->data(ComicModel::Number).toString());
|
||||||
|
} else {
|
||||||
|
return c2->data(ComicModel::Number).isNull();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
ComicModel::ComicModel(QObject *parent)
|
ComicModel::ComicModel(QObject *parent)
|
||||||
: QAbstractItemModel(parent), showRecent(false), recentDays(1)
|
: QAbstractItemModel(parent), showRecent(false), recentDays(1)
|
||||||
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
ComicModel::ComicModel(QSqlQuery &sqlquery, QObject *parent)
|
|
||||||
: QAbstractItemModel(parent), showRecent(false), recentDays(1)
|
|
||||||
{
|
|
||||||
setupModelData(sqlquery);
|
|
||||||
}
|
|
||||||
|
|
||||||
ComicModel::~ComicModel()
|
ComicModel::~ComicModel()
|
||||||
{
|
{
|
||||||
qDeleteAll(_data);
|
qDeleteAll(_data);
|
||||||
@ -456,7 +461,30 @@ QStringList ComicModel::getPaths(const QString &_source)
|
|||||||
return paths;
|
return paths;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define COMIC_MODEL_QUERY_FIELDS "ci.number,ci.title,c.fileName,ci.numPages,c.id,c.parentId,c.path,ci.hash,ci.read,ci.isBis,ci.currentPage,ci.rating,ci.hasBeenOpened,ci.date,ci.added,ci.type"
|
#define COMIC_MODEL_QUERY_FIELDS "ci.number,ci.title,c.fileName,ci.numPages,c.id,c.parentId,c.path,ci.hash,ci.read,ci.isBis,ci.currentPage,ci.rating,ci.hasBeenOpened,ci.date,ci.added,ci.type,ci.lastTimeOpened"
|
||||||
|
|
||||||
|
QList<ComicItem *> ComicModel::createFolderModelData(unsigned long long folderId, const QString &databasePath) const
|
||||||
|
{
|
||||||
|
QList<ComicItem *> modelData;
|
||||||
|
|
||||||
|
QString connectionName = "";
|
||||||
|
{
|
||||||
|
QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath);
|
||||||
|
QSqlQuery selectQuery(db);
|
||||||
|
selectQuery.prepare("SELECT " COMIC_MODEL_QUERY_FIELDS " "
|
||||||
|
"FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) "
|
||||||
|
"WHERE c.parentId = :parentId");
|
||||||
|
selectQuery.bindValue(":parentId", folderId);
|
||||||
|
selectQuery.exec();
|
||||||
|
|
||||||
|
modelData = createModelData(selectQuery);
|
||||||
|
|
||||||
|
connectionName = db.connectionName();
|
||||||
|
}
|
||||||
|
QSqlDatabase::removeDatabase(connectionName);
|
||||||
|
|
||||||
|
return modelData;
|
||||||
|
}
|
||||||
|
|
||||||
void ComicModel::setupFolderModelData(unsigned long long int folderId, const QString &databasePath)
|
void ComicModel::setupFolderModelData(unsigned long long int folderId, const QString &databasePath)
|
||||||
{
|
{
|
||||||
@ -469,20 +497,33 @@ void ComicModel::setupFolderModelData(unsigned long long int folderId, const QSt
|
|||||||
_data.clear();
|
_data.clear();
|
||||||
|
|
||||||
_databasePath = databasePath;
|
_databasePath = databasePath;
|
||||||
|
|
||||||
|
takeData(createFolderModelData(folderId, databasePath));
|
||||||
|
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<ComicItem *> ComicModel::createLabelModelData(unsigned long long parentLabel, const QString &databasePath) const
|
||||||
|
{
|
||||||
|
QList<ComicItem *> modelData;
|
||||||
|
|
||||||
QString connectionName = "";
|
QString connectionName = "";
|
||||||
{
|
{
|
||||||
QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath);
|
QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath);
|
||||||
QSqlQuery selectQuery(db);
|
QSqlQuery selectQuery(db);
|
||||||
selectQuery.prepare("SELECT " COMIC_MODEL_QUERY_FIELDS " "
|
selectQuery.prepare("SELECT " COMIC_MODEL_QUERY_FIELDS " "
|
||||||
"FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) "
|
"FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) "
|
||||||
"WHERE c.parentId = :parentId");
|
"INNER JOIN comic_label cl ON (c.id == cl.comic_id) "
|
||||||
selectQuery.bindValue(":parentId", folderId);
|
"WHERE cl.label_id = :parentLabelId "
|
||||||
|
"ORDER BY cl.ordering");
|
||||||
|
selectQuery.bindValue(":parentLabelId", parentLabel);
|
||||||
selectQuery.exec();
|
selectQuery.exec();
|
||||||
setupModelData(selectQuery);
|
modelData = createModelDataForList(selectQuery);
|
||||||
connectionName = db.connectionName();
|
connectionName = db.connectionName();
|
||||||
}
|
}
|
||||||
QSqlDatabase::removeDatabase(connectionName);
|
QSqlDatabase::removeDatabase(connectionName);
|
||||||
endResetModel();
|
|
||||||
|
return modelData;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ComicModel::setupLabelModelData(unsigned long long parentLabel, const QString &databasePath)
|
void ComicModel::setupLabelModelData(unsigned long long parentLabel, const QString &databasePath)
|
||||||
@ -496,34 +537,16 @@ void ComicModel::setupLabelModelData(unsigned long long parentLabel, const QStri
|
|||||||
_data.clear();
|
_data.clear();
|
||||||
|
|
||||||
_databasePath = databasePath;
|
_databasePath = databasePath;
|
||||||
QString connectionName = "";
|
|
||||||
{
|
takeData(createLabelModelData(parentLabel, databasePath));
|
||||||
QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath);
|
|
||||||
QSqlQuery selectQuery(db);
|
|
||||||
selectQuery.prepare("SELECT " COMIC_MODEL_QUERY_FIELDS " "
|
|
||||||
"FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) "
|
|
||||||
"INNER JOIN comic_label cl ON (c.id == cl.comic_id) "
|
|
||||||
"WHERE cl.label_id = :parentLabelId "
|
|
||||||
"ORDER BY cl.ordering");
|
|
||||||
selectQuery.bindValue(":parentLabelId", parentLabel);
|
|
||||||
selectQuery.exec();
|
|
||||||
setupModelDataForList(selectQuery);
|
|
||||||
connectionName = db.connectionName();
|
|
||||||
}
|
|
||||||
QSqlDatabase::removeDatabase(connectionName);
|
|
||||||
endResetModel();
|
endResetModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ComicModel::setupReadingListModelData(unsigned long long parentReadingList, const QString &databasePath)
|
QList<ComicItem *> ComicModel::createReadingListData(unsigned long long parentReadingList, const QString &databasePath, bool &enableResorting) const
|
||||||
{
|
{
|
||||||
mode = ReadingList;
|
QList<ComicItem *> modelData;
|
||||||
sourceId = parentReadingList;
|
|
||||||
|
|
||||||
beginResetModel();
|
|
||||||
qDeleteAll(_data);
|
|
||||||
_data.clear();
|
|
||||||
|
|
||||||
_databasePath = databasePath;
|
|
||||||
QString connectionName = "";
|
QString connectionName = "";
|
||||||
{
|
{
|
||||||
QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath);
|
QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath);
|
||||||
@ -552,20 +575,54 @@ void ComicModel::setupReadingListModelData(unsigned long long parentReadingList,
|
|||||||
selectQuery.bindValue(":parentReadingList", id);
|
selectQuery.bindValue(":parentReadingList", id);
|
||||||
selectQuery.exec();
|
selectQuery.exec();
|
||||||
|
|
||||||
// TODO, extra information is needed (resorting)
|
modelData << createModelDataForList(selectQuery);
|
||||||
QList<ComicItem *> tempData = _data;
|
|
||||||
_data.clear();
|
|
||||||
|
|
||||||
setupModelDataForList(selectQuery);
|
|
||||||
|
|
||||||
_data = tempData << _data;
|
|
||||||
}
|
}
|
||||||
connectionName = db.connectionName();
|
connectionName = db.connectionName();
|
||||||
}
|
}
|
||||||
QSqlDatabase::removeDatabase(connectionName);
|
QSqlDatabase::removeDatabase(connectionName);
|
||||||
|
|
||||||
|
return modelData;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ComicModel::setupReadingListModelData(unsigned long long parentReadingList, const QString &databasePath)
|
||||||
|
{
|
||||||
|
mode = ReadingList;
|
||||||
|
sourceId = parentReadingList;
|
||||||
|
|
||||||
|
beginResetModel();
|
||||||
|
qDeleteAll(_data);
|
||||||
|
_data.clear();
|
||||||
|
|
||||||
|
_databasePath = databasePath;
|
||||||
|
|
||||||
|
takeData(createReadingListData(parentReadingList, databasePath, enableResorting));
|
||||||
|
|
||||||
endResetModel();
|
endResetModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<ComicItem *> ComicModel::createFavoritesModelData(const QString &databasePath) const
|
||||||
|
{
|
||||||
|
QList<ComicItem *> modelData;
|
||||||
|
|
||||||
|
QString connectionName = "";
|
||||||
|
{
|
||||||
|
QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath);
|
||||||
|
QSqlQuery selectQuery(db);
|
||||||
|
selectQuery.prepare("SELECT " COMIC_MODEL_QUERY_FIELDS " "
|
||||||
|
"FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) "
|
||||||
|
"INNER JOIN comic_default_reading_list cdrl ON (c.id == cdrl.comic_id) "
|
||||||
|
"WHERE cdrl.default_reading_list_id = :parentDefaultListId "
|
||||||
|
"ORDER BY cdrl.ordering");
|
||||||
|
selectQuery.bindValue(":parentDefaultListId", 1);
|
||||||
|
selectQuery.exec();
|
||||||
|
modelData = createModelDataForList(selectQuery);
|
||||||
|
connectionName = db.connectionName();
|
||||||
|
}
|
||||||
|
QSqlDatabase::removeDatabase(connectionName);
|
||||||
|
|
||||||
|
return modelData;
|
||||||
|
}
|
||||||
|
|
||||||
void ComicModel::setupFavoritesModelData(const QString &databasePath)
|
void ComicModel::setupFavoritesModelData(const QString &databasePath)
|
||||||
{
|
{
|
||||||
enableResorting = true;
|
enableResorting = true;
|
||||||
@ -577,22 +634,32 @@ void ComicModel::setupFavoritesModelData(const QString &databasePath)
|
|||||||
_data.clear();
|
_data.clear();
|
||||||
|
|
||||||
_databasePath = databasePath;
|
_databasePath = databasePath;
|
||||||
|
|
||||||
|
takeData(createFavoritesModelData(databasePath));
|
||||||
|
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<ComicItem *> ComicModel::createReadingModelData(const QString &databasePath) const
|
||||||
|
{
|
||||||
|
QList<ComicItem *> modelData;
|
||||||
|
|
||||||
QString connectionName = "";
|
QString connectionName = "";
|
||||||
{
|
{
|
||||||
QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath);
|
QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath);
|
||||||
QSqlQuery selectQuery(db);
|
QSqlQuery selectQuery(db);
|
||||||
selectQuery.prepare("SELECT " COMIC_MODEL_QUERY_FIELDS " "
|
selectQuery.prepare("SELECT " COMIC_MODEL_QUERY_FIELDS " "
|
||||||
"FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) "
|
"FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) "
|
||||||
"INNER JOIN comic_default_reading_list cdrl ON (c.id == cdrl.comic_id) "
|
"WHERE ci.hasBeenOpened = 1 AND ci.read = 0 "
|
||||||
"WHERE cdrl.default_reading_list_id = :parentDefaultListId "
|
"ORDER BY ci.lastTimeOpened DESC");
|
||||||
"ORDER BY cdrl.ordering");
|
|
||||||
selectQuery.bindValue(":parentDefaultListId", 1);
|
|
||||||
selectQuery.exec();
|
selectQuery.exec();
|
||||||
setupModelDataForList(selectQuery);
|
|
||||||
|
modelData = createModelDataForList(selectQuery);
|
||||||
connectionName = db.connectionName();
|
connectionName = db.connectionName();
|
||||||
}
|
}
|
||||||
QSqlDatabase::removeDatabase(connectionName);
|
QSqlDatabase::removeDatabase(connectionName);
|
||||||
endResetModel();
|
|
||||||
|
return modelData;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ComicModel::setupReadingModelData(const QString &databasePath)
|
void ComicModel::setupReadingModelData(const QString &databasePath)
|
||||||
@ -606,21 +673,33 @@ void ComicModel::setupReadingModelData(const QString &databasePath)
|
|||||||
_data.clear();
|
_data.clear();
|
||||||
|
|
||||||
_databasePath = databasePath;
|
_databasePath = databasePath;
|
||||||
|
|
||||||
|
takeData(createReadingModelData(databasePath));
|
||||||
|
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<ComicItem *> ComicModel::createRecentModelData(const QString &databasePath) const
|
||||||
|
{
|
||||||
|
QList<ComicItem *> modelData;
|
||||||
|
|
||||||
QString connectionName = "";
|
QString connectionName = "";
|
||||||
{
|
{
|
||||||
QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath);
|
QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath);
|
||||||
QSqlQuery selectQuery(db);
|
QSqlQuery selectQuery(db);
|
||||||
selectQuery.prepare("SELECT " COMIC_MODEL_QUERY_FIELDS " "
|
selectQuery.prepare("SELECT " COMIC_MODEL_QUERY_FIELDS " "
|
||||||
"FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) "
|
"FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) "
|
||||||
"WHERE ci.hasBeenOpened = 1 AND ci.read = 0 "
|
"WHERE ci.added > :limit "
|
||||||
"ORDER BY ci.lastTimeOpened DESC");
|
"ORDER BY ci.added DESC");
|
||||||
|
selectQuery.bindValue(":limit", QDateTime::currentDateTime().addDays(-recentDays).toSecsSinceEpoch());
|
||||||
selectQuery.exec();
|
selectQuery.exec();
|
||||||
|
|
||||||
setupModelDataForList(selectQuery);
|
modelData = createModelDataForList(selectQuery);
|
||||||
connectionName = db.connectionName();
|
connectionName = db.connectionName();
|
||||||
}
|
}
|
||||||
QSqlDatabase::removeDatabase(connectionName);
|
QSqlDatabase::removeDatabase(connectionName);
|
||||||
endResetModel();
|
|
||||||
|
return modelData;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ComicModel::setupRecentModelData(const QString &databasePath)
|
void ComicModel::setupRecentModelData(const QString &databasePath)
|
||||||
@ -635,26 +714,17 @@ void ComicModel::setupRecentModelData(const QString &databasePath)
|
|||||||
|
|
||||||
_databasePath = databasePath;
|
_databasePath = databasePath;
|
||||||
|
|
||||||
QString connectionName = "";
|
takeData(createRecentModelData(databasePath));
|
||||||
{
|
|
||||||
QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath);
|
|
||||||
QSqlQuery selectQuery(db);
|
|
||||||
selectQuery.prepare("SELECT " COMIC_MODEL_QUERY_FIELDS " "
|
|
||||||
"FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) "
|
|
||||||
"WHERE ci.added > :limit "
|
|
||||||
"ORDER BY ci.added DESC");
|
|
||||||
selectQuery.bindValue(":limit", QDateTime::currentDateTime().addDays(-recentDays).toSecsSinceEpoch());
|
|
||||||
selectQuery.exec();
|
|
||||||
|
|
||||||
setupModelDataForList(selectQuery);
|
|
||||||
connectionName = db.connectionName();
|
|
||||||
}
|
|
||||||
QSqlDatabase::removeDatabase(connectionName);
|
|
||||||
endResetModel();
|
endResetModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ComicModel::setModelData(QList<ComicItem *> *data, const QString &databasePath)
|
void ComicModel::setModelData(QList<ComicItem *> *data, const QString &databasePath)
|
||||||
{
|
{
|
||||||
|
enableResorting = false;
|
||||||
|
mode = SearchResult;
|
||||||
|
sourceId = -1;
|
||||||
|
|
||||||
_databasePath = databasePath;
|
_databasePath = databasePath;
|
||||||
|
|
||||||
beginResetModel();
|
beginResetModel();
|
||||||
@ -679,8 +749,10 @@ QString ComicModel::getComicPath(QModelIndex mi)
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
void ComicModel::setupModelData(QSqlQuery &sqlquery)
|
QList<ComicItem *> ComicModel::createModelData(QSqlQuery &sqlquery) const
|
||||||
{
|
{
|
||||||
|
QList<ComicItem *> modelData;
|
||||||
|
|
||||||
int numColumns = sqlquery.record().count();
|
int numColumns = sqlquery.record().count();
|
||||||
|
|
||||||
while (sqlquery.next()) {
|
while (sqlquery.next()) {
|
||||||
@ -689,25 +761,19 @@ void ComicModel::setupModelData(QSqlQuery &sqlquery)
|
|||||||
for (int i = 0; i < numColumns; i++)
|
for (int i = 0; i < numColumns; i++)
|
||||||
data << sqlquery.value(i);
|
data << sqlquery.value(i);
|
||||||
|
|
||||||
_data.append(new ComicItem(data));
|
modelData.append(new ComicItem(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::sort(_data.begin(), _data.end(), [](const ComicItem *c1, const ComicItem *c2) {
|
std::sort(modelData.begin(), modelData.end(), defaultFolderContentSortFunction);
|
||||||
if (c1->data(ComicModel::Number).isNull() && c2->data(ComicModel::Number).isNull()) {
|
|
||||||
return naturalSortLessThanCI(c1->data(ComicModel::FileName).toString(), c2->data(ComicModel::FileName).toString());
|
return modelData;
|
||||||
} else {
|
|
||||||
if (c1->data(ComicModel::Number).isNull() == false && c2->data(ComicModel::Number).isNull() == false) {
|
|
||||||
return naturalSortLessThanCI(c1->data(ComicModel::Number).toString(), c2->data(ComicModel::Number).toString());
|
|
||||||
} else {
|
|
||||||
return c2->data(ComicModel::Number).isNull();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// comics are sorted by "ordering", the sorting is done in the sql query
|
// the sorting is done in the sql query
|
||||||
void ComicModel::setupModelDataForList(QSqlQuery &sqlquery)
|
QList<ComicItem *> ComicModel::createModelDataForList(QSqlQuery &sqlquery) const
|
||||||
{
|
{
|
||||||
|
QList<ComicItem *> modelData;
|
||||||
|
|
||||||
int numColumns = sqlquery.record().count();
|
int numColumns = sqlquery.record().count();
|
||||||
|
|
||||||
while (sqlquery.next()) {
|
while (sqlquery.next()) {
|
||||||
@ -715,7 +781,92 @@ void ComicModel::setupModelDataForList(QSqlQuery &sqlquery)
|
|||||||
for (int i = 0; i < numColumns; i++)
|
for (int i = 0; i < numColumns; i++)
|
||||||
data << sqlquery.value(i);
|
data << sqlquery.value(i);
|
||||||
|
|
||||||
_data.append(new ComicItem(data));
|
modelData.append(new ComicItem(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
return modelData;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ComicModel::takeData(const QList<ComicItem *> &data)
|
||||||
|
{
|
||||||
|
qDeleteAll(_data);
|
||||||
|
_data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ComicModel::takeUpdatedData(const QList<ComicItem *> &updatedData, std::function<bool(ComicItem *, ComicItem *)> comparator)
|
||||||
|
{
|
||||||
|
int lenght = _data.size();
|
||||||
|
int lenghtUpdated = updatedData.size();
|
||||||
|
|
||||||
|
int i; // index of the internal data
|
||||||
|
int j; // index of the updated children
|
||||||
|
for (i = 0, j = 0; i < lenght && j < lenghtUpdated;) {
|
||||||
|
auto comic = _data.at(i);
|
||||||
|
auto updatedComic = updatedData.at(j);
|
||||||
|
|
||||||
|
auto sameComic = comic->data(ComicModel::Id) == updatedComic->data(ComicModel::Id);
|
||||||
|
if (sameComic) {
|
||||||
|
if (comic->getData() != updatedComic->getData()) {
|
||||||
|
auto modelIndexToUpdate = index(i, 0, QModelIndex());
|
||||||
|
|
||||||
|
comic->setData(updatedComic->getData());
|
||||||
|
|
||||||
|
emit dataChanged(modelIndexToUpdate, modelIndexToUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
j++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto lessThan = comparator(comic, updatedComic);
|
||||||
|
|
||||||
|
// comic added
|
||||||
|
if (!lessThan) {
|
||||||
|
beginInsertRows(QModelIndex(), i, i);
|
||||||
|
|
||||||
|
_data.insert(i, updatedComic);
|
||||||
|
|
||||||
|
endInsertRows();
|
||||||
|
|
||||||
|
i++;
|
||||||
|
j++;
|
||||||
|
lenght++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// comic removed
|
||||||
|
if (lessThan) {
|
||||||
|
beginRemoveRows(QModelIndex(), i, i);
|
||||||
|
|
||||||
|
_data.removeAt(i);
|
||||||
|
|
||||||
|
endRemoveRows();
|
||||||
|
|
||||||
|
lenght--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add remaining comics
|
||||||
|
for (; j < lenghtUpdated; j++) {
|
||||||
|
beginInsertRows(QModelIndex(), i, i);
|
||||||
|
|
||||||
|
_data.append(updatedData.at(j));
|
||||||
|
|
||||||
|
endInsertRows();
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove remaining comics {
|
||||||
|
for (; i < lenght; i++) {
|
||||||
|
beginRemoveRows(QModelIndex(), i, i);
|
||||||
|
|
||||||
|
delete _data.at(i);
|
||||||
|
_data.removeAt(i);
|
||||||
|
|
||||||
|
endRemoveRows();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -929,6 +1080,7 @@ void ComicModel::removeInTransaction(int row)
|
|||||||
|
|
||||||
DBHelper::removeFromDB(&c, dbTransaction);
|
DBHelper::removeFromDB(&c, dbTransaction);
|
||||||
beginRemoveRows(QModelIndex(), row, row);
|
beginRemoveRows(QModelIndex(), row, row);
|
||||||
|
|
||||||
removeRow(row);
|
removeRow(row);
|
||||||
delete _data.at(row);
|
delete _data.at(row);
|
||||||
_data.removeAt(row);
|
_data.removeAt(row);
|
||||||
@ -941,26 +1093,34 @@ void ComicModel::reloadContinueReading()
|
|||||||
setupReadingModelData(_databasePath);
|
setupReadingModelData(_databasePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The `comparator` passed to `takeUpdatedData` is used to determine if a row has been removed or added
|
||||||
void ComicModel::reload()
|
void ComicModel::reload()
|
||||||
{
|
{
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case Folder:
|
case Folder:
|
||||||
setupFolderModelData(sourceId, _databasePath);
|
takeUpdatedData(createFolderModelData(sourceId, _databasePath), defaultFolderContentSortFunction);
|
||||||
break;
|
break;
|
||||||
case Favorites:
|
case Favorites:
|
||||||
setupFavoritesModelData(_databasePath);
|
setupFavoritesModelData(_databasePath); // TODO we need a comparator
|
||||||
break;
|
break;
|
||||||
case Reading:
|
case Reading:
|
||||||
setupReadingModelData(_databasePath);
|
takeUpdatedData(createReadingModelData(_databasePath), [](const ComicItem *c1, const ComicItem *c2) {
|
||||||
|
return c1->data(ComicModel::LastTimeOpened).toDateTime() > c2->data(ComicModel::LastTimeOpened).toDateTime();
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
case Recent:
|
case Recent:
|
||||||
setupRecentModelData(_databasePath);
|
takeUpdatedData(createRecentModelData(_databasePath), [](const ComicItem *c1, const ComicItem *c2) {
|
||||||
|
return c1->data(ComicModel::Added).toDateTime() > c2->data(ComicModel::Added).toDateTime();
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
case Label:
|
case Label:
|
||||||
setupLabelModelData(sourceId, _databasePath);
|
setupLabelModelData(sourceId, _databasePath); // TODO we need a comparator
|
||||||
break;
|
break;
|
||||||
case ReadingList:
|
case ReadingList:
|
||||||
setupReadingListModelData(sourceId, _databasePath);
|
setupReadingListModelData(sourceId, _databasePath); // TODO we need a comparator
|
||||||
|
break;
|
||||||
|
case SearchResult:
|
||||||
|
// TODO: reload search results, we don't have a way to recreate the query in this class
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,7 @@ public:
|
|||||||
PublicationDate = 13,
|
PublicationDate = 13,
|
||||||
Added = 14,
|
Added = 14,
|
||||||
Type = 15,
|
Type = 15,
|
||||||
|
LastTimeOpened = 16,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Roles {
|
enum Roles {
|
||||||
@ -69,12 +70,12 @@ public:
|
|||||||
Reading,
|
Reading,
|
||||||
Recent,
|
Recent,
|
||||||
Label,
|
Label,
|
||||||
ReadingList
|
ReadingList,
|
||||||
|
SearchResult
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ComicModel(QObject *parent = nullptr);
|
explicit ComicModel(QObject *parent = nullptr);
|
||||||
explicit ComicModel(QSqlQuery &sqlquery, QObject *parent = nullptr);
|
|
||||||
~ComicModel() override;
|
~ComicModel() override;
|
||||||
|
|
||||||
QVariant data(const QModelIndex &index, int role) const override;
|
QVariant data(const QModelIndex &index, int role) const override;
|
||||||
@ -162,8 +163,18 @@ public slots:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
private:
|
private:
|
||||||
void setupModelData(QSqlQuery &sqlquery);
|
QList<ComicItem *> createModelData(QSqlQuery &sqlquery) const;
|
||||||
void setupModelDataForList(QSqlQuery &sqlquery);
|
QList<ComicItem *> createModelDataForList(QSqlQuery &sqlquery) const;
|
||||||
|
|
||||||
|
QList<ComicItem *> createFolderModelData(unsigned long long parentLabel, const QString &databasePath) const;
|
||||||
|
QList<ComicItem *> createLabelModelData(unsigned long long parentLabel, const QString &databasePath) const;
|
||||||
|
QList<ComicItem *> createReadingListData(unsigned long long parentReadingList, const QString &databasePath, bool &enableResorting) const;
|
||||||
|
QList<ComicItem *> createFavoritesModelData(const QString &databasePath) const;
|
||||||
|
QList<ComicItem *> createReadingModelData(const QString &databasePath) const;
|
||||||
|
QList<ComicItem *> createRecentModelData(const QString &databasePath) const;
|
||||||
|
|
||||||
|
void takeData(const QList<ComicItem *> &data);
|
||||||
|
void takeUpdatedData(const QList<ComicItem *> &updatedData, std::function<bool(ComicItem *, ComicItem *)> comparator);
|
||||||
ComicDB _getComic(const QModelIndex &mi);
|
ComicDB _getComic(const QModelIndex &mi);
|
||||||
QList<ComicItem *> _data;
|
QList<ComicItem *> _data;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user