Add new fields to the DB and make then available to be used in the apps

This commit is contained in:
Luis Ángel San Martín 2023-05-12 16:59:23 +02:00
parent 830d8d911f
commit f2bf53ce5b
23 changed files with 957 additions and 591 deletions

View File

@ -1575,7 +1575,7 @@ void MainWindowViewer::sendComic()
auto client = new YACReaderLocalClient; auto client = new YACReaderLocalClient;
connect(client, &YACReaderLocalClient::finished, client, &YACReaderLocalClient::deleteLater); connect(client, &YACReaderLocalClient::finished, client, &YACReaderLocalClient::deleteLater);
currentComicDB.info.lastTimeOpened = QDateTime::currentMSecsSinceEpoch() / 1000; currentComicDB.info.lastTimeOpened = QDateTime::currentSecsSinceEpoch();
viewer->updateComic(currentComicDB); viewer->updateComic(currentComicDB);

View File

@ -239,6 +239,7 @@ QHash<int, QByteArray> ComicModel::roleNames() const
roles[CoverPathRole] = "cover_path"; roles[CoverPathRole] = "cover_path";
roles[PublicationDate] = "date"; roles[PublicationDate] = "date";
roles[ReadableTitle] = "readable_title"; roles[ReadableTitle] = "readable_title";
roles[Added] = "added_date";
return roles; return roles;
} }
@ -301,6 +302,10 @@ QVariant ComicModel::data(const QModelIndex &index, int role) const
return item->data(Id); return item->data(Id);
else if (role == PublicationDateRole) else if (role == PublicationDateRole)
return QVariant(localizedDate(item->data(PublicationDate).toString())); return QVariant(localizedDate(item->data(PublicationDate).toString()));
else if (role == AddedRole)
return item->data(Added);
else if (role == TypeRole)
return item->data(Type);
if (role != Qt::DisplayRole) if (role != Qt::DisplayRole)
return QVariant(); return QVariant();
@ -443,6 +448,8 @@ 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"
void ComicModel::setupFolderModelData(unsigned long long int folderId, const QString &databasePath) void ComicModel::setupFolderModelData(unsigned long long int folderId, const QString &databasePath)
{ {
enableResorting = false; enableResorting = false;
@ -458,7 +465,7 @@ void ComicModel::setupFolderModelData(unsigned long long int folderId, const QSt
{ {
QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath); QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath);
QSqlQuery selectQuery(db); QSqlQuery selectQuery(db);
selectQuery.prepare("SELECT 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 " 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"); "WHERE c.parentId = :parentId");
selectQuery.bindValue(":parentId", folderId); selectQuery.bindValue(":parentId", folderId);
@ -485,7 +492,7 @@ void ComicModel::setupLabelModelData(unsigned long long parentLabel, const QStri
{ {
QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath); QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath);
QSqlQuery selectQuery(db); QSqlQuery selectQuery(db);
selectQuery.prepare("SELECT 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 " 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_label cl ON (c.id == cl.comic_id) " "INNER JOIN comic_label cl ON (c.id == cl.comic_id) "
"WHERE cl.label_id = :parentLabelId " "WHERE cl.label_id = :parentLabelId "
@ -529,7 +536,7 @@ void ComicModel::setupReadingListModelData(unsigned long long parentReadingList,
foreach (qulonglong id, ids) { foreach (qulonglong id, ids) {
QSqlQuery selectQuery(db); QSqlQuery selectQuery(db);
selectQuery.prepare("SELECT 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 " 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_reading_list crl ON (c.id == crl.comic_id) " "INNER JOIN comic_reading_list crl ON (c.id == crl.comic_id) "
"WHERE crl.reading_list_id = :parentReadingList " "WHERE crl.reading_list_id = :parentReadingList "
@ -566,7 +573,7 @@ void ComicModel::setupFavoritesModelData(const QString &databasePath)
{ {
QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath); QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath);
QSqlQuery selectQuery(db); QSqlQuery selectQuery(db);
selectQuery.prepare("SELECT 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 " 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) " "INNER JOIN comic_default_reading_list cdrl ON (c.id == cdrl.comic_id) "
"WHERE cdrl.default_reading_list_id = :parentDefaultListId " "WHERE cdrl.default_reading_list_id = :parentDefaultListId "
@ -595,7 +602,7 @@ void ComicModel::setupReadingModelData(const QString &databasePath)
{ {
QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath); QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath);
QSqlQuery selectQuery(db); QSqlQuery selectQuery(db);
selectQuery.prepare("SELECT 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 " 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.hasBeenOpened = 1 AND ci.read = 0 "
"ORDER BY ci.lastTimeOpened DESC"); "ORDER BY ci.lastTimeOpened DESC");
@ -652,7 +659,7 @@ void ComicModel::setupModelData(QSqlQuery &sqlquery)
return naturalSortLessThanCI(c1->data(ComicModel::FileName).toString(), c2->data(ComicModel::FileName).toString()); return naturalSortLessThanCI(c1->data(ComicModel::FileName).toString(), c2->data(ComicModel::FileName).toString());
} else { } else {
if (c1->data(ComicModel::Number).isNull() == false && c2->data(ComicModel::Number).isNull() == false) { if (c1->data(ComicModel::Number).isNull() == false && c2->data(ComicModel::Number).isNull() == false) {
return c1->data(ComicModel::Number).toInt() < c2->data(ComicModel::Number).toInt(); return naturalSortLessThanCI(c1->data(ComicModel::Number).toString(), c2->data(ComicModel::Number).toString());
} else { } else {
return c2->data(ComicModel::Number).isNull(); return c2->data(ComicModel::Number).isNull();
} }
@ -794,7 +801,7 @@ QVector<YACReaderComicReadStatus> ComicModel::setComicsRead(QList<QModelIndex> l
return getReadList(); return getReadList();
} }
void ComicModel::setComicsManga(QList<QModelIndex> list, bool isManga) void ComicModel::setComicsType(QList<QModelIndex> list, FileType type)
{ {
QString connectionName = ""; QString connectionName = "";
{ {
@ -803,7 +810,7 @@ void ComicModel::setComicsManga(QList<QModelIndex> list, bool isManga)
foreach (QModelIndex mi, list) { foreach (QModelIndex mi, list) {
bool found; bool found;
ComicDB c = DBHelper::loadComic(_data.value(mi.row())->data(ComicModel::Id).toULongLong(), db, found); ComicDB c = DBHelper::loadComic(_data.value(mi.row())->data(ComicModel::Id).toULongLong(), db, found);
c.info.manga = isManga; c.info.type = QVariant::fromValue(type);
DBHelper::update(&(c.info), db); DBHelper::update(&(c.info), db);
} }
db.commit(); db.commit();

View File

@ -31,11 +31,13 @@ public:
Path = 6, Path = 6,
Hash = 7, Hash = 7,
ReadColumn = 8, ReadColumn = 8,
IsBis = 9, IsBis = 9, // TODO_METADATA: Remove this column
CurrentPage = 10, CurrentPage = 10,
Rating = 11, Rating = 11,
HasBeenOpened = 12, HasBeenOpened = 12,
PublicationDate = 13, PublicationDate = 13,
Added = 14,
Type = 15,
}; };
enum Roles { enum Roles {
@ -55,6 +57,8 @@ public:
CoverPathRole, CoverPathRole,
PublicationDateRole, PublicationDateRole,
ReadableTitle, ReadableTitle,
AddedRole,
TypeRole,
}; };
enum Mode { enum Mode {
@ -107,7 +111,7 @@ public:
// setComicInfoForAllComics(); --> inserta la información común a todos los cómics de una sola vez. // setComicInfoForAllComics(); --> inserta la información común a todos los cómics de una sola vez.
// setComicInfoForSelectedComis(QList<QModelIndex> list); -->inserta la información común para los comics seleccionados // setComicInfoForSelectedComis(QList<QModelIndex> list); -->inserta la información común para los comics seleccionados
QVector<YACReaderComicReadStatus> setComicsRead(QList<QModelIndex> list, YACReaderComicReadStatus read); QVector<YACReaderComicReadStatus> setComicsRead(QList<QModelIndex> list, YACReaderComicReadStatus read);
void setComicsManga(QList<QModelIndex> list, bool isManga); void setComicsType(QList<QModelIndex> list, FileType type);
qint64 asignNumbers(QList<QModelIndex> list, int startingNumber); qint64 asignNumbers(QList<QModelIndex> list, int startingNumber);
// void remove(ComicDB * comic, int row); // void remove(ComicDB * comic, int row);
void removeInTransaction(int row); void removeInTransaction(int row);

View File

@ -64,23 +64,29 @@ static QString fields = "title,"
//"coverSizeRatio," cover may have changed since the info was exported... //"coverSizeRatio," cover may have changed since the info was exported...
//"originalCoverSize," // h/w //"originalCoverSize," // h/w
// new 9.8 fields // new 9.8 fields
"manga"; "manga,"
// new 9.13 fields
"added,"
"type,"
"editor,"
"imprint,"
"teams,"
"locations,"
"series,"
"alternateSeries,"
"alternateNumber,"
"alternateCount,"
"languageISO,"
"seriesGroup,"
"mainCharacterOrTeam,"
"review,"
"tags";
DataBaseManagement::DataBaseManagement() DataBaseManagement::DataBaseManagement()
: QObject(), dataBasesList() : QObject(), dataBasesList()
{ {
} }
/*TreeModel * DataBaseManagement::newTreeModel(QString path)
{
//la consulta se ejecuta...
QSqlQuery selectQuery(loadDatabase(path));
selectQuery.setForwardOnly(true);
selectQuery.exec("select * from folder order by parentId,name");
//selectQuery.finish();
return new TreeModel(selectQuery);
}*/
QSqlDatabase DataBaseManagement::createDatabase(QString name, QString path) QSqlDatabase DataBaseManagement::createDatabase(QString name, QString path)
{ {
return createDatabase(QDir::cleanPath(path) + "/" + name + ".ydb"); return createDatabase(QDir::cleanPath(path) + "/" + name + ".ydb");
@ -106,8 +112,6 @@ QSqlDatabase DataBaseManagement::createDatabase(QString dest)
"VALUES (1,'root', '/')", "VALUES (1,'root', '/')",
db); db);
} }
// query.finish();
// db.close();
return db; return db;
} }
@ -156,13 +160,13 @@ bool DataBaseManagement::createTables(QSqlDatabase &database)
"coverPage INTEGER DEFAULT 1," "coverPage INTEGER DEFAULT 1,"
"numPages INTEGER," "numPages INTEGER,"
"number INTEGER," "number TEXT," // changed to text from INTEGER (9.13)
"isBis BOOLEAN," "isBis BOOLEAN,"
"count INTEGER," "count INTEGER,"
"volume TEXT," "volume TEXT,"
"storyArc TEXT," "storyArc TEXT,"
"arcNumber INTEGER," "arcNumber TEXT," // changed to text from INTEGER (9.13)
"arcCount INTEGER," "arcCount INTEGER,"
"genere TEXT," "genere TEXT,"
@ -174,7 +178,7 @@ bool DataBaseManagement::createTables(QSqlDatabase &database)
"letterer TEXT," "letterer TEXT,"
"coverArtist TEXT," "coverArtist TEXT,"
"date TEXT," // dd/mm/yyyy --> se mostrará en 3 campos diferentes "date TEXT," // publication date dd/mm/yyyy --> se mostrará en 3 campos diferentes
"publisher TEXT," "publisher TEXT,"
"format TEXT," "format TEXT,"
"color BOOLEAN," "color BOOLEAN,"
@ -190,7 +194,7 @@ bool DataBaseManagement::createTables(QSqlDatabase &database)
// new 7.0 fields // new 7.0 fields
"hasBeenOpened BOOLEAN DEFAULT 0," "hasBeenOpened BOOLEAN DEFAULT 0,"
"rating INTEGER DEFAULT 0," "rating INTEGER DEFAULT 0," // TODO_METADATA change type to REAL with two decimals
"currentPage INTEGER DEFAULT 1, " "currentPage INTEGER DEFAULT 1, "
"bookmark1 INTEGER DEFAULT -1, " "bookmark1 INTEGER DEFAULT -1, "
"bookmark2 INTEGER DEFAULT -1, " "bookmark2 INTEGER DEFAULT -1, "
@ -205,8 +209,23 @@ bool DataBaseManagement::createTables(QSqlDatabase &database)
"coverSizeRatio REAL," "coverSizeRatio REAL,"
"originalCoverSize STRING," // h/w "originalCoverSize STRING," // h/w
// new 9.8 fields // new 9.8 fields
"manga BOOLEAN DEFAULT 0" "manga BOOLEAN DEFAULT 0," // deprecated 9.13
// new 9.13 fields
"added INTEGER,"
"type INTEGER DEFAULT 0," // 0 = comic, 1 = manga, 2 = manga left to right, 3 = webcomic, 4 = 4koma
"editor TEXT,"
"imprint TEXT,"
"teams TEXT,"
"locations TEXT,"
"series TEXT,"
"alternateSeries TEXT,"
"alternateNumber TEXT,"
"alternateCount INTEGER,"
"languageISO TEXT,"
"seriesGroup TEXT,"
"mainCharacterOrTeam TEXT,"
"review TEXT,"
"tags TEXT"
")"); ")");
success = success && queryComicInfo.exec(); success = success && queryComicInfo.exec();
// queryComicInfo.finish(); // queryComicInfo.finish();
@ -226,7 +245,11 @@ bool DataBaseManagement::createTables(QSqlDatabase &database)
"firstChildHash TEXT," "firstChildHash TEXT,"
"customImage TEXT," "customImage TEXT,"
// new 9.8 fields // new 9.8 fields
"manga BOOLEAN DEFAULT 0," "manga BOOLEAN DEFAULT 0," // deprecated 9.13
// new 9.13 fields
"type INTEGER DEFAULT 0," // 0 = comic, 1 = manga, 2 = manga left to right, 3 = webcomic, 4 = 4koma
"added INTEGER,"
"updated INTEGER," // updated when the folder gets new content
"FOREIGN KEY(parentId) REFERENCES folder(id) ON DELETE CASCADE)"); "FOREIGN KEY(parentId) REFERENCES folder(id) ON DELETE CASCADE)");
success = success && queryFolder.exec(); success = success && queryFolder.exec();
@ -460,7 +483,25 @@ bool DataBaseManagement::importComicsInfo(QString source, QString dest)
//-- //--
// new 9.8 fields // new 9.8 fields
"manga = :manga" "manga = :manga,"
// new 9.13 fields
"added = :added,"
"type = :type," // 0 = comic, 1 = manga, 2 = manga left to right, 3 = webcomic,
"editor = :editor,"
"imprint = :imprint,"
"teams = :teams,"
"locations = :locations,"
"series = :series,"
"alternateSeries = :alternateSeries,"
"alternateNumber = :alternateNumber,"
"alternateCount = :alternateCount,"
"languageISO = :languageISO,"
"seriesGroup = :seriesGroup,"
"mainCharacterOrTeam = :mainCharacterOrTeam,"
"review = :review,"
"tags = :tags"
//-- //--
" WHERE hash = :hash "); " WHERE hash = :hash ");
@ -496,6 +537,21 @@ bool DataBaseManagement::importComicsInfo(QString source, QString dest)
"comicVineID," "comicVineID,"
"lastTimeOpened," "lastTimeOpened,"
"coverSizeRatio," "coverSizeRatio,"
"manga,"
"added,"
"type,"
"editor,"
"imprint,"
"teams,"
"locations,"
"series,"
"alternateSeries,"
"alternateNumber,"
"alternateCount,"
"languageISO,"
"seriesGroup,"
"mainCharacterOrTeam,"
"review,"
"hash)" "hash)"
"VALUES (:title," "VALUES (:title,"
@ -539,6 +595,23 @@ bool DataBaseManagement::importComicsInfo(QString source, QString dest)
":coverSizeRatio," ":coverSizeRatio,"
":originalCoverSize," ":originalCoverSize,"
":manga,"
":added,"
":type,"
":editor,"
":imprint,"
":teams,"
":locations,"
":series,"
":alternateSeries,"
":alternateNumber,"
":alternateCount,"
":languageISO,"
":seriesGroup,"
":mainCharacterOrTeam,"
":review,"
":tags,"
":hash )"); ":hash )");
QSqlRecord record = newInfo.record(); QSqlRecord record = newInfo.record();
@ -596,6 +669,8 @@ bool DataBaseManagement::importComicsInfo(QString source, QString dest)
return b; return b;
} }
// TODO: update fields
// TODO fix these bindings // TODO fix these bindings
void DataBaseManagement::bindValuesFromRecord(const QSqlRecord &record, QSqlQuery &query) void DataBaseManagement::bindValuesFromRecord(const QSqlRecord &record, QSqlQuery &query)
{ {
@ -654,6 +729,22 @@ void DataBaseManagement::bindValuesFromRecord(const QSqlRecord &record, QSqlQuer
bindValue("coverSizeRatio", record, query); bindValue("coverSizeRatio", record, query);
bindValue("originalCoverSize", record, query); bindValue("originalCoverSize", record, query);
bindValue("added", record, query);
bindValue("type", record, query);
bindValue("editor", record, query);
bindValue("imprint", record, query);
bindValue("teams", record, query);
bindValue("locations", record, query);
bindValue("series", record, query);
bindValue("alternateSeries", record, query);
bindValue("alternateNumber", record, query);
bindValue("alternateCount", record, query);
bindValue("languageISO", record, query);
bindValue("seriesGroup", record, query);
bindValue("mainCharacterOrTeam", record, query);
bindValue("review", record, query);
bindValue("tags", record, query);
bindValue("hash", record, query); bindValue("hash", record, query);
} }
@ -757,6 +848,7 @@ bool DataBaseManagement::updateToCurrentVersion(const QString &path)
bool pre8 = false; bool pre8 = false;
bool pre9_5 = false; bool pre9_5 = false;
bool pre9_8 = false; bool pre9_8 = false;
bool pre9_13 = false;
QString fullPath = path + "/library.ydb"; QString fullPath = path + "/library.ydb";
@ -770,6 +862,8 @@ bool DataBaseManagement::updateToCurrentVersion(const QString &path)
pre9_5 = true; pre9_5 = true;
if (compareVersions(DataBaseManagement::checkValidDB(fullPath), "9.8.0") < 0) if (compareVersions(DataBaseManagement::checkValidDB(fullPath), "9.8.0") < 0)
pre9_8 = true; pre9_8 = true;
if (compareVersions(DataBaseManagement::checkValidDB(fullPath), "9.13.0") < 0)
pre9_13 = true;
QString connectionName = ""; QString connectionName = "";
bool returnValue = false; bool returnValue = false;
@ -895,6 +989,53 @@ bool DataBaseManagement::updateToCurrentVersion(const QString &path)
returnValue = returnValue && successAddingColumns; returnValue = returnValue && successAddingColumns;
} }
} }
if (pre9_13) {
{ // comic_info
QStringList columnDefs;
columnDefs << "added INTEGER";
columnDefs << "type INTEGER DEFAULT 0"; // 0 = comic, 1 = manga, 2 = manga left to right, 3 = webcomic,
columnDefs << "editor TEXT";
columnDefs << "imprint TEXT";
columnDefs << "teams TEXT";
columnDefs << "locations TEXT";
columnDefs << "series TEXT";
columnDefs << "alternateSeries TEXT";
columnDefs << "alternateNumber TEXT";
columnDefs << "alternateCount INTEGER";
columnDefs << "languageISO TEXT";
columnDefs << "seriesGroup TEXT";
columnDefs << "mainCharacterOrTeam TEXT";
columnDefs << "review TEXT";
columnDefs << "tags TEXT";
bool successAddingColumns = addColumns("comic_info", columnDefs, db);
returnValue = returnValue && successAddingColumns;
QSqlQuery updateTypeQueryToManga(db);
updateTypeQueryToManga.prepare("UPDATE comic_info SET type = manga");
bool successMigratingManga = updateTypeQueryToManga.exec();
returnValue = returnValue && successMigratingManga;
QSqlQuery updateNumberQueryToBis(db);
updateNumberQueryToBis.prepare("UPDATE comic_info SET number = number + 0.5 WHERE isBis = 1");
bool successMigratingBis = updateNumberQueryToBis.exec();
returnValue = returnValue && successMigratingBis;
}
{ // folder
QStringList columnDefs;
columnDefs << "added INTEGER";
columnDefs << "updated INTEGER";
columnDefs << "type INTEGER DEFAULT 0";
bool successAddingColumns = addColumns("folder", columnDefs, db);
returnValue = returnValue && successAddingColumns;
QSqlQuery updateTypeQueryToManga(db);
updateTypeQueryToManga.prepare("UPDATE folder SET type = manga");
bool successMigratingManga = updateTypeQueryToManga.exec();
returnValue = returnValue && successMigratingManga;
}
}
} }
connectionName = db.connectionName(); connectionName = db.connectionName();
} }

View File

@ -42,7 +42,6 @@ private:
public: public:
DataBaseManagement(); DataBaseManagement();
// TreeModel * newTreeModel(QString path);
// crea una base de datos y todas sus tablas // crea una base de datos y todas sus tablas
static QSqlDatabase createDatabase(QString name, QString path); static QSqlDatabase createDatabase(QString name, QString path);
static QSqlDatabase createDatabase(QString dest); static QSqlDatabase createDatabase(QString dest);

View File

@ -6,8 +6,6 @@
#include "db_helper.h" #include "db_helper.h"
#include "qnaturalsorting.h" #include "qnaturalsorting.h"
#include "yacreader_global_gui.h" #include "yacreader_global_gui.h"
#include "QsLog.h"
#include "query_parser.h"
#include <QtGui> #include <QtGui>
@ -61,14 +59,12 @@ FolderModel::FolderModel(QObject *parent)
FolderModel::FolderModel(QSqlQuery &sqlquery, QObject *parent) FolderModel::FolderModel(QSqlQuery &sqlquery, QObject *parent)
: QAbstractItemModel(parent), isSubfolder(false), rootItem(nullptr) : QAbstractItemModel(parent), isSubfolder(false), rootItem(nullptr)
{ {
// lo m<>s probable es que el nodo ra<72>z no necesite tener informaci<63>n
QList<QVariant> rootData; QList<QVariant> rootData;
rootData << "root"; // id 0, padre 0, title "root" (el id, y el id del padre van a ir en la clase TreeItem) rootData << "root"; // id 1, parent 1, title "root"
rootItem = new FolderItem(rootData); rootItem = new FolderItem(rootData);
rootItem->id = ROOT; rootItem->id = ROOT;
rootItem->parentItem = nullptr; rootItem->parentItem = nullptr;
setupModelData(sqlquery, rootItem); setupModelData(sqlquery, rootItem);
// sqlquery.finish();
} }
FolderModel::~FolderModel() FolderModel::~FolderModel()
@ -98,7 +94,11 @@ QHash<int, QByteArray> FolderModel::roleNames() const
roles[IdRole] = "id"; roles[IdRole] = "id";
roles[MangaRole] = "is_manga"; roles[MangaRole] = "is_manga";
roles[CoverPathRole] = "cover_path"; roles[CoverPathRole] = "cover_path";
roles[FolderName] = "name"; roles[FolderNameRole] = "name";
roles[NumChildrenRole] = "num_children";
roles[TypeRole] = "type";
roles[AddedRole] = "added";
roles[UpdatedRole] = "type";
return roles; return roles;
} }
@ -150,7 +150,7 @@ QVariant FolderModel::data(const QModelIndex &index, int role) const
#endif #endif
} }
if (role == FolderModel::FolderName) { if (role == FolderModel::FolderNameRole) {
return item->data(FolderModel::Name); return item->data(FolderModel::Name);
} }
@ -169,6 +169,18 @@ QVariant FolderModel::data(const QModelIndex &index, int role) const
if (role == FolderModel::CoverPathRole) if (role == FolderModel::CoverPathRole)
return getCoverUrlPathForComicHash(item->data(FirstChildHash).toString()); return getCoverUrlPathForComicHash(item->data(FirstChildHash).toString());
if (role == FolderModel::NumChildrenRole)
return item->data(NumChildren);
if (role == FolderModel::TypeRole)
return item->data(Type);
if (role == FolderModel::AddedRole)
return item->data(Added);
if (role == FolderModel::UpdatedRole)
return item->data(Updated);
if (role != Qt::DisplayRole) if (role != Qt::DisplayRole)
return QVariant(); return QVariant();
@ -323,65 +335,39 @@ void FolderModel::setupModelData(QSqlQuery &sqlquery, FolderItem *parent)
int manga = record.indexOf("manga"); int manga = record.indexOf("manga");
int id = record.indexOf("id"); int id = record.indexOf("id");
int parentId = record.indexOf("parentId"); int parentId = record.indexOf("parentId");
int numChildren = record.indexOf("numChildren");
int firstChildHash = record.indexOf("firstChildHash"); int firstChildHash = record.indexOf("firstChildHash");
int customImage = record.indexOf("customImage");
int type = record.indexOf("type");
int added = record.indexOf("added");
int updated = record.indexOf("updated");
while (sqlquery.next()) { while (sqlquery.next()) {
QList<QVariant> data; QList<QVariant> data;
data << sqlquery.value(name).toString(); data << sqlquery.value(name);
data << sqlquery.value(path).toString(); data << sqlquery.value(path);
data << sqlquery.value(finished).toBool(); data << sqlquery.value(finished);
data << sqlquery.value(completed).toBool(); data << sqlquery.value(completed);
data << sqlquery.value(manga).toBool(); data << sqlquery.value(manga);
data << sqlquery.value(firstChildHash).toString(); data << sqlquery.value(numChildren);
data << sqlquery.value(firstChildHash);
data << sqlquery.value(customImage);
data << sqlquery.value(type);
data << sqlquery.value(added);
data << sqlquery.value(updated);
auto item = new FolderItem(data); auto item = new FolderItem(data);
item->id = sqlquery.value(id).toULongLong(); item->id = sqlquery.value(id).toULongLong();
// la inserci<63>n de hijos se hace de forma ordenada // la inserci<63>n de hijos se hace de forma ordenada
FolderItem *parent = items.value(sqlquery.value(parentId).toULongLong()); FolderItem *parent = items.value(sqlquery.value(parentId).toULongLong());
// if(parent !=0) //TODO if parent==0 the parent of item was removed from the DB and delete on cascade didn't work, ERROR.
parent->appendChild(item); parent->appendChild(item);
// se a<>ade el item al map, de forma que se pueda encontrar como padre en siguientes iteraciones // se a<>ade el item al map, de forma que se pueda encontrar como padre en siguientes iteraciones
items.insert(item->id, item); items.insert(item->id, item);
} }
} }
void FolderModel::updateFolderModelData(QSqlQuery &sqlquery, FolderItem *parent)
{
Q_UNUSED(parent);
QSqlRecord record = sqlquery.record();
int name = record.indexOf("name");
int path = record.indexOf("path");
int finished = record.indexOf("finished");
int completed = record.indexOf("completed");
int manga = record.indexOf("manga");
int id = record.indexOf("id");
int parentId = record.indexOf("parentId");
int firstChildHash = record.indexOf("firstChildHash");
while (sqlquery.next()) {
QList<QVariant> data;
data << sqlquery.value(name).toString();
data << sqlquery.value(path).toString();
data << sqlquery.value(finished).toBool();
data << sqlquery.value(completed).toBool();
data << sqlquery.value(manga).toBool();
data << sqlquery.value(firstChildHash).toString();
auto item = new FolderItem(data);
item->id = sqlquery.value(id).toULongLong();
// la inserci<63>n de hijos se hace de forma ordenada
FolderItem *parent = items.value(sqlquery.value(parentId).toULongLong());
if (parent != 0) // TODO if parent==0 the parent of item was removed from the DB and delete on cascade didn't work, ERROR.
parent->appendChild(item);
// se a<>ade el item al map, de forma que se pueda encontrar como padre en siguientes iteraciones
items.insert(item->id, item);
}
}
QString FolderModel::getDatabase() QString FolderModel::getDatabase()
{ {
return _databasePath; return _databasePath;
@ -406,7 +392,7 @@ void FolderModel::updateFolderCompletedStatus(const QModelIndexList &list, bool
if (!isSubfolder) { if (!isSubfolder) {
Folder f = DBHelper::loadFolder(item->id, db); Folder f = DBHelper::loadFolder(item->id, db);
f.setCompleted(status); f.completed = status;
DBHelper::update(f, db); DBHelper::update(f, db);
} }
} }
@ -430,7 +416,7 @@ void FolderModel::updateFolderFinishedStatus(const QModelIndexList &list, bool s
if (!isSubfolder) { if (!isSubfolder) {
Folder f = DBHelper::loadFolder(item->id, db); Folder f = DBHelper::loadFolder(item->id, db);
f.setFinished(status); f.finished = status;
DBHelper::update(f, db); DBHelper::update(f, db);
} }
} }
@ -439,10 +425,10 @@ void FolderModel::updateFolderFinishedStatus(const QModelIndexList &list, bool s
} }
QSqlDatabase::removeDatabase(connectionName); QSqlDatabase::removeDatabase(connectionName);
emit dataChanged(index(list.first().row(), FolderModel::Name), index(list.last().row(), FolderModel::FirstChildHash)); emit dataChanged(index(list.first().row(), FolderModel::Name), index(list.last().row(), FolderModel::Updated));
} }
void FolderModel::updateFolderManga(const QModelIndexList &list, bool manga) void FolderModel::updateFolderType(const QModelIndexList &list, YACReader::FileType type)
{ {
QString connectionName = ""; QString connectionName = "";
{ {
@ -451,19 +437,19 @@ void FolderModel::updateFolderManga(const QModelIndexList &list, bool manga)
foreach (QModelIndex mi, list) { foreach (QModelIndex mi, list) {
auto item = static_cast<FolderItem *>(mi.internalPointer()); auto item = static_cast<FolderItem *>(mi.internalPointer());
std::function<void(FolderItem *, bool)> setManga; std::function<void(FolderItem *, YACReader::FileType)> setType;
setManga = [&setManga](FolderItem *item, bool manga) -> void { setType = [&setType](FolderItem *item, YACReader::FileType type) -> void {
item->setData(FolderModel::Manga, manga); item->setData(FolderModel::Type, QVariant::fromValue(type));
for (auto child : item->children()) { for (auto child : item->children()) {
setManga(child, manga); setType(child, type);
} }
}; };
setManga(item, manga); setType(item, type);
if (!isSubfolder) { if (!isSubfolder) {
DBHelper::updateFolderTreeManga(item->id, db, manga); DBHelper::updateFolderTreeType(item->id, db, type);
} }
} }
db.commit(); db.commit();
@ -471,7 +457,7 @@ void FolderModel::updateFolderManga(const QModelIndexList &list, bool manga)
} }
QSqlDatabase::removeDatabase(connectionName); QSqlDatabase::removeDatabase(connectionName);
emit dataChanged(index(list.first().row(), FolderModel::Name), index(list.last().row(), FolderModel::FirstChildHash)); emit dataChanged(index(list.first().row(), FolderModel::Name), index(list.last().row(), FolderModel::Updated));
} }
QStringList FolderModel::getSubfoldersNames(const QModelIndex &mi) QStringList FolderModel::getSubfoldersNames(const QModelIndex &mi)
@ -552,7 +538,13 @@ Folder FolderModel::getFolder(const QModelIndex &mi)
folderItem->parent()->data(Columns::Path).toString() + "/" + name, folderItem->parent()->data(Columns::Path).toString() + "/" + name,
folderItem->data(Columns::Completed).toBool(), folderItem->data(Columns::Completed).toBool(),
folderItem->data(Columns::Finished).toBool(), folderItem->data(Columns::Finished).toBool(),
folderItem->data(Columns::Manga).toBool()); folderItem->data(Columns::Manga).toBool(),
folderItem->data(Columns::NumChildren).toInt(),
folderItem->data(Columns::FirstChildHash).toString(),
folderItem->data(Columns::CustomImage).toString(),
folderItem->data(Columns::Type).value<YACReader::FileType>(),
folderItem->data(Columns::Added).toLongLong(),
folderItem->data(Columns::Updated).toLongLong());
return folder; return folder;
} }
@ -589,74 +581,6 @@ QModelIndex FolderModel::getIndexFromFolder(const Folder &folder, const QModelIn
return QModelIndex(); return QModelIndex();
} }
void FolderModel::fetchMoreFromDB(const QModelIndex &parent)
{
FolderItem *item;
if (parent.isValid())
item = static_cast<FolderItem *>(parent.internalPointer());
else
item = rootItem;
// Remove all children
if (item->childCount() > 0) {
beginRemoveRows(parent, 0, item->childCount() - 1);
item->clearChildren();
endRemoveRows();
}
QString connectionName = "";
{
QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath);
QList<FolderItem *> items;
QList<FolderItem *> nextLevelItems;
QSqlQuery selectQuery(db);
selectQuery.prepare("select * from folder where id <> 1 and parentId = :parentId order by parentId,name");
items << item;
bool firstLevelUpdated = false;
while (items.size() > 0) {
nextLevelItems.clear();
foreach (FolderItem *item, items) {
QLOG_DEBUG() << "ID " << item->id;
selectQuery.bindValue(":parentId", item->id);
selectQuery.exec();
if (!firstLevelUpdated) {
// NO size support
int numResults = 0;
while (selectQuery.next())
numResults++;
if (!selectQuery.seek(-1))
selectQuery.exec();
// END no size support
beginInsertRows(parent, 0, numResults - 1);
}
updateFolderModelData(selectQuery, item);
if (!firstLevelUpdated) {
endInsertRows();
firstLevelUpdated = true;
}
nextLevelItems << item->children();
}
items.clear();
items = nextLevelItems;
}
connectionName = db.connectionName();
}
QLOG_DEBUG() << "item->childCount()-1" << item->childCount() - 1;
QSqlDatabase::removeDatabase(connectionName);
}
QModelIndex FolderModel::addFolderAtParent(const QString &folderName, const QModelIndex &parent) QModelIndex FolderModel::addFolderAtParent(const QString &folderName, const QModelIndex &parent)
{ {
FolderItem *parentItem; FolderItem *parentItem;
@ -670,7 +594,9 @@ QModelIndex FolderModel::addFolderAtParent(const QString &folderName, const QMod
newFolder.name = folderName; newFolder.name = folderName;
newFolder.parentId = parentItem->id; newFolder.parentId = parentItem->id;
newFolder.path = parentItem->data(Columns::Path).toString() + "/" + folderName; newFolder.path = parentItem->data(Columns::Path).toString() + "/" + folderName;
newFolder.setManga(parentItem->data(Columns::Manga).toBool()); newFolder.manga = parentItem->data(Columns::Manga).toBool();
newFolder.type = parentItem->data(Columns::Type).value<YACReader::FileType>();
QString connectionName = ""; QString connectionName = "";
{ {
QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath);
@ -687,7 +613,13 @@ QModelIndex FolderModel::addFolderAtParent(const QString &folderName, const QMod
data << newFolder.path; data << newFolder.path;
data << false; // finished data << false; // finished
data << true; // completed data << true; // completed
data << newFolder.isManga(); data << newFolder.manga;
data << 0; // numChildren
data << QVariant(); // first child hash, new folder is empty
data << QVariant(); // custom cover
data << QVariant::fromValue(newFolder.type);
data << newFolder.added;
data << newFolder.updated;
auto item = new FolderItem(data); auto item = new FolderItem(data);
item->id = newFolder.id; item->id = newFolder.id;

View File

@ -66,13 +66,10 @@ public:
void setupModelData(QString path); void setupModelData(QString path);
QString getDatabase(); QString getDatabase();
QString getFolderPath(const QModelIndex &folder); QString getFolderPath(const QModelIndex &folder);
// QModelIndex indexFromItem(FolderItem * item, int column);
// bool isFilterEnabled(){return filterEnabled;};
void updateFolderCompletedStatus(const QModelIndexList &list, bool status); void updateFolderCompletedStatus(const QModelIndexList &list, bool status);
void updateFolderFinishedStatus(const QModelIndexList &list, bool status); void updateFolderFinishedStatus(const QModelIndexList &list, bool status);
void updateFolderManga(const QModelIndexList &list, bool manga); void updateFolderType(const QModelIndexList &list, YACReader::FileType type);
QStringList getSubfoldersNames(const QModelIndex &mi); QStringList getSubfoldersNames(const QModelIndex &mi);
FolderModel *getSubfoldersModel(const QModelIndex &mi); FolderModel *getSubfoldersModel(const QModelIndex &mi);
@ -80,28 +77,35 @@ public:
Folder getFolder(const QModelIndex &mi); Folder getFolder(const QModelIndex &mi);
QModelIndex getIndexFromFolder(const Folder &folder, const QModelIndex &parent = QModelIndex()); QModelIndex getIndexFromFolder(const Folder &folder, const QModelIndex &parent = QModelIndex());
void fetchMoreFromDB(const QModelIndex &parent);
QModelIndex addFolderAtParent(const QString &folderName, const QModelIndex &parent); QModelIndex addFolderAtParent(const QString &folderName, const QModelIndex &parent);
Q_INVOKABLE QUrl getCoverUrlPathForComicHash(const QString &hash) const; Q_INVOKABLE QUrl getCoverUrlPathForComicHash(const QString &hash) const;
enum Columns { enum Columns {
Name = 0, Name = 0,
Path = 1, Path,
Finished = 2, Finished,
Completed = 3, Completed,
Manga = 4, Manga, // deprecated
FirstChildHash = 5 NumChildren,
}; // id INTEGER PRIMARY KEY, parentId INTEGER NOT NULL, name TEXT NOT NULL, path TEXT NOT NULL FirstChildHash,
CustomImage,
Type, // FileType
Added,
Updated,
};
enum Roles { enum Roles {
FinishedRole = Qt::UserRole + 1, FinishedRole = Qt::UserRole + 1,
CompletedRole, CompletedRole,
IdRole, IdRole,
MangaRole, MangaRole, // deprecated
CoverPathRole, CoverPathRole,
FolderName, FolderNameRole,
NumChildrenRole,
TypeRole,
AddedRole,
UpdatedRole,
}; };
bool isSubfolder; bool isSubfolder;
@ -112,9 +116,7 @@ public slots:
private: private:
void fullSetup(QSqlQuery &sqlquery, FolderItem *parent); void fullSetup(QSqlQuery &sqlquery, FolderItem *parent);
void setupModelData(QSqlQuery &sqlquery, FolderItem *parent); void setupModelData(QSqlQuery &sqlquery, FolderItem *parent);
void updateFolderModelData(QSqlQuery &sqlquery, FolderItem *parent);
FolderItem *rootItem; // el árbol FolderItem *rootItem; // el árbol
QMap<unsigned long long int, FolderItem *> items; // relación entre folders QMap<unsigned long long int, FolderItem *> items; // relación entre folders

View File

@ -5,14 +5,17 @@
#include <numeric> #include <numeric>
#include <stdexcept> #include <stdexcept>
#include <QsLog.h>
const std::map<QueryParser::FieldType, std::vector<std::string>> QueryParser::fieldNames { const std::map<QueryParser::FieldType, std::vector<std::string>> QueryParser::fieldNames {
{ FieldType::numeric, { "numpages", "number", "count", "arcnumber", "arccount" } }, { FieldType::numeric, { "numpages", "count", "arccount", "alternateCount" } },
{ FieldType::text, { "title", "volume", "storyarc", "genere", "writer", "penciller", "inker", "colorist", "letterer", "coverartist", "publisher", "format", "agerating", "synopsis", "characters", "notes" } }, { FieldType::text, { "number", "arcnumber", "title", "volume", "storyarc", "genere", "writer", "penciller", "inker", "colorist", "letterer", "coverartist", "publisher", "format", "agerating", "synopsis", "characters", "notes", "editor", "imprint", "teams", "locations", "series", "alternateSeries", "alternateNumber", "languageISO", "seriesGroup", "mainCharacterOrTeam", "review", "tags" } },
{ FieldType::boolean, { "isbis", "color", "read", "manga" } }, { FieldType::boolean, { "isbis", "color", "read" } },
{ FieldType::date, { "date" } }, { FieldType::date, { "date", "added", "lastTimeOpened" } },
{ FieldType::filename, { "filename" } }, { FieldType::filename, { "filename" } },
{ FieldType::folder, { "folder" } }, { FieldType::folder, { "folder" } },
{ FieldType::booleanFolder, { "completed", "finished" } }, { FieldType::booleanFolder, { "completed", "finished" } }, // TODO_METADTA include new folder fields, e.g. type
{ FieldType::enumField, { "type" } }
}; };
int QueryParser::TreeNode::buildSqlString(std::string &sqlString, int bindPosition) const int QueryParser::TreeNode::buildSqlString(std::string &sqlString, int bindPosition) const
@ -26,7 +29,7 @@ int QueryParser::TreeNode::buildSqlString(std::string &sqlString, int bindPositi
} }
sqlString += "UPPER(c.filename) LIKE UPPER(:bindPosition" + std::to_string(bindPosition) + ") OR "; sqlString += "UPPER(c.filename) LIKE UPPER(:bindPosition" + std::to_string(bindPosition) + ") OR ";
sqlString += "UPPER(f.name) LIKE UPPER(:bindPosition" + std::to_string(bindPosition) + ")) "; sqlString += "UPPER(f.name) LIKE UPPER(:bindPosition" + std::to_string(bindPosition) + ")) ";
} else if (isIn(fieldType(children[0].t), { FieldType::numeric, FieldType::boolean })) { } else if (isIn(fieldType(children[0].t), { FieldType::numeric, FieldType::boolean, FieldType::enumField })) {
sqlString += "ci." + children[0].t + " = :bindPosition" + std::to_string(bindPosition) + " "; sqlString += "ci." + children[0].t + " = :bindPosition" + std::to_string(bindPosition) + " ";
} else if (fieldType(children[0].t) == FieldType::filename) { } else if (fieldType(children[0].t) == FieldType::filename) {
sqlString += "(UPPER(c." + children[0].t + ") LIKE UPPER(:bindPosition" + std::to_string(bindPosition) + ")) "; sqlString += "(UPPER(c." + children[0].t + ") LIKE UPPER(:bindPosition" + std::to_string(bindPosition) + ")) ";
@ -67,6 +70,24 @@ int QueryParser::TreeNode::bindValues(QSqlQuery &selectQuery, int bindPosition)
} else { } else {
selectQuery.bindValue(QString::fromStdString(bind_string), std::stoi(value)); selectQuery.bindValue(QString::fromStdString(bind_string), std::stoi(value));
} }
} else if ((isIn(fieldType(children[0].t), { FieldType::enumField }))) {
auto enumType = children[0].t;
auto value = toLower(children[1].t);
if (enumType == "type") {
if (value == "comic") {
selectQuery.bindValue(QString::fromStdString(bind_string), 0);
} else if (value == "manga") {
selectQuery.bindValue(QString::fromStdString(bind_string), 1);
} else if (value == "westernmanga") {
selectQuery.bindValue(QString::fromStdString(bind_string), 2);
} else if (value == "webcomic" || value == "web") {
selectQuery.bindValue(QString::fromStdString(bind_string), 3);
} else if (value == "4koma" || value == "yonkoma") {
selectQuery.bindValue(QString::fromStdString(bind_string), 4);
}
} else {
selectQuery.bindValue(QString::fromStdString(bind_string), std::stoi(children[1].t));
}
} else { } else {
selectQuery.bindValue(QString::fromStdString(bind_string), QString::fromStdString("%%" + children[1].t + "%%")); selectQuery.bindValue(QString::fromStdString(bind_string), QString::fromStdString("%%" + children[1].t + "%%"));
} }
@ -232,6 +253,7 @@ QueryParser::TreeNode QueryParser::baseToken()
return TreeNode("token", { TreeNode("all", {}), TreeNode(token(true), {}) }); return TreeNode("token", { TreeNode("all", {}), TreeNode(token(true), {}) });
} }
// TODO ":" should come from the lexer as a token
auto words(split(token(true), ':')); auto words(split(token(true), ':'));
if (words.size() > 1 && fieldType(words[0].toStdString()) != FieldType::unknown) { if (words.size() > 1 && fieldType(words[0].toStdString()) != FieldType::unknown) {

View File

@ -85,7 +85,8 @@ private:
date, date,
folder, folder,
booleanFolder, booleanFolder,
filename }; filename,
enumField };
static FieldType fieldType(const std::string &str); static FieldType fieldType(const std::string &str);
static std::string join(const QStringList &strings, const std::string &delim); static std::string join(const QStringList &strings, const std::string &delim);

View File

@ -66,7 +66,7 @@ QList<LibraryItem *> DBHelper::getFolderComicsFromLibraryForReading(qulonglong l
return naturalSortLessThanCI(c1->name, c2->name); return naturalSortLessThanCI(c1->name, c2->name);
} else { } else {
if (c1->info.number.isNull() == false && c2->info.number.isNull() == false) { if (c1->info.number.isNull() == false && c2->info.number.isNull() == false) {
return c1->info.number.toInt() < c2->info.number.toInt(); return naturalSortLessThanCI(c1->info.number.toString(), c2->info.number.toString());
} else { } else {
return c2->info.number.isNull(); return c2->info.number.isNull();
} }
@ -637,9 +637,28 @@ void DBHelper::update(ComicInfo *comicInfo, QSqlDatabase &db)
//-- //--
// new 9.8 fields // new 9.8 fields
"manga = :manga" "manga = :manga,"
//-- //--
" WHERE id = :id ");
// new 9.13 fields
"added = :added,"
"type = :type,"
"editor = :editor,"
"imprint = :imprint,"
"teams = :teams,"
"locations = :locations,"
"series = :series,"
"alternateSeries = :alternateSeries,"
"alternateNumber = :alternateNumber,"
"alternateCount = :alternateCount,"
"languageISO = :languageISO,"
"seriesGroup = :seriesGroup,"
"mainCharacterOrTeam = :mainCharacterOrTeam,"
"review = :review,"
"tags = :tags"
//--
" WHERE id = :id");
updateComicInfo.bindValue(":title", comicInfo->title); updateComicInfo.bindValue(":title", comicInfo->title);
@ -698,7 +717,28 @@ void DBHelper::update(ComicInfo *comicInfo, QSqlDatabase &db)
updateComicInfo.bindValue(":coverSizeRatio", comicInfo->coverSizeRatio); updateComicInfo.bindValue(":coverSizeRatio", comicInfo->coverSizeRatio);
updateComicInfo.bindValue(":originalCoverSize", comicInfo->originalCoverSize); updateComicInfo.bindValue(":originalCoverSize", comicInfo->originalCoverSize);
updateComicInfo.bindValue(":added", comicInfo->added);
auto intType = static_cast<int>(comicInfo->type.value<YACReader::FileType>());
updateComicInfo.bindValue(":type", intType);
updateComicInfo.bindValue(":editor", comicInfo->editor);
updateComicInfo.bindValue(":imprint", comicInfo->imprint);
updateComicInfo.bindValue(":teams", comicInfo->teams);
updateComicInfo.bindValue(":locations", comicInfo->locations);
updateComicInfo.bindValue(":series", comicInfo->series);
updateComicInfo.bindValue(":alternateSeries", comicInfo->alternateSeries);
updateComicInfo.bindValue(":alternateNumber", comicInfo->alternateNumber);
updateComicInfo.bindValue(":alternateCount", comicInfo->alternateCount);
updateComicInfo.bindValue(":languageISO", comicInfo->languageISO);
updateComicInfo.bindValue(":seriesGroup", comicInfo->seriesGroup);
updateComicInfo.bindValue(":mainCharacterOrTeam", comicInfo->mainCharacterOrTeam);
updateComicInfo.bindValue(":review", comicInfo->review);
updateComicInfo.bindValue(":tags", comicInfo->tags);
updateComicInfo.exec(); updateComicInfo.exec();
QLOG_INFO() << updateComicInfo.lastError().databaseText();
QLOG_INFO() << updateComicInfo.lastError().text();
QLOG_INFO() << updateComicInfo.lastQuery();
} }
void DBHelper::updateRead(ComicInfo *comicInfo, QSqlDatabase &db) void DBHelper::updateRead(ComicInfo *comicInfo, QSqlDatabase &db)
@ -718,12 +758,10 @@ void DBHelper::update(const Folder &folder, QSqlDatabase &db)
QSqlQuery updateFolderInfo(db); QSqlQuery updateFolderInfo(db);
updateFolderInfo.prepare("UPDATE folder SET " updateFolderInfo.prepare("UPDATE folder SET "
"finished = :finished, " "finished = :finished, "
"completed = :completed, " "completed = :completed "
"manga = :manga "
"WHERE id = :id "); "WHERE id = :id ");
updateFolderInfo.bindValue(":finished", folder.isFinished() ? 1 : 0); updateFolderInfo.bindValue(":finished", folder.finished ? 1 : 0);
updateFolderInfo.bindValue(":completed", folder.isCompleted() ? 1 : 0); updateFolderInfo.bindValue(":completed", folder.completed ? 1 : 0);
updateFolderInfo.bindValue(":manga", folder.isManga() ? 1 : 0);
updateFolderInfo.bindValue(":id", folder.id); updateFolderInfo.bindValue(":id", folder.id);
updateFolderInfo.exec(); updateFolderInfo.exec();
} }
@ -762,7 +800,7 @@ Folder DBHelper::updateChildrenInfo(qulonglong folderId, QSqlDatabase &db)
} else { } else {
for (auto item : updatedSubfolders) { for (auto item : updatedSubfolders) {
auto f = static_cast<Folder *>(item); auto f = static_cast<Folder *>(item);
auto firstChildHash = f->getFirstChildHash(); auto firstChildHash = f->firstChildHash;
if (!firstChildHash.isEmpty()) { if (!firstChildHash.isEmpty()) {
coverHash = firstChildHash; coverHash = firstChildHash;
break; break;
@ -770,16 +808,16 @@ Folder DBHelper::updateChildrenInfo(qulonglong folderId, QSqlDatabase &db)
} }
} }
folder.setNumChildren(subfolders.count() + comics.count()); folder.numChildren = subfolders.count() + comics.count();
folder.setFirstChildHash(coverHash); folder.firstChildHash = coverHash;
QSqlQuery updateFolderInfo(db); QSqlQuery updateFolderInfo(db);
updateFolderInfo.prepare("UPDATE folder SET " updateFolderInfo.prepare("UPDATE folder SET "
"numChildren = :numChildren, " "numChildren = :numChildren, "
"firstChildHash = :firstChildHash " "firstChildHash = :firstChildHash "
"WHERE id = :id "); "WHERE id = :id ");
updateFolderInfo.bindValue(":numChildren", folder.getNumChildren()); updateFolderInfo.bindValue(":numChildren", folder.numChildren);
updateFolderInfo.bindValue(":firstChildHash", folder.getFirstChildHash()); updateFolderInfo.bindValue(":firstChildHash", folder.firstChildHash);
updateFolderInfo.bindValue(":id", folderId); updateFolderInfo.bindValue(":id", folderId);
updateFolderInfo.exec(); updateFolderInfo.exec();
@ -854,7 +892,7 @@ void DBHelper::updateReadingRemoteProgress(const ComicInfo &comicInfo, QSqlDatab
updateComicInfo.bindValue(":read", comicInfo.read ? 1 : 0); updateComicInfo.bindValue(":read", comicInfo.read ? 1 : 0);
updateComicInfo.bindValue(":currentPage", comicInfo.currentPage); updateComicInfo.bindValue(":currentPage", comicInfo.currentPage);
updateComicInfo.bindValue(":hasBeenOpened", comicInfo.hasBeenOpened ? 1 : 0); updateComicInfo.bindValue(":hasBeenOpened", comicInfo.hasBeenOpened ? 1 : 0);
updateComicInfo.bindValue(":lastTimeOpened", QDateTime::currentMSecsSinceEpoch() / 1000); updateComicInfo.bindValue(":lastTimeOpened", QDateTime::currentSecsSinceEpoch());
updateComicInfo.bindValue(":id", comicInfo.id); updateComicInfo.bindValue(":id", comicInfo.id);
updateComicInfo.bindValue(":rating", comicInfo.rating); updateComicInfo.bindValue(":rating", comicInfo.rating);
updateComicInfo.exec(); updateComicInfo.exec();
@ -1067,7 +1105,7 @@ void DBHelper::updateFromRemoteClientWithHash(const QList<ComicInfo> &comics)
updateComicInfo.bindValue(":read", info.read ? 1 : 0); updateComicInfo.bindValue(":read", info.read ? 1 : 0);
updateComicInfo.bindValue(":currentPage", info.currentPage); updateComicInfo.bindValue(":currentPage", info.currentPage);
updateComicInfo.bindValue(":hasBeenOpened", info.hasBeenOpened ? 1 : 0); updateComicInfo.bindValue(":hasBeenOpened", info.hasBeenOpened ? 1 : 0);
updateComicInfo.bindValue(":lastTimeOpened", QDateTime::currentMSecsSinceEpoch() / 1000); updateComicInfo.bindValue(":lastTimeOpened", QDateTime::currentSecsSinceEpoch());
updateComicInfo.bindValue(":id", info.id); updateComicInfo.bindValue(":id", info.id);
updateComicInfo.bindValue(":rating", info.rating); updateComicInfo.bindValue(":rating", info.rating);
updateComicInfo.exec(); updateComicInfo.exec();
@ -1195,11 +1233,12 @@ void DBHelper::updateComicsInfo(QList<ComicDB> &comics, const QString &databaseP
qulonglong DBHelper::insert(Folder *folder, QSqlDatabase &db) qulonglong DBHelper::insert(Folder *folder, QSqlDatabase &db)
{ {
QSqlQuery query(db); QSqlQuery query(db);
query.prepare("INSERT INTO folder (parentId, name, path) " query.prepare("INSERT INTO folder (parentId, name, path, added) "
"VALUES (:parentId, :name, :path)"); "VALUES (:parentId, :name, :path, :added)");
query.bindValue(":parentId", folder->parentId); query.bindValue(":parentId", folder->parentId);
query.bindValue(":name", folder->name); query.bindValue(":name", folder->name);
query.bindValue(":path", folder->path); query.bindValue(":path", folder->path);
query.bindValue(":added", QDateTime::currentSecsSinceEpoch());
query.exec(); query.exec();
return query.lastInsertId().toULongLong(); return query.lastInsertId().toULongLong();
@ -1207,16 +1246,21 @@ qulonglong DBHelper::insert(Folder *folder, QSqlDatabase &db)
qulonglong DBHelper::insert(ComicDB *comic, QSqlDatabase &db, bool insertAllInfo) qulonglong DBHelper::insert(ComicDB *comic, QSqlDatabase &db, bool insertAllInfo)
{ {
auto added = QDateTime::currentSecsSinceEpoch();
if (!comic->info.existOnDb) { if (!comic->info.existOnDb) {
QSqlQuery comicInfoInsert(db); QSqlQuery comicInfoInsert(db);
comicInfoInsert.prepare("INSERT INTO comic_info (hash,numPages,coverSizeRatio,originalCoverSize) "
"VALUES (:hash,:numPages,:coverSizeRatio,:originalCoverSize)"); comicInfoInsert.prepare("INSERT INTO comic_info (hash,numPages,coverSizeRatio,originalCoverSize,added) "
"VALUES (:hash,:numPages,:coverSizeRatio,:originalCoverSize,:added)");
comicInfoInsert.bindValue(":hash", comic->info.hash); comicInfoInsert.bindValue(":hash", comic->info.hash);
comicInfoInsert.bindValue(":numPages", comic->info.numPages); comicInfoInsert.bindValue(":numPages", comic->info.numPages);
comicInfoInsert.bindValue(":coverSizeRatio", comic->info.coverSizeRatio); comicInfoInsert.bindValue(":coverSizeRatio", comic->info.coverSizeRatio);
comicInfoInsert.bindValue(":originalCoverSize", comic->info.originalCoverSize); comicInfoInsert.bindValue(":originalCoverSize", comic->info.originalCoverSize);
comicInfoInsert.bindValue(":added", added);
comicInfoInsert.exec(); comicInfoInsert.exec();
comic->info.id = comicInfoInsert.lastInsertId().toULongLong(); comic->info.id = comicInfoInsert.lastInsertId().toULongLong();
comic->info.added = added;
comic->_hasCover = false; comic->_hasCover = false;
if (insertAllInfo) { if (insertAllInfo) {
@ -1234,6 +1278,14 @@ qulonglong DBHelper::insert(ComicDB *comic, QSqlDatabase &db, bool insertAllInfo
query.bindValue(":path", comic->path); query.bindValue(":path", comic->path);
query.exec(); query.exec();
QSqlQuery updateFolder(db);
updateFolder.prepare("UPDATE folder SET "
"updated = :updated "
"WHERE id = :id ");
updateFolder.bindValue(":updated", added);
updateFolder.bindValue(":id", comic->parentId);
updateFolder.exec();
return query.lastInsertId().toULongLong(); return query.lastInsertId().toULongLong();
} }
@ -1342,6 +1394,7 @@ void DBHelper::insertComicsInReadingList(const QList<ComicDB> &comicsList, qulon
db.commit(); db.commit();
} }
// queries // queries
QList<LibraryItem *> DBHelper::getFoldersFromParent(qulonglong parentId, QSqlDatabase &db, bool sort) QList<LibraryItem *> DBHelper::getFoldersFromParent(qulonglong parentId, QSqlDatabase &db, bool sort)
{ {
@ -1356,20 +1409,33 @@ QList<LibraryItem *> DBHelper::getFoldersFromParent(qulonglong parentId, QSqlDat
int name = record.indexOf("name"); int name = record.indexOf("name");
int path = record.indexOf("path"); int path = record.indexOf("path");
int finished = record.indexOf("finished");
int completed = record.indexOf("completed");
int manga = record.indexOf("manga");
int id = record.indexOf("id"); int id = record.indexOf("id");
int numChildren = record.indexOf("numChildren"); int numChildren = record.indexOf("numChildren");
int firstChildHash = record.indexOf("firstChildHash"); int firstChildHash = record.indexOf("firstChildHash");
int customImage = record.indexOf("customImage"); int customImage = record.indexOf("customImage");
int type = record.indexOf("type");
int added = record.indexOf("added");
int updated = record.indexOf("updated");
Folder *currentItem; Folder *currentItem;
while (selectQuery.next()) { while (selectQuery.next()) {
// TODO sort by sort indicator and name // TODO sort by sort indicator and name
currentItem = new Folder(selectQuery.value(id).toULongLong(), parentId, selectQuery.value(name).toString(), selectQuery.value(path).toString()); currentItem = new Folder(selectQuery.value(id).toULongLong(), parentId, selectQuery.value(name).toString(), selectQuery.value(path).toString());
if (!selectQuery.value(numChildren).isNull() && selectQuery.value(numChildren).isValid()) currentItem->finished = selectQuery.value(finished).toBool();
currentItem->setNumChildren(selectQuery.value(numChildren).toInt()); currentItem->completed = selectQuery.value(completed).toBool();
currentItem->setFirstChildHash(selectQuery.value(firstChildHash).toString()); if (!selectQuery.value(numChildren).isNull() && selectQuery.value(numChildren).isValid()) {
currentItem->setCustomImage(selectQuery.value(customImage).toString()); currentItem->numChildren = selectQuery.value(numChildren).toInt();
}
currentItem->firstChildHash = selectQuery.value(firstChildHash).toString();
currentItem->customImage = selectQuery.value(customImage).toString();
currentItem->manga = selectQuery.value(manga).toBool();
currentItem->type = selectQuery.value(type).value<YACReader::FileType>();
currentItem->added = selectQuery.value(added).toLongLong();
currentItem->updated = selectQuery.value(updated).toLongLong();
int lessThan = 0; int lessThan = 0;
@ -1524,21 +1590,21 @@ QList<Label> DBHelper::getLabels(qulonglong libraryId)
return labels; return labels;
} }
void DBHelper::updateFolderTreeManga(qulonglong id, QSqlDatabase &db, bool manga) void DBHelper::updateFolderTreeType(qulonglong id, QSqlDatabase &db, YACReader::FileType type)
{ {
QSqlQuery updateFolderQuery(db); QSqlQuery updateFolderQuery(db);
updateFolderQuery.prepare("UPDATE folder " updateFolderQuery.prepare("UPDATE folder "
"SET manga = :manga " "SET type = :type "
"WHERE id = :id"); "WHERE id = :id");
updateFolderQuery.bindValue(":manga", manga ? 1 : 0); updateFolderQuery.bindValue(":type", static_cast<int>(type));
updateFolderQuery.bindValue(":id", id); updateFolderQuery.bindValue(":id", id);
updateFolderQuery.exec(); updateFolderQuery.exec();
QSqlQuery updateComicInfo(db); QSqlQuery updateComicInfo(db);
updateComicInfo.prepare("UPDATE comic_info " updateComicInfo.prepare("UPDATE comic_info "
"SET manga = :manga " "SET type = :type "
"WHERE id IN (SELECT ci.id FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) WHERE c.parentId = :parentId)"); "WHERE id IN (SELECT ci.id FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) WHERE c.parentId = :parentId)");
updateComicInfo.bindValue(":manga", manga ? 1 : 0); updateComicInfo.bindValue(":type", static_cast<int>(type));
updateComicInfo.bindValue(":parentId", id); updateComicInfo.bindValue(":parentId", id);
updateComicInfo.exec(); updateComicInfo.exec();
@ -1550,22 +1616,46 @@ void DBHelper::updateFolderTreeManga(qulonglong id, QSqlDatabase &db, bool manga
int childFolderIdPos = getSubFoldersQuery.record().indexOf("id"); int childFolderIdPos = getSubFoldersQuery.record().indexOf("id");
while (getSubFoldersQuery.next()) { while (getSubFoldersQuery.next()) {
updateFolderTreeManga(getSubFoldersQuery.value(childFolderIdPos).toULongLong(), db, manga); updateFolderTreeType(getSubFoldersQuery.value(childFolderIdPos).toULongLong(), db, type);
} }
} }
// loads
Folder DBHelper::loadFolder(qulonglong id, QSqlDatabase &db) Folder DBHelper::loadFolder(qulonglong id, QSqlDatabase &db)
{ {
Folder folder;
QSqlQuery query(db); QSqlQuery query(db);
query.prepare("SELECT * FROM folder WHERE id = :id"); query.prepare("SELECT * FROM folder WHERE id = :id");
query.bindValue(":id", id); query.bindValue(":id", id);
query.exec(); query.exec();
Folder folder;
folder.id = id; folder.id = id;
folder.parentId = 0; folder.parentId = 0;
DBHelper::readFolderFromQuery(folder, query);
return folder;
}
Folder DBHelper::loadFolder(const QString &folderName, qulonglong parentId, QSqlDatabase &db)
{
QSqlQuery query(db);
query.prepare("SELECT * FROM folder WHERE parentId = :parentId AND name = :folderName");
query.bindValue(":parentId", parentId);
query.bindValue(":folderName", folderName);
query.exec();
Folder folder;
folder.parentId = parentId;
DBHelper::readFolderFromQuery(folder, query);
return folder;
}
void DBHelper::readFolderFromQuery(Folder &folder, QSqlQuery &query)
{
QSqlRecord record = query.record(); QSqlRecord record = query.record();
int parentId = record.indexOf("parentId"); int parentId = record.indexOf("parentId");
@ -1577,6 +1667,9 @@ Folder DBHelper::loadFolder(qulonglong id, QSqlDatabase &db)
int numChildren = record.indexOf("numChildren"); int numChildren = record.indexOf("numChildren");
int firstChildHash = record.indexOf("firstChildHash"); int firstChildHash = record.indexOf("firstChildHash");
int customImage = record.indexOf("customImage"); int customImage = record.indexOf("customImage");
int type = record.indexOf("type");
int added = record.indexOf("added");
int updated = record.indexOf("updated");
if (query.next()) { if (query.next()) {
folder.parentId = query.value(parentId).toULongLong(); folder.parentId = query.value(parentId).toULongLong();
@ -1585,66 +1678,24 @@ Folder DBHelper::loadFolder(qulonglong id, QSqlDatabase &db)
folder.knownId = true; folder.knownId = true;
// new 7.1 // new 7.1
folder.setFinished(query.value(finished).toBool()); folder.finished = query.value(finished).toBool();
folder.setCompleted(query.value(completed).toBool()); folder.completed = query.value(completed).toBool();
// new 9.5 // new 9.5
if (!query.value(numChildren).isNull() && query.value(numChildren).isValid()) if (!query.value(numChildren).isNull() && query.value(numChildren).isValid()) {
folder.setNumChildren(query.value(numChildren).toInt()); folder.numChildren = query.value(numChildren).toInt();
folder.setFirstChildHash(query.value(firstChildHash).toString()); }
folder.setCustomImage(query.value(customImage).toString()); folder.firstChildHash = query.value(firstChildHash).toString();
folder.customImage = query.value(customImage).toString();
// new 9.8 // new 9.8
folder.setManga(query.value(manga).toBool()); folder.manga = query.value(manga).toBool();
// new 9.13
folder.type = query.value(type).value<YACReader::FileType>();
folder.added = query.value(added).toLongLong();
folder.updated = query.value(updated).toLongLong();
} }
return folder;
}
Folder DBHelper::loadFolder(const QString &folderName, qulonglong parentId, QSqlDatabase &db)
{
Folder folder;
QSqlQuery query(db);
query.prepare("SELECT * FROM folder WHERE parentId = :parentId AND name = :folderName");
query.bindValue(":parentId", parentId);
query.bindValue(":folderName", folderName);
query.exec();
QSqlRecord record = query.record();
int id = record.indexOf("id");
int name = record.indexOf("name");
int path = record.indexOf("path");
int finished = record.indexOf("finished");
int completed = record.indexOf("completed");
int manga = record.indexOf("manga");
int numChildren = record.indexOf("numChildren");
int firstChildHash = record.indexOf("firstChildHash");
int customImage = record.indexOf("customImage");
folder.parentId = parentId;
if (query.next()) {
folder.id = query.value(id).toULongLong();
folder.name = query.value(name).toString();
folder.path = query.value(path).toString();
folder.knownId = true;
// new 7.1
folder.setFinished(query.value(finished).toBool());
folder.setCompleted(query.value(completed).toBool());
// new 9.5
if (!query.value(numChildren).isNull() && query.value(numChildren).isValid())
folder.setNumChildren(query.value(numChildren).toInt());
folder.setFirstChildHash(query.value(firstChildHash).toString());
folder.setCustomImage(query.value(customImage).toString());
// new 9.8
folder.setManga(query.value(manga).toBool());
}
return folder;
} }
ComicDB DBHelper::loadComic(qulonglong id, QSqlDatabase &db, bool &found) ComicDB DBHelper::loadComic(qulonglong id, QSqlDatabase &db, bool &found)
@ -1776,6 +1827,22 @@ ComicInfo DBHelper::getComicInfoFromQuery(QSqlQuery &query, const QString &idKey
int coverSizeRatio = record.indexOf("coverSizeRatio"); int coverSizeRatio = record.indexOf("coverSizeRatio");
int originalCoverSize = record.indexOf("originalCoverSize"); int originalCoverSize = record.indexOf("originalCoverSize");
int added = record.indexOf("added");
int type = record.indexOf("type");
int editor = record.indexOf("editor");
int imprint = record.indexOf("imprint");
int teams = record.indexOf("teams");
int locations = record.indexOf("locations");
int series = record.indexOf("series");
int alternateSeries = record.indexOf("alternateSeries");
int alternateNumber = record.indexOf("alternateNumber");
int alternateCount = record.indexOf("alternateCount");
int languageISO = record.indexOf("languageISO");
int seriesGroup = record.indexOf("seriesGroup");
int mainCharacterOrTeam = record.indexOf("mainCharacterOrTeam");
int review = record.indexOf("review");
int tags = record.indexOf("tags");
ComicInfo comicInfo; ComicInfo comicInfo;
comicInfo.hash = query.value(hash).toString(); comicInfo.hash = query.value(hash).toString();
@ -1840,6 +1907,24 @@ ComicInfo DBHelper::getComicInfoFromQuery(QSqlQuery &query, const QString &idKey
comicInfo.manga = query.value(manga); comicInfo.manga = query.value(manga);
//-- //--
// new 9.13 fields
comicInfo.added = query.value(added);
comicInfo.type = query.value(type);
comicInfo.editor = query.value(editor);
comicInfo.imprint = query.value(imprint);
comicInfo.teams = query.value(teams);
comicInfo.locations = query.value(locations);
comicInfo.series = query.value(series);
comicInfo.alternateSeries = query.value(alternateSeries);
comicInfo.alternateNumber = query.value(alternateNumber);
comicInfo.alternateCount = query.value(alternateCount);
comicInfo.languageISO = query.value(languageISO);
comicInfo.seriesGroup = query.value(seriesGroup);
comicInfo.mainCharacterOrTeam = query.value(mainCharacterOrTeam);
comicInfo.review = query.value(review);
comicInfo.tags = query.value(tags);
//--
comicInfo.existOnDb = true; comicInfo.existOnDb = true;
return comicInfo; return comicInfo;

View File

@ -65,7 +65,7 @@ public:
static void update(ComicDB *comics, QSqlDatabase &db); static void update(ComicDB *comics, QSqlDatabase &db);
static void update(ComicInfo *comicInfo, QSqlDatabase &db); static void update(ComicInfo *comicInfo, QSqlDatabase &db);
static void updateRead(ComicInfo *comicInfo, QSqlDatabase &db); static void updateRead(ComicInfo *comicInfo, QSqlDatabase &db);
static void update(const Folder &folder, QSqlDatabase &db); static void update(const Folder &folder, QSqlDatabase &db); // only for finished/completed fields
static void propagateFolderUpdatesToParent(const Folder &folder, QSqlDatabase &db); static void propagateFolderUpdatesToParent(const Folder &folder, QSqlDatabase &db);
static Folder updateChildrenInfo(qulonglong folderId, QSqlDatabase &db); static Folder updateChildrenInfo(qulonglong folderId, QSqlDatabase &db);
static void updateChildrenInfo(QSqlDatabase &db); static void updateChildrenInfo(QSqlDatabase &db);
@ -89,11 +89,12 @@ public:
static QList<LibraryItem *> getComicsFromParent(qulonglong parentId, QSqlDatabase &db, bool sort = true); static QList<LibraryItem *> getComicsFromParent(qulonglong parentId, QSqlDatabase &db, bool sort = true);
static QList<Label> getLabels(qulonglong libraryId); static QList<Label> getLabels(qulonglong libraryId);
static void updateFolderTreeManga(qulonglong id, QSqlDatabase &db, bool manga); static void updateFolderTreeType(qulonglong id, QSqlDatabase &db, YACReader::FileType type);
// load // load
static Folder loadFolder(qulonglong id, QSqlDatabase &db); static Folder loadFolder(qulonglong id, QSqlDatabase &db);
static Folder loadFolder(const QString &folderName, qulonglong parentId, QSqlDatabase &db); static Folder loadFolder(const QString &folderName, qulonglong parentId, QSqlDatabase &db);
static void readFolderFromQuery(Folder &folder, QSqlQuery &query);
static ComicDB loadComic(qulonglong id, QSqlDatabase &db, bool &found); static ComicDB loadComic(qulonglong id, QSqlDatabase &db, bool &found);
static ComicDB loadComic(QString cname, QString cpath, QString chash, QSqlDatabase &database); static ComicDB loadComic(QString cname, QString cpath, QString chash, QSqlDatabase &database);
static ComicInfo loadComicInfo(QString hash, QSqlDatabase &db); static ComicInfo loadComicInfo(QString hash, QSqlDatabase &db);

View File

@ -232,7 +232,8 @@ qulonglong LibraryCreator::insertFolders()
for (i = _currentPathFolders.begin(); i != _currentPathFolders.end(); ++i) { for (i = _currentPathFolders.begin(); i != _currentPathFolders.end(); ++i) {
if (!(i->knownId)) { if (!(i->knownId)) {
i->setFather(currentId); i->setFather(currentId);
i->setManga(currentParent.isManga()); i->manga = currentParent.manga;
i->type = currentParent.type;
currentId = DBHelper::insert(&(*i), _database); // insertFolder(currentId,*i); currentId = DBHelper::insert(&(*i), _database); // insertFolder(currentId,*i);
i->setId(currentId); i->setId(currentId);
} else { } else {
@ -325,7 +326,8 @@ void LibraryCreator::insertComic(const QString &relativePath, const QFileInfo &f
} }
comic.parentId = _currentPathFolders.last().id; comic.parentId = _currentPathFolders.last().id;
comic.info.manga = _currentPathFolders.last().isManga(); comic.info.manga = _currentPathFolders.last().manga;
comic.info.type = QVariant::fromValue(_currentPathFolders.last().type); // TODO_METADATA test this
DBHelper::insert(&comic, _database, parsed); DBHelper::insert(&comic, _database, parsed);
} }
@ -539,14 +541,24 @@ void LibraryCreator::update(QDir dirS)
} else // same file } else // same file
{ {
if (fileInfoS.isFile() && !fileInfoD->isDir()) { if (fileInfoS.isFile() && !fileInfoD->isDir()) {
// TODO comprobar fechas + tamaño // TODO_METADATA use added,
// if(fileInfoS.lastModified()>fileInfoD.lastModified()) // if added < modified, do something
//{
// dirD.mkpath(_target+(QDir::cleanPath(fileInfoS.absolutePath()).remove(_source))); // copy metadata to avoid loosing it if the imported comics doesn't have it.
// emit(coverExtracted(QDir::cleanPath(fileInfoS.absoluteFilePath()).remove(_source)));
// ThumbnailCreator tc(QDir::cleanPath(fileInfoS.absoluteFilePath()),_target+(QDir::cleanPath(fileInfoS.absoluteFilePath()).remove(_source))+".jpg"); // DBHelper::removeFromDB(fileInfoD, _database);
// tc.create(); // #ifdef Q_OS_MAC
// } // QStringList src = _source.split("/");
// QString filePath = fileInfoS.absoluteFilePath();
// QStringList fp = filePath.split("/");
// for (int i = 0; i < src.count(); i++) {
// fp.removeFirst();
// }
// QString path = "/" + fp.join("/");
// #else
// QString path = QDir::cleanPath(fileInfoS.absoluteFilePath()).remove(_source);
// #endif
// insertComic(path, fileInfoS);
} }
i++; i++;
j++; j++;

View File

@ -31,7 +31,6 @@
#include "library_creator.h" #include "library_creator.h"
#include "package_manager.h" #include "package_manager.h"
#include "xml_info_library_scanner.h" #include "xml_info_library_scanner.h"
#include "comic_flow_widget.h"
#include "create_library_dialog.h" #include "create_library_dialog.h"
#include "rename_library_dialog.h" #include "rename_library_dialog.h"
#include "properties_dialog.h" #include "properties_dialog.h"
@ -44,10 +43,7 @@
#include "help_about_dialog.h" #include "help_about_dialog.h"
#include "server_config_dialog.h" #include "server_config_dialog.h"
#include "comic_model.h" #include "comic_model.h"
#include "yacreader_tool_bar_stretch.h"
#include "yacreader_table_view.h"
#include "yacreader_dark_menu.h"
#include "yacreader_titled_toolbar.h" #include "yacreader_titled_toolbar.h"
#include "yacreader_main_toolbar.h" #include "yacreader_main_toolbar.h"
@ -587,18 +583,35 @@ void LibraryWindow::createActions()
setAsNonReadAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SET_AS_NON_READ_ACTION_YL)); setAsNonReadAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SET_AS_NON_READ_ACTION_YL));
setAsNonReadAction->setIcon(QIcon(":/images/comics_view_toolbar/setUnread.svg")); setAsNonReadAction->setIcon(QIcon(":/images/comics_view_toolbar/setUnread.svg"));
setMangaAction = new QAction(tr("Set as manga"), this); setMangaAction = new QAction(tr("manga"), this);
setMangaAction->setToolTip(tr("Set issue as manga")); setMangaAction->setToolTip(tr("Set issue as manga"));
setMangaAction->setData(SET_AS_MANGA_ACTION_YL); setMangaAction->setData(SET_AS_MANGA_ACTION_YL);
setMangaAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SET_AS_MANGA_ACTION_YL)); setMangaAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SET_AS_MANGA_ACTION_YL));
setMangaAction->setIcon(QIcon(":/images/comics_view_toolbar/setManga.svg")); setMangaAction->setIcon(QIcon(":/images/comics_view_toolbar/setManga.svg"));
setNormalAction = new QAction(tr("Set as normal"), this); setNormalAction = new QAction(tr("comic"), this);
setNormalAction->setToolTip(tr("Set issue as normal")); setNormalAction->setToolTip(tr("Set issue as normal"));
setNormalAction->setData(SET_AS_NORMAL_ACTION_YL); setNormalAction->setData(SET_AS_NORMAL_ACTION_YL);
setNormalAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SET_AS_NORMAL_ACTION_YL)); setNormalAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SET_AS_NORMAL_ACTION_YL));
setNormalAction->setIcon(QIcon(":/images/comics_view_toolbar/setNormal.svg")); setNormalAction->setIcon(QIcon(":/images/comics_view_toolbar/setNormal.svg"));
setWesternMangaAction = new QAction(tr("western manga"), this);
setWesternMangaAction->setToolTip(tr("Set issue as western manga"));
setWesternMangaAction->setData(SET_AS_WESTERN_MANGA_ACTION_YL);
setWesternMangaAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SET_AS_WESTERN_MANGA_ACTION_YL));
// setWesternMangaAction->setIcon(QIcon(":/images/comics_view_toolbar/setWesternManga.svg"));
setWebComicAction = new QAction(tr("web comic"), this);
setWebComicAction->setToolTip(tr("Set issue as web comic"));
setWebComicAction->setData(SET_AS_WEB_COMIC_ACTION_YL);
setWebComicAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SET_AS_WEB_COMIC_ACTION_YL));
// setWebComicAction->setIcon(QIcon(":/images/comics_view_toolbar/setWebComic.svg"));
setYonkomaAction = new QAction(tr("yonkoma"), this);
setYonkomaAction->setToolTip(tr("Set issue as yonkoma"));
setYonkomaAction->setData(SET_AS_YONKOMA_ACTION_YL);
setYonkomaAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SET_AS_YONKOMA_ACTION_YL));
/*setAllAsReadAction = new QAction(tr("Set all as read"),this); /*setAllAsReadAction = new QAction(tr("Set all as read"),this);
setAllAsReadAction->setToolTip(tr("Set all comics as read")); setAllAsReadAction->setToolTip(tr("Set all comics as read"));
setAllAsReadAction->setIcon(QIcon(":/images/comics_view_toolbar/setAllRead.png")); setAllAsReadAction->setIcon(QIcon(":/images/comics_view_toolbar/setAllRead.png"));
@ -722,15 +735,30 @@ void LibraryWindow::createActions()
setFolderAsUnreadAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SET_FOLDER_AS_UNREAD_ACTION_YL)); setFolderAsUnreadAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SET_FOLDER_AS_UNREAD_ACTION_YL));
setFolderAsMangaAction = new QAction(this); setFolderAsMangaAction = new QAction(this);
setFolderAsMangaAction->setText(tr("Set as manga")); setFolderAsMangaAction->setText(tr("manga"));
setFolderAsMangaAction->setData(SET_FOLDER_AS_MANGA_ACTION_YL); setFolderAsMangaAction->setData(SET_FOLDER_AS_MANGA_ACTION_YL);
setFolderAsMangaAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SET_FOLDER_AS_MANGA_ACTION_YL)); setFolderAsMangaAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SET_FOLDER_AS_MANGA_ACTION_YL));
setFolderAsNormalAction = new QAction(this); setFolderAsNormalAction = new QAction(this);
setFolderAsNormalAction->setText(tr("Set as comic")); setFolderAsNormalAction->setText(tr("comic"));
setFolderAsNormalAction->setData(SET_FOLDER_AS_NORMAL_ACTION_YL); setFolderAsNormalAction->setData(SET_FOLDER_AS_NORMAL_ACTION_YL);
setFolderAsNormalAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SET_FOLDER_AS_NORMAL_ACTION_YL)); setFolderAsNormalAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SET_FOLDER_AS_NORMAL_ACTION_YL));
setFolderAsWesternMangaAction = new QAction(this);
setFolderAsWesternMangaAction->setText(tr("western manga (left to right)"));
setFolderAsWesternMangaAction->setData(SET_FOLDER_AS_WESTERN_MANGA_ACTION_YL);
setFolderAsWesternMangaAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SET_FOLDER_AS_WESTERN_MANGA_ACTION_YL));
setFolderAsWebComicAction = new QAction(this);
setFolderAsWebComicAction->setText(tr("web comic"));
setFolderAsWebComicAction->setData(SET_FOLDER_AS_WEB_COMIC_ACTION_YL);
setFolderAsWebComicAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SET_FOLDER_AS_WEB_COMIC_ACTION_YL));
setFolderAsYonkomaAction = new QAction(this);
setFolderAsYonkomaAction->setText(tr("yonkoma"));
setFolderAsYonkomaAction->setData(SET_FOLDER_AS_YONKOMA_ACTION_YL);
setFolderAsYonkomaAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SET_FOLDER_AS_YONKOMA_ACTION_YL));
//---- //----
openContainingFolderComicAction = new QAction(this); openContainingFolderComicAction = new QAction(this);
@ -867,6 +895,9 @@ void LibraryWindow::createActions()
this->addAction(setFolderAsUnreadAction); this->addAction(setFolderAsUnreadAction);
this->addAction(setFolderAsMangaAction); this->addAction(setFolderAsMangaAction);
this->addAction(setFolderAsNormalAction); this->addAction(setFolderAsNormalAction);
this->addAction(setFolderAsWesternMangaAction);
this->addAction(setFolderAsWebComicAction);
this->addAction(setFolderAsYonkomaAction);
this->addAction(deleteMetadataAction); this->addAction(deleteMetadataAction);
this->addAction(rescanXMLFromCurrentFolderAction); this->addAction(rescanXMLFromCurrentFolderAction);
#ifndef Q_OS_MAC #ifndef Q_OS_MAC
@ -891,6 +922,9 @@ void LibraryWindow::disableComicsActions(bool disabled)
setAsNonReadAction->setDisabled(disabled); setAsNonReadAction->setDisabled(disabled);
setNormalAction->setDisabled(disabled); setNormalAction->setDisabled(disabled);
setMangaAction->setDisabled(disabled); setMangaAction->setDisabled(disabled);
setWebComicAction->setDisabled(disabled);
setWesternMangaAction->setDisabled(disabled);
setYonkomaAction->setDisabled(disabled);
// setAllAsReadAction->setDisabled(disabled); // setAllAsReadAction->setDisabled(disabled);
// setAllAsNonReadAction->setDisabled(disabled); // setAllAsNonReadAction->setDisabled(disabled);
showHideMarksAction->setDisabled(disabled); showHideMarksAction->setDisabled(disabled);
@ -1009,8 +1043,15 @@ void LibraryWindow::createToolBars()
editInfoToolBar->addSeparator(); editInfoToolBar->addSeparator();
editInfoToolBar->addAction(setNormalAction); auto setTypeToolButton = new QToolButton();
editInfoToolBar->addAction(setMangaAction); setTypeToolButton->addAction(setNormalAction);
setTypeToolButton->addAction(setMangaAction);
setTypeToolButton->addAction(setWesternMangaAction);
setTypeToolButton->addAction(setWebComicAction);
setTypeToolButton->addAction(setYonkomaAction);
setTypeToolButton->setPopupMode(QToolButton::InstantPopup);
setTypeToolButton->setDefaultAction(setNormalAction);
editInfoToolBar->addWidget(setTypeToolButton);
editInfoToolBar->addSeparator(); editInfoToolBar->addSeparator();
@ -1037,8 +1078,11 @@ void LibraryWindow::createMenus()
foldersView->addAction(setFolderAsUnreadAction); foldersView->addAction(setFolderAsUnreadAction);
YACReader::addSperator(foldersView); YACReader::addSperator(foldersView);
foldersView->addAction(setFolderAsMangaAction);
foldersView->addAction(setFolderAsNormalAction); foldersView->addAction(setFolderAsNormalAction);
foldersView->addAction(setFolderAsMangaAction);
foldersView->addAction(setFolderAsWesternMangaAction);
foldersView->addAction(setFolderAsWebComicAction);
foldersView->addAction(setFolderAsYonkomaAction);
selectedLibrary->addAction(updateLibraryAction); selectedLibrary->addAction(updateLibraryAction);
selectedLibrary->addAction(renameLibraryAction); selectedLibrary->addAction(renameLibraryAction);
@ -1093,8 +1137,11 @@ void LibraryWindow::createMenus()
folderMenu->addAction(setFolderAsReadAction); folderMenu->addAction(setFolderAsReadAction);
folderMenu->addAction(setFolderAsUnreadAction); folderMenu->addAction(setFolderAsUnreadAction);
folderMenu->addSeparator(); folderMenu->addSeparator();
foldersView->addAction(setFolderAsMangaAction);
foldersView->addAction(setFolderAsNormalAction); foldersView->addAction(setFolderAsNormalAction);
foldersView->addAction(setFolderAsMangaAction);
foldersView->addAction(setFolderAsWesternMangaAction);
foldersView->addAction(setFolderAsWebComicAction);
foldersView->addAction(setFolderAsYonkomaAction);
// comic // comic
QMenu *comicMenu = new QMenu(tr("Comic")); QMenu *comicMenu = new QMenu(tr("Comic"));
@ -1185,10 +1232,22 @@ void LibraryWindow::createConnections()
connect(openLibraryAction, &QAction::triggered, this, &LibraryWindow::showAddLibrary); connect(openLibraryAction, &QAction::triggered, this, &LibraryWindow::showAddLibrary);
connect(setAsReadAction, &QAction::triggered, this, &LibraryWindow::setCurrentComicReaded); connect(setAsReadAction, &QAction::triggered, this, &LibraryWindow::setCurrentComicReaded);
connect(setAsNonReadAction, &QAction::triggered, this, &LibraryWindow::setCurrentComicUnreaded); connect(setAsNonReadAction, &QAction::triggered, this, &LibraryWindow::setCurrentComicUnreaded);
connect(setNormalAction, &QAction::triggered, this, &LibraryWindow::setSelectedComicsAsNormal);
connect(setMangaAction, &QAction::triggered, this, &LibraryWindow::setSelectedComicsAsManga); connect(setNormalAction, &QAction::triggered, this, [=]() {
// connect(setAllAsReadAction,SIGNAL(triggered()),this,SLOT(setComicsReaded())); setSelectedComicsType(FileType::Comic);
// connect(setAllAsNonReadAction,SIGNAL(triggered()),this,SLOT(setComicsUnreaded())); });
connect(setMangaAction, &QAction::triggered, this, [=]() {
setSelectedComicsType(FileType::Manga);
});
connect(setWesternMangaAction, &QAction::triggered, this, [=]() {
setSelectedComicsType(FileType::WesternManga);
});
connect(setWebComicAction, &QAction::triggered, this, [=]() {
setSelectedComicsType(FileType::WebComic);
});
connect(setYonkomaAction, &QAction::triggered, this, [=]() {
setSelectedComicsType(FileType::Yonkoma);
});
// comicsInfoManagement // comicsInfoManagement
connect(exportComicsInfoAction, &QAction::triggered, this, &LibraryWindow::showExportComicsInfo); connect(exportComicsInfoAction, &QAction::triggered, this, &LibraryWindow::showExportComicsInfo);
@ -1241,8 +1300,22 @@ void LibraryWindow::createConnections()
connect(setFolderAsReadAction, &QAction::triggered, this, &LibraryWindow::setFolderAsRead); connect(setFolderAsReadAction, &QAction::triggered, this, &LibraryWindow::setFolderAsRead);
connect(setFolderAsUnreadAction, &QAction::triggered, this, &LibraryWindow::setFolderAsUnread); connect(setFolderAsUnreadAction, &QAction::triggered, this, &LibraryWindow::setFolderAsUnread);
connect(openContainingFolderAction, &QAction::triggered, this, &LibraryWindow::openContainingFolder); connect(openContainingFolderAction, &QAction::triggered, this, &LibraryWindow::openContainingFolder);
connect(setFolderAsMangaAction, &QAction::triggered, this, &LibraryWindow::setFolderAsManga);
connect(setFolderAsNormalAction, &QAction::triggered, this, &LibraryWindow::setFolderAsNormal); connect(setFolderAsMangaAction, &QAction::triggered, this, [=]() {
setFolderType(FileType::Manga);
});
connect(setFolderAsNormalAction, &QAction::triggered, this, [=]() {
setFolderType(FileType::Comic);
});
connect(setFolderAsWesternMangaAction, &QAction::triggered, this, [=]() {
setFolderType(FileType::WesternManga);
});
connect(setFolderAsWebComicAction, &QAction::triggered, this, [=]() {
setFolderType(FileType::WebComic);
});
connect(setFolderAsYonkomaAction, &QAction::triggered, this, [=]() {
setFolderType(FileType::Yonkoma);
});
connect(resetComicRatingAction, &QAction::triggered, this, &LibraryWindow::resetComicRating); connect(resetComicRatingAction, &QAction::triggered, this, &LibraryWindow::resetComicRating);
@ -1779,8 +1852,13 @@ void LibraryWindow::showComicsViewContextMenu(const QPoint &point)
menu.addAction(setAsReadAction); menu.addAction(setAsReadAction);
menu.addAction(setAsNonReadAction); menu.addAction(setAsNonReadAction);
menu.addSeparator(); menu.addSeparator();
menu.addAction(setNormalAction); auto typeMenu = new QMenu(tr("Set type"));
menu.addAction(setMangaAction); menu.addMenu(typeMenu);
typeMenu->addAction(setNormalAction);
typeMenu->addAction(setMangaAction);
typeMenu->addAction(setWesternMangaAction);
typeMenu->addAction(setWebComicAction);
typeMenu->addAction(setYonkomaAction);
menu.addSeparator(); menu.addSeparator();
menu.addAction(deleteMetadataAction); menu.addAction(deleteMetadataAction);
menu.addSeparator(); menu.addSeparator();
@ -1817,8 +1895,13 @@ void LibraryWindow::showComicsItemContextMenu(const QPoint &point)
menu.addAction(setAsReadAction); menu.addAction(setAsReadAction);
menu.addAction(setAsNonReadAction); menu.addAction(setAsNonReadAction);
menu.addSeparator(); menu.addSeparator();
menu.addAction(setNormalAction); auto typeMenu = new QMenu(tr("Set type"));
menu.addAction(setMangaAction); menu.addMenu(typeMenu);
typeMenu->addAction(setNormalAction);
typeMenu->addAction(setMangaAction);
typeMenu->addAction(setWesternMangaAction);
typeMenu->addAction(setWebComicAction);
typeMenu->addAction(setYonkomaAction);
menu.addSeparator(); menu.addSeparator();
menu.addAction(deleteMetadataAction); menu.addAction(deleteMetadataAction);
menu.addSeparator(); menu.addSeparator();
@ -1857,30 +1940,43 @@ void LibraryWindow::showGridFoldersContextMenu(QPoint point, Folder folder)
setFolderAsUnreadAction->setText(tr("Set as unread")); setFolderAsUnreadAction->setText(tr("Set as unread"));
auto setFolderAsMangaAction = new QAction(); auto setFolderAsMangaAction = new QAction();
setFolderAsMangaAction->setText(tr("Set as manga")); setFolderAsMangaAction->setText(tr("manga"));
auto setFolderAsNormalAction = new QAction(); auto setFolderAsNormalAction = new QAction();
setFolderAsNormalAction->setText(tr("Set as comic")); setFolderAsNormalAction->setText(tr("comic"));
auto setFolderAsWesternMangaAction = new QAction();
setFolderAsMangaAction->setText(tr("manga (or left to right)"));
auto setFolderAsWebComicAction = new QAction();
setFolderAsNormalAction->setText(tr("web comic"));
auto setFolderAs4KomaAction = new QAction();
setFolderAsMangaAction->setText(tr("4koma (or top to botom"));
menu.addAction(openContainingFolderAction); menu.addAction(openContainingFolderAction);
menu.addAction(updateFolderAction); menu.addAction(updateFolderAction);
menu.addSeparator(); menu.addSeparator();
menu.addAction(rescanLibraryForXMLInfoAction); menu.addAction(rescanLibraryForXMLInfoAction);
menu.addSeparator(); menu.addSeparator();
if (folder.isCompleted()) if (folder.completed)
menu.addAction(setFolderAsNotCompletedAction); menu.addAction(setFolderAsNotCompletedAction);
else else
menu.addAction(setFolderAsCompletedAction); menu.addAction(setFolderAsCompletedAction);
menu.addSeparator(); menu.addSeparator();
if (folder.isFinished()) if (folder.finished)
menu.addAction(setFolderAsUnreadAction); menu.addAction(setFolderAsUnreadAction);
else else
menu.addAction(setFolderAsReadAction); menu.addAction(setFolderAsReadAction);
menu.addSeparator(); menu.addSeparator();
if (folder.isManga())
menu.addAction(setFolderAsNormalAction); auto typeMenu = new QMenu(tr("Set type"));
else menu.addMenu(typeMenu);
menu.addAction(setFolderAsMangaAction); typeMenu->addAction(setFolderAsNormalAction);
typeMenu->addAction(setFolderAsMangaAction);
typeMenu->addAction(setFolderAsWesternMangaAction);
typeMenu->addAction(setFolderAsWebComicAction);
typeMenu->addAction(setFolderAs4KomaAction);
auto subfolderModel = contentViewsManager->folderContentView->currentFolderModel(); auto subfolderModel = contentViewsManager->folderContentView->currentFolderModel();
@ -1910,12 +2006,24 @@ void LibraryWindow::showGridFoldersContextMenu(QPoint point, Folder folder)
subfolderModel->updateFolderFinishedStatus(QModelIndexList() << subfolderModel->getIndexFromFolder(folder), false); subfolderModel->updateFolderFinishedStatus(QModelIndexList() << subfolderModel->getIndexFromFolder(folder), false);
}); });
connect(setFolderAsMangaAction, &QAction::triggered, this, [=]() { connect(setFolderAsMangaAction, &QAction::triggered, this, [=]() {
foldersModel->updateFolderManga(QModelIndexList() << foldersModel->getIndexFromFolder(folder), true); foldersModel->updateFolderType(QModelIndexList() << foldersModel->getIndexFromFolder(folder), FileType::Manga);
subfolderModel->updateFolderManga(QModelIndexList() << subfolderModel->getIndexFromFolder(folder), true); subfolderModel->updateFolderType(QModelIndexList() << foldersModel->getIndexFromFolder(folder), FileType::Manga);
}); });
connect(setFolderAsNormalAction, &QAction::triggered, this, [=]() { connect(setFolderAsNormalAction, &QAction::triggered, this, [=]() {
foldersModel->updateFolderManga(QModelIndexList() << foldersModel->getIndexFromFolder(folder), false); foldersModel->updateFolderType(QModelIndexList() << foldersModel->getIndexFromFolder(folder), FileType::Comic);
subfolderModel->updateFolderManga(QModelIndexList() << subfolderModel->getIndexFromFolder(folder), false); subfolderModel->updateFolderType(QModelIndexList() << foldersModel->getIndexFromFolder(folder), FileType::Comic);
});
connect(setFolderAsWesternMangaAction, &QAction::triggered, this, [=]() {
foldersModel->updateFolderType(QModelIndexList() << foldersModel->getIndexFromFolder(folder), FileType::WesternManga);
subfolderModel->updateFolderType(QModelIndexList() << foldersModel->getIndexFromFolder(folder), FileType::WesternManga);
});
connect(setFolderAsWebComicAction, &QAction::triggered, this, [=]() {
foldersModel->updateFolderType(QModelIndexList() << foldersModel->getIndexFromFolder(folder), FileType::WebComic);
subfolderModel->updateFolderType(QModelIndexList() << foldersModel->getIndexFromFolder(folder), FileType::WebComic);
});
connect(setFolderAs4KomaAction, &QAction::triggered, this, [=]() {
foldersModel->updateFolderType(QModelIndexList() << foldersModel->getIndexFromFolder(folder), FileType::Yonkoma);
subfolderModel->updateFolderType(QModelIndexList() << foldersModel->getIndexFromFolder(folder), FileType::Yonkoma);
}); });
menu.exec(contentViewsManager->folderContentView->mapToGlobal(point)); menu.exec(contentViewsManager->folderContentView->mapToGlobal(point));
@ -2091,14 +2199,9 @@ void LibraryWindow::setCurrentComicUnreaded()
this->setCurrentComicsStatusReaded(YACReader::Unread); this->setCurrentComicsStatusReaded(YACReader::Unread);
} }
void LibraryWindow::setSelectedComicsAsNormal() void LibraryWindow::setSelectedComicsType(FileType type)
{ {
comicsModel->setComicsManga(getSelectedComics(), false); comicsModel->setComicsType(getSelectedComics(), type);
}
void LibraryWindow::setSelectedComicsAsManga()
{
comicsModel->setComicsManga(getSelectedComics(), true);
} }
void LibraryWindow::createLibrary() void LibraryWindow::createLibrary()
@ -2109,7 +2212,7 @@ void LibraryWindow::createLibrary()
void LibraryWindow::create(QString source, QString dest, QString name) void LibraryWindow::create(QString source, QString dest, QString name)
{ {
QLOG_INFO() << QString("About to create a library from '%1' to '%2' with name '%3'").arg(source).arg(dest).arg(name); QLOG_INFO() << QString("About to create a library from '%1' to '%2' with name '%3'").arg(source, dest, name);
libraryCreator->createLibrary(source, dest); libraryCreator->createLibrary(source, dest);
libraryCreator->start(); libraryCreator->start();
_lastAdded = name; _lastAdded = name;
@ -2625,14 +2728,9 @@ void LibraryWindow::setFolderAsUnread()
foldersModel->updateFolderFinishedStatus(QModelIndexList() << foldersModelProxy->mapToSource(foldersView->currentIndex()), false); foldersModel->updateFolderFinishedStatus(QModelIndexList() << foldersModelProxy->mapToSource(foldersView->currentIndex()), false);
} }
void LibraryWindow::setFolderAsManga() void LibraryWindow::setFolderType(FileType type)
{ {
foldersModel->updateFolderManga(QModelIndexList() << foldersModelProxy->mapToSource(foldersView->currentIndex()), true); foldersModel->updateFolderType(QModelIndexList() << foldersModelProxy->mapToSource(foldersView->currentIndex()), type);
}
void LibraryWindow::setFolderAsNormal()
{
foldersModel->updateFolderManga(QModelIndexList() << foldersModelProxy->mapToSource(foldersView->currentIndex()), false);
} }
void LibraryWindow::exportLibrary(QString destPath) void LibraryWindow::exportLibrary(QString destPath)
@ -2872,10 +2970,9 @@ void LibraryWindow::showFoldersContextMenu(const QPoint &point)
bool isCompleted = sourceMI.data(FolderModel::CompletedRole).toBool(); bool isCompleted = sourceMI.data(FolderModel::CompletedRole).toBool();
bool isRead = sourceMI.data(FolderModel::FinishedRole).toBool(); bool isRead = sourceMI.data(FolderModel::FinishedRole).toBool();
bool isManga = sourceMI.data(FolderModel::MangaRole).toBool();
QMenu menu; QMenu menu;
// QMenu * folderMenu = new QMenu(tr("Folder"));
menu.addAction(openContainingFolderAction); menu.addAction(openContainingFolderAction);
menu.addAction(updateFolderAction); menu.addAction(updateFolderAction);
menu.addSeparator(); //------------------------------- menu.addSeparator(); //-------------------------------
@ -2891,10 +2988,13 @@ void LibraryWindow::showFoldersContextMenu(const QPoint &point)
else else
menu.addAction(setFolderAsReadAction); menu.addAction(setFolderAsReadAction);
menu.addSeparator(); //------------------------------- menu.addSeparator(); //-------------------------------
if (isManga) auto typeMenu = new QMenu(tr("Set type"));
menu.addAction(setFolderAsNormalAction); menu.addMenu(typeMenu);
else typeMenu->addAction(setFolderAsNormalAction);
menu.addAction(setFolderAsMangaAction); typeMenu->addAction(setFolderAsMangaAction);
typeMenu->addAction(setFolderAsWesternMangaAction);
typeMenu->addAction(setFolderAsWebComicAction);
typeMenu->addAction(setFolderAsYonkomaAction);
menu.exec(foldersView->mapToGlobal(point)); menu.exec(foldersView->mapToGlobal(point));
} }

View File

@ -197,8 +197,12 @@ public:
//-- //--
QAction *setFolderAsReadAction; QAction *setFolderAsReadAction;
QAction *setFolderAsUnreadAction; QAction *setFolderAsUnreadAction;
//--
QAction *setFolderAsMangaAction; QAction *setFolderAsMangaAction;
QAction *setFolderAsNormalAction; QAction *setFolderAsNormalAction;
QAction *setFolderAsWesternMangaAction;
QAction *setFolderAsWebComicAction;
QAction *setFolderAsYonkomaAction;
QAction *openContainingFolderComicAction; QAction *openContainingFolderComicAction;
QAction *setAsReadAction; QAction *setAsReadAction;
@ -206,6 +210,9 @@ public:
QAction *setMangaAction; QAction *setMangaAction;
QAction *setNormalAction; QAction *setNormalAction;
QAction *setWesternMangaAction;
QAction *setWebComicAction;
QAction *setYonkomaAction;
// QAction * setAllAsReadAction; // QAction * setAllAsReadAction;
// QAction * setAllAsNonReadAction; // QAction * setAllAsNonReadAction;
@ -340,8 +347,7 @@ public slots:
void setFolderAsCompleted(); void setFolderAsCompleted();
void setFolderAsRead(); void setFolderAsRead();
void setFolderAsUnread(); void setFolderAsUnread();
void setFolderAsManga(); void setFolderType(FileType type);
void setFolderAsNormal();
void openContainingFolderComic(); void openContainingFolderComic();
void deleteCurrentLibrary(); void deleteCurrentLibrary();
void removeLibrary(); void removeLibrary();
@ -368,8 +374,7 @@ public slots:
void setCurrentComicsStatusReaded(YACReaderComicReadStatus readStatus); void setCurrentComicsStatusReaded(YACReaderComicReadStatus readStatus);
void setCurrentComicReaded(); void setCurrentComicReaded();
void setCurrentComicUnreaded(); void setCurrentComicUnreaded();
void setSelectedComicsAsNormal(); void setSelectedComicsType(FileType type);
void setSelectedComicsAsManga();
void showExportComicsInfo(); void showExportComicsInfo();
void showImportComicsInfo(); void showImportComicsInfo();
void asignNumbers(); void asignNumbers();

View File

@ -144,8 +144,8 @@ void PropertiesDialog::createGeneralInfoBox()
auto number = new QHBoxLayout; auto number = new QHBoxLayout;
number->addWidget(numberEdit = new YACReaderFieldEdit()); number->addWidget(numberEdit = new YACReaderFieldEdit());
numberValidator.setBottom(0); // numberValidator.setBottom(0);
numberEdit->setValidator(&numberValidator); // numberEdit->setValidator(&numberValidator);
number->addWidget(new QLabel("Bis:")); number->addWidget(new QLabel("Bis:"));
number->addWidget(isBisCheck = new QCheckBox()); number->addWidget(isBisCheck = new QCheckBox());
number->addWidget(new QLabel(tr("of:"))); number->addWidget(new QLabel(tr("of:")));
@ -163,8 +163,8 @@ void PropertiesDialog::createGeneralInfoBox()
arc->addWidget(storyArcEdit = new YACReaderFieldEdit()); arc->addWidget(storyArcEdit = new YACReaderFieldEdit());
arc->addWidget(new QLabel(tr("Arc number:"))); arc->addWidget(new QLabel(tr("Arc number:")));
arc->addWidget(arcNumberEdit = new YACReaderFieldEdit()); arc->addWidget(arcNumberEdit = new YACReaderFieldEdit());
arcNumberValidator.setBottom(0); // arcNumberValidator.setBottom(0);
arcNumberEdit->setValidator(&arcNumberValidator); // arcNumberEdit->setValidator(&arcNumberValidator);
arc->addWidget(new QLabel(tr("of:"))); arc->addWidget(new QLabel(tr("of:")));
arc->addWidget(arcCountEdit = new YACReaderFieldEdit()); arc->addWidget(arcCountEdit = new YACReaderFieldEdit());
arcCountValidator.setBottom(0); arcCountValidator.setBottom(0);

View File

@ -6,8 +6,8 @@ QString YACReaderServerDataHelper::folderToYSFormat(const qulonglong libraryId,
.arg(libraryId) .arg(libraryId)
.arg(folder.id) .arg(folder.id)
.arg(folder.name) .arg(folder.name)
.arg(folder.getNumChildren()) .arg(folder.numChildren)
.arg(folder.getFirstChildHash()); .arg(folder.firstChildHash);
} }
QString YACReaderServerDataHelper::comicToYSFormat(const qulonglong libraryId, const ComicDB &comic) QString YACReaderServerDataHelper::comicToYSFormat(const qulonglong libraryId, const ComicDB &comic)
@ -31,8 +31,15 @@ QJsonObject YACReaderServerDataHelper::folderToJSON(const qulonglong libraryId,
json["id"] = QString::number(folder.id); json["id"] = QString::number(folder.id);
json["library_id"] = QString::number(libraryId); json["library_id"] = QString::number(libraryId);
json["folder_name"] = folder.name; json["folder_name"] = folder.name;
json["num_children"] = folder.getNumChildren(); json["num_children"] = folder.numChildren;
json["first_comic_hash"] = folder.getFirstChildHash(); json["first_comic_hash"] = folder.firstChildHash;
// 9.13
json["finished"] = folder.finished;
json["completed"] = folder.completed;
json["custom_image"] = folder.customImage;
json["file_type"] = static_cast<typename std::underlying_type<YACReader::FileType>::type>(folder.type);
json["added"] = folder.added;
json["updated"] = folder.updated;
return json; return json;
} }
@ -47,14 +54,18 @@ QJsonObject YACReaderServerDataHelper::comicToJSON(const qulonglong libraryId, c
json["file_name"] = comic.name; json["file_name"] = comic.name;
json["file_size"] = QString::number(comic.getFileSize()); json["file_size"] = QString::number(comic.getFileSize());
json["hash"] = comic.info.hash; json["hash"] = comic.info.hash;
json["cover_page"] = comic.info.coverPage.toInt(); // 9.13
json["current_page"] = comic.info.currentPage; json["current_page"] = comic.info.currentPage;
json["num_pages"] = comic.info.numPages.toInt(); json["num_pages"] = comic.info.numPages.toInt();
json["read"] = comic.info.read; json["read"] = comic.info.read;
json["cover_size_ratio"] = comic.info.coverSizeRatio.toFloat(); json["cover_size_ratio"] = comic.info.coverSizeRatio.toFloat();
json["title"] = comic.info.title.toString(); json["title"] = comic.info.title.toString();
json["number"] = comic.info.number.toInt(); json["number"] = comic.info.number.toInt(); // 9.13 legacy, kept for compatibility with old clients
json["universal_number"] = comic.info.number.toString(); // 9.13, text based number
json["last_time_opened"] = comic.info.lastTimeOpened.toLongLong(); json["last_time_opened"] = comic.info.lastTimeOpened.toLongLong();
json["manga"] = comic.info.manga.toBool(); auto type = comic.info.type.value<YACReader::FileType>();
json["manga"] = type == YACReader::FileType::Manga; // legacy, kept for compatibility with old clients
json["file_type"] = comic.info.type.toInt(); // 9.13
return json; return json;
} }
@ -70,6 +81,39 @@ QJsonObject YACReaderServerDataHelper::fullComicToJSON(const qulonglong libraryI
json["synopsis"] = comic.info.synopsis.toString(); json["synopsis"] = comic.info.synopsis.toString();
// 9.13
json["count"] = comic.info.count.toInt();
json["story_arc"] = comic.info.storyArc.toString();
json["arc_number"] = comic.info.arcNumber.toString();
json["arc_count"] = comic.info.arcCount.toInt();
json["writer"] = comic.info.writer.toString();
json["penciller"] = comic.info.penciller.toString();
json["inker"] = comic.info.inker.toString();
json["colorist"] = comic.info.colorist.toString();
json["letterer"] = comic.info.letterer.toString();
json["cover_artist"] = comic.info.coverArtist.toString();
json["publisher"] = comic.info.publisher.toString();
json["format"] = comic.info.format.toString();
json["color"] = comic.info.color.toBool();
json["age_rating"] = comic.info.ageRating.toString();
json["editor"] = comic.info.editor.toString();
json["characters"] = comic.info.characters.toString();
json["notes"] = comic.info.notes.toString();
json["added"] = comic.info.added.toLongLong();
json["editor"] = comic.info.editor.toString();
json["imprint"] = comic.info.imprint.toString();
json["teams"] = comic.info.teams.toString();
json["locations"] = comic.info.locations.toString();
json["series"] = comic.info.series.toString();
json["alternate_series"] = comic.info.alternateSeries.toString();
json["alternate_number"] = comic.info.alternateNumber.toString();
json["alternate_count"] = comic.info.alternateCount.toInt();
json["language_iso"] = comic.info.languageISO.toString();
json["series_group"] = comic.info.seriesGroup.toString();
json["main_character_or_team"] = comic.info.mainCharacterOrTeam.toString();
json["review"] = comic.info.review.toString();
json["tags"] = comic.info.tags.toString();
return json; return json;
} }

View File

@ -118,6 +118,51 @@ QString ComicDB::toTXT()
if (!info.lastTimeOpened.isNull()) if (!info.lastTimeOpened.isNull())
txt.append(QString("lastTimeOpened:%1\r\n").arg(info.lastTimeOpened.toULongLong())); txt.append(QString("lastTimeOpened:%1\r\n").arg(info.lastTimeOpened.toULongLong()));
if (!info.added.isNull())
txt.append(QString("added:%1\r\n").arg(info.added.toULongLong()));
if (!info.type.isNull())
txt.append(QString("type:%1\r\n").arg(info.type.toInt()));
if (!info.editor.isNull())
txt.append(QString("editor:%1\r\n").arg(info.editor.toString()));
if (!info.imprint.isNull())
txt.append(QString("imprint:%1\r\n").arg(info.imprint.toString()));
if (!info.teams.isNull())
txt.append(QString("teams:%1\r\n").arg(info.teams.toString()));
if (!info.locations.isNull())
txt.append(QString("locations:%1\r\n").arg(info.locations.toString()));
if (!info.series.isNull())
txt.append(QString("series:%1\r\n").arg(info.series.toString()));
if (!info.alternateSeries.isNull())
txt.append(QString("alternateSeries:%1\r\n").arg(info.alternateSeries.toString()));
if (!info.alternateNumber.isNull())
txt.append(QString("alternateNumber:%1\r\n").arg(info.alternateNumber.toString()));
if (!info.alternateCount.isNull())
txt.append(QString("alternateCount:%1\r\n").arg(info.alternateCount.toString()));
if (!info.languageISO.isNull())
txt.append(QString("languageISO:%1\r\n").arg(info.languageISO.toString()));
if (!info.seriesGroup.isNull())
txt.append(QString("seriesGroup:%1\r\n").arg(info.seriesGroup.toString()));
if (!info.mainCharacterOrTeam.isNull())
txt.append(QString("mainCharacterOrTeam:%1\r\n").arg(info.mainCharacterOrTeam.toString()));
if (!info.review.isNull())
txt.append(QString("review:%1\r\n").arg(info.review.toString()));
if (!info.tags.isNull())
txt.append(QString("tags:%1\r\n").arg(info.tags.toString()));
return txt; return txt;
} }
@ -238,6 +283,22 @@ void ComicInfo::deleteMetadata()
characters = QVariant(); characters = QVariant();
notes = QVariant(); notes = QVariant();
// type = QVariant(); reset or not???
editor = QVariant();
imprint = QVariant();
teams = QVariant();
locations = QVariant();
series = QVariant();
alternateSeries = QVariant();
alternateNumber = QVariant();
alternateCount = QVariant();
languageISO = QVariant();
seriesGroup = QVariant();
mainCharacterOrTeam = QVariant();
review = QVariant();
// tags = QVariant(); reset or not???
comicVineID = QVariant(); comicVineID = QVariant();
} }
// the default operator= should work // the default operator= should work
@ -292,135 +353,25 @@ ComicInfo &ComicInfo::operator=(const ComicInfo &comicInfo)
coverSizeRatio = comicInfo.coverSizeRatio; coverSizeRatio = comicInfo.coverSizeRatio;
originalCoverSize = comicInfo.originalCoverSize; originalCoverSize = comicInfo.originalCoverSize;
added = comicInfo.added;
type = comicInfo.type;
editor = comicInfo.editor;
imprint = comicInfo.imprint;
teams = comicInfo.teams;
locations = comicInfo.locations;
series = comicInfo.series;
alternateSeries = comicInfo.alternateSeries;
alternateNumber = comicInfo.alternateNumber;
alternateCount = comicInfo.alternateCount;
languageISO = comicInfo.languageISO;
seriesGroup = comicInfo.seriesGroup;
mainCharacterOrTeam = comicInfo.mainCharacterOrTeam;
review = comicInfo.review;
tags = comicInfo.tags;
return *this; return *this;
} }
// set fields
/*
void ComicInfo::setTitle(QString value)
{
setValue(title,value);
}
void ComicInfo::setCoverPage(int value)
{
setValue(coverPage,value);
}
void ComicInfo::setNumPages(int value)
{
setValue(numPages,value);
}
void ComicInfo::setNumber(int value)
{
setValue(number,value);
}
void ComicInfo::setIsBis(bool value)
{
setValue(isBis,value);
}
void ComicInfo::setCount(int value)
{
setValue(count,value);
}
void ComicInfo::setVolume(QString value)
{
setValue(volume,value);
}
void ComicInfo::setStoryArc(QString value)
{
setValue(storyArc,value);
}
void ComicInfo::setArcNumber(int value)
{
setValue(arcNumber,value);
}
void ComicInfo::setArcCount(int value)
{
setValue(arcCount,value);
}
void ComicInfo::setGenere(QString value)
{
setValue(genere,value);
}
void ComicInfo::setWriter(QString value)
{
setValue(writer,value);
}
void ComicInfo::setPenciller(QString value)
{
setValue(penciller,value);
}
void ComicInfo::setInker(QString value)
{
setValue(inker,value);
}
void ComicInfo::setColorist(QString value)
{
setValue(colorist,value);
}
void ComicInfo::setLetterer(QString value)
{
setValue(letterer,value);
}
void ComicInfo::setCoverArtist(QString value)
{
setValue(coverArtist,value);
}
void ComicInfo::setDate(QString value)
{
setValue(date,value);
}
void ComicInfo::setPublisher(QString value)
{
setValue(publisher,value);
}
void ComicInfo::setFormat(QString value)
{
setValue(format,value);
}
void ComicInfo::setColor(bool value)
{
setValue(color,value);
}
void ComicInfo::setAgeRating(QString value)
{
setValue(ageRating,value);
}
void ComicInfo::setSynopsis(QString value)
{
setValue(synopsis,value);
}
void ComicInfo::setCharacters(QString value)
{
setValue(characters,value);
}
void ComicInfo::setNotes(QString value)
{
setValue(notes,value);
}*/
QPixmap ComicInfo::getCover(const QString &basePath) QPixmap ComicInfo::getCover(const QString &basePath)
{ {
if (cover.isNull()) { if (cover.isNull()) {
@ -494,6 +445,33 @@ QStringList ComicInfo::getCharacters()
return QStringList(); return QStringList();
} }
QStringList ComicInfo::getTeams()
{
if (teams.toString().length() > 0) {
return teams.toString().split("\n");
}
return QStringList();
}
QStringList ComicInfo::getLocations()
{
if (locations.toString().length() > 0) {
return locations.toString().split("\n");
}
return QStringList();
}
QStringList ComicInfo::getTags()
{
if (tags.toString().length() > 0) {
return tags.toString().split("\n");
}
return QStringList();
}
void ComicInfo::setRead(bool r) void ComicInfo::setRead(bool r)
{ {
if (r != read) { if (r != read) {
@ -599,6 +577,24 @@ QDataStream &operator<<(QDataStream &stream, const ComicInfo &comicInfo)
stream << comicInfo.coverSizeRatio; stream << comicInfo.coverSizeRatio;
stream << comicInfo.originalCoverSize; stream << comicInfo.originalCoverSize;
stream << comicInfo.added;
stream << comicInfo.type;
stream << comicInfo.added;
stream << comicInfo.type;
stream << comicInfo.editor;
stream << comicInfo.imprint;
stream << comicInfo.teams;
stream << comicInfo.locations;
stream << comicInfo.series;
stream << comicInfo.alternateSeries;
stream << comicInfo.alternateNumber;
stream << comicInfo.alternateCount;
stream << comicInfo.languageISO;
stream << comicInfo.seriesGroup;
stream << comicInfo.mainCharacterOrTeam;
stream << comicInfo.review;
stream << comicInfo.tags;
return stream; return stream;
} }
@ -661,5 +657,23 @@ QDataStream &operator>>(QDataStream &stream, ComicInfo &comicInfo)
stream >> comicInfo.coverSizeRatio; stream >> comicInfo.coverSizeRatio;
stream >> comicInfo.originalCoverSize; stream >> comicInfo.originalCoverSize;
stream >> comicInfo.added;
stream >> comicInfo.type;
stream >> comicInfo.added;
stream >> comicInfo.type;
stream >> comicInfo.editor;
stream >> comicInfo.imprint;
stream >> comicInfo.teams;
stream >> comicInfo.locations;
stream >> comicInfo.series;
stream >> comicInfo.alternateSeries;
stream >> comicInfo.alternateNumber;
stream >> comicInfo.alternateCount;
stream >> comicInfo.languageISO;
stream >> comicInfo.seriesGroup;
stream >> comicInfo.mainCharacterOrTeam;
stream >> comicInfo.review;
stream >> comicInfo.tags;
return stream; return stream;
} }

View File

@ -33,7 +33,7 @@ public:
QString hash; QString hash;
bool existOnDb; bool existOnDb;
int rating; int rating; // TODO_METADATA: change to float
bool hasBeenOpened; bool hasBeenOpened;
@ -52,13 +52,13 @@ public:
QVariant coverPage; // int QVariant coverPage; // int
QVariant numPages; // int QVariant numPages; // int
QVariant number; // int QVariant number; // string (changed in 9.13 from int)
QVariant isBis; // bool QVariant isBis; // bool
QVariant count; // int QVariant count; // int
QVariant volume; // string QVariant volume; // string
QVariant storyArc; // string QVariant storyArc; // string
QVariant arcNumber; // int QVariant arcNumber; // string (changed in 9.13 from int)
QVariant arcCount; // int QVariant arcCount; // int
QVariant genere; // string QVariant genere; // string
@ -80,7 +80,7 @@ public:
QVariant format; // string QVariant format; // string
QVariant color; // bool QVariant color; // bool
QVariant ageRating; // string QVariant ageRating; // string
QVariant manga; // bool [[deprecated("use type instead")]] QVariant manga; // bool
QVariant synopsis; // string QVariant synopsis; // string
QVariant characters; // string QVariant characters; // string
@ -94,38 +94,21 @@ public:
QVariant coverSizeRatio; // h/w QVariant coverSizeRatio; // h/w
QVariant originalCoverSize; // string "WxH" QVariant originalCoverSize; // string "WxH"
/*void setTitle(QVariant value); QVariant added; // integer/date
QVariant type; // enum
void setCoverPage(QVariant value); QVariant editor; // string
void setNumPages(QVariant value); QVariant imprint; // string
QVariant teams; // string/list
void setNumber(QVariant value); QVariant locations; // string/list
void setIsBis(QVariant value); QVariant series; // string
void setCount(QVariant value); QVariant alternateSeries; // string
QVariant alternateNumber; // string
void setVolume(QVariant value); QVariant alternateCount; // int
void setStoryArc(QVariant value); QVariant languageISO; // string
void setArcNumber(QVariant value); QVariant seriesGroup; // string
void setArcCount(QVariant value); QVariant mainCharacterOrTeam; // string
QVariant review; // string
void setGenere(QVariant value); QVariant tags; // string/list
void setWriter(QVariant value);
void setPenciller(QVariant value);
void setInker(QVariant value);
void setColorist(QVariant value);
void setLetterer(QVariant value);
void setCoverArtist(QVariant value);
void setDate(QVariant value);
void setPublisher(QVariant value);
void setFormat(QVariant value);
void setColor(QVariant value);
void setAgeRating(QVariant value);
void setSynopsis(QVariant value);
void setCharacters(QVariant value);
void setNotes(QVariant value);*/
QPixmap getCover(const QString &basePath); QPixmap getCover(const QString &basePath);
@ -138,6 +121,11 @@ public:
Q_INVOKABLE QStringList getCharacters(); Q_INVOKABLE QStringList getCharacters();
Q_INVOKABLE QStringList getTeams();
Q_INVOKABLE QStringList getLocations();
Q_INVOKABLE QStringList getTags();
friend QDataStream &operator<<(QDataStream &stream, const ComicInfo &comicInfo); friend QDataStream &operator<<(QDataStream &stream, const ComicInfo &comicInfo);
friend QDataStream &operator>>(QDataStream &stream, ComicInfo &comicInfo); friend QDataStream &operator>>(QDataStream &stream, ComicInfo &comicInfo);
@ -206,11 +194,27 @@ public:
Q_PROPERTY(QVariant coverSizeRatio MEMBER coverSizeRatio CONSTANT) Q_PROPERTY(QVariant coverSizeRatio MEMBER coverSizeRatio CONSTANT)
Q_PROPERTY(QVariant originalCoverSize MEMBER originalCoverSize CONSTANT) Q_PROPERTY(QVariant originalCoverSize MEMBER originalCoverSize CONSTANT)
Q_PROPERTY(QVariant added MEMBER added CONSTANT)
Q_PROPERTY(QVariant type MEMBER type CONSTANT)
Q_PROPERTY(QVariant editor MEMBER editor CONSTANT)
Q_PROPERTY(QVariant imprint MEMBER imprint CONSTANT)
Q_PROPERTY(QVariant teams MEMBER teams CONSTANT)
Q_PROPERTY(QVariant locations MEMBER locations CONSTANT)
Q_PROPERTY(QVariant series MEMBER series CONSTANT)
Q_PROPERTY(QVariant alternateSeries MEMBER alternateSeries CONSTANT)
Q_PROPERTY(QVariant alternateNumber MEMBER alternateNumber CONSTANT)
Q_PROPERTY(QVariant alternateCount MEMBER alternateCount CONSTANT)
Q_PROPERTY(QVariant languageISO MEMBER languageISO CONSTANT)
Q_PROPERTY(QVariant seriesGroup MEMBER seriesGroup CONSTANT)
Q_PROPERTY(QVariant mainCharacterOrTeam MEMBER mainCharacterOrTeam CONSTANT)
Q_PROPERTY(QVariant review MEMBER review CONSTANT)
Q_PROPERTY(QVariant tags MEMBER tags CONSTANT)
//-new properties, not loaded from the DB automatically //-new properties, not loaded from the DB automatically
bool isFavorite; bool isFavorite;
Q_PROPERTY(bool isFavorite MEMBER isFavorite WRITE setFavorite NOTIFY favoriteChanged) Q_PROPERTY(bool isFavorite MEMBER isFavorite WRITE setFavorite NOTIFY favoriteChanged)
// setters, used in QML only by now // setters, used in QML only for now
void setRead(bool r); void setRead(bool r);
void setRating(int r); void setRating(int r);
void setFavorite(bool f); void setFavorite(bool f);

View File

@ -20,7 +20,19 @@ Folder::Folder(qulonglong folderId, qulonglong parentId, const QString &folderNa
this->path = folderPath; this->path = folderPath;
} }
Folder::Folder(qulonglong folderId, qulonglong parentId, const QString &folderName, const QString &folderPath, bool completed, bool finished, bool manga) Folder::Folder(qulonglong folderId,
qulonglong parentId,
const QString &folderName,
const QString &folderPath,
bool completed,
bool finished,
bool manga,
int numChildren,
const QString &firstChildHash,
const QString &customImage,
YACReader::FileType type,
qint64 added,
qint64 updated)
: knownParent(true), : knownParent(true),
knownId(true), knownId(true),
numChildren(-1) numChildren(-1)
@ -32,6 +44,12 @@ Folder::Folder(qulonglong folderId, qulonglong parentId, const QString &folderNa
this->completed = completed; this->completed = completed;
this->finished = finished; this->finished = finished;
this->manga = manga; this->manga = manga;
this->numChildren = numChildren;
this->firstChildHash = firstChildHash;
this->customImage = customImage;
this->type = type;
this->added = added;
this->updated = updated;
} }
Folder::Folder(const Folder &folder) Folder::Folder(const Folder &folder)
@ -51,6 +69,9 @@ Folder &Folder::operator=(const Folder &other)
this->numChildren = other.numChildren; this->numChildren = other.numChildren;
this->firstChildHash = other.firstChildHash; this->firstChildHash = other.firstChildHash;
this->customImage = other.customImage; this->customImage = other.customImage;
this->type = other.type;
this->added = other.added;
this->updated = other.updated;
return *this; return *this;
} }

View File

@ -2,6 +2,7 @@
#define __FOLDER_H #define __FOLDER_H
#include "library_item.h" #include "library_item.h"
#include "yacreader_global.h"
#include <QList> #include <QList>
@ -11,9 +12,33 @@ public:
bool knownParent; bool knownParent;
bool knownId; bool knownId;
bool finished; // finished means read, the user has read all the content in this folder
bool completed; // completed means the folder has all the content, e.g. a series got its final issue and the user has collected all of them
[[deprecated("use type instead")]] bool manga;
qint32 numChildren; //-1 for unknown number of children
QString firstChildHash; // empty for unknown first child
QString customImage; // empty for none custom image
YACReader::FileType type;
qint64 added; // epoch in seconds
qint64 updated; // epoch in seconds
Folder(); Folder();
Folder(qulonglong folderId, qulonglong parentId, const QString &folderName, const QString &folderPath); Folder(qulonglong folderId, qulonglong parentId, const QString &folderName, const QString &folderPath);
Folder(qulonglong folderId, qulonglong parentId, const QString &folderName, const QString &folderPath, bool completed, bool finished, bool manga); Folder(qulonglong folderId,
qulonglong parentId,
const QString &folderName,
const QString &folderPath,
bool completed,
bool finished,
bool manga,
int numChildren,
const QString &firstChildHash,
const QString &customImage,
YACReader::FileType type,
qint64 added,
qint64 updated);
Folder(const QString &folderName, const QString &folderPath); Folder(const QString &folderName, const QString &folderPath);
Folder(const Folder &folder); Folder(const Folder &folder);
Folder &operator=(const Folder &other); Folder &operator=(const Folder &other);
@ -33,75 +58,6 @@ public:
{ {
return true; return true;
} }
inline bool isFinished() const
{
return finished;
}
inline bool isCompleted() const
{
return completed;
}
inline bool isManga() const
{
return manga;
}
inline void setFinished(bool b)
{
finished = b;
}
inline void setCompleted(bool b)
{
completed = b;
}
inline void setManga(bool b)
{
manga = b;
}
inline qint32 getNumChildren() const
{
return numChildren;
}
inline void setNumChildren(const qint32 v)
{
numChildren = v;
}
inline QString getFirstChildHash() const
{
return firstChildHash;
}
inline void setFirstChildHash(const QString &v)
{
firstChildHash = v;
}
inline QString getCustomImage() const
{
return customImage;
}
inline void setCustomImage(const QString &s)
{
customImage = s;
}
private:
bool finished; // finished means read, the user has read all the content in this folder
bool completed; // completed means the folder has all the content, e.g. a series got its final issue and the user has collected all of them
bool manga;
qint32 numChildren; //-1 for unknown number of children
QString firstChildHash; // empty for unknown first child
QString customImage; // empty for none custom image
}; };
#endif #endif

View File

@ -7,6 +7,7 @@ int naturalCompare(const QString &s1, const QString &s2, Qt::CaseSensitivity cas
QCollator c; QCollator c;
c.setCaseSensitivity(caseSensitivity); c.setCaseSensitivity(caseSensitivity);
c.setNumericMode(true); c.setNumericMode(true);
c.setIgnorePunctuation(false);
return c.compare(s1, s2); return c.compare(s1, s2);
} }
bool naturalSortLessThanCS(const QString &left, const QString &right) bool naturalSortLessThanCS(const QString &left, const QString &right)

View File

@ -6,7 +6,7 @@
#include <QMetaType> #include <QMetaType>
#include <QAbstractItemModel> #include <QAbstractItemModel>
#define VERSION "9.12.0" #define VERSION "9.13.0"
#define IMPORT_COMIC_INFO_XML_METADATA "IMPORT_COMIC_INFO_XML_METADATA" #define IMPORT_COMIC_INFO_XML_METADATA "IMPORT_COMIC_INFO_XML_METADATA"
@ -51,6 +51,14 @@ enum LabelColors {
YDark YDark
}; };
enum class FileType : int {
Comic = 0,
Manga,
WesternManga,
WebComic, // continuous vertical reading
Yonkoma, // 4Koma
};
struct OpenComicSource { struct OpenComicSource {
enum Source { enum Source {
Folder = 0, Folder = 0,
@ -76,5 +84,6 @@ void iterate(const QModelIndex &index,
Q_DECLARE_METATYPE(YACReader::OpenComicSource::Source) Q_DECLARE_METATYPE(YACReader::OpenComicSource::Source)
Q_DECLARE_METATYPE(YACReader::OpenComicSource) Q_DECLARE_METATYPE(YACReader::OpenComicSource)
Q_DECLARE_METATYPE(YACReader::FileType)
#endif #endif

View File

@ -51,6 +51,9 @@ public:
#define SET_AS_NON_READ_ACTION_YL "SET_AS_NON_READ_ACTION_YL" #define SET_AS_NON_READ_ACTION_YL "SET_AS_NON_READ_ACTION_YL"
#define SET_AS_MANGA_ACTION_YL "SET_AS_MANGA_ACTION_YL" #define SET_AS_MANGA_ACTION_YL "SET_AS_MANGA_ACTION_YL"
#define SET_AS_NORMAL_ACTION_YL "SET_AS_MANGA_ACTION_YL" #define SET_AS_NORMAL_ACTION_YL "SET_AS_MANGA_ACTION_YL"
#define SET_AS_WESTERN_MANGA_ACTION_YL "SET_AS_WESTERN_MANGA_ACTION_YL"
#define SET_AS_WEB_COMIC_ACTION_YL "SET_AS_WEB_COMIC_ACTION_YL"
#define SET_AS_YONKOMA_ACTION_YL "SET_AS_YONKOMA_ACTION_YL"
#define SHOW_HIDE_MARKS_ACTION_YL "SHOW_HIDE_MARKS_ACTION_YL" #define SHOW_HIDE_MARKS_ACTION_YL "SHOW_HIDE_MARKS_ACTION_YL"
#define TOGGLE_FULL_SCREEN_ACTION_YL "TOGGLE_FULL_SCREEN_ACTION_YL" #define TOGGLE_FULL_SCREEN_ACTION_YL "TOGGLE_FULL_SCREEN_ACTION_YL"
#define HELP_ABOUT_ACTION_YL "HELP_ABOUT_ACTION_YL" #define HELP_ABOUT_ACTION_YL "HELP_ABOUT_ACTION_YL"
@ -66,7 +69,10 @@ public:
#define SET_FOLDER_AS_READ_ACTION_YL "SET_FOLDER_AS_READ_ACTION_YL" #define SET_FOLDER_AS_READ_ACTION_YL "SET_FOLDER_AS_READ_ACTION_YL"
#define SET_FOLDER_AS_UNREAD_ACTION_YL "SET_FOLDER_AS_UNREAD_ACTION_YL" #define SET_FOLDER_AS_UNREAD_ACTION_YL "SET_FOLDER_AS_UNREAD_ACTION_YL"
#define SET_FOLDER_AS_MANGA_ACTION_YL "SET_FOLDER_AS_MANGA_ACTION_YL" #define SET_FOLDER_AS_MANGA_ACTION_YL "SET_FOLDER_AS_MANGA_ACTION_YL"
#define SET_FOLDER_AS_WESTERN_MANGA_ACTION_YL "SET_FOLDER_AS_WESTERN_MANGA_ACTION_YL"
#define SET_FOLDER_AS_NORMAL_ACTION_YL "SET_FOLDER_AS_NORMAL_ACTION_YL" #define SET_FOLDER_AS_NORMAL_ACTION_YL "SET_FOLDER_AS_NORMAL_ACTION_YL"
#define SET_FOLDER_AS_WEB_COMIC_ACTION_YL "SET_FOLDER_AS_WEB_COMIC_ACTION_YL"
#define SET_FOLDER_AS_YONKOMA_ACTION_YL "SET_FOLDER_AS_YONKOMA_ACTION_YL"
#define OPEN_CONTAINING_FOLDER_COMIC_ACTION_YL "OPEN_CONTAINING_FOLDER_COMIC_ACTION_YL" #define OPEN_CONTAINING_FOLDER_COMIC_ACTION_YL "OPEN_CONTAINING_FOLDER_COMIC_ACTION_YL"
#define RESET_COMIC_RATING_ACTION_YL "RESET_COMIC_RATING_ACTION_YL" #define RESET_COMIC_RATING_ACTION_YL "RESET_COMIC_RATING_ACTION_YL"
#define SELECT_ALL_COMICS_ACTION_YL "SELECT_ALL_COMICS_ACTION_YL" #define SELECT_ALL_COMICS_ACTION_YL "SELECT_ALL_COMICS_ACTION_YL"