mirror of
https://github.com/YACReader/yacreader
synced 2025-05-28 03:10:27 -04:00
Merge pull request #381 from YACReader/new_metadata
feature: New metadata support
This commit is contained in:
commit
b45fabe057
@ -6,6 +6,12 @@ Version counting is based on semantic versioning (Major.Feature.Patch)
|
||||
|
||||
### YACReaderLibrary
|
||||
* Avoid showing stale information in the server config dialog by updating the connection information when the dialog is opened.
|
||||
* Add new metadata support, it improves compatibility with ComicInfo.xml
|
||||
* Add support for showing a "recently added/updated" indicator.
|
||||
* Improved comic metadata dialog.
|
||||
* Add textual tags support that can be queried through the search engine.
|
||||
* Make = in the search engine work as : does.
|
||||
* Add new operators to the search engine: exact match ==, <, >, <=, >=.
|
||||
|
||||
## 9.12
|
||||
|
||||
|
@ -1575,7 +1575,7 @@ void MainWindowViewer::sendComic()
|
||||
auto client = new YACReaderLocalClient;
|
||||
|
||||
connect(client, &YACReaderLocalClient::finished, client, &YACReaderLocalClient::deleteLater);
|
||||
currentComicDB.info.lastTimeOpened = QDateTime::currentMSecsSinceEpoch() / 1000;
|
||||
currentComicDB.info.lastTimeOpened = QDateTime::currentSecsSinceEpoch();
|
||||
|
||||
viewer->updateComic(currentComicDB);
|
||||
|
||||
|
@ -85,6 +85,7 @@ HEADERS += comic_flow.h \
|
||||
library_creator.h \
|
||||
library_window.h \
|
||||
add_library_dialog.h \
|
||||
recent_visibility_coordinator.h \
|
||||
rename_library_dialog.h \
|
||||
properties_dialog.h \
|
||||
options_dialog.h \
|
||||
@ -171,6 +172,7 @@ SOURCES += comic_flow.cpp \
|
||||
library_window.cpp \
|
||||
main.cpp \
|
||||
add_library_dialog.cpp \
|
||||
recent_visibility_coordinator.cpp \
|
||||
rename_library_dialog.cpp \
|
||||
properties_dialog.cpp \
|
||||
options_dialog.cpp \
|
||||
|
@ -90,7 +90,7 @@ ClassicComicsView::ClassicComicsView(QWidget *parent)
|
||||
hideFlowViewAction->setText(tr("Hide comic flow"));
|
||||
hideFlowViewAction->setData(HIDE_COMIC_VIEW_ACTION_YL);
|
||||
hideFlowViewAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(HIDE_COMIC_VIEW_ACTION_YL));
|
||||
hideFlowViewAction->setIcon(QIcon(":/images/comics_view_toolbar/hideComicFlow.png"));
|
||||
hideFlowViewAction->setIcon(QIcon(":/images/comics_view_toolbar/hideComicFlow.svg"));
|
||||
hideFlowViewAction->setCheckable(true);
|
||||
hideFlowViewAction->setChecked(false);
|
||||
|
||||
@ -120,9 +120,7 @@ void ClassicComicsView::setToolBar(QToolBar *toolBar)
|
||||
static_cast<QVBoxLayout *>(comics->layout())->insertWidget(0, toolBar);
|
||||
this->toolbar = toolBar;
|
||||
|
||||
toolBarStretch = new YACReaderToolBarStretch(this);
|
||||
|
||||
toolBarStretchAction = toolBar->addWidget(toolBarStretch);
|
||||
startSeparatorAction = toolBar->addSeparator();
|
||||
toolBar->addAction(hideFlowViewAction);
|
||||
}
|
||||
|
||||
@ -343,7 +341,7 @@ void ClassicComicsView::removeItemsFromFlow(const QModelIndex &parent, int from,
|
||||
|
||||
void ClassicComicsView::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
toolbar->removeAction(toolBarStretchAction);
|
||||
toolbar->removeAction(startSeparatorAction);
|
||||
toolbar->removeAction(hideFlowViewAction);
|
||||
|
||||
saveTableHeadersStatus();
|
||||
|
@ -54,8 +54,6 @@ protected slots:
|
||||
|
||||
private:
|
||||
YACReaderTableView *tableView;
|
||||
YACReaderToolBarStretch *toolBarStretch;
|
||||
QAction *toolBarStretchAction;
|
||||
QToolBar *toolbar;
|
||||
QWidget *comics;
|
||||
QSplitter *sVertical;
|
||||
@ -63,6 +61,7 @@ private:
|
||||
QSettings *settings;
|
||||
void closeEvent(QCloseEvent *event) override;
|
||||
QAction *hideFlowViewAction;
|
||||
QAction *startSeparatorAction;
|
||||
|
||||
QStackedWidget *stack;
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/comic_vine_json_parser.h \
|
||||
comic_vine/comic_vine_dialog.h \
|
||||
comic_vine/comic_vine_client.h \
|
||||
comic_vine/scraper_lineedit.h \
|
||||
@ -24,6 +25,7 @@ HEADERS += \
|
||||
$$PWD/comic_vine_all_volume_comics_retriever.h
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/comic_vine_json_parser.cpp \
|
||||
comic_vine/comic_vine_dialog.cpp \
|
||||
comic_vine/comic_vine_client.cpp \
|
||||
comic_vine/scraper_lineedit.cpp \
|
||||
|
@ -10,12 +10,11 @@
|
||||
#include <QtWidgets>
|
||||
#include <QtConcurrent/QtConcurrentRun>
|
||||
#include "data_base_management.h"
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonParseError>
|
||||
#include <QSqlDatabase>
|
||||
|
||||
#include "yacreader_busy_widget.h"
|
||||
#include "comic_vine_client.h"
|
||||
#include "comic_vine_json_parser.h"
|
||||
#include "scraper_lineedit.h"
|
||||
#include "title_header.h"
|
||||
#include "series_question.h"
|
||||
@ -461,7 +460,7 @@ void ComicVineDialog::getComicsInfo(QList<QPair<ComicDB, QString>> matchingInfo,
|
||||
QByteArray result = comicVineClient->getComicDetail(p.second, error, timeout); // TODO check timeOut or Connection error
|
||||
if (error || timeout)
|
||||
continue; // TODO
|
||||
ComicDB comic = parseComicInfo(p.first, result, count, publisher); // TODO check result error
|
||||
ComicDB comic = YACReader::parseCVJSONComicInfo(p.first, result, count, publisher); // TODO check result error
|
||||
comic.info.comicVineID = p.second;
|
||||
comics.push_back(comic);
|
||||
|
||||
@ -489,7 +488,7 @@ void ComicVineDialog::getComicInfo(const QString &comicId, int count, const QStr
|
||||
}
|
||||
}
|
||||
|
||||
ComicDB comic = parseComicInfo(comics[currentIndex], result, count, publisher); // TODO check result error
|
||||
ComicDB comic = YACReader::parseCVJSONComicInfo(comics[currentIndex], result, count, publisher); // TODO check result error
|
||||
comic.info.comicVineID = comicId;
|
||||
setLoadingMessage(tr("Retrieving tags for : %1").arg(comics[currentIndex].getFileName()));
|
||||
QString connectionName = "";
|
||||
@ -512,196 +511,6 @@ void ComicVineDialog::getComicInfo(const QString &comicId, int count, const QStr
|
||||
}
|
||||
}
|
||||
|
||||
ComicDB ComicVineDialog::parseComicInfo(ComicDB &comic, const QString &json, int count, const QString &publisher)
|
||||
{
|
||||
QJsonParseError Err;
|
||||
|
||||
QVariantMap sc = QJsonDocument::fromJson(json.toUtf8(), &Err).toVariant().toMap();
|
||||
if (Err.error != QJsonParseError::NoError) {
|
||||
qDebug("Error detected");
|
||||
return comic;
|
||||
}
|
||||
|
||||
int numResults = sc.value("number_of_total_results").toInt(); // fix to weird behaviour using hasNext
|
||||
|
||||
if (numResults > 0) {
|
||||
QVariantMap result = sc.value("results").toMap();
|
||||
comic.info.title = result.value("name");
|
||||
comic.info.number = result.value("issue_number");
|
||||
comic.info.volume = result.value("volume").toMap().value("name");
|
||||
|
||||
if (result.contains("person_credits") && !result.value("person_credits").isNull()) {
|
||||
auto authors = getAuthors(result.value("person_credits"));
|
||||
|
||||
QString writer = authors.values("writer").join("\n");
|
||||
QString penciller = authors.values("penciller").join("\n");
|
||||
QString inker = authors.values("inker").join("\n");
|
||||
QString colorist = authors.values("colorist").join("\n");
|
||||
QString letterer = authors.values("letterer").join("\n");
|
||||
QString coverArtist = authors.values("cover").join("\n");
|
||||
|
||||
comic.info.writer = writer;
|
||||
comic.info.penciller = penciller;
|
||||
comic.info.inker = inker;
|
||||
comic.info.colorist = colorist;
|
||||
comic.info.letterer = letterer;
|
||||
comic.info.coverArtist = coverArtist;
|
||||
}
|
||||
|
||||
if (result.contains("cover_date") && !result.value("cover_date").isNull()) {
|
||||
QString date = result.value("cover_date").toString();
|
||||
|
||||
QStringList tempList = date.split("-");
|
||||
|
||||
if (tempList.length() == 3) {
|
||||
std::reverse(tempList.begin(), tempList.end());
|
||||
comic.info.date = tempList.join("/");
|
||||
}
|
||||
}
|
||||
|
||||
if (result.contains("description") && !result.value("description").isNull()) {
|
||||
comic.info.synopsis = result.value("description");
|
||||
}
|
||||
|
||||
if (result.contains("character_credits") && !result.value("character_credits").isNull()) {
|
||||
comic.info.characters = getCharacters(result.value("character_credits"));
|
||||
}
|
||||
|
||||
if (result.contains("story_arc_credits") && !result.value("story_arc_credits").isNull()) {
|
||||
QPair<QString, QString> storyArcIdAndName = getFirstStoryArcIdAndName(result.value("story_arc_credits"));
|
||||
QString storyArcId = storyArcIdAndName.first;
|
||||
QString storyArcName = storyArcIdAndName.second;
|
||||
if (!storyArcId.isNull()) {
|
||||
|
||||
QString comicId = result.value("id").toString();
|
||||
|
||||
QPair<QString, QString> arcNumberAndArcCount = getArcNumberAndArcCount(storyArcId, comicId);
|
||||
if (!arcNumberAndArcCount.first.isNull()) {
|
||||
QString arcNumber = arcNumberAndArcCount.first;
|
||||
QString arcCount = arcNumberAndArcCount.second;
|
||||
|
||||
comic.info.storyArc = storyArcName;
|
||||
comic.info.arcNumber = arcNumber;
|
||||
comic.info.arcCount = arcCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
comic.info.count = count;
|
||||
|
||||
comic.info.publisher = publisher;
|
||||
|
||||
comic.info.edited = true;
|
||||
}
|
||||
|
||||
return comic;
|
||||
}
|
||||
|
||||
QString ComicVineDialog::getCharacters(const QVariant &json_characters)
|
||||
{
|
||||
QStringList characters;
|
||||
|
||||
QListIterator<QVariant> it(json_characters.toList());
|
||||
QVariantMap resultsValue;
|
||||
while (it.hasNext()) {
|
||||
resultsValue = it.next().toMap();
|
||||
|
||||
characters << resultsValue.value("name").toString();
|
||||
}
|
||||
|
||||
return (characters.isEmpty()) ? "" : (characters.join("\n") + "\n");
|
||||
}
|
||||
|
||||
QMultiMap<QString, QString> ComicVineDialog::getAuthors(const QVariant &json_authors)
|
||||
{
|
||||
QMultiMap<QString, QString> authors;
|
||||
|
||||
QListIterator<QVariant> it(json_authors.toList());
|
||||
QVariantMap resultsValue;
|
||||
while (it.hasNext()) {
|
||||
resultsValue = it.next().toMap();
|
||||
|
||||
QString authorName = resultsValue.value("name").toString();
|
||||
|
||||
QStringList roles = resultsValue.value("role").toString().split(",");
|
||||
foreach (QString role, roles) {
|
||||
if (role.trimmed() == "writer")
|
||||
authors.insert("writer", authorName);
|
||||
else if (role.trimmed() == "inker")
|
||||
authors.insert("inker", authorName);
|
||||
else if (role.trimmed() == "penciler" || role.trimmed() == "penciller")
|
||||
authors.insert("penciller", authorName);
|
||||
else if (role.trimmed() == "colorist")
|
||||
authors.insert("colorist", authorName);
|
||||
else if (role.trimmed() == "letterer")
|
||||
authors.insert("letterer", authorName);
|
||||
else if (role.trimmed() == "cover")
|
||||
authors.insert("cover", authorName);
|
||||
}
|
||||
}
|
||||
|
||||
return authors;
|
||||
}
|
||||
|
||||
QPair<QString, QString> ComicVineDialog::getFirstStoryArcIdAndName(const QVariant &json_story_arcs)
|
||||
{
|
||||
QString story_arc_id = QString();
|
||||
QString story_arc_name = QString();
|
||||
|
||||
QListIterator<QVariant> it(json_story_arcs.toList());
|
||||
QVariantMap resultsValue;
|
||||
while (it.hasNext()) {
|
||||
resultsValue = it.next().toMap();
|
||||
story_arc_id = resultsValue.value("id").toString();
|
||||
story_arc_name = resultsValue.value("name").toString();
|
||||
break;
|
||||
}
|
||||
return qMakePair(story_arc_id, story_arc_name);
|
||||
}
|
||||
|
||||
QPair<QString, QString> ComicVineDialog::getArcNumberAndArcCount(const QString &storyArcId, const QString &comicId)
|
||||
{
|
||||
auto comicVineClient = new ComicVineClient;
|
||||
bool error;
|
||||
bool timeout;
|
||||
QByteArray result = comicVineClient->getStoryArcDetail(storyArcId, error, timeout);
|
||||
if (error || timeout)
|
||||
return qMakePair(QString(), QString());
|
||||
QString json = result;
|
||||
|
||||
QJsonParseError Err;
|
||||
QVariantMap sc = QJsonDocument::fromJson(json.toUtf8(), &Err).toVariant().toMap();
|
||||
|
||||
if (Err.error != QJsonParseError::NoError) {
|
||||
qDebug("Error detected");
|
||||
return qMakePair(QString(), QString());
|
||||
}
|
||||
|
||||
int numResults = sc.value("number_of_total_results").toInt(); // fix to weird behaviour using hasNext
|
||||
|
||||
if (numResults > 0) {
|
||||
QVariantMap result = sc.value("results").toMap();
|
||||
|
||||
if (result.contains("issues")) {
|
||||
QListIterator<QVariant> it(result.value("issues").toList());
|
||||
int arcNumber = 0;
|
||||
int arcCount = 0;
|
||||
|
||||
QVariantMap resultsValue;
|
||||
while (it.hasNext()) {
|
||||
resultsValue = it.next().toMap();
|
||||
if (comicId == resultsValue.value("id").toString()) {
|
||||
arcNumber = arcCount + 1;
|
||||
}
|
||||
arcCount++;
|
||||
}
|
||||
return qMakePair(QString::number(arcNumber), QString::number(arcCount));
|
||||
}
|
||||
return qMakePair(QString(), QString());
|
||||
}
|
||||
return qMakePair(QString(), QString());
|
||||
}
|
||||
|
||||
void ComicVineDialog::toggleSkipButton()
|
||||
{
|
||||
if (mode == SingleComicInList)
|
||||
|
@ -58,16 +58,11 @@ protected slots:
|
||||
void showSelectComic(const QString &json);
|
||||
void showSortVolumeComics(const QString &json);
|
||||
void queryTimeOut();
|
||||
ComicDB parseComicInfo(ComicDB &comic, const QString &json, int count, const QString &publisher);
|
||||
void setLoadingMessage(const QString &message);
|
||||
void goToNextComic();
|
||||
|
||||
private:
|
||||
void clearState();
|
||||
QString getCharacters(const QVariant &json_characters);
|
||||
QMultiMap<QString, QString> getAuthors(const QVariant &json_authors);
|
||||
QPair<QString, QString> getFirstStoryArcIdAndName(const QVariant &json_story_arcs);
|
||||
QPair<QString, QString> getArcNumberAndArcCount(const QString &storyArcId, const QString &comicId);
|
||||
|
||||
void toggleSkipButton();
|
||||
|
||||
|
233
YACReaderLibrary/comic_vine/comic_vine_json_parser.cpp
Normal file
233
YACReaderLibrary/comic_vine/comic_vine_json_parser.cpp
Normal file
@ -0,0 +1,233 @@
|
||||
|
||||
#include "comic_vine_json_parser.h"
|
||||
|
||||
#include "comic_vine_client.h"
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonParseError>
|
||||
|
||||
QString getCharacters(const QVariant &json_characters);
|
||||
QMultiMap<QString, QString> getAuthors(const QVariant &json_authors);
|
||||
QPair<QString, QString> getFirstStoryArcIdAndName(const QVariant &json_story_arcs);
|
||||
QPair<QString, QString> getArcNumberAndArcCount(const QString &storyArcId, const QString &comicId);
|
||||
QList<QString> getNamesFromList(const QVariant &json_list);
|
||||
|
||||
ComicDB YACReader::parseCVJSONComicInfo(ComicDB &comic, const QString &json, int count, const QString &publisher)
|
||||
{
|
||||
QJsonParseError Err;
|
||||
|
||||
QVariantMap sc = QJsonDocument::fromJson(json.toUtf8(), &Err).toVariant().toMap();
|
||||
if (Err.error != QJsonParseError::NoError) {
|
||||
qDebug("Error detected");
|
||||
return comic;
|
||||
}
|
||||
|
||||
int numResults = sc.value("number_of_total_results").toInt(); // fix to weird behaviour using hasNext
|
||||
|
||||
if (numResults > 0) {
|
||||
QVariantMap result = sc.value("results").toMap();
|
||||
comic.info.title = result.value("name");
|
||||
comic.info.number = result.value("issue_number");
|
||||
|
||||
// changed in 9.13, volume actually means series in ComicVine
|
||||
comic.info.series = result.value("volume").toMap().value("name");
|
||||
|
||||
if (result.contains("person_credits") && !result.value("person_credits").isNull()) {
|
||||
auto authors = getAuthors(result.value("person_credits"));
|
||||
|
||||
QString writer = authors.values("writer").join("\n");
|
||||
QString penciller = authors.values("penciller").join("\n");
|
||||
QString inker = authors.values("inker").join("\n");
|
||||
QString colorist = authors.values("colorist").join("\n");
|
||||
QString letterer = authors.values("letterer").join("\n");
|
||||
QString coverArtist = authors.values("cover").join("\n");
|
||||
|
||||
comic.info.writer = writer;
|
||||
comic.info.penciller = penciller;
|
||||
comic.info.inker = inker;
|
||||
comic.info.colorist = colorist;
|
||||
comic.info.letterer = letterer;
|
||||
comic.info.coverArtist = coverArtist;
|
||||
}
|
||||
|
||||
if (result.contains("cover_date") && !result.value("cover_date").isNull()) {
|
||||
QString date = result.value("cover_date").toString();
|
||||
|
||||
QStringList tempList = date.split("-");
|
||||
|
||||
if (tempList.length() == 3) {
|
||||
std::reverse(tempList.begin(), tempList.end());
|
||||
comic.info.date = tempList.join("/");
|
||||
}
|
||||
}
|
||||
|
||||
if (result.contains("description") && !result.value("description").isNull()) {
|
||||
comic.info.synopsis = result.value("description");
|
||||
}
|
||||
|
||||
if (result.contains("character_credits") && !result.value("character_credits").isNull()) {
|
||||
comic.info.characters = getCharacters(result.value("character_credits"));
|
||||
}
|
||||
|
||||
if (result.contains("story_arc_credits") && !result.value("story_arc_credits").isNull()) {
|
||||
QPair<QString, QString> storyArcIdAndName = getFirstStoryArcIdAndName(result.value("story_arc_credits"));
|
||||
QString storyArcId = storyArcIdAndName.first;
|
||||
QString storyArcName = storyArcIdAndName.second;
|
||||
if (!storyArcId.isNull()) {
|
||||
|
||||
QString comicId = result.value("id").toString();
|
||||
|
||||
QPair<QString, QString> arcNumberAndArcCount = getArcNumberAndArcCount(storyArcId, comicId);
|
||||
if (!arcNumberAndArcCount.first.isNull()) {
|
||||
QString arcNumber = arcNumberAndArcCount.first;
|
||||
QString arcCount = arcNumberAndArcCount.second;
|
||||
|
||||
comic.info.storyArc = storyArcName;
|
||||
comic.info.arcNumber = arcNumber;
|
||||
comic.info.arcCount = arcCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result.contains("location_credits") && !result.value("location_credits").isNull()) {
|
||||
comic.info.locations = getNamesFromList(result.value("location_credits")).join("\n");
|
||||
}
|
||||
|
||||
if (result.contains("team_credits") && !result.value("team_credits").isNull()) {
|
||||
comic.info.teams = getNamesFromList(result.value("team_credits")).join("\n");
|
||||
}
|
||||
|
||||
if (result.contains("character_credits") && !result.value("character_credits").isNull()) {
|
||||
comic.info.characters = getNamesFromList(result.value("character_credits")).join("\n");
|
||||
}
|
||||
|
||||
comic.info.count = count;
|
||||
|
||||
comic.info.publisher = publisher;
|
||||
|
||||
comic.info.edited = true;
|
||||
}
|
||||
|
||||
return comic;
|
||||
}
|
||||
|
||||
QString getCharacters(const QVariant &json_characters)
|
||||
{
|
||||
QStringList characters;
|
||||
|
||||
QListIterator<QVariant> it(json_characters.toList());
|
||||
QVariantMap resultsValue;
|
||||
while (it.hasNext()) {
|
||||
resultsValue = it.next().toMap();
|
||||
|
||||
characters << resultsValue.value("name").toString();
|
||||
}
|
||||
|
||||
return (characters.isEmpty()) ? "" : (characters.join("\n") + "\n");
|
||||
}
|
||||
|
||||
QMultiMap<QString, QString> getAuthors(const QVariant &json_authors)
|
||||
{
|
||||
QMultiMap<QString, QString> authors;
|
||||
|
||||
QListIterator<QVariant> it(json_authors.toList());
|
||||
QVariantMap resultsValue;
|
||||
while (it.hasNext()) {
|
||||
resultsValue = it.next().toMap();
|
||||
|
||||
QString authorName = resultsValue.value("name").toString();
|
||||
|
||||
QStringList roles = resultsValue.value("role").toString().split(",");
|
||||
foreach (QString role, roles) {
|
||||
if (role.trimmed() == "writer")
|
||||
authors.insert("writer", authorName);
|
||||
else if (role.trimmed() == "inker")
|
||||
authors.insert("inker", authorName);
|
||||
else if (role.trimmed() == "penciler" || role.trimmed() == "penciller")
|
||||
authors.insert("penciller", authorName);
|
||||
else if (role.trimmed() == "colorist")
|
||||
authors.insert("colorist", authorName);
|
||||
else if (role.trimmed() == "letterer")
|
||||
authors.insert("letterer", authorName);
|
||||
else if (role.trimmed() == "cover")
|
||||
authors.insert("cover", authorName);
|
||||
}
|
||||
}
|
||||
|
||||
return authors;
|
||||
}
|
||||
|
||||
QPair<QString, QString> getFirstStoryArcIdAndName(const QVariant &json_story_arcs)
|
||||
{
|
||||
QString story_arc_id = QString();
|
||||
QString story_arc_name = QString();
|
||||
|
||||
QListIterator<QVariant> it(json_story_arcs.toList());
|
||||
QVariantMap resultsValue;
|
||||
while (it.hasNext()) {
|
||||
resultsValue = it.next().toMap();
|
||||
story_arc_id = resultsValue.value("id").toString();
|
||||
story_arc_name = resultsValue.value("name").toString();
|
||||
break;
|
||||
}
|
||||
return qMakePair(story_arc_id, story_arc_name);
|
||||
}
|
||||
|
||||
QPair<QString, QString> getArcNumberAndArcCount(const QString &storyArcId, const QString &comicId)
|
||||
{
|
||||
auto comicVineClient = new ComicVineClient;
|
||||
bool error;
|
||||
bool timeout;
|
||||
QByteArray result = comicVineClient->getStoryArcDetail(storyArcId, error, timeout);
|
||||
if (error || timeout)
|
||||
return qMakePair(QString(), QString());
|
||||
QString json = result;
|
||||
|
||||
QJsonParseError Err;
|
||||
QVariantMap sc = QJsonDocument::fromJson(json.toUtf8(), &Err).toVariant().toMap();
|
||||
|
||||
if (Err.error != QJsonParseError::NoError) {
|
||||
qDebug("Error detected");
|
||||
return qMakePair(QString(), QString());
|
||||
}
|
||||
|
||||
int numResults = sc.value("number_of_total_results").toInt(); // fix to weird behaviour using hasNext
|
||||
|
||||
if (numResults > 0) {
|
||||
QVariantMap result = sc.value("results").toMap();
|
||||
|
||||
if (result.contains("issues")) {
|
||||
QListIterator<QVariant> it(result.value("issues").toList());
|
||||
int arcNumber = 0;
|
||||
int arcCount = 0;
|
||||
|
||||
QVariantMap resultsValue;
|
||||
while (it.hasNext()) {
|
||||
resultsValue = it.next().toMap();
|
||||
if (comicId == resultsValue.value("id").toString()) {
|
||||
arcNumber = arcCount + 1;
|
||||
}
|
||||
arcCount++;
|
||||
}
|
||||
return qMakePair(QString::number(arcNumber), QString::number(arcCount));
|
||||
}
|
||||
return qMakePair(QString(), QString());
|
||||
}
|
||||
return qMakePair(QString(), QString());
|
||||
}
|
||||
|
||||
QList<QString> getNamesFromList(const QVariant &json_list)
|
||||
{
|
||||
QList<QString> names;
|
||||
|
||||
QListIterator<QVariant> it(json_list.toList());
|
||||
QVariantMap resultsValue;
|
||||
while (it.hasNext()) {
|
||||
resultsValue = it.next().toMap();
|
||||
|
||||
QString name = resultsValue.value("name").toString();
|
||||
names.append(name);
|
||||
}
|
||||
|
||||
return names;
|
||||
}
|
13
YACReaderLibrary/comic_vine/comic_vine_json_parser.h
Normal file
13
YACReaderLibrary/comic_vine/comic_vine_json_parser.h
Normal file
@ -0,0 +1,13 @@
|
||||
|
||||
#ifndef COMIC_VINE_JSON_PARSER_H
|
||||
#define COMIC_VINE_JSON_PARSER_H
|
||||
|
||||
#include "comic_db.h"
|
||||
|
||||
namespace YACReader {
|
||||
|
||||
ComicDB parseCVJSONComicInfo(ComicDB &comic, const QString &json, int count, const QString &publisher);
|
||||
|
||||
}
|
||||
|
||||
#endif // COMIC_VINE_JSON_PARSER_H
|
@ -17,12 +17,13 @@
|
||||
#include "QsLog.h"
|
||||
|
||||
ComicModel::ComicModel(QObject *parent)
|
||||
: QAbstractItemModel(parent)
|
||||
: QAbstractItemModel(parent), showRecent(false), recentDays(1)
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
ComicModel::ComicModel(QSqlQuery &sqlquery, QObject *parent)
|
||||
: QAbstractItemModel(parent)
|
||||
: QAbstractItemModel(parent), showRecent(false), recentDays(1)
|
||||
{
|
||||
setupModelData(sqlquery);
|
||||
}
|
||||
@ -239,6 +240,10 @@ QHash<int, QByteArray> ComicModel::roleNames() const
|
||||
roles[CoverPathRole] = "cover_path";
|
||||
roles[PublicationDate] = "date";
|
||||
roles[ReadableTitle] = "readable_title";
|
||||
roles[AddedRole] = "added_date";
|
||||
roles[TypeRole] = "type";
|
||||
roles[ShowRecentRole] = "show_recent";
|
||||
roles[RecentRangeRole] = "recent_range";
|
||||
|
||||
return roles;
|
||||
}
|
||||
@ -301,6 +306,14 @@ QVariant ComicModel::data(const QModelIndex &index, int role) const
|
||||
return item->data(Id);
|
||||
else if (role == PublicationDateRole)
|
||||
return QVariant(localizedDate(item->data(PublicationDate).toString()));
|
||||
else if (role == AddedRole)
|
||||
return item->data(Added);
|
||||
else if (role == TypeRole)
|
||||
return item->data(Type);
|
||||
else if (role == ShowRecentRole)
|
||||
return showRecent;
|
||||
else if (role == ComicModel::RecentRangeRole)
|
||||
return recentDays * 86400;
|
||||
|
||||
if (role != Qt::DisplayRole)
|
||||
return QVariant();
|
||||
@ -443,6 +456,8 @@ QStringList ComicModel::getPaths(const QString &_source)
|
||||
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)
|
||||
{
|
||||
enableResorting = false;
|
||||
@ -458,7 +473,7 @@ void ComicModel::setupFolderModelData(unsigned long long int folderId, const QSt
|
||||
{
|
||||
QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath);
|
||||
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) "
|
||||
"WHERE c.parentId = :parentId");
|
||||
selectQuery.bindValue(":parentId", folderId);
|
||||
@ -485,7 +500,7 @@ void ComicModel::setupLabelModelData(unsigned long long parentLabel, const QStri
|
||||
{
|
||||
QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath);
|
||||
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) "
|
||||
"INNER JOIN comic_label cl ON (c.id == cl.comic_id) "
|
||||
"WHERE cl.label_id = :parentLabelId "
|
||||
@ -529,7 +544,7 @@ void ComicModel::setupReadingListModelData(unsigned long long parentReadingList,
|
||||
|
||||
foreach (qulonglong id, ids) {
|
||||
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) "
|
||||
"INNER JOIN comic_reading_list crl ON (c.id == crl.comic_id) "
|
||||
"WHERE crl.reading_list_id = :parentReadingList "
|
||||
@ -566,7 +581,7 @@ void ComicModel::setupFavoritesModelData(const QString &databasePath)
|
||||
{
|
||||
QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath);
|
||||
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) "
|
||||
"INNER JOIN comic_default_reading_list cdrl ON (c.id == cdrl.comic_id) "
|
||||
"WHERE cdrl.default_reading_list_id = :parentDefaultListId "
|
||||
@ -595,7 +610,7 @@ void ComicModel::setupReadingModelData(const QString &databasePath)
|
||||
{
|
||||
QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath);
|
||||
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) "
|
||||
"WHERE ci.hasBeenOpened = 1 AND ci.read = 0 "
|
||||
"ORDER BY ci.lastTimeOpened DESC");
|
||||
@ -652,7 +667,7 @@ void ComicModel::setupModelData(QSqlQuery &sqlquery)
|
||||
return naturalSortLessThanCI(c1->data(ComicModel::FileName).toString(), c2->data(ComicModel::FileName).toString());
|
||||
} else {
|
||||
if (c1->data(ComicModel::Number).isNull() == false && c2->data(ComicModel::Number).isNull() == false) {
|
||||
return c1->data(ComicModel::Number).toInt() < c2->data(ComicModel::Number).toInt();
|
||||
return naturalSortLessThanCI(c1->data(ComicModel::Number).toString(), c2->data(ComicModel::Number).toString());
|
||||
} else {
|
||||
return c2->data(ComicModel::Number).isNull();
|
||||
}
|
||||
@ -794,7 +809,7 @@ QVector<YACReaderComicReadStatus> ComicModel::setComicsRead(QList<QModelIndex> l
|
||||
return getReadList();
|
||||
}
|
||||
|
||||
void ComicModel::setComicsManga(QList<QModelIndex> list, bool isManga)
|
||||
void ComicModel::setComicsType(QList<QModelIndex> list, FileType type)
|
||||
{
|
||||
QString connectionName = "";
|
||||
{
|
||||
@ -803,7 +818,7 @@ void ComicModel::setComicsManga(QList<QModelIndex> list, bool isManga)
|
||||
foreach (QModelIndex mi, list) {
|
||||
bool 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);
|
||||
}
|
||||
db.commit();
|
||||
@ -1122,6 +1137,26 @@ bool ComicModel::isFavorite(const QModelIndex &index)
|
||||
return isFavorite;
|
||||
}
|
||||
|
||||
void ComicModel::setShowRecent(bool showRecent)
|
||||
{
|
||||
if (this->showRecent == showRecent)
|
||||
return;
|
||||
|
||||
this->showRecent = showRecent;
|
||||
|
||||
emit dataChanged(index(0, 0), index(rowCount() - 1, 0), { ComicModel::ShowRecentRole });
|
||||
}
|
||||
|
||||
void ComicModel::setRecentRange(int days)
|
||||
{
|
||||
if (this->recentDays == days)
|
||||
return;
|
||||
|
||||
this->recentDays = days;
|
||||
|
||||
emit dataChanged(index(0, 0), index(rowCount() - 1, 0), { ComicModel::RecentRangeRole });
|
||||
}
|
||||
|
||||
void ComicModel::updateRating(int rating, QModelIndex mi)
|
||||
{
|
||||
ComicDB comic = getComic(mi);
|
||||
|
@ -31,11 +31,13 @@ public:
|
||||
Path = 6,
|
||||
Hash = 7,
|
||||
ReadColumn = 8,
|
||||
IsBis = 9,
|
||||
IsBis = 9, // TODO_METADATA: Remove this column
|
||||
CurrentPage = 10,
|
||||
Rating = 11,
|
||||
HasBeenOpened = 12,
|
||||
PublicationDate = 13,
|
||||
Added = 14,
|
||||
Type = 15,
|
||||
};
|
||||
|
||||
enum Roles {
|
||||
@ -55,6 +57,10 @@ public:
|
||||
CoverPathRole,
|
||||
PublicationDateRole,
|
||||
ReadableTitle,
|
||||
AddedRole,
|
||||
TypeRole,
|
||||
ShowRecentRole,
|
||||
RecentRangeRole,
|
||||
};
|
||||
|
||||
enum Mode {
|
||||
@ -107,7 +113,7 @@ public:
|
||||
// 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
|
||||
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);
|
||||
// void remove(ComicDB * comic, int row);
|
||||
void removeInTransaction(int row);
|
||||
@ -135,6 +141,9 @@ public:
|
||||
ComicModel::Mode getMode() { return mode; }
|
||||
unsigned long long int getSourceId() { return sourceId; }
|
||||
|
||||
void setShowRecent(bool visible);
|
||||
void setRecentRange(int days);
|
||||
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
public slots:
|
||||
@ -164,6 +173,9 @@ private:
|
||||
qulonglong sourceId;
|
||||
QString localizedDate(const QString &dbDate) const;
|
||||
|
||||
bool showRecent;
|
||||
qlonglong recentDays;
|
||||
|
||||
signals:
|
||||
void isEmpty();
|
||||
void searchNumResults(int);
|
||||
|
@ -64,23 +64,29 @@ static QString fields = "title,"
|
||||
//"coverSizeRatio," cover may have changed since the info was exported...
|
||||
//"originalCoverSize," // h/w
|
||||
// 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()
|
||||
: 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)
|
||||
{
|
||||
return createDatabase(QDir::cleanPath(path) + "/" + name + ".ydb");
|
||||
@ -102,12 +108,12 @@ QSqlDatabase DataBaseManagement::createDatabase(QString dest)
|
||||
// pragma.finish();
|
||||
DataBaseManagement::createTables(db);
|
||||
|
||||
QSqlQuery query("INSERT INTO folder (parentId, name, path) "
|
||||
"VALUES (1,'root', '/')",
|
||||
db);
|
||||
QSqlQuery insertRootQuery(db);
|
||||
insertRootQuery.prepare("INSERT INTO folder (parentId, name, path, added) "
|
||||
"VALUES (1, 'root', '/', :added)");
|
||||
insertRootQuery.bindValue(":added", QDateTime::currentSecsSinceEpoch());
|
||||
insertRootQuery.exec();
|
||||
}
|
||||
// query.finish();
|
||||
// db.close();
|
||||
|
||||
return db;
|
||||
}
|
||||
@ -156,13 +162,13 @@ bool DataBaseManagement::createTables(QSqlDatabase &database)
|
||||
"coverPage INTEGER DEFAULT 1,"
|
||||
"numPages INTEGER,"
|
||||
|
||||
"number INTEGER,"
|
||||
"number TEXT," // changed to text from INTEGER (9.13)
|
||||
"isBis BOOLEAN,"
|
||||
"count INTEGER,"
|
||||
|
||||
"volume TEXT,"
|
||||
"storyArc TEXT,"
|
||||
"arcNumber INTEGER,"
|
||||
"arcNumber TEXT," // changed to text from INTEGER (9.13)
|
||||
"arcCount INTEGER,"
|
||||
|
||||
"genere TEXT,"
|
||||
@ -174,11 +180,11 @@ bool DataBaseManagement::createTables(QSqlDatabase &database)
|
||||
"letterer 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,"
|
||||
"format TEXT,"
|
||||
"color BOOLEAN,"
|
||||
"ageRating BOOLEAN," // this is actually a string (TEXT), funny thing is that the current implementation works
|
||||
"ageRating TEXT,"
|
||||
|
||||
"synopsis TEXT,"
|
||||
"characters TEXT,"
|
||||
@ -190,7 +196,7 @@ bool DataBaseManagement::createTables(QSqlDatabase &database)
|
||||
// new 7.0 fields
|
||||
|
||||
"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, "
|
||||
"bookmark1 INTEGER DEFAULT -1, "
|
||||
"bookmark2 INTEGER DEFAULT -1, "
|
||||
@ -205,8 +211,23 @@ bool DataBaseManagement::createTables(QSqlDatabase &database)
|
||||
"coverSizeRatio REAL,"
|
||||
"originalCoverSize STRING," // h/w
|
||||
// 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();
|
||||
// queryComicInfo.finish();
|
||||
@ -226,7 +247,11 @@ bool DataBaseManagement::createTables(QSqlDatabase &database)
|
||||
"firstChildHash TEXT,"
|
||||
"customImage TEXT,"
|
||||
// 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)");
|
||||
success = success && queryFolder.exec();
|
||||
|
||||
@ -460,7 +485,25 @@ bool DataBaseManagement::importComicsInfo(QString source, QString dest)
|
||||
//--
|
||||
|
||||
// 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 ");
|
||||
|
||||
@ -496,6 +539,21 @@ bool DataBaseManagement::importComicsInfo(QString source, QString dest)
|
||||
"comicVineID,"
|
||||
"lastTimeOpened,"
|
||||
"coverSizeRatio,"
|
||||
"manga,"
|
||||
"added,"
|
||||
"type,"
|
||||
"editor,"
|
||||
"imprint,"
|
||||
"teams,"
|
||||
"locations,"
|
||||
"series,"
|
||||
"alternateSeries,"
|
||||
"alternateNumber,"
|
||||
"alternateCount,"
|
||||
"languageISO,"
|
||||
"seriesGroup,"
|
||||
"mainCharacterOrTeam,"
|
||||
"review,"
|
||||
"hash)"
|
||||
|
||||
"VALUES (:title,"
|
||||
@ -539,6 +597,23 @@ bool DataBaseManagement::importComicsInfo(QString source, QString dest)
|
||||
":coverSizeRatio,"
|
||||
":originalCoverSize,"
|
||||
|
||||
":manga,"
|
||||
":added,"
|
||||
":type,"
|
||||
":editor,"
|
||||
":imprint,"
|
||||
":teams,"
|
||||
":locations,"
|
||||
":series,"
|
||||
":alternateSeries,"
|
||||
":alternateNumber,"
|
||||
":alternateCount,"
|
||||
":languageISO,"
|
||||
":seriesGroup,"
|
||||
":mainCharacterOrTeam,"
|
||||
":review,"
|
||||
":tags,"
|
||||
|
||||
":hash )");
|
||||
|
||||
QSqlRecord record = newInfo.record();
|
||||
@ -596,6 +671,8 @@ bool DataBaseManagement::importComicsInfo(QString source, QString dest)
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
// TODO: update fields
|
||||
// TODO fix these bindings
|
||||
void DataBaseManagement::bindValuesFromRecord(const QSqlRecord &record, QSqlQuery &query)
|
||||
{
|
||||
@ -654,6 +731,22 @@ void DataBaseManagement::bindValuesFromRecord(const QSqlRecord &record, QSqlQuer
|
||||
bindValue("coverSizeRatio", 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);
|
||||
}
|
||||
|
||||
@ -757,6 +850,7 @@ bool DataBaseManagement::updateToCurrentVersion(const QString &path)
|
||||
bool pre8 = false;
|
||||
bool pre9_5 = false;
|
||||
bool pre9_8 = false;
|
||||
bool pre9_13 = false;
|
||||
|
||||
QString fullPath = path + "/library.ydb";
|
||||
|
||||
@ -770,6 +864,8 @@ bool DataBaseManagement::updateToCurrentVersion(const QString &path)
|
||||
pre9_5 = true;
|
||||
if (compareVersions(DataBaseManagement::checkValidDB(fullPath), "9.8.0") < 0)
|
||||
pre9_8 = true;
|
||||
if (compareVersions(DataBaseManagement::checkValidDB(fullPath), "9.13.0") < 0)
|
||||
pre9_13 = true;
|
||||
|
||||
QString connectionName = "";
|
||||
bool returnValue = false;
|
||||
@ -895,6 +991,53 @@ bool DataBaseManagement::updateToCurrentVersion(const QString &path)
|
||||
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();
|
||||
}
|
||||
|
@ -42,7 +42,6 @@ private:
|
||||
|
||||
public:
|
||||
DataBaseManagement();
|
||||
// TreeModel * newTreeModel(QString path);
|
||||
// crea una base de datos y todas sus tablas
|
||||
static QSqlDatabase createDatabase(QString name, QString path);
|
||||
static QSqlDatabase createDatabase(QString dest);
|
||||
|
@ -6,8 +6,6 @@
|
||||
#include "db_helper.h"
|
||||
#include "qnaturalsorting.h"
|
||||
#include "yacreader_global_gui.h"
|
||||
#include "QsLog.h"
|
||||
#include "query_parser.h"
|
||||
|
||||
#include <QtGui>
|
||||
|
||||
@ -54,21 +52,19 @@ void drawMacOSXFinishedFolderIcon()
|
||||
#define ROOT 1
|
||||
|
||||
FolderModel::FolderModel(QObject *parent)
|
||||
: QAbstractItemModel(parent), isSubfolder(false), rootItem(nullptr), folderIcon(YACReader::noHighlightedIcon(":/images/sidebar/folder.svg")), folderFinishedIcon(YACReader::noHighlightedIcon(":/images/sidebar/folder_finished.svg"))
|
||||
: QAbstractItemModel(parent), isSubfolder(false), rootItem(nullptr), folderIcon(YACReader::noHighlightedIcon(":/images/sidebar/folder.svg")), folderFinishedIcon(YACReader::noHighlightedIcon(":/images/sidebar/folder_finished.svg")), showRecent(false), recentDays(1)
|
||||
{
|
||||
}
|
||||
|
||||
FolderModel::FolderModel(QSqlQuery &sqlquery, QObject *parent)
|
||||
: QAbstractItemModel(parent), isSubfolder(false), rootItem(nullptr)
|
||||
: QAbstractItemModel(parent), isSubfolder(false), rootItem(nullptr), showRecent(false), recentDays(1)
|
||||
{
|
||||
// lo m<>s probable es que el nodo ra<72>z no necesite tener informaci<63>n
|
||||
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->id = ROOT;
|
||||
rootItem->parentItem = nullptr;
|
||||
setupModelData(sqlquery, rootItem);
|
||||
// sqlquery.finish();
|
||||
}
|
||||
|
||||
FolderModel::~FolderModel()
|
||||
@ -98,7 +94,13 @@ QHash<int, QByteArray> FolderModel::roleNames() const
|
||||
roles[IdRole] = "id";
|
||||
roles[MangaRole] = "is_manga";
|
||||
roles[CoverPathRole] = "cover_path";
|
||||
roles[FolderName] = "name";
|
||||
roles[FolderNameRole] = "name";
|
||||
roles[NumChildrenRole] = "num_children";
|
||||
roles[TypeRole] = "type";
|
||||
roles[AddedRole] = "added";
|
||||
roles[UpdatedRole] = "updated";
|
||||
roles[ShowRecentRole] = "show_recent";
|
||||
roles[RecentRangeRole] = "recent_range";
|
||||
|
||||
return roles;
|
||||
}
|
||||
@ -150,7 +152,7 @@ QVariant FolderModel::data(const QModelIndex &index, int role) const
|
||||
#endif
|
||||
}
|
||||
|
||||
if (role == FolderModel::FolderName) {
|
||||
if (role == FolderModel::FolderNameRole) {
|
||||
return item->data(FolderModel::Name);
|
||||
}
|
||||
|
||||
@ -169,6 +171,24 @@ QVariant FolderModel::data(const QModelIndex &index, int role) const
|
||||
if (role == FolderModel::CoverPathRole)
|
||||
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 == FolderModel::ShowRecentRole)
|
||||
return showRecent;
|
||||
|
||||
if (role == FolderModel::RecentRangeRole)
|
||||
return recentDays * 86400;
|
||||
|
||||
if (role != Qt::DisplayRole)
|
||||
return QVariant();
|
||||
|
||||
@ -183,7 +203,8 @@ Qt::ItemFlags FolderModel::flags(const QModelIndex &index) const
|
||||
return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDropEnabled | Qt::ItemIsDragEnabled;
|
||||
}
|
||||
|
||||
QVariant FolderModel::headerData(int section, Qt::Orientation orientation,
|
||||
QVariant FolderModel::headerData(int section,
|
||||
Qt::Orientation orientation,
|
||||
int role) const
|
||||
{
|
||||
if (rootItem == nullptr) {
|
||||
@ -323,65 +344,39 @@ void FolderModel::setupModelData(QSqlQuery &sqlquery, FolderItem *parent)
|
||||
int manga = record.indexOf("manga");
|
||||
int id = record.indexOf("id");
|
||||
int parentId = record.indexOf("parentId");
|
||||
int numChildren = record.indexOf("numChildren");
|
||||
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()) {
|
||||
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();
|
||||
data << sqlquery.value(name);
|
||||
data << sqlquery.value(path);
|
||||
data << sqlquery.value(finished);
|
||||
data << sqlquery.value(completed);
|
||||
data << sqlquery.value(manga);
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
return _databasePath;
|
||||
@ -406,7 +401,7 @@ void FolderModel::updateFolderCompletedStatus(const QModelIndexList &list, bool
|
||||
|
||||
if (!isSubfolder) {
|
||||
Folder f = DBHelper::loadFolder(item->id, db);
|
||||
f.setCompleted(status);
|
||||
f.completed = status;
|
||||
DBHelper::update(f, db);
|
||||
}
|
||||
}
|
||||
@ -415,7 +410,7 @@ void FolderModel::updateFolderCompletedStatus(const QModelIndexList &list, bool
|
||||
}
|
||||
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::updateFolderFinishedStatus(const QModelIndexList &list, bool status)
|
||||
@ -430,7 +425,7 @@ void FolderModel::updateFolderFinishedStatus(const QModelIndexList &list, bool s
|
||||
|
||||
if (!isSubfolder) {
|
||||
Folder f = DBHelper::loadFolder(item->id, db);
|
||||
f.setFinished(status);
|
||||
f.finished = status;
|
||||
DBHelper::update(f, db);
|
||||
}
|
||||
}
|
||||
@ -439,10 +434,10 @@ void FolderModel::updateFolderFinishedStatus(const QModelIndexList &list, bool s
|
||||
}
|
||||
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 = "";
|
||||
{
|
||||
@ -451,19 +446,19 @@ void FolderModel::updateFolderManga(const QModelIndexList &list, bool manga)
|
||||
foreach (QModelIndex mi, list) {
|
||||
auto item = static_cast<FolderItem *>(mi.internalPointer());
|
||||
|
||||
std::function<void(FolderItem *, bool)> setManga;
|
||||
setManga = [&setManga](FolderItem *item, bool manga) -> void {
|
||||
item->setData(FolderModel::Manga, manga);
|
||||
std::function<void(FolderItem *, YACReader::FileType)> setType;
|
||||
setType = [&setType](FolderItem *item, YACReader::FileType type) -> void {
|
||||
item->setData(FolderModel::Type, QVariant::fromValue(type));
|
||||
|
||||
for (auto child : item->children()) {
|
||||
setManga(child, manga);
|
||||
setType(child, type);
|
||||
}
|
||||
};
|
||||
|
||||
setManga(item, manga);
|
||||
setType(item, type);
|
||||
|
||||
if (!isSubfolder) {
|
||||
DBHelper::updateFolderTreeManga(item->id, db, manga);
|
||||
DBHelper::updateFolderTreeType(item->id, db, type);
|
||||
}
|
||||
}
|
||||
db.commit();
|
||||
@ -471,7 +466,7 @@ void FolderModel::updateFolderManga(const QModelIndexList &list, bool manga)
|
||||
}
|
||||
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)
|
||||
@ -552,7 +547,13 @@ Folder FolderModel::getFolder(const QModelIndex &mi)
|
||||
folderItem->parent()->data(Columns::Path).toString() + "/" + name,
|
||||
folderItem->data(Columns::Completed).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;
|
||||
}
|
||||
@ -589,74 +590,6 @@ QModelIndex FolderModel::getIndexFromFolder(const Folder &folder, const QModelIn
|
||||
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)
|
||||
{
|
||||
FolderItem *parentItem;
|
||||
@ -670,7 +603,9 @@ QModelIndex FolderModel::addFolderAtParent(const QString &folderName, const QMod
|
||||
newFolder.name = folderName;
|
||||
newFolder.parentId = parentItem->id;
|
||||
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 = "";
|
||||
{
|
||||
QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath);
|
||||
@ -687,7 +622,13 @@ QModelIndex FolderModel::addFolderAtParent(const QString &folderName, const QMod
|
||||
data << newFolder.path;
|
||||
data << false; // finished
|
||||
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);
|
||||
item->id = newFolder.id;
|
||||
@ -708,6 +649,26 @@ QUrl FolderModel::getCoverUrlPathForComicHash(const QString &hash) const
|
||||
return QUrl("file:" + _databasePath + "/covers/" + hash + ".jpg");
|
||||
}
|
||||
|
||||
void FolderModel::setShowRecent(bool showRecent)
|
||||
{
|
||||
if (this->showRecent == showRecent)
|
||||
return;
|
||||
|
||||
this->showRecent = showRecent;
|
||||
|
||||
emit dataChanged(index(0, 0), index(rowCount() - 1, 0), { FolderModel::ShowRecentRole });
|
||||
}
|
||||
|
||||
void FolderModel::setRecentRange(int days)
|
||||
{
|
||||
if (this->recentDays == days)
|
||||
return;
|
||||
|
||||
this->recentDays = days;
|
||||
|
||||
emit dataChanged(index(0, 0), index(rowCount() - 1, 0), { FolderModel::RecentRangeRole });
|
||||
}
|
||||
|
||||
void FolderModel::deleteFolder(const QModelIndex &mi)
|
||||
{
|
||||
beginRemoveRows(mi.parent(), mi.row(), mi.row());
|
||||
|
@ -66,13 +66,10 @@ public:
|
||||
void setupModelData(QString path);
|
||||
QString getDatabase();
|
||||
QString getFolderPath(const QModelIndex &folder);
|
||||
// QModelIndex indexFromItem(FolderItem * item, int column);
|
||||
|
||||
// bool isFilterEnabled(){return filterEnabled;};
|
||||
|
||||
void updateFolderCompletedStatus(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);
|
||||
FolderModel *getSubfoldersModel(const QModelIndex &mi);
|
||||
@ -80,28 +77,40 @@ public:
|
||||
Folder getFolder(const QModelIndex &mi);
|
||||
QModelIndex getIndexFromFolder(const Folder &folder, const QModelIndex &parent = QModelIndex());
|
||||
|
||||
void fetchMoreFromDB(const QModelIndex &parent);
|
||||
|
||||
QModelIndex addFolderAtParent(const QString &folderName, const QModelIndex &parent);
|
||||
|
||||
Q_INVOKABLE QUrl getCoverUrlPathForComicHash(const QString &hash) const;
|
||||
|
||||
void setShowRecent(bool showRecent);
|
||||
void setRecentRange(int days);
|
||||
|
||||
enum Columns {
|
||||
Name = 0,
|
||||
Path = 1,
|
||||
Finished = 2,
|
||||
Completed = 3,
|
||||
Manga = 4,
|
||||
FirstChildHash = 5
|
||||
}; // id INTEGER PRIMARY KEY, parentId INTEGER NOT NULL, name TEXT NOT NULL, path TEXT NOT NULL
|
||||
Path,
|
||||
Finished,
|
||||
Completed,
|
||||
Manga, // deprecated
|
||||
NumChildren,
|
||||
FirstChildHash,
|
||||
CustomImage,
|
||||
Type, // FileType
|
||||
Added,
|
||||
Updated,
|
||||
};
|
||||
|
||||
enum Roles {
|
||||
FinishedRole = Qt::UserRole + 1,
|
||||
CompletedRole,
|
||||
IdRole,
|
||||
MangaRole,
|
||||
MangaRole, // deprecated
|
||||
CoverPathRole,
|
||||
FolderName,
|
||||
FolderNameRole,
|
||||
NumChildrenRole,
|
||||
TypeRole,
|
||||
AddedRole,
|
||||
UpdatedRole,
|
||||
ShowRecentRole,
|
||||
RecentRangeRole,
|
||||
};
|
||||
|
||||
bool isSubfolder;
|
||||
@ -112,9 +121,7 @@ public slots:
|
||||
|
||||
private:
|
||||
void fullSetup(QSqlQuery &sqlquery, FolderItem *parent);
|
||||
|
||||
void setupModelData(QSqlQuery &sqlquery, FolderItem *parent);
|
||||
void updateFolderModelData(QSqlQuery &sqlquery, FolderItem *parent);
|
||||
|
||||
FolderItem *rootItem; // el árbol
|
||||
QMap<unsigned long long int, FolderItem *> items; // relación entre folders
|
||||
@ -123,6 +130,9 @@ private:
|
||||
|
||||
QIcon folderIcon;
|
||||
QIcon folderFinishedIcon;
|
||||
|
||||
bool showRecent;
|
||||
qlonglong recentDays;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -17,6 +17,14 @@ Token QueryLexer::next()
|
||||
case '(':
|
||||
case ')':
|
||||
return single(Token::Type::opcode);
|
||||
case ':':
|
||||
return single(Token::Type::equal);
|
||||
case '=':
|
||||
return equal();
|
||||
case '<':
|
||||
return minor();
|
||||
case '>':
|
||||
return major();
|
||||
case '"':
|
||||
return quotedWord();
|
||||
default:
|
||||
@ -44,7 +52,7 @@ Token QueryLexer::word()
|
||||
auto start = index;
|
||||
get();
|
||||
auto current = peek();
|
||||
while (current != '\0' && !isSpace(current) && current != '"' && current != '(' && current != ')') {
|
||||
while (current != '\0' && !isSpace(current) && current != '"' && current != '(' && current != ')' && current != ':' && current != '=' && current != '<' && current != '>') {
|
||||
get();
|
||||
current = peek();
|
||||
}
|
||||
@ -70,6 +78,45 @@ Token QueryLexer::quotedWord()
|
||||
return Token(Token::Type::eof);
|
||||
}
|
||||
|
||||
Token QueryLexer::minor()
|
||||
{
|
||||
auto start = index;
|
||||
get();
|
||||
auto current = peek();
|
||||
if (current == '=') {
|
||||
get();
|
||||
return Token(Token::Type::minorOrEqual, input.substr(start, index - start));
|
||||
}
|
||||
|
||||
return Token(Token::Type::minor, input.substr(start, index - start));
|
||||
}
|
||||
|
||||
Token QueryLexer::major()
|
||||
{
|
||||
auto start = index;
|
||||
get();
|
||||
auto current = peek();
|
||||
if (current == '=') {
|
||||
get();
|
||||
return Token(Token::Type::majorOrEqual, input.substr(start, index - start));
|
||||
}
|
||||
|
||||
return Token(Token::Type::major, input.substr(start, index - start));
|
||||
}
|
||||
|
||||
Token QueryLexer::equal()
|
||||
{
|
||||
auto start = index;
|
||||
get();
|
||||
auto current = peek();
|
||||
if (current == '=') {
|
||||
get();
|
||||
return Token(Token::Type::exactEqual, input.substr(start, index - start));
|
||||
}
|
||||
|
||||
return Token(Token::Type::equal, input.substr(start, index - start));
|
||||
}
|
||||
|
||||
bool QueryLexer::isSpace(char c)
|
||||
{
|
||||
switch (c) {
|
||||
|
@ -11,6 +11,12 @@ public:
|
||||
opcode,
|
||||
word,
|
||||
quotedWord,
|
||||
equal, // =
|
||||
exactEqual, // ==
|
||||
minor,
|
||||
major,
|
||||
minorOrEqual,
|
||||
majorOrEqual,
|
||||
undefined
|
||||
};
|
||||
|
||||
@ -50,6 +56,9 @@ private:
|
||||
Token single(Token::Type type);
|
||||
Token word();
|
||||
Token quotedWord();
|
||||
Token minor();
|
||||
Token major();
|
||||
Token equal();
|
||||
|
||||
bool isSpace(char c);
|
||||
};
|
||||
|
@ -5,19 +5,25 @@
|
||||
#include <numeric>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <QsLog.h>
|
||||
|
||||
const std::map<QueryParser::FieldType, std::vector<std::string>> QueryParser::fieldNames {
|
||||
{ FieldType::numeric, { "numpages", "number", "count", "arcnumber", "arccount" } },
|
||||
{ FieldType::text, { "title", "volume", "storyarc", "genere", "writer", "penciller", "inker", "colorist", "letterer", "coverartist", "publisher", "format", "agerating", "synopsis", "characters", "notes" } },
|
||||
{ FieldType::boolean, { "isbis", "color", "read", "manga" } },
|
||||
{ FieldType::date, { "date" } },
|
||||
// TODO_METADATA support dates
|
||||
{ FieldType::numeric, { "numpages", "count", "arccount", "alternateCount", "rating" } },
|
||||
{ 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, { "color", "read", "edited", "hasBeenOpened" } },
|
||||
{ FieldType::date, { "date", "added", "lastTimeOpened" } },
|
||||
{ FieldType::filename, { "filename" } },
|
||||
{ FieldType::folder, { "folder" } },
|
||||
{ FieldType::booleanFolder, { "completed", "finished" } },
|
||||
{ FieldType::enumField, { "type" } },
|
||||
{ FieldType::enumFieldFolder, { "foldertype" } }
|
||||
};
|
||||
|
||||
int QueryParser::TreeNode::buildSqlString(std::string &sqlString, int bindPosition) const
|
||||
{
|
||||
if (t == "token") {
|
||||
// TODO: add some semantic checks, not all operators apply to all fields
|
||||
if (t == "expression") {
|
||||
++bindPosition;
|
||||
if (toLower(children[0].t) == "all") {
|
||||
sqlString += "(";
|
||||
@ -26,7 +32,15 @@ int QueryParser::TreeNode::buildSqlString(std::string &sqlString, int bindPositi
|
||||
}
|
||||
sqlString += "UPPER(c.filename) LIKE UPPER(:bindPosition" + std::to_string(bindPosition) + ") OR ";
|
||||
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 })) {
|
||||
std::string sqlOperator;
|
||||
if (expOperator == ":" || expOperator == "=" || expOperator == "==") {
|
||||
sqlOperator = "=";
|
||||
} else {
|
||||
sqlOperator = expOperator;
|
||||
}
|
||||
sqlString += "ci." + children[0].t + " " + sqlOperator + " :bindPosition" + std::to_string(bindPosition) + " ";
|
||||
} else if (isIn(fieldType(children[0].t), { FieldType::boolean, FieldType::enumField })) {
|
||||
sqlString += "ci." + children[0].t + " = :bindPosition" + std::to_string(bindPosition) + " ";
|
||||
} else if (fieldType(children[0].t) == FieldType::filename) {
|
||||
sqlString += "(UPPER(c." + children[0].t + ") LIKE UPPER(:bindPosition" + std::to_string(bindPosition) + ")) ";
|
||||
@ -34,8 +48,23 @@ int QueryParser::TreeNode::buildSqlString(std::string &sqlString, int bindPositi
|
||||
sqlString += "(UPPER(f.name) LIKE UPPER(:bindPosition" + std::to_string(bindPosition) + ")) ";
|
||||
} else if (fieldType(children[0].t) == FieldType::booleanFolder) {
|
||||
sqlString += "f." + children[0].t + " = :bindPosition" + std::to_string(bindPosition) + " ";
|
||||
} else if (fieldType(children[0].t) == FieldType::enumFieldFolder) {
|
||||
if (children[0].t == "foldertype") {
|
||||
sqlString += "f.type = :bindPosition" + std::to_string(bindPosition) + " ";
|
||||
} else {
|
||||
sqlString += "f." + children[0].t + " = :bindPosition" + std::to_string(bindPosition) + " ";
|
||||
}
|
||||
} else {
|
||||
sqlString += "(UPPER(ci." + children[0].t + ") LIKE UPPER(:bindPosition" + std::to_string(bindPosition) + ")) ";
|
||||
if (expOperator == "=" || expOperator == ":" || expOperator == "") {
|
||||
sqlString += "(UPPER(ci." + children[0].t + ") LIKE UPPER(:bindPosition" + std::to_string(bindPosition) + ")) ";
|
||||
} else {
|
||||
if (expOperator == "==") {
|
||||
sqlString += "(UPPER(ci." + children[0].t + ") = UPPER(:bindPosition" + std::to_string(bindPosition) + ")) ";
|
||||
} else {
|
||||
// support for <,>,<=,>= in text fields makes sense for number, arcNumber, alternateNumber, but (TODO) the syntax won't prevent other fields from using this operators
|
||||
sqlString += "(CAST(ci." + children[0].t + " as REAL) " + expOperator + " CAST(:bindPosition" + std::to_string(bindPosition) + " as REAL)) ";
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (t == "not") {
|
||||
sqlString += "(NOT ";
|
||||
@ -54,7 +83,7 @@ int QueryParser::TreeNode::buildSqlString(std::string &sqlString, int bindPositi
|
||||
|
||||
int QueryParser::TreeNode::bindValues(QSqlQuery &selectQuery, int bindPosition) const
|
||||
{
|
||||
if (t == "token") {
|
||||
if (t == "expression") {
|
||||
std::string bind_string(":bindPosition" + std::to_string(++bindPosition));
|
||||
if (isIn(fieldType(children[0].t), { FieldType::numeric })) {
|
||||
selectQuery.bindValue(QString::fromStdString(bind_string), std::stoi(children[1].t));
|
||||
@ -67,8 +96,30 @@ int QueryParser::TreeNode::bindValues(QSqlQuery &selectQuery, int bindPosition)
|
||||
} else {
|
||||
selectQuery.bindValue(QString::fromStdString(bind_string), std::stoi(value));
|
||||
}
|
||||
} else if ((isIn(fieldType(children[0].t), { FieldType::enumField, FieldType::enumFieldFolder }))) {
|
||||
auto enumType = children[0].t;
|
||||
auto value = toLower(children[1].t);
|
||||
if (enumType == "type" || enumType == "foldertype") {
|
||||
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 {
|
||||
selectQuery.bindValue(QString::fromStdString(bind_string), QString::fromStdString("%%" + children[1].t + "%%"));
|
||||
if (expOperator == "=" || expOperator == ":" || expOperator == "") {
|
||||
selectQuery.bindValue(QString::fromStdString(bind_string), QString::fromStdString("%%" + children[1].t + "%%"));
|
||||
} else {
|
||||
selectQuery.bindValue(QString::fromStdString(bind_string), QString::fromStdString(children[1].t));
|
||||
}
|
||||
}
|
||||
} else if (t == "not") {
|
||||
bindPosition = children[0].bindValues(selectQuery, bindPosition);
|
||||
@ -151,6 +202,16 @@ void QueryParser::advance()
|
||||
currentToken = lexer.next();
|
||||
}
|
||||
|
||||
bool QueryParser::isOperatorToken(Token::Type type)
|
||||
{
|
||||
return type == Token::Type::equal ||
|
||||
type == Token::Type::exactEqual ||
|
||||
type == Token::Type::minor ||
|
||||
type == Token::Type::minorOrEqual ||
|
||||
type == Token::Type::major ||
|
||||
type == Token::Type::majorOrEqual;
|
||||
}
|
||||
|
||||
QueryParser::FieldType QueryParser::fieldType(const std::string &str)
|
||||
{
|
||||
for (const auto &names : fieldNames) {
|
||||
@ -223,25 +284,39 @@ QueryParser::TreeNode QueryParser::locationExpression()
|
||||
if (!isIn(tokenType(), { Token::Type::word, Token::Type::quotedWord })) {
|
||||
throw std::invalid_argument("Invalid syntax. Expected a lookup name or a word");
|
||||
}
|
||||
|
||||
return expression();
|
||||
}
|
||||
|
||||
QueryParser::TreeNode QueryParser::expression()
|
||||
{
|
||||
if (tokenType() == Token::Type::word) {
|
||||
auto left = token(true);
|
||||
if (isOperatorToken(tokenType())) {
|
||||
auto expOperator = token(true);
|
||||
if (tokenType() != Token::Type::word && tokenType() != Token::Type::quotedWord) {
|
||||
throw std::invalid_argument("missing right operand");
|
||||
}
|
||||
auto right = token(true);
|
||||
|
||||
return TreeNode("expression", { TreeNode(toLower(left), {}), TreeNode(right, {}) }, expOperator);
|
||||
} else {
|
||||
return TreeNode("expression", { TreeNode("all", {}), TreeNode(left, {}) });
|
||||
}
|
||||
}
|
||||
|
||||
return baseToken();
|
||||
}
|
||||
|
||||
QueryParser::TreeNode QueryParser::baseToken()
|
||||
{
|
||||
if (tokenType() == Token::Type::quotedWord) {
|
||||
return TreeNode("token", { TreeNode("all", {}), TreeNode(token(true), {}) });
|
||||
return TreeNode("expression", { TreeNode("all", {}), TreeNode(token(true), {}) });
|
||||
}
|
||||
|
||||
auto words(split(token(true), ':'));
|
||||
|
||||
if (words.size() > 1 && fieldType(words[0].toStdString()) != FieldType::unknown) {
|
||||
auto loc(toLower(words[0].toStdString()));
|
||||
words.erase(words.begin());
|
||||
if (words.size() == 1 && tokenType() == Token::Type::quotedWord) {
|
||||
return TreeNode("token", { TreeNode(loc, {}), TreeNode(token(true), {}) });
|
||||
}
|
||||
return TreeNode("token", { TreeNode(loc, {}), TreeNode(join(words, ":"), {}) });
|
||||
if (tokenType() == Token::Type::word) {
|
||||
return TreeNode("expression", { TreeNode("all", {}), TreeNode(token(true), {}) });
|
||||
}
|
||||
|
||||
return TreeNode("token", { TreeNode("all", {}), TreeNode(join(words, ":"), {}) });
|
||||
return TreeNode("expression", { TreeNode("all", {}), TreeNode(token(true), {}) });
|
||||
}
|
||||
|
@ -9,8 +9,8 @@
|
||||
#include <vector>
|
||||
#include <list>
|
||||
|
||||
#define SEARCH_FOLDERS_QUERY "SELECT DISTINCT f.id, f.parentId, f.name, f.path, f.finished, f.completed, f.numChildren, f.firstChildHash FROM folder f LEFT JOIN comic c ON (f.id = c.parentId) INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) WHERE "
|
||||
#define SEARCH_COMICS_QUERY "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.coverSizeRatio,ci.lastTimeOpened,ci.manga FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) LEFT JOIN folder f ON (f.id == c.parentId) WHERE "
|
||||
#define SEARCH_FOLDERS_QUERY "SELECT DISTINCT * FROM folder f LEFT JOIN comic c ON (f.id = c.parentId) INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) WHERE "
|
||||
#define SEARCH_COMICS_QUERY "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,ci.added,ci.type FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) LEFT JOIN folder f ON (f.id == c.parentId) WHERE "
|
||||
|
||||
/**
|
||||
* This class is used to generate an SQL query string from a search expression,
|
||||
@ -25,7 +25,9 @@
|
||||
* and_expression ::= not_expression [ [ 'and' ] and_expression ]
|
||||
* not_expression ::= [ 'not' ] location_expression
|
||||
* location_expression ::= base_token | ( '(' or_expression ')' )
|
||||
* base_token ::= a sequence of letters and colons, perhaps quoted
|
||||
* expression :: base_token | base_token 'operator' base_token
|
||||
* operator :: [':' '=' '<' '>' '<=' '=>']
|
||||
* base_token ::= a sequence of letters, perhaps quoted
|
||||
*
|
||||
* Usage Example:
|
||||
* QSqlQuery selectQuery(db);
|
||||
@ -47,9 +49,10 @@ public:
|
||||
struct TreeNode {
|
||||
std::string t;
|
||||
std::vector<TreeNode> children;
|
||||
std::string expOperator;
|
||||
|
||||
explicit TreeNode(std::string t, std::vector<TreeNode> children)
|
||||
: t(t), children(children)
|
||||
explicit TreeNode(std::string t, std::vector<TreeNode> children, std::string expOperator = "")
|
||||
: t(t), children(children), expOperator(expOperator)
|
||||
{
|
||||
}
|
||||
|
||||
@ -78,6 +81,8 @@ private:
|
||||
return std::find(v.begin(), v.end(), e) != v.end();
|
||||
}
|
||||
|
||||
bool isOperatorToken(Token::Type type);
|
||||
|
||||
enum class FieldType { unknown,
|
||||
numeric,
|
||||
text,
|
||||
@ -85,7 +90,9 @@ private:
|
||||
date,
|
||||
folder,
|
||||
booleanFolder,
|
||||
filename };
|
||||
filename,
|
||||
enumField,
|
||||
enumFieldFolder };
|
||||
static FieldType fieldType(const std::string &str);
|
||||
|
||||
static std::string join(const QStringList &strings, const std::string &delim);
|
||||
@ -95,6 +102,7 @@ private:
|
||||
TreeNode andExpression();
|
||||
TreeNode notExpression();
|
||||
TreeNode locationExpression();
|
||||
TreeNode expression();
|
||||
TreeNode baseToken();
|
||||
|
||||
static const std::map<FieldType, std::vector<std::string>> fieldNames;
|
||||
|
@ -66,7 +66,7 @@ QList<LibraryItem *> DBHelper::getFolderComicsFromLibraryForReading(qulonglong l
|
||||
return naturalSortLessThanCI(c1->name, c2->name);
|
||||
} else {
|
||||
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 {
|
||||
return c2->info.number.isNull();
|
||||
}
|
||||
@ -637,9 +637,28 @@ void DBHelper::update(ComicInfo *comicInfo, QSqlDatabase &db)
|
||||
//--
|
||||
|
||||
// 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);
|
||||
|
||||
@ -698,7 +717,28 @@ void DBHelper::update(ComicInfo *comicInfo, QSqlDatabase &db)
|
||||
updateComicInfo.bindValue(":coverSizeRatio", comicInfo->coverSizeRatio);
|
||||
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();
|
||||
|
||||
QLOG_INFO() << updateComicInfo.lastError().databaseText();
|
||||
QLOG_INFO() << updateComicInfo.lastError().text();
|
||||
QLOG_INFO() << updateComicInfo.lastQuery();
|
||||
}
|
||||
|
||||
void DBHelper::updateRead(ComicInfo *comicInfo, QSqlDatabase &db)
|
||||
@ -718,12 +758,10 @@ void DBHelper::update(const Folder &folder, QSqlDatabase &db)
|
||||
QSqlQuery updateFolderInfo(db);
|
||||
updateFolderInfo.prepare("UPDATE folder SET "
|
||||
"finished = :finished, "
|
||||
"completed = :completed, "
|
||||
"manga = :manga "
|
||||
"completed = :completed "
|
||||
"WHERE id = :id ");
|
||||
updateFolderInfo.bindValue(":finished", folder.isFinished() ? 1 : 0);
|
||||
updateFolderInfo.bindValue(":completed", folder.isCompleted() ? 1 : 0);
|
||||
updateFolderInfo.bindValue(":manga", folder.isManga() ? 1 : 0);
|
||||
updateFolderInfo.bindValue(":finished", folder.finished ? 1 : 0);
|
||||
updateFolderInfo.bindValue(":completed", folder.completed ? 1 : 0);
|
||||
updateFolderInfo.bindValue(":id", folder.id);
|
||||
updateFolderInfo.exec();
|
||||
}
|
||||
@ -762,7 +800,7 @@ Folder DBHelper::updateChildrenInfo(qulonglong folderId, QSqlDatabase &db)
|
||||
} else {
|
||||
for (auto item : updatedSubfolders) {
|
||||
auto f = static_cast<Folder *>(item);
|
||||
auto firstChildHash = f->getFirstChildHash();
|
||||
auto firstChildHash = f->firstChildHash;
|
||||
if (!firstChildHash.isEmpty()) {
|
||||
coverHash = firstChildHash;
|
||||
break;
|
||||
@ -770,16 +808,16 @@ Folder DBHelper::updateChildrenInfo(qulonglong folderId, QSqlDatabase &db)
|
||||
}
|
||||
}
|
||||
|
||||
folder.setNumChildren(subfolders.count() + comics.count());
|
||||
folder.setFirstChildHash(coverHash);
|
||||
folder.numChildren = subfolders.count() + comics.count();
|
||||
folder.firstChildHash = coverHash;
|
||||
|
||||
QSqlQuery updateFolderInfo(db);
|
||||
updateFolderInfo.prepare("UPDATE folder SET "
|
||||
"numChildren = :numChildren, "
|
||||
"firstChildHash = :firstChildHash "
|
||||
"WHERE id = :id ");
|
||||
updateFolderInfo.bindValue(":numChildren", folder.getNumChildren());
|
||||
updateFolderInfo.bindValue(":firstChildHash", folder.getFirstChildHash());
|
||||
updateFolderInfo.bindValue(":numChildren", folder.numChildren);
|
||||
updateFolderInfo.bindValue(":firstChildHash", folder.firstChildHash);
|
||||
updateFolderInfo.bindValue(":id", folderId);
|
||||
updateFolderInfo.exec();
|
||||
|
||||
@ -854,7 +892,7 @@ void DBHelper::updateReadingRemoteProgress(const ComicInfo &comicInfo, QSqlDatab
|
||||
updateComicInfo.bindValue(":read", comicInfo.read ? 1 : 0);
|
||||
updateComicInfo.bindValue(":currentPage", comicInfo.currentPage);
|
||||
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(":rating", comicInfo.rating);
|
||||
updateComicInfo.exec();
|
||||
@ -1067,7 +1105,7 @@ void DBHelper::updateFromRemoteClientWithHash(const QList<ComicInfo> &comics)
|
||||
updateComicInfo.bindValue(":read", info.read ? 1 : 0);
|
||||
updateComicInfo.bindValue(":currentPage", info.currentPage);
|
||||
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(":rating", info.rating);
|
||||
updateComicInfo.exec();
|
||||
@ -1194,12 +1232,16 @@ void DBHelper::updateComicsInfo(QList<ComicDB> &comics, const QString &databaseP
|
||||
// inserts
|
||||
qulonglong DBHelper::insert(Folder *folder, QSqlDatabase &db)
|
||||
{
|
||||
auto added = QDateTime::currentSecsSinceEpoch();
|
||||
folder->added = added;
|
||||
|
||||
QSqlQuery query(db);
|
||||
query.prepare("INSERT INTO folder (parentId, name, path) "
|
||||
"VALUES (:parentId, :name, :path)");
|
||||
query.prepare("INSERT INTO folder (parentId, name, path, added) "
|
||||
"VALUES (:parentId, :name, :path, :added)");
|
||||
query.bindValue(":parentId", folder->parentId);
|
||||
query.bindValue(":name", folder->name);
|
||||
query.bindValue(":path", folder->path);
|
||||
query.bindValue(":added", added);
|
||||
query.exec();
|
||||
|
||||
return query.lastInsertId().toULongLong();
|
||||
@ -1207,16 +1249,21 @@ qulonglong DBHelper::insert(Folder *folder, QSqlDatabase &db)
|
||||
|
||||
qulonglong DBHelper::insert(ComicDB *comic, QSqlDatabase &db, bool insertAllInfo)
|
||||
{
|
||||
auto added = QDateTime::currentSecsSinceEpoch();
|
||||
|
||||
if (!comic->info.existOnDb) {
|
||||
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(":numPages", comic->info.numPages);
|
||||
comicInfoInsert.bindValue(":coverSizeRatio", comic->info.coverSizeRatio);
|
||||
comicInfoInsert.bindValue(":originalCoverSize", comic->info.originalCoverSize);
|
||||
comicInfoInsert.bindValue(":added", added);
|
||||
comicInfoInsert.exec();
|
||||
comic->info.id = comicInfoInsert.lastInsertId().toULongLong();
|
||||
comic->info.added = added;
|
||||
comic->_hasCover = false;
|
||||
|
||||
if (insertAllInfo) {
|
||||
@ -1234,6 +1281,14 @@ qulonglong DBHelper::insert(ComicDB *comic, QSqlDatabase &db, bool insertAllInfo
|
||||
query.bindValue(":path", comic->path);
|
||||
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();
|
||||
}
|
||||
|
||||
@ -1342,6 +1397,7 @@ void DBHelper::insertComicsInReadingList(const QList<ComicDB> &comicsList, qulon
|
||||
|
||||
db.commit();
|
||||
}
|
||||
|
||||
// queries
|
||||
QList<LibraryItem *> DBHelper::getFoldersFromParent(qulonglong parentId, QSqlDatabase &db, bool sort)
|
||||
{
|
||||
@ -1356,20 +1412,33 @@ QList<LibraryItem *> DBHelper::getFoldersFromParent(qulonglong parentId, QSqlDat
|
||||
|
||||
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 numChildren = record.indexOf("numChildren");
|
||||
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");
|
||||
|
||||
Folder *currentItem;
|
||||
while (selectQuery.next()) {
|
||||
// TODO sort by sort indicator and name
|
||||
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->setNumChildren(selectQuery.value(numChildren).toInt());
|
||||
currentItem->setFirstChildHash(selectQuery.value(firstChildHash).toString());
|
||||
currentItem->setCustomImage(selectQuery.value(customImage).toString());
|
||||
currentItem->finished = selectQuery.value(finished).toBool();
|
||||
currentItem->completed = selectQuery.value(completed).toBool();
|
||||
if (!selectQuery.value(numChildren).isNull() && selectQuery.value(numChildren).isValid()) {
|
||||
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;
|
||||
|
||||
@ -1524,21 +1593,21 @@ QList<Label> DBHelper::getLabels(qulonglong libraryId)
|
||||
return labels;
|
||||
}
|
||||
|
||||
void DBHelper::updateFolderTreeManga(qulonglong id, QSqlDatabase &db, bool manga)
|
||||
void DBHelper::updateFolderTreeType(qulonglong id, QSqlDatabase &db, YACReader::FileType type)
|
||||
{
|
||||
QSqlQuery updateFolderQuery(db);
|
||||
updateFolderQuery.prepare("UPDATE folder "
|
||||
"SET manga = :manga "
|
||||
"SET type = :type "
|
||||
"WHERE id = :id");
|
||||
updateFolderQuery.bindValue(":manga", manga ? 1 : 0);
|
||||
updateFolderQuery.bindValue(":type", static_cast<int>(type));
|
||||
updateFolderQuery.bindValue(":id", id);
|
||||
updateFolderQuery.exec();
|
||||
|
||||
QSqlQuery updateComicInfo(db);
|
||||
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)");
|
||||
updateComicInfo.bindValue(":manga", manga ? 1 : 0);
|
||||
updateComicInfo.bindValue(":type", static_cast<int>(type));
|
||||
updateComicInfo.bindValue(":parentId", id);
|
||||
updateComicInfo.exec();
|
||||
|
||||
@ -1550,24 +1619,49 @@ void DBHelper::updateFolderTreeManga(qulonglong id, QSqlDatabase &db, bool manga
|
||||
int childFolderIdPos = getSubFoldersQuery.record().indexOf("id");
|
||||
|
||||
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 folder;
|
||||
|
||||
QSqlQuery query(db);
|
||||
query.prepare("SELECT * FROM folder WHERE id = :id");
|
||||
query.bindValue(":id", id);
|
||||
query.exec();
|
||||
|
||||
Folder folder;
|
||||
|
||||
folder.id = id;
|
||||
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();
|
||||
|
||||
int id = record.indexOf("id");
|
||||
int parentId = record.indexOf("parentId");
|
||||
int name = record.indexOf("name");
|
||||
int path = record.indexOf("path");
|
||||
@ -1577,74 +1671,36 @@ Folder DBHelper::loadFolder(qulonglong id, QSqlDatabase &db)
|
||||
int numChildren = record.indexOf("numChildren");
|
||||
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");
|
||||
|
||||
if (query.next()) {
|
||||
folder.id = query.value(id).toULongLong();
|
||||
folder.parentId = query.value(parentId).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());
|
||||
folder.finished = query.value(finished).toBool();
|
||||
folder.completed = 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());
|
||||
if (!query.value(numChildren).isNull() && query.value(numChildren).isValid()) {
|
||||
folder.numChildren = query.value(numChildren).toInt();
|
||||
}
|
||||
folder.firstChildHash = query.value(firstChildHash).toString();
|
||||
folder.customImage = query.value(customImage).toString();
|
||||
|
||||
// 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)
|
||||
@ -1776,6 +1832,22 @@ ComicInfo DBHelper::getComicInfoFromQuery(QSqlQuery &query, const QString &idKey
|
||||
int coverSizeRatio = record.indexOf("coverSizeRatio");
|
||||
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.hash = query.value(hash).toString();
|
||||
@ -1840,6 +1912,24 @@ ComicInfo DBHelper::getComicInfoFromQuery(QSqlQuery &query, const QString &idKey
|
||||
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;
|
||||
|
||||
return comicInfo;
|
||||
|
@ -65,7 +65,7 @@ public:
|
||||
static void update(ComicDB *comics, QSqlDatabase &db);
|
||||
static void update(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 Folder updateChildrenInfo(qulonglong folderId, 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<Label> getLabels(qulonglong libraryId);
|
||||
|
||||
static void updateFolderTreeManga(qulonglong id, QSqlDatabase &db, bool manga);
|
||||
static void updateFolderTreeType(qulonglong id, QSqlDatabase &db, YACReader::FileType type);
|
||||
|
||||
// load
|
||||
static Folder loadFolder(qulonglong id, 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(QString cname, QString cpath, QString chash, QSqlDatabase &database);
|
||||
static ComicInfo loadComicInfo(QString hash, QSqlDatabase &db);
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
using namespace YACReader;
|
||||
|
||||
FolderContentView::FolderContentView(QWidget *parent)
|
||||
FolderContentView::FolderContentView(QAction *toogleRecentVisibilityAction, QWidget *parent)
|
||||
: QWidget { parent }, parent(QModelIndex()), comicModel(new ComicModel()), folderModel(new FolderModel())
|
||||
{
|
||||
qmlRegisterType<FolderModel>("com.yacreader.FolderModel", 1, 0, "FolderModel");
|
||||
@ -59,7 +59,11 @@ FolderContentView::FolderContentView(QWidget *parent)
|
||||
connect(coverSizeSlider, &QAbstractSlider::valueChanged, this, &FolderContentView::setCoversSize);
|
||||
|
||||
toolbar = new QToolBar();
|
||||
toolbar->setStyleSheet("QToolBar {border: none;}");
|
||||
toolbar->setIconSize(QSize(18, 18));
|
||||
toolbar->addWidget(new YACReaderToolBarStretch);
|
||||
toolbar->addAction(toogleRecentVisibilityAction);
|
||||
toolbar->addSeparator();
|
||||
toolbar->addWidget(coverSizeSliderWidget);
|
||||
|
||||
auto l = new QVBoxLayout;
|
||||
@ -205,6 +209,16 @@ void FolderContentView::reloadContinueReadingModel()
|
||||
}
|
||||
}
|
||||
|
||||
void FolderContentView::setShowRecent(bool visible)
|
||||
{
|
||||
folderModel->setShowRecent(visible);
|
||||
}
|
||||
|
||||
void FolderContentView::setRecentRange(int days)
|
||||
{
|
||||
folderModel->setRecentRange(days);
|
||||
}
|
||||
|
||||
void FolderContentView::openFolder(int index)
|
||||
{
|
||||
emit subfolderSelected(this->parent, index);
|
||||
|
@ -19,10 +19,12 @@ class FolderContentView : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit FolderContentView(QWidget *parent = nullptr);
|
||||
explicit FolderContentView(QAction *toogleRecentVisibilityAction, QWidget *parent = nullptr);
|
||||
void setModel(const QModelIndex &parent, FolderModel *model);
|
||||
void setContinueReadingModel(ComicModel *model);
|
||||
void reloadContinueReadingModel();
|
||||
void setShowRecent(bool visible);
|
||||
void setRecentRange(int days);
|
||||
|
||||
FolderModel *currentFolderModel() { return folderModel; }
|
||||
signals:
|
||||
|
@ -170,7 +170,6 @@ GridComicsView::~GridComicsView()
|
||||
|
||||
void GridComicsView::createCoverSizeSliderWidget()
|
||||
{
|
||||
toolBarStretch = new YACReaderToolBarStretch(this);
|
||||
coverSizeSliderWidget = new QWidget(this);
|
||||
coverSizeSliderWidget->setFixedWidth(200);
|
||||
coverSizeSlider = new QSlider();
|
||||
@ -206,7 +205,7 @@ void GridComicsView::setToolBar(QToolBar *toolBar)
|
||||
|
||||
createCoverSizeSliderWidget();
|
||||
|
||||
toolBarStretchAction = toolBar->addWidget(toolBarStretch);
|
||||
startSeparatorAction = toolBar->addSeparator();
|
||||
toolBar->addAction(showInfoAction);
|
||||
showInfoSeparatorAction = toolBar->addSeparator();
|
||||
coverSizeSliderAction = toolBar->addWidget(coverSizeSliderWidget);
|
||||
@ -553,7 +552,7 @@ void GridComicsView::setShowMarks(bool show)
|
||||
|
||||
void GridComicsView::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
toolbar->removeAction(toolBarStretchAction);
|
||||
toolbar->removeAction(startSeparatorAction);
|
||||
toolbar->removeAction(showInfoAction);
|
||||
toolbar->removeAction(showInfoSeparatorAction);
|
||||
toolbar->removeAction(coverSizeSliderAction);
|
||||
|
@ -97,13 +97,12 @@ signals:
|
||||
private:
|
||||
QSettings *settings;
|
||||
QToolBar *toolbar;
|
||||
YACReaderToolBarStretch *toolBarStretch;
|
||||
QAction *toolBarStretchAction;
|
||||
QWidget *coverSizeSliderWidget;
|
||||
QSlider *coverSizeSlider;
|
||||
QAction *coverSizeSliderAction;
|
||||
QAction *showInfoAction;
|
||||
QAction *showInfoSeparatorAction;
|
||||
QAction *startSeparatorAction;
|
||||
|
||||
bool filterEnabled;
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
<file>../images/comics_view_toolbar/show_comic_info.svg</file>
|
||||
<file>../images/comics_view_toolbar/setManga.svg</file>
|
||||
<file>../images/comics_view_toolbar/setNormal.svg</file>
|
||||
<file>../images/comics_view_toolbar/showRecentIndicator.svg</file>
|
||||
<file>../images/defaultCover.png</file>
|
||||
<file>../images/edit.png</file>
|
||||
<file>../images/empty_current_readings.png</file>
|
||||
|
@ -232,7 +232,8 @@ qulonglong LibraryCreator::insertFolders()
|
||||
for (i = _currentPathFolders.begin(); i != _currentPathFolders.end(); ++i) {
|
||||
if (!(i->knownId)) {
|
||||
i->setFather(currentId);
|
||||
i->setManga(currentParent.isManga());
|
||||
i->manga = currentParent.manga;
|
||||
i->type = currentParent.type;
|
||||
currentId = DBHelper::insert(&(*i), _database); // insertFolder(currentId,*i);
|
||||
i->setId(currentId);
|
||||
} else {
|
||||
@ -325,7 +326,8 @@ void LibraryCreator::insertComic(const QString &relativePath, const QFileInfo &f
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
@ -539,14 +541,24 @@ void LibraryCreator::update(QDir dirS)
|
||||
} else // same file
|
||||
{
|
||||
if (fileInfoS.isFile() && !fileInfoD->isDir()) {
|
||||
// TODO comprobar fechas + tamaño
|
||||
// if(fileInfoS.lastModified()>fileInfoD.lastModified())
|
||||
//{
|
||||
// dirD.mkpath(_target+(QDir::cleanPath(fileInfoS.absolutePath()).remove(_source)));
|
||||
// emit(coverExtracted(QDir::cleanPath(fileInfoS.absoluteFilePath()).remove(_source)));
|
||||
// ThumbnailCreator tc(QDir::cleanPath(fileInfoS.absoluteFilePath()),_target+(QDir::cleanPath(fileInfoS.absoluteFilePath()).remove(_source))+".jpg");
|
||||
// tc.create();
|
||||
// }
|
||||
// TODO_METADATA use added,
|
||||
// if added < modified, do something
|
||||
|
||||
// copy metadata to avoid loosing it if the imported comics doesn't have it.
|
||||
|
||||
// DBHelper::removeFromDB(fileInfoD, _database);
|
||||
// #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++;
|
||||
j++;
|
||||
|
@ -1,5 +1,4 @@
|
||||
#include "library_window.h"
|
||||
#include "custom_widgets.h"
|
||||
#include "folder_item.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
@ -31,7 +30,6 @@
|
||||
#include "library_creator.h"
|
||||
#include "package_manager.h"
|
||||
#include "xml_info_library_scanner.h"
|
||||
#include "comic_flow_widget.h"
|
||||
#include "create_library_dialog.h"
|
||||
#include "rename_library_dialog.h"
|
||||
#include "properties_dialog.h"
|
||||
@ -45,9 +43,7 @@
|
||||
#include "server_config_dialog.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_main_toolbar.h"
|
||||
|
||||
@ -87,6 +83,8 @@
|
||||
|
||||
#include "library_comic_opener.h"
|
||||
|
||||
#include "recent_visibility_coordinator.h"
|
||||
|
||||
#include "QsLog.h"
|
||||
|
||||
#include "yacreader_http_server.h"
|
||||
@ -204,6 +202,8 @@ void LibraryWindow::setupUI()
|
||||
createToolBars();
|
||||
createMenus();
|
||||
|
||||
setupCoordinators();
|
||||
|
||||
navigationController = new YACReaderNavigationController(this, contentViewsManager);
|
||||
|
||||
createConnections();
|
||||
@ -222,24 +222,6 @@ void LibraryWindow::setupUI()
|
||||
trayIconController = new TrayIconController(settings, this);
|
||||
}
|
||||
|
||||
/*void LibraryWindow::changeEvent(QEvent *event)
|
||||
{
|
||||
QMainWindow::changeEvent(event);
|
||||
|
||||
if (event->type() == QEvent::WindowStateChange && isMinimized() &&
|
||||
trayIcon.isVisible()) {
|
||||
#ifdef Q_OS_MACOS
|
||||
OSXHideDockIcon();
|
||||
#endif
|
||||
hide();
|
||||
} else if (event->type() == QEvent::WindowStateChange) {
|
||||
#ifdef Q_OS_MACOS
|
||||
OSXShowDockIcon();
|
||||
#endif
|
||||
show();
|
||||
}
|
||||
}*/
|
||||
|
||||
void LibraryWindow::doLayout()
|
||||
{
|
||||
// LAYOUT ELEMENTS------------------------------------------------------------
|
||||
@ -461,6 +443,7 @@ void LibraryWindow::setUpShortcutsManagement()
|
||||
editShortcutsDialog->addActionsGroup("Visualization", QIcon(":/images/shortcuts_group_visualization.svg"),
|
||||
tmpList = QList<QAction *>()
|
||||
<< showHideMarksAction
|
||||
<< toogleShowRecentIndicatorAction
|
||||
#ifndef Q_OS_MAC
|
||||
<< toggleFullScreenAction
|
||||
#endif
|
||||
@ -485,6 +468,11 @@ void LibraryWindow::doModels()
|
||||
listsModelProxy = new ReadingListModelProxy(this);
|
||||
}
|
||||
|
||||
void LibraryWindow::setupCoordinators()
|
||||
{
|
||||
recentVisibilityCoordinator = new RecentVisibilityCoordinator(settings, foldersModel, contentViewsManager->folderContentView, comicsModel);
|
||||
}
|
||||
|
||||
void LibraryWindow::createActions()
|
||||
{
|
||||
backAction = new QAction(this);
|
||||
@ -587,25 +575,34 @@ void LibraryWindow::createActions()
|
||||
setAsNonReadAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SET_AS_NON_READ_ACTION_YL));
|
||||
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->setData(SET_AS_MANGA_ACTION_YL);
|
||||
setMangaAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SET_AS_MANGA_ACTION_YL));
|
||||
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->setData(SET_AS_NORMAL_ACTION_YL);
|
||||
setNormalAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SET_AS_NORMAL_ACTION_YL));
|
||||
setNormalAction->setIcon(QIcon(":/images/comics_view_toolbar/setNormal.svg"));
|
||||
|
||||
/*setAllAsReadAction = new QAction(tr("Set all as read"),this);
|
||||
setAllAsReadAction->setToolTip(tr("Set all comics as read"));
|
||||
setAllAsReadAction->setIcon(QIcon(":/images/comics_view_toolbar/setAllRead.png"));
|
||||
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"));
|
||||
|
||||
setAllAsNonReadAction = new QAction(tr("Set all as unread"),this);
|
||||
setAllAsNonReadAction->setToolTip(tr("Set all comics as unread"));
|
||||
setAllAsNonReadAction->setIcon(QIcon(":/images/comics_view_toolbar/setAllUnread.png"));*/
|
||||
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));
|
||||
|
||||
showHideMarksAction = new QAction(tr("Show/Hide marks"), this);
|
||||
showHideMarksAction->setToolTip(tr("Show or hide read marks"));
|
||||
@ -614,6 +611,15 @@ void LibraryWindow::createActions()
|
||||
showHideMarksAction->setCheckable(true);
|
||||
showHideMarksAction->setIcon(QIcon(":/images/comics_view_toolbar/showMarks.svg"));
|
||||
showHideMarksAction->setChecked(true);
|
||||
|
||||
toogleShowRecentIndicatorAction = new QAction(tr("Show/Hide recent indicator"), this);
|
||||
toogleShowRecentIndicatorAction->setToolTip(tr("Show or hide recent indicator"));
|
||||
toogleShowRecentIndicatorAction->setData(SHOW_HIDE_RECENT_INDICATOR_ACTION_YL);
|
||||
toogleShowRecentIndicatorAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SHOW_HIDE_RECENT_INDICATOR_ACTION_YL));
|
||||
toogleShowRecentIndicatorAction->setCheckable(true);
|
||||
toogleShowRecentIndicatorAction->setIcon(QIcon(":/images/comics_view_toolbar/showRecentIndicator.svg"));
|
||||
toogleShowRecentIndicatorAction->setChecked(settings->value(DISPLAY_RECENTLY_INDICATOR, true).toBool());
|
||||
|
||||
#ifndef Q_OS_MAC
|
||||
toggleFullScreenAction = new QAction(tr("Fullscreen mode on/off"), this);
|
||||
toggleFullScreenAction->setToolTip(tr("Fullscreen mode on/off"));
|
||||
@ -722,15 +728,30 @@ void LibraryWindow::createActions()
|
||||
setFolderAsUnreadAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SET_FOLDER_AS_UNREAD_ACTION_YL));
|
||||
|
||||
setFolderAsMangaAction = new QAction(this);
|
||||
setFolderAsMangaAction->setText(tr("Set as manga"));
|
||||
setFolderAsMangaAction->setText(tr("manga"));
|
||||
setFolderAsMangaAction->setData(SET_FOLDER_AS_MANGA_ACTION_YL);
|
||||
setFolderAsMangaAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SET_FOLDER_AS_MANGA_ACTION_YL));
|
||||
|
||||
setFolderAsNormalAction = new QAction(this);
|
||||
setFolderAsNormalAction->setText(tr("Set as comic"));
|
||||
setFolderAsNormalAction->setText(tr("comic"));
|
||||
setFolderAsNormalAction->setData(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);
|
||||
@ -867,6 +888,9 @@ void LibraryWindow::createActions()
|
||||
this->addAction(setFolderAsUnreadAction);
|
||||
this->addAction(setFolderAsMangaAction);
|
||||
this->addAction(setFolderAsNormalAction);
|
||||
this->addAction(setFolderAsWesternMangaAction);
|
||||
this->addAction(setFolderAsWebComicAction);
|
||||
this->addAction(setFolderAsYonkomaAction);
|
||||
this->addAction(deleteMetadataAction);
|
||||
this->addAction(rescanXMLFromCurrentFolderAction);
|
||||
#ifndef Q_OS_MAC
|
||||
@ -891,6 +915,9 @@ void LibraryWindow::disableComicsActions(bool disabled)
|
||||
setAsNonReadAction->setDisabled(disabled);
|
||||
setNormalAction->setDisabled(disabled);
|
||||
setMangaAction->setDisabled(disabled);
|
||||
setWebComicAction->setDisabled(disabled);
|
||||
setWesternMangaAction->setDisabled(disabled);
|
||||
setYonkomaAction->setDisabled(disabled);
|
||||
// setAllAsReadAction->setDisabled(disabled);
|
||||
// setAllAsNonReadAction->setDisabled(disabled);
|
||||
showHideMarksAction->setDisabled(disabled);
|
||||
@ -1001,21 +1028,31 @@ void LibraryWindow::createToolBars()
|
||||
editInfoToolBar->addSeparator();
|
||||
|
||||
editInfoToolBar->addAction(setAsReadAction);
|
||||
// editInfoToolBar->addAction(setAllAsReadAction);
|
||||
editInfoToolBar->addAction(setAsNonReadAction);
|
||||
// editInfoToolBar->addAction(setAllAsNonReadAction);
|
||||
|
||||
editInfoToolBar->addAction(showHideMarksAction);
|
||||
|
||||
editInfoToolBar->addSeparator();
|
||||
|
||||
editInfoToolBar->addAction(setNormalAction);
|
||||
editInfoToolBar->addAction(setMangaAction);
|
||||
auto setTypeToolButton = new QToolButton();
|
||||
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->addAction(deleteComicsAction);
|
||||
|
||||
auto toolBarStretch = new YACReaderToolBarStretch(this);
|
||||
editInfoToolBar->addWidget(toolBarStretch);
|
||||
|
||||
editInfoToolBar->addAction(toogleShowRecentIndicatorAction);
|
||||
|
||||
contentViewsManager->comicsView->setToolBar(editInfoToolBar);
|
||||
}
|
||||
|
||||
@ -1037,8 +1074,11 @@ void LibraryWindow::createMenus()
|
||||
foldersView->addAction(setFolderAsUnreadAction);
|
||||
YACReader::addSperator(foldersView);
|
||||
|
||||
foldersView->addAction(setFolderAsMangaAction);
|
||||
foldersView->addAction(setFolderAsNormalAction);
|
||||
foldersView->addAction(setFolderAsMangaAction);
|
||||
foldersView->addAction(setFolderAsWesternMangaAction);
|
||||
foldersView->addAction(setFolderAsWebComicAction);
|
||||
foldersView->addAction(setFolderAsYonkomaAction);
|
||||
|
||||
selectedLibrary->addAction(updateLibraryAction);
|
||||
selectedLibrary->addAction(renameLibraryAction);
|
||||
@ -1093,8 +1133,11 @@ void LibraryWindow::createMenus()
|
||||
folderMenu->addAction(setFolderAsReadAction);
|
||||
folderMenu->addAction(setFolderAsUnreadAction);
|
||||
folderMenu->addSeparator();
|
||||
foldersView->addAction(setFolderAsMangaAction);
|
||||
foldersView->addAction(setFolderAsNormalAction);
|
||||
foldersView->addAction(setFolderAsMangaAction);
|
||||
foldersView->addAction(setFolderAsWesternMangaAction);
|
||||
foldersView->addAction(setFolderAsWebComicAction);
|
||||
foldersView->addAction(setFolderAsYonkomaAction);
|
||||
|
||||
// comic
|
||||
QMenu *comicMenu = new QMenu(tr("Comic"));
|
||||
@ -1133,7 +1176,7 @@ void LibraryWindow::createConnections()
|
||||
connect(libraryCreator, &LibraryCreator::comicAdded, importWidget, &ImportWidget::newComic);
|
||||
// libraryCreator errors
|
||||
connect(libraryCreator, &LibraryCreator::failedCreatingDB, this, &LibraryWindow::manageCreatingError);
|
||||
connect(libraryCreator, SIGNAL(failedUpdatingDB(QString)), this, SLOT(manageUpdatingError(QString))); // TODO: implement failedUpdatingDB
|
||||
// connect(libraryCreator, SIGNAL(failedUpdatingDB(QString)), this, SLOT(manageUpdatingError(QString))); // TODO: implement failedUpdatingDB
|
||||
|
||||
connect(xmlInfoLibraryScanner, &QThread::finished, this, &LibraryWindow::showRootWidget);
|
||||
connect(xmlInfoLibraryScanner, &QThread::finished, this, &LibraryWindow::reloadCurrentFolderComicsContent);
|
||||
@ -1185,10 +1228,22 @@ void LibraryWindow::createConnections()
|
||||
connect(openLibraryAction, &QAction::triggered, this, &LibraryWindow::showAddLibrary);
|
||||
connect(setAsReadAction, &QAction::triggered, this, &LibraryWindow::setCurrentComicReaded);
|
||||
connect(setAsNonReadAction, &QAction::triggered, this, &LibraryWindow::setCurrentComicUnreaded);
|
||||
connect(setNormalAction, &QAction::triggered, this, &LibraryWindow::setSelectedComicsAsNormal);
|
||||
connect(setMangaAction, &QAction::triggered, this, &LibraryWindow::setSelectedComicsAsManga);
|
||||
// connect(setAllAsReadAction,SIGNAL(triggered()),this,SLOT(setComicsReaded()));
|
||||
// connect(setAllAsNonReadAction,SIGNAL(triggered()),this,SLOT(setComicsUnreaded()));
|
||||
|
||||
connect(setNormalAction, &QAction::triggered, this, [=]() {
|
||||
setSelectedComicsType(FileType::Comic);
|
||||
});
|
||||
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
|
||||
connect(exportComicsInfoAction, &QAction::triggered, this, &LibraryWindow::showExportComicsInfo);
|
||||
@ -1241,8 +1296,22 @@ void LibraryWindow::createConnections()
|
||||
connect(setFolderAsReadAction, &QAction::triggered, this, &LibraryWindow::setFolderAsRead);
|
||||
connect(setFolderAsUnreadAction, &QAction::triggered, this, &LibraryWindow::setFolderAsUnread);
|
||||
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);
|
||||
|
||||
@ -1288,6 +1357,8 @@ void LibraryWindow::createConnections()
|
||||
// upgrade library
|
||||
connect(this, &LibraryWindow::libraryUpgraded, this, &LibraryWindow::loadLibrary, Qt::QueuedConnection);
|
||||
connect(this, &LibraryWindow::errorUpgradingLibrary, this, &LibraryWindow::showErrorUpgradingLibrary, Qt::QueuedConnection);
|
||||
|
||||
connect(toogleShowRecentIndicatorAction, &QAction::toggled, recentVisibilityCoordinator, &RecentVisibilityCoordinator::toggleVisibility);
|
||||
}
|
||||
|
||||
void LibraryWindow::showErrorUpgradingLibrary(const QString &path)
|
||||
@ -1582,12 +1653,18 @@ void LibraryWindow::reloadAfterCopyMove(const QModelIndex &mi)
|
||||
{
|
||||
if (getCurrentFolderIndex() == mi) {
|
||||
auto item = static_cast<FolderItem *>(mi.internalPointer());
|
||||
auto id = item->id;
|
||||
foldersModel->reload(mi);
|
||||
auto newMi = foldersModel->index(id);
|
||||
|
||||
foldersView->setCurrentIndex(foldersModelProxy->mapFromSource(newMi));
|
||||
navigationController->loadFolderInfo(newMi);
|
||||
if (item == nullptr) {
|
||||
foldersModel->reload();
|
||||
navigationController->loadFolderInfo(QModelIndex());
|
||||
} else {
|
||||
auto id = item->id;
|
||||
foldersModel->reload(mi);
|
||||
auto newMi = foldersModel->index(id);
|
||||
|
||||
foldersView->setCurrentIndex(foldersModelProxy->mapFromSource(newMi));
|
||||
navigationController->loadFolderInfo(newMi);
|
||||
}
|
||||
}
|
||||
|
||||
enableNeededActions();
|
||||
@ -1779,8 +1856,13 @@ void LibraryWindow::showComicsViewContextMenu(const QPoint &point)
|
||||
menu.addAction(setAsReadAction);
|
||||
menu.addAction(setAsNonReadAction);
|
||||
menu.addSeparator();
|
||||
menu.addAction(setNormalAction);
|
||||
menu.addAction(setMangaAction);
|
||||
auto typeMenu = new QMenu(tr("Set type"));
|
||||
menu.addMenu(typeMenu);
|
||||
typeMenu->addAction(setNormalAction);
|
||||
typeMenu->addAction(setMangaAction);
|
||||
typeMenu->addAction(setWesternMangaAction);
|
||||
typeMenu->addAction(setWebComicAction);
|
||||
typeMenu->addAction(setYonkomaAction);
|
||||
menu.addSeparator();
|
||||
menu.addAction(deleteMetadataAction);
|
||||
menu.addSeparator();
|
||||
@ -1817,8 +1899,13 @@ void LibraryWindow::showComicsItemContextMenu(const QPoint &point)
|
||||
menu.addAction(setAsReadAction);
|
||||
menu.addAction(setAsNonReadAction);
|
||||
menu.addSeparator();
|
||||
menu.addAction(setNormalAction);
|
||||
menu.addAction(setMangaAction);
|
||||
auto typeMenu = new QMenu(tr("Set type"));
|
||||
menu.addMenu(typeMenu);
|
||||
typeMenu->addAction(setNormalAction);
|
||||
typeMenu->addAction(setMangaAction);
|
||||
typeMenu->addAction(setWesternMangaAction);
|
||||
typeMenu->addAction(setWebComicAction);
|
||||
typeMenu->addAction(setYonkomaAction);
|
||||
menu.addSeparator();
|
||||
menu.addAction(deleteMetadataAction);
|
||||
menu.addSeparator();
|
||||
@ -1857,30 +1944,43 @@ void LibraryWindow::showGridFoldersContextMenu(QPoint point, Folder folder)
|
||||
setFolderAsUnreadAction->setText(tr("Set as unread"));
|
||||
|
||||
auto setFolderAsMangaAction = new QAction();
|
||||
setFolderAsMangaAction->setText(tr("Set as manga"));
|
||||
setFolderAsMangaAction->setText(tr("manga"));
|
||||
|
||||
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(updateFolderAction);
|
||||
menu.addSeparator();
|
||||
menu.addAction(rescanLibraryForXMLInfoAction);
|
||||
menu.addSeparator();
|
||||
if (folder.isCompleted())
|
||||
if (folder.completed)
|
||||
menu.addAction(setFolderAsNotCompletedAction);
|
||||
else
|
||||
menu.addAction(setFolderAsCompletedAction);
|
||||
menu.addSeparator();
|
||||
if (folder.isFinished())
|
||||
if (folder.finished)
|
||||
menu.addAction(setFolderAsUnreadAction);
|
||||
else
|
||||
menu.addAction(setFolderAsReadAction);
|
||||
menu.addSeparator();
|
||||
if (folder.isManga())
|
||||
menu.addAction(setFolderAsNormalAction);
|
||||
else
|
||||
menu.addAction(setFolderAsMangaAction);
|
||||
|
||||
auto typeMenu = new QMenu(tr("Set type"));
|
||||
menu.addMenu(typeMenu);
|
||||
typeMenu->addAction(setFolderAsNormalAction);
|
||||
typeMenu->addAction(setFolderAsMangaAction);
|
||||
typeMenu->addAction(setFolderAsWesternMangaAction);
|
||||
typeMenu->addAction(setFolderAsWebComicAction);
|
||||
typeMenu->addAction(setFolderAs4KomaAction);
|
||||
|
||||
auto subfolderModel = contentViewsManager->folderContentView->currentFolderModel();
|
||||
|
||||
@ -1910,12 +2010,24 @@ void LibraryWindow::showGridFoldersContextMenu(QPoint point, Folder folder)
|
||||
subfolderModel->updateFolderFinishedStatus(QModelIndexList() << subfolderModel->getIndexFromFolder(folder), false);
|
||||
});
|
||||
connect(setFolderAsMangaAction, &QAction::triggered, this, [=]() {
|
||||
foldersModel->updateFolderManga(QModelIndexList() << foldersModel->getIndexFromFolder(folder), true);
|
||||
subfolderModel->updateFolderManga(QModelIndexList() << subfolderModel->getIndexFromFolder(folder), true);
|
||||
foldersModel->updateFolderType(QModelIndexList() << foldersModel->getIndexFromFolder(folder), FileType::Manga);
|
||||
subfolderModel->updateFolderType(QModelIndexList() << foldersModel->getIndexFromFolder(folder), FileType::Manga);
|
||||
});
|
||||
connect(setFolderAsNormalAction, &QAction::triggered, this, [=]() {
|
||||
foldersModel->updateFolderManga(QModelIndexList() << foldersModel->getIndexFromFolder(folder), false);
|
||||
subfolderModel->updateFolderManga(QModelIndexList() << subfolderModel->getIndexFromFolder(folder), false);
|
||||
foldersModel->updateFolderType(QModelIndexList() << foldersModel->getIndexFromFolder(folder), FileType::Comic);
|
||||
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));
|
||||
@ -2091,14 +2203,9 @@ void LibraryWindow::setCurrentComicUnreaded()
|
||||
this->setCurrentComicsStatusReaded(YACReader::Unread);
|
||||
}
|
||||
|
||||
void LibraryWindow::setSelectedComicsAsNormal()
|
||||
void LibraryWindow::setSelectedComicsType(FileType type)
|
||||
{
|
||||
comicsModel->setComicsManga(getSelectedComics(), false);
|
||||
}
|
||||
|
||||
void LibraryWindow::setSelectedComicsAsManga()
|
||||
{
|
||||
comicsModel->setComicsManga(getSelectedComics(), true);
|
||||
comicsModel->setComicsType(getSelectedComics(), type);
|
||||
}
|
||||
|
||||
void LibraryWindow::createLibrary()
|
||||
@ -2109,7 +2216,7 @@ void LibraryWindow::createLibrary()
|
||||
|
||||
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->start();
|
||||
_lastAdded = name;
|
||||
@ -2625,14 +2732,9 @@ void LibraryWindow::setFolderAsUnread()
|
||||
foldersModel->updateFolderFinishedStatus(QModelIndexList() << foldersModelProxy->mapToSource(foldersView->currentIndex()), false);
|
||||
}
|
||||
|
||||
void LibraryWindow::setFolderAsManga()
|
||||
void LibraryWindow::setFolderType(FileType type)
|
||||
{
|
||||
foldersModel->updateFolderManga(QModelIndexList() << foldersModelProxy->mapToSource(foldersView->currentIndex()), true);
|
||||
}
|
||||
|
||||
void LibraryWindow::setFolderAsNormal()
|
||||
{
|
||||
foldersModel->updateFolderManga(QModelIndexList() << foldersModelProxy->mapToSource(foldersView->currentIndex()), false);
|
||||
foldersModel->updateFolderType(QModelIndexList() << foldersModelProxy->mapToSource(foldersView->currentIndex()), type);
|
||||
}
|
||||
|
||||
void LibraryWindow::exportLibrary(QString destPath)
|
||||
@ -2654,6 +2756,8 @@ void LibraryWindow::reloadOptions()
|
||||
contentViewsManager->comicsView->updateConfig(settings);
|
||||
|
||||
trayIconController->updateIconVisibility();
|
||||
|
||||
recentVisibilityCoordinator->updateTimeRange();
|
||||
}
|
||||
|
||||
QString LibraryWindow::currentPath()
|
||||
@ -2872,10 +2976,9 @@ void LibraryWindow::showFoldersContextMenu(const QPoint &point)
|
||||
|
||||
bool isCompleted = sourceMI.data(FolderModel::CompletedRole).toBool();
|
||||
bool isRead = sourceMI.data(FolderModel::FinishedRole).toBool();
|
||||
bool isManga = sourceMI.data(FolderModel::MangaRole).toBool();
|
||||
|
||||
QMenu menu;
|
||||
// QMenu * folderMenu = new QMenu(tr("Folder"));
|
||||
|
||||
menu.addAction(openContainingFolderAction);
|
||||
menu.addAction(updateFolderAction);
|
||||
menu.addSeparator(); //-------------------------------
|
||||
@ -2891,10 +2994,13 @@ void LibraryWindow::showFoldersContextMenu(const QPoint &point)
|
||||
else
|
||||
menu.addAction(setFolderAsReadAction);
|
||||
menu.addSeparator(); //-------------------------------
|
||||
if (isManga)
|
||||
menu.addAction(setFolderAsNormalAction);
|
||||
else
|
||||
menu.addAction(setFolderAsMangaAction);
|
||||
auto typeMenu = new QMenu(tr("Set type"));
|
||||
menu.addMenu(typeMenu);
|
||||
typeMenu->addAction(setFolderAsNormalAction);
|
||||
typeMenu->addAction(setFolderAsMangaAction);
|
||||
typeMenu->addAction(setFolderAsWesternMangaAction);
|
||||
typeMenu->addAction(setFolderAsWebComicAction);
|
||||
typeMenu->addAction(setFolderAsYonkomaAction);
|
||||
|
||||
menu.exec(foldersView->mapToGlobal(point));
|
||||
}
|
||||
|
@ -81,6 +81,7 @@ class YACReaderHistoryController;
|
||||
class EmptyLabelWidget;
|
||||
class EmptySpecialListWidget;
|
||||
class EmptyReadingListWidget;
|
||||
class RecentVisibilityCoordinator;
|
||||
|
||||
namespace YACReader {
|
||||
class TrayIconController;
|
||||
@ -197,8 +198,12 @@ public:
|
||||
//--
|
||||
QAction *setFolderAsReadAction;
|
||||
QAction *setFolderAsUnreadAction;
|
||||
//--
|
||||
QAction *setFolderAsMangaAction;
|
||||
QAction *setFolderAsNormalAction;
|
||||
QAction *setFolderAsWesternMangaAction;
|
||||
QAction *setFolderAsWebComicAction;
|
||||
QAction *setFolderAsYonkomaAction;
|
||||
|
||||
QAction *openContainingFolderComicAction;
|
||||
QAction *setAsReadAction;
|
||||
@ -206,13 +211,16 @@ public:
|
||||
|
||||
QAction *setMangaAction;
|
||||
QAction *setNormalAction;
|
||||
QAction *setWesternMangaAction;
|
||||
QAction *setWebComicAction;
|
||||
QAction *setYonkomaAction;
|
||||
|
||||
// QAction * setAllAsReadAction;
|
||||
// QAction * setAllAsNonReadAction;
|
||||
QAction *showHideMarksAction;
|
||||
QAction *getInfoAction; // comic vine
|
||||
QAction *resetComicRatingAction;
|
||||
|
||||
QAction *toogleShowRecentIndicatorAction;
|
||||
|
||||
// edit info actions
|
||||
QAction *selectAllComicsAction;
|
||||
QAction *editSelectedComicsAction;
|
||||
@ -259,10 +267,6 @@ public:
|
||||
QString _lastAdded;
|
||||
QString _sourceLastAdded;
|
||||
|
||||
// QModelIndex _rootIndex;
|
||||
// QModelIndex _rootIndexCV;
|
||||
// QModelIndex updateDestination;
|
||||
|
||||
quint64 _comicIdEdited;
|
||||
|
||||
enum NavigationStatus {
|
||||
@ -283,6 +287,7 @@ public:
|
||||
void doDialogs();
|
||||
void setUpShortcutsManagement();
|
||||
void doModels();
|
||||
void setupCoordinators();
|
||||
|
||||
// ACTIONS MANAGEMENT
|
||||
void disableComicsActions(bool disabled);
|
||||
@ -291,9 +296,6 @@ public:
|
||||
void disableFoldersActions(bool disabled);
|
||||
|
||||
void disableAllActions();
|
||||
// void disableActions();
|
||||
// void enableActions();
|
||||
// void enableLibraryActions();
|
||||
|
||||
QString currentPath();
|
||||
QString currentFolderPath();
|
||||
@ -340,8 +342,7 @@ public slots:
|
||||
void setFolderAsCompleted();
|
||||
void setFolderAsRead();
|
||||
void setFolderAsUnread();
|
||||
void setFolderAsManga();
|
||||
void setFolderAsNormal();
|
||||
void setFolderType(FileType type);
|
||||
void openContainingFolderComic();
|
||||
void deleteCurrentLibrary();
|
||||
void removeLibrary();
|
||||
@ -368,8 +369,7 @@ public slots:
|
||||
void setCurrentComicsStatusReaded(YACReaderComicReadStatus readStatus);
|
||||
void setCurrentComicReaded();
|
||||
void setCurrentComicUnreaded();
|
||||
void setSelectedComicsAsNormal();
|
||||
void setSelectedComicsAsManga();
|
||||
void setSelectedComicsType(FileType type);
|
||||
void showExportComicsInfo();
|
||||
void showImportComicsInfo();
|
||||
void asignNumbers();
|
||||
@ -450,6 +450,8 @@ private:
|
||||
TrayIconController *trayIconController;
|
||||
ComicQueryResultProcessor comicQueryResultProcessor;
|
||||
std::unique_ptr<FolderQueryResultProcessor> folderQueryResultProcessor;
|
||||
|
||||
RecentVisibilityCoordinator *recentVisibilityCoordinator;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -86,6 +86,18 @@ OptionsDialog::OptionsDialog(QWidget *parent)
|
||||
comicInfoXMLBoxLayout->addWidget(comicInfoXMLCheckbox);
|
||||
comicInfoXMLBox->setLayout(comicInfoXMLBoxLayout);
|
||||
|
||||
auto recentlyAddedBox = new QGroupBox(tr("Consider 'recent' items added or updated since X days ago"));
|
||||
recentIntervalSlider = new QSlider(Qt::Horizontal);
|
||||
recentIntervalSlider->setRange(1, 30);
|
||||
auto recentlyAddedLayout = new QHBoxLayout();
|
||||
numDaysLabel = new QLabel();
|
||||
numDaysLabel->setMidLineWidth(50);
|
||||
recentlyAddedLayout->addWidget(numDaysLabel);
|
||||
recentlyAddedLayout->addWidget(recentIntervalSlider);
|
||||
recentlyAddedBox->setLayout(recentlyAddedLayout);
|
||||
|
||||
connect(recentIntervalSlider, &QAbstractSlider::valueChanged, this, &OptionsDialog::numDaysToConsiderRecentChanged);
|
||||
|
||||
// grid view background config
|
||||
useBackgroundImageCheck = new QCheckBox(tr("Enable background image"));
|
||||
|
||||
@ -152,6 +164,7 @@ OptionsDialog::OptionsDialog(QWidget *parent)
|
||||
generalLayout->addWidget(shortcutsBox);
|
||||
generalLayout->addWidget(apiKeyBox);
|
||||
generalLayout->addWidget(comicInfoXMLBox);
|
||||
generalLayout->addWidget(recentlyAddedBox);
|
||||
generalLayout->addStretch();
|
||||
|
||||
tabWidget->addTab(generalW, tr("General"));
|
||||
@ -163,8 +176,6 @@ OptionsDialog::OptionsDialog(QWidget *parent)
|
||||
layout->addWidget(tabWidget);
|
||||
layout->addLayout(buttons);
|
||||
setLayout(layout);
|
||||
// restoreOptions(settings); //load options
|
||||
// resize(200,0);
|
||||
setModal(true);
|
||||
setWindowTitle(tr("Options"));
|
||||
|
||||
@ -187,6 +198,8 @@ void OptionsDialog::restoreOptions(QSettings *settings)
|
||||
|
||||
comicInfoXMLCheckbox->setChecked(settings->value(IMPORT_COMIC_INFO_XML_METADATA, false).toBool());
|
||||
|
||||
recentIntervalSlider->setValue(settings->value(NUM_DAYS_TO_CONSIDER_RECENT, 1).toInt());
|
||||
|
||||
bool useBackgroundImage = settings->value(USE_BACKGROUND_IMAGE_IN_GRID_VIEW, true).toBool();
|
||||
|
||||
useBackgroundImageCheck->setChecked(useBackgroundImage);
|
||||
@ -237,6 +250,15 @@ void OptionsDialog::useCurrentComicCoverCheckClicked(bool checked)
|
||||
emit optionsChanged();
|
||||
}
|
||||
|
||||
void OptionsDialog::numDaysToConsiderRecentChanged(int value)
|
||||
{
|
||||
settings->setValue(NUM_DAYS_TO_CONSIDER_RECENT, value);
|
||||
|
||||
numDaysLabel->setText(QString("%1").arg(value));
|
||||
|
||||
emit optionsChanged();
|
||||
}
|
||||
|
||||
void OptionsDialog::resetToDefaults()
|
||||
{
|
||||
settings->setValue(OPACITY_BACKGROUND_IMAGE_IN_GRID_VIEW, 0.2);
|
||||
|
@ -24,6 +24,7 @@ private slots:
|
||||
void backgroundImageOpacitySliderChanged(int value);
|
||||
void backgroundImageBlurRadiusSliderChanged(int value);
|
||||
void useCurrentComicCoverCheckClicked(bool checked);
|
||||
void numDaysToConsiderRecentChanged(int value);
|
||||
void resetToDefaults();
|
||||
|
||||
private:
|
||||
@ -38,6 +39,8 @@ private:
|
||||
QCheckBox *trayIconCheckbox;
|
||||
QCheckBox *startToTrayCheckbox;
|
||||
QCheckBox *comicInfoXMLCheckbox;
|
||||
QSlider *recentIntervalSlider;
|
||||
QLabel *numDaysLabel;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -31,6 +31,7 @@ PropertiesDialog::PropertiesDialog(QWidget *parent)
|
||||
createPublishingBox();
|
||||
createButtonBox();
|
||||
createPlotBox();
|
||||
createNotesBox(); // review, notes, tags
|
||||
|
||||
createTabBar();
|
||||
auto rootLayout = new QGridLayout;
|
||||
@ -80,9 +81,10 @@ void PropertiesDialog::createTabBar()
|
||||
{
|
||||
tabBar = new QTabWidget;
|
||||
tabBar->addTab(generalInfoBox, tr("General info"));
|
||||
tabBar->addTab(plotBox, tr("Plot"));
|
||||
tabBar->addTab(authorsBox, tr("Authors"));
|
||||
tabBar->addTab(publishingBox, tr("Publishing"));
|
||||
tabBar->addTab(plotBox, tr("Plot"));
|
||||
tabBar->addTab(notesBox, tr("Notes"));
|
||||
}
|
||||
|
||||
void PropertiesDialog::createCoverBox()
|
||||
@ -140,38 +142,44 @@ void PropertiesDialog::createGeneralInfoBox()
|
||||
|
||||
generalInfoLayout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
|
||||
generalInfoLayout->setRowWrapPolicy(QFormLayout::WrapAllRows);
|
||||
generalInfoLayout->addRow(tr("Series:"), series = new YACReaderFieldEdit());
|
||||
generalInfoLayout->addRow(tr("Title:"), title = new YACReaderFieldEdit());
|
||||
|
||||
auto number = new QHBoxLayout;
|
||||
number->addWidget(numberEdit = new YACReaderFieldEdit());
|
||||
numberValidator.setBottom(0);
|
||||
numberEdit->setValidator(&numberValidator);
|
||||
number->addWidget(new QLabel("Bis:"));
|
||||
number->addWidget(isBisCheck = new QCheckBox());
|
||||
number->addWidget(new QLabel(tr("of:")));
|
||||
number->addWidget(countEdit = new YACReaderFieldEdit());
|
||||
countValidator.setBottom(0);
|
||||
countEdit->setValidator(&countValidator);
|
||||
number->addStretch(1);
|
||||
/*generalInfoLayout->addRow(tr("&Issue number:"), );
|
||||
generalInfoLayout->addRow(tr("&Bis:"), );*/
|
||||
generalInfoLayout->addRow(tr("Issue number:"), number);
|
||||
|
||||
generalInfoLayout->addRow(tr("Volume:"), volumeEdit = new YACReaderFieldEdit());
|
||||
|
||||
auto arc = new QHBoxLayout;
|
||||
arc->addWidget(storyArcEdit = new YACReaderFieldEdit());
|
||||
arc->addWidget(storyArcEdit = new YACReaderFieldEdit(), 1);
|
||||
storyArcEdit->setMinimumWidth(200);
|
||||
arc->addWidget(new QLabel(tr("Arc number:")));
|
||||
arc->addWidget(arcNumberEdit = new YACReaderFieldEdit());
|
||||
arcNumberValidator.setBottom(0);
|
||||
arcNumberEdit->setValidator(&arcNumberValidator);
|
||||
arc->addWidget(new QLabel(tr("of:")));
|
||||
arc->addWidget(arcCountEdit = new YACReaderFieldEdit());
|
||||
arcCountValidator.setBottom(0);
|
||||
arcCountEdit->setValidator(&arcCountValidator);
|
||||
arc->addStretch(1);
|
||||
generalInfoLayout->addRow(tr("Story arc:"), arc);
|
||||
|
||||
auto alternate = new QHBoxLayout;
|
||||
alternate->addWidget(alternateSeriesEdit = new YACReaderFieldEdit(), 1);
|
||||
alternateSeriesEdit->setMinimumWidth(200);
|
||||
alternate->addWidget(new QLabel(tr("alt. number:")));
|
||||
alternate->addWidget(alternateNumberEdit = new YACReaderFieldEdit());
|
||||
alternate->addWidget(new QLabel(tr("of:")));
|
||||
alternate->addWidget(alternateCountEdit = new YACReaderFieldEdit());
|
||||
arcCountValidator.setBottom(0);
|
||||
alternateCountEdit->setValidator(&arcCountValidator);
|
||||
generalInfoLayout->addRow(tr("Alternate series:"), alternate);
|
||||
|
||||
generalInfoLayout->addRow(tr("Series Group:"), seriesGroupEdit = new YACReaderFieldEdit());
|
||||
|
||||
generalInfoLayout->addRow(tr("Genre:"), genereEdit = new YACReaderFieldEdit());
|
||||
|
||||
generalInfoLayout->addRow(tr("Size:"), size = new QLabel("size"));
|
||||
@ -221,9 +229,20 @@ void PropertiesDialog::createAuthorsBox()
|
||||
vr3->addWidget(coverArtist = new YACReaderFieldPlainTextEdit());
|
||||
h3->addLayout(vr3);
|
||||
|
||||
auto h4 = new QHBoxLayout;
|
||||
auto vl4 = new QVBoxLayout;
|
||||
auto vr4 = new QVBoxLayout;
|
||||
vl4->addWidget(new QLabel(tr("Editor(s):")));
|
||||
vl4->addWidget(editor = new YACReaderFieldPlainTextEdit());
|
||||
h4->addLayout(vl4);
|
||||
vr4->addWidget(new QLabel(tr("Imprint:")));
|
||||
vr4->addWidget(imprint = new YACReaderFieldPlainTextEdit());
|
||||
h4->addLayout(vr4);
|
||||
|
||||
authorsLayout->addLayout(h1);
|
||||
authorsLayout->addLayout(h2);
|
||||
authorsLayout->addLayout(h3);
|
||||
authorsLayout->addLayout(h4);
|
||||
authorsLayout->addStretch(1);
|
||||
authorsBox->setLayout(authorsLayout);
|
||||
}
|
||||
@ -257,7 +276,16 @@ void PropertiesDialog::createPublishingBox()
|
||||
publishingLayout->addRow(tr("Format:"), formatEdit = new YACReaderFieldEdit());
|
||||
publishingLayout->addRow(tr("Color/BW:"), colorCheck = new QCheckBox());
|
||||
publishingLayout->addRow(tr("Age rating:"), ageRatingEdit = new YACReaderFieldEdit());
|
||||
publishingLayout->addRow(tr("Manga:"), mangaCheck = new QCheckBox());
|
||||
publishingLayout->addRow(tr("Type:"), typeCombo = new QComboBox());
|
||||
publishingLayout->addRow(tr("Language (ISO):"), languageEdit = new YACReaderFieldEdit());
|
||||
|
||||
typeCombo->addItem("Comic");
|
||||
typeCombo->addItem("Manga");
|
||||
typeCombo->addItem("Western Manga");
|
||||
typeCombo->addItem("Web Comic");
|
||||
typeCombo->addItem("4koma");
|
||||
|
||||
typeCombo->setCurrentIndex(-1);
|
||||
|
||||
publishingBox->setLayout(publishingLayout);
|
||||
}
|
||||
@ -266,17 +294,61 @@ void PropertiesDialog::createPlotBox()
|
||||
{
|
||||
plotBox = new QWidget;
|
||||
|
||||
auto plotLayout = new QFormLayout;
|
||||
plotLayout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
|
||||
auto plotLayout = new QVBoxLayout;
|
||||
|
||||
plotLayout->setRowWrapPolicy(QFormLayout::WrapAllRows);
|
||||
plotLayout->addRow(tr("Synopsis:"), synopsis = new YACReaderFieldPlainTextEdit());
|
||||
plotLayout->addRow(tr("Characters:"), characters = new YACReaderFieldPlainTextEdit());
|
||||
plotLayout->addRow(tr("Notes:"), notes = new YACReaderFieldPlainTextEdit());
|
||||
auto h1 = new QHBoxLayout;
|
||||
auto vl1 = new QVBoxLayout;
|
||||
vl1->addWidget(new QLabel(tr("Synopsis:")));
|
||||
vl1->addWidget(synopsis = new YACReaderFieldPlainTextEdit());
|
||||
h1->addLayout(vl1);
|
||||
|
||||
auto h2 = new QHBoxLayout;
|
||||
auto vl2 = new QVBoxLayout;
|
||||
auto vr2 = new QVBoxLayout;
|
||||
vl2->addWidget(new QLabel(tr("Characters:")));
|
||||
vl2->addWidget(characters = new YACReaderFieldPlainTextEdit());
|
||||
h2->addLayout(vl2);
|
||||
vr2->addWidget(new QLabel(tr("Teams:")));
|
||||
vr2->addWidget(teams = new YACReaderFieldPlainTextEdit());
|
||||
h2->addLayout(vr2);
|
||||
|
||||
auto h3 = new QHBoxLayout;
|
||||
auto vl3 = new QVBoxLayout;
|
||||
vl3->addWidget(new QLabel(tr("Locations:")));
|
||||
vl3->addWidget(locations = new YACReaderFieldPlainTextEdit());
|
||||
h3->addLayout(vl3);
|
||||
|
||||
auto h4 = new QHBoxLayout;
|
||||
auto vl4 = new QVBoxLayout;
|
||||
vl4->addWidget(new QLabel(tr("Main character or team:")));
|
||||
vl4->addWidget(mainCharacterOrTeamEdit = new YACReaderFieldEdit());
|
||||
h4->addLayout(vl4);
|
||||
|
||||
plotLayout->addLayout(h1);
|
||||
plotLayout->addLayout(h2);
|
||||
plotLayout->addLayout(h3);
|
||||
plotLayout->addLayout(h4);
|
||||
plotLayout->addStretch(1);
|
||||
|
||||
plotBox->setLayout(plotLayout);
|
||||
}
|
||||
|
||||
void PropertiesDialog::createNotesBox()
|
||||
{
|
||||
notesBox = new QWidget;
|
||||
|
||||
auto notesLayout = new QFormLayout;
|
||||
notesLayout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
|
||||
|
||||
notesLayout->setRowWrapPolicy(QFormLayout::WrapAllRows);
|
||||
|
||||
notesLayout->addRow(tr("Review:"), review = new YACReaderFieldPlainTextEdit());
|
||||
notesLayout->addRow(tr("Notes:"), notes = new YACReaderFieldPlainTextEdit());
|
||||
notesLayout->addRow(tr("Tags:"), tags = new YACReaderFieldPlainTextEdit());
|
||||
|
||||
notesBox->setLayout(notesLayout);
|
||||
}
|
||||
|
||||
void PropertiesDialog::createButtonBox()
|
||||
{
|
||||
buttonBox = new QDialogButtonBox;
|
||||
@ -362,6 +434,8 @@ QImage blurred(const QImage &image, const QRect &rect, int radius, bool alphaOnl
|
||||
|
||||
void PropertiesDialog::loadComic(ComicDB &comic)
|
||||
{
|
||||
if (!comic.info.series.isNull())
|
||||
series->setText(comic.info.series.toString());
|
||||
if (!comic.info.title.isNull())
|
||||
title->setText(comic.info.title.toString());
|
||||
if (!comic.info.comicVineID.isNull()) {
|
||||
@ -401,8 +475,6 @@ void PropertiesDialog::loadComic(ComicDB &comic)
|
||||
|
||||
if (!comic.info.number.isNull())
|
||||
numberEdit->setText(comic.info.number.toString());
|
||||
if (!comic.info.isBis.isNull())
|
||||
isBisCheck->setChecked(comic.info.isBis.toBool());
|
||||
if (!comic.info.count.isNull())
|
||||
countEdit->setText(comic.info.count.toString());
|
||||
|
||||
@ -414,6 +486,14 @@ void PropertiesDialog::loadComic(ComicDB &comic)
|
||||
arcNumberEdit->setText(comic.info.arcNumber.toString());
|
||||
if (!comic.info.arcCount.isNull())
|
||||
arcCountEdit->setText(comic.info.arcCount.toString());
|
||||
if (!comic.info.alternateSeries.isNull())
|
||||
alternateSeriesEdit->setText(comic.info.alternateSeries.toString());
|
||||
if (!comic.info.alternateNumber.isNull())
|
||||
alternateNumberEdit->setText(comic.info.alternateNumber.toString());
|
||||
if (!comic.info.alternateCount.isNull())
|
||||
alternateCountEdit->setText(comic.info.alternateCount.toString());
|
||||
if (!comic.info.seriesGroup.isNull())
|
||||
seriesGroupEdit->setText(comic.info.seriesGroup.toString());
|
||||
|
||||
if (!comic.info.genere.isNull())
|
||||
genereEdit->setText(comic.info.genere.toString());
|
||||
@ -430,6 +510,10 @@ void PropertiesDialog::loadComic(ComicDB &comic)
|
||||
letterer->setPlainText(comic.info.letterer.toString());
|
||||
if (!comic.info.coverArtist.isNull())
|
||||
coverArtist->setPlainText(comic.info.coverArtist.toString());
|
||||
if (!comic.info.editor.isNull())
|
||||
editor->setPlainText(comic.info.editor.toString());
|
||||
if (!comic.info.imprint.isNull())
|
||||
imprint->setPlainText(comic.info.imprint.toString());
|
||||
|
||||
size->setText(QString::number(comic.info.hash.right(comic.info.hash.length() - 40).toInt() / 1024.0 / 1024.0, 'f', 2) + "Mb");
|
||||
|
||||
@ -452,7 +536,10 @@ void PropertiesDialog::loadComic(ComicDB &comic)
|
||||
else
|
||||
colorCheck->setCheckState(Qt::PartiallyChecked);
|
||||
|
||||
mangaCheck->setChecked(comic.info.manga.toBool());
|
||||
typeCombo->setCurrentIndex(comic.info.type.toInt());
|
||||
|
||||
if (!comic.info.languageISO.isNull())
|
||||
languageEdit->setText(comic.info.languageISO.toString());
|
||||
|
||||
if (!comic.info.ageRating.isNull())
|
||||
ageRatingEdit->setText(comic.info.ageRating.toString());
|
||||
@ -461,8 +548,19 @@ void PropertiesDialog::loadComic(ComicDB &comic)
|
||||
synopsis->setPlainText(comic.info.synopsis.toString());
|
||||
if (!comic.info.characters.isNull())
|
||||
characters->setPlainText(comic.info.characters.toString());
|
||||
if (!comic.info.teams.isNull())
|
||||
teams->setPlainText(comic.info.teams.toString());
|
||||
if (!comic.info.locations.isNull())
|
||||
locations->setPlainText(comic.info.locations.toString());
|
||||
if (!comic.info.mainCharacterOrTeam.isNull())
|
||||
mainCharacterOrTeamEdit->setText(comic.info.mainCharacterOrTeam.toString());
|
||||
|
||||
if (!comic.info.review.isNull())
|
||||
review->setPlainText(comic.info.review.toString());
|
||||
if (!comic.info.notes.isNull())
|
||||
notes->setPlainText(comic.info.notes.toString());
|
||||
if (!comic.info.tags.isNull())
|
||||
tags->setPlainText(comic.info.tags.toString());
|
||||
|
||||
this->setWindowTitle(tr("Edit comic information"));
|
||||
setCover(comic.info.getCover(basePath));
|
||||
@ -503,6 +601,9 @@ void PropertiesDialog::setComics(QList<ComicDB> comics)
|
||||
|
||||
QList<ComicDB>::iterator itr;
|
||||
for (itr = ++comics.begin(); itr != comics.end(); itr++) {
|
||||
if (itr->info.series.isNull() || itr->info.series.toString() != series->text())
|
||||
series->clear();
|
||||
|
||||
if (itr->info.title.isNull() || itr->info.title.toString() != title->text())
|
||||
title->clear();
|
||||
|
||||
@ -516,8 +617,15 @@ void PropertiesDialog::setComics(QList<ComicDB> comics)
|
||||
if (itr->info.arcCount.isNull() || itr->info.arcCount.toString() != storyArcEdit->text())
|
||||
arcCountEdit->clear();
|
||||
|
||||
if (itr->info.alternateSeries.isNull() || itr->info.alternateSeries.toString() != alternateSeriesEdit->text())
|
||||
alternateSeriesEdit->clear();
|
||||
if (itr->info.alternateCount.isNull() || itr->info.alternateCount.toString() != alternateCountEdit->text())
|
||||
alternateCountEdit->clear();
|
||||
|
||||
if (itr->info.genere.isNull() || itr->info.genere.toString() != genereEdit->text())
|
||||
genereEdit->clear();
|
||||
if (itr->info.seriesGroup.isNull() || itr->info.seriesGroup.toString() != seriesGroupEdit->text())
|
||||
seriesGroupEdit->clear();
|
||||
|
||||
if (itr->info.writer.isNull() || itr->info.writer.toString() != writer->toPlainText())
|
||||
writer->clear();
|
||||
@ -531,6 +639,10 @@ void PropertiesDialog::setComics(QList<ComicDB> comics)
|
||||
letterer->clear();
|
||||
if (itr->info.coverArtist.isNull() || itr->info.coverArtist.toString() != coverArtist->toPlainText())
|
||||
coverArtist->clear();
|
||||
if (itr->info.editor.isNull() || itr->info.editor.toString() != editor->toPlainText())
|
||||
editor->clear();
|
||||
if (itr->info.imprint.isNull() || itr->info.imprint.toString() != imprint->toPlainText())
|
||||
imprint->clear();
|
||||
|
||||
if (itr->info.date.isNull()) {
|
||||
dayEdit->clear();
|
||||
@ -552,8 +664,16 @@ void PropertiesDialog::setComics(QList<ComicDB> comics)
|
||||
formatEdit->clear();
|
||||
if (itr->info.color.isNull() || itr->info.color.toBool() != colorCheck->isChecked())
|
||||
colorCheck->setCheckState(Qt::PartiallyChecked);
|
||||
if (itr->info.manga.toBool() != colorCheck->isChecked())
|
||||
mangaCheck->setCheckState(Qt::PartiallyChecked);
|
||||
|
||||
if (itr->info.type.toInt() != typeCombo->currentIndex()) {
|
||||
typeCombo->setCurrentIndex(-1);
|
||||
} else {
|
||||
typeCombo->setCurrentIndex(itr->info.type.toInt());
|
||||
}
|
||||
|
||||
if (itr->info.languageISO.toString() != languageEdit->text())
|
||||
languageEdit->clear();
|
||||
|
||||
if (itr->info.ageRating.isNull() || itr->info.ageRating.toString() != ageRatingEdit->text())
|
||||
ageRatingEdit->clear();
|
||||
|
||||
@ -561,8 +681,19 @@ void PropertiesDialog::setComics(QList<ComicDB> comics)
|
||||
synopsis->clear();
|
||||
if (itr->info.characters.isNull() || itr->info.characters.toString() != characters->toPlainText())
|
||||
characters->clear();
|
||||
if (itr->info.teams.isNull() || itr->info.teams.toString() != teams->toPlainText())
|
||||
teams->clear();
|
||||
if (itr->info.locations.isNull() || itr->info.locations.toString() != locations->toPlainText())
|
||||
locations->clear();
|
||||
if (itr->info.mainCharacterOrTeam.isNull() || itr->info.mainCharacterOrTeam.toString() != mainCharacterOrTeamEdit->text())
|
||||
mainCharacterOrTeamEdit->clear();
|
||||
|
||||
if (itr->info.review.isNull() || itr->info.review.toString() != review->toPlainText())
|
||||
review->clear();
|
||||
if (itr->info.notes.isNull() || itr->info.notes.toString() != notes->toPlainText())
|
||||
notes->clear();
|
||||
if (itr->info.tags.isNull() || itr->info.tags.toString() != tags->toPlainText())
|
||||
tags->clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -615,7 +746,7 @@ void PropertiesDialog::setMultipleCover()
|
||||
|
||||
void PropertiesDialog::setCover(const QPixmap &coverI)
|
||||
{
|
||||
coverImage = coverI.scaledToHeight(444, Qt::SmoothTransformation);
|
||||
coverImage = coverI.scaledToHeight(575, Qt::SmoothTransformation);
|
||||
|
||||
cover->setPixmap(coverImage);
|
||||
}
|
||||
@ -642,6 +773,12 @@ void PropertiesDialog::save()
|
||||
for (itr = begin; itr != end; itr++) {
|
||||
bool edited = false;
|
||||
|
||||
if (series->isModified()) {
|
||||
auto seriesString = series->text();
|
||||
itr->info.series = seriesString.isEmpty() ? QVariant() : series->text();
|
||||
edited = true;
|
||||
}
|
||||
|
||||
if (title->isModified()) {
|
||||
auto titleString = title->text();
|
||||
itr->info.title = titleString.isEmpty() ? QVariant() : title->text();
|
||||
@ -654,8 +791,6 @@ void PropertiesDialog::save()
|
||||
edited = true;
|
||||
}
|
||||
|
||||
/*if(comic.info.numPages != NULL)
|
||||
numPagesEdit->setText(QString::number(*comic.info.numPages));*/
|
||||
if (sequentialEditing)
|
||||
if (numberEdit->isModified()) {
|
||||
if (numberEdit->text().isEmpty())
|
||||
@ -664,11 +799,6 @@ void PropertiesDialog::save()
|
||||
itr->info.number = numberEdit->text();
|
||||
edited = true;
|
||||
}
|
||||
if (sequentialEditing)
|
||||
if (!itr->info.isBis.isNull() || isBisCheck->isChecked()) {
|
||||
itr->info.isBis = isBisCheck->isChecked();
|
||||
edited = true;
|
||||
}
|
||||
|
||||
if (countEdit->isModified()) {
|
||||
itr->info.count = countEdit->text();
|
||||
@ -693,6 +823,23 @@ void PropertiesDialog::save()
|
||||
edited = true;
|
||||
}
|
||||
|
||||
if (alternateSeriesEdit->isModified()) {
|
||||
itr->info.alternateSeries = alternateSeriesEdit->text();
|
||||
edited = true;
|
||||
}
|
||||
|
||||
if (sequentialEditing) {
|
||||
if (alternateNumberEdit->isModified()) {
|
||||
itr->info.alternateNumber = alternateNumberEdit->text();
|
||||
edited = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (alternateCountEdit->isModified()) {
|
||||
itr->info.alternateCount = alternateCountEdit->text();
|
||||
edited = true;
|
||||
}
|
||||
|
||||
if (genereEdit->isModified()) {
|
||||
itr->info.genere = genereEdit->text();
|
||||
edited = true;
|
||||
@ -722,6 +869,14 @@ void PropertiesDialog::save()
|
||||
itr->info.coverArtist = coverArtist->toPlainText();
|
||||
edited = true;
|
||||
}
|
||||
if (editor->document()->isModified()) {
|
||||
itr->info.editor = editor->toPlainText();
|
||||
edited = true;
|
||||
}
|
||||
if (imprint->document()->isModified()) {
|
||||
itr->info.imprint = imprint->toPlainText();
|
||||
edited = true;
|
||||
}
|
||||
|
||||
if (dayEdit->isModified() || monthEdit->isModified() || yearEdit->isModified()) {
|
||||
itr->info.date = dayEdit->text() + "/" + monthEdit->text() + "/" + yearEdit->text();
|
||||
@ -740,8 +895,13 @@ void PropertiesDialog::save()
|
||||
edited = true;
|
||||
}
|
||||
|
||||
if (mangaCheck->checkState() != Qt::PartiallyChecked) {
|
||||
itr->info.manga = mangaCheck->isChecked();
|
||||
if (typeCombo->currentIndex() != -1 && itr->info.type.toInt() != typeCombo->currentIndex()) {
|
||||
itr->info.type = typeCombo->currentIndex();
|
||||
edited = true;
|
||||
}
|
||||
|
||||
if (languageEdit->isModified()) {
|
||||
itr->info.languageISO = languageEdit->text();
|
||||
edited = true;
|
||||
}
|
||||
|
||||
@ -754,14 +914,40 @@ void PropertiesDialog::save()
|
||||
itr->info.synopsis = synopsis->toPlainText();
|
||||
edited = true;
|
||||
}
|
||||
|
||||
if (characters->document()->isModified()) {
|
||||
itr->info.characters = characters->toPlainText();
|
||||
edited = true;
|
||||
}
|
||||
if (locations->document()->isModified()) {
|
||||
itr->info.locations = locations->toPlainText();
|
||||
edited = true;
|
||||
}
|
||||
if (teams->document()->isModified()) {
|
||||
itr->info.teams = teams->toPlainText();
|
||||
edited = true;
|
||||
}
|
||||
if (mainCharacterOrTeamEdit->isModified()) {
|
||||
itr->info.mainCharacterOrTeam = mainCharacterOrTeamEdit->text();
|
||||
edited = true;
|
||||
}
|
||||
if (seriesGroupEdit->isModified()) {
|
||||
itr->info.seriesGroup = seriesGroupEdit->text();
|
||||
edited = true;
|
||||
}
|
||||
|
||||
if (review->document()->isModified()) {
|
||||
itr->info.review = review->toPlainText();
|
||||
edited = true;
|
||||
}
|
||||
if (notes->document()->isModified()) {
|
||||
itr->info.notes = notes->toPlainText();
|
||||
edited = true;
|
||||
}
|
||||
if (tags->document()->isModified()) {
|
||||
itr->info.tags = tags->toPlainText();
|
||||
edited = true;
|
||||
}
|
||||
|
||||
itr->info.edited = edited;
|
||||
}
|
||||
@ -829,10 +1015,10 @@ void PropertiesDialog::setDisableUniqueValues(bool disabled)
|
||||
coverPageEdit->clear();
|
||||
numberEdit->setDisabled(disabled);
|
||||
numberEdit->clear();
|
||||
isBisCheck->setDisabled(disabled);
|
||||
isBisCheck->setChecked(false);
|
||||
arcNumberEdit->setDisabled(disabled);
|
||||
arcNumberEdit->clear();
|
||||
alternateNumberEdit->setDisabled(disabled);
|
||||
alternateNumberEdit->clear();
|
||||
}
|
||||
|
||||
void PropertiesDialog::closeEvent(QCloseEvent *e)
|
||||
@ -841,9 +1027,7 @@ void PropertiesDialog::closeEvent(QCloseEvent *e)
|
||||
title->clear();
|
||||
title->setModified(false);
|
||||
coverPageEdit->clear();
|
||||
// numPagesEdit->setText(QString::number(*comic.info.numPages));
|
||||
numberEdit->clear();
|
||||
isBisCheck->setChecked(false);
|
||||
countEdit->clear();
|
||||
volumeEdit->clear();
|
||||
storyArcEdit->clear();
|
||||
@ -862,12 +1046,27 @@ void PropertiesDialog::closeEvent(QCloseEvent *e)
|
||||
publisherEdit->clear();
|
||||
formatEdit->clear();
|
||||
colorCheck->setCheckState(Qt::PartiallyChecked);
|
||||
mangaCheck->setChecked(false);
|
||||
ageRatingEdit->clear();
|
||||
synopsis->clear();
|
||||
characters->clear();
|
||||
notes->clear();
|
||||
|
||||
// 9.13 fields
|
||||
typeCombo->setCurrentIndex(-1);
|
||||
editor->clear();
|
||||
imprint->clear();
|
||||
teams->clear();
|
||||
locations->clear();
|
||||
series->clear();
|
||||
alternateSeriesEdit->clear();
|
||||
alternateNumberEdit->clear();
|
||||
alternateCountEdit->clear();
|
||||
languageEdit->clear();
|
||||
seriesGroupEdit->clear();
|
||||
mainCharacterOrTeamEdit->clear();
|
||||
review->clear();
|
||||
tags->clear();
|
||||
|
||||
setDisableUniqueValues(false);
|
||||
|
||||
tabBar->setCurrentIndex(0);
|
||||
|
@ -15,6 +15,7 @@ class YACReaderFieldEdit;
|
||||
class YACReaderFieldPlainTextEdit;
|
||||
class QDialogButtonBox;
|
||||
class QCheckBox;
|
||||
class QComboBox;
|
||||
// class YACReaderBusyWidget;
|
||||
class QToolButton;
|
||||
|
||||
@ -36,6 +37,7 @@ private:
|
||||
QScrollArea *sa;
|
||||
|
||||
QWidget *generalInfoBox;
|
||||
YACReaderFieldEdit *series;
|
||||
YACReaderFieldEdit *title;
|
||||
YACReaderFieldEdit *numPagesEdit;
|
||||
QLabel *size;
|
||||
@ -46,7 +48,6 @@ private:
|
||||
|
||||
YACReaderFieldEdit *numberEdit;
|
||||
QIntValidator numberValidator;
|
||||
QCheckBox *isBisCheck;
|
||||
YACReaderFieldEdit *countEdit;
|
||||
QIntValidator countValidator;
|
||||
|
||||
@ -57,6 +58,12 @@ private:
|
||||
YACReaderFieldEdit *arcCountEdit;
|
||||
QIntValidator arcCountValidator;
|
||||
|
||||
YACReaderFieldEdit *alternateSeriesEdit;
|
||||
YACReaderFieldEdit *alternateNumberEdit;
|
||||
YACReaderFieldEdit *alternateCountEdit;
|
||||
|
||||
YACReaderFieldEdit *seriesGroupEdit;
|
||||
|
||||
YACReaderFieldEdit *genereEdit;
|
||||
|
||||
YACReaderFieldPlainTextEdit *writer;
|
||||
@ -65,6 +72,8 @@ private:
|
||||
YACReaderFieldPlainTextEdit *colorist;
|
||||
YACReaderFieldPlainTextEdit *letterer;
|
||||
YACReaderFieldPlainTextEdit *coverArtist;
|
||||
YACReaderFieldPlainTextEdit *editor;
|
||||
YACReaderFieldPlainTextEdit *imprint;
|
||||
|
||||
YACReaderFieldEdit *dayEdit;
|
||||
QIntValidator dayValidator;
|
||||
@ -76,11 +85,14 @@ private:
|
||||
YACReaderFieldEdit *formatEdit;
|
||||
QCheckBox *colorCheck;
|
||||
YACReaderFieldEdit *ageRatingEdit;
|
||||
QCheckBox *mangaCheck;
|
||||
QComboBox *typeCombo;
|
||||
YACReaderFieldEdit *languageEdit;
|
||||
|
||||
YACReaderFieldPlainTextEdit *synopsis;
|
||||
YACReaderFieldPlainTextEdit *characters;
|
||||
YACReaderFieldPlainTextEdit *notes;
|
||||
YACReaderFieldPlainTextEdit *teams;
|
||||
YACReaderFieldPlainTextEdit *locations;
|
||||
YACReaderFieldEdit *mainCharacterOrTeamEdit;
|
||||
|
||||
QWidget *authorsBox;
|
||||
|
||||
@ -88,6 +100,12 @@ private:
|
||||
|
||||
QWidget *plotBox;
|
||||
|
||||
QWidget *notesBox;
|
||||
|
||||
YACReaderFieldPlainTextEdit *review;
|
||||
YACReaderFieldPlainTextEdit *notes;
|
||||
YACReaderFieldPlainTextEdit *tags;
|
||||
|
||||
QDialogButtonBox *buttonBox;
|
||||
QPushButton *closeButton;
|
||||
QPushButton *saveButton;
|
||||
@ -107,6 +125,7 @@ private:
|
||||
void createAuthorsBox();
|
||||
void createPublishingBox();
|
||||
void createPlotBox();
|
||||
void createNotesBox();
|
||||
|
||||
void createButtonBox();
|
||||
|
||||
|
@ -140,7 +140,7 @@ Rectangle {
|
||||
font.pixelSize: mainContainer.compact ? 18 : 21;
|
||||
wrapMode: Text.WordWrap
|
||||
|
||||
text: comic ? comic.getTitleIncludingNumber() ?? "" : ""
|
||||
text: comic ? comic.getInfoTitle() ?? "" : ""
|
||||
}
|
||||
|
||||
RowLayout
|
||||
@ -202,6 +202,33 @@ Rectangle {
|
||||
visible : comicInfo ? comicInfo.number ?? false : false
|
||||
}
|
||||
|
||||
Text {
|
||||
id: arc
|
||||
color: infoColor
|
||||
font: mainContainer.infoFont
|
||||
text: comicInfo ? comicInfo.getStoryArcInfoString() : ""
|
||||
rightPadding: 20
|
||||
visible : comicInfo ? comicInfo.getStoryArcInfoString().length : false
|
||||
}
|
||||
|
||||
Text {
|
||||
id: alternate
|
||||
color: infoColor
|
||||
font: mainContainer.infoFont
|
||||
text: comicInfo ? comicInfo.getAlternateSeriesString() : ""
|
||||
rightPadding: 20
|
||||
visible : comicInfo ? comicInfo.getAlternateSeriesString().length : false
|
||||
}
|
||||
|
||||
Text {
|
||||
id: seriesGroup
|
||||
color: infoColor
|
||||
font: mainContainer.infoFont
|
||||
text: comicInfo ? comicInfo.seriesGroup ?? "" : ""
|
||||
rightPadding: 20
|
||||
visible: comicInfo ? comicInfo.seriesGroup ?? false : false
|
||||
}
|
||||
|
||||
Text {
|
||||
id: genre
|
||||
color: infoColor
|
||||
@ -266,6 +293,129 @@ Rectangle {
|
||||
textFormat: Text.RichText
|
||||
}
|
||||
|
||||
Text {
|
||||
Layout.topMargin: 25
|
||||
Layout.bottomMargin: 5
|
||||
|
||||
id: characters_title
|
||||
color: infoTitleColor
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 18
|
||||
font.bold: true
|
||||
|
||||
text: qsTr("Characters")
|
||||
|
||||
visible: comicInfo ? comicInfo.getCharacters().length > 0 : false
|
||||
}
|
||||
|
||||
Flow {
|
||||
Layout.fillWidth: true
|
||||
spacing: 20
|
||||
Repeater {
|
||||
id: characters
|
||||
model: comicInfo ? comicInfo.getCharacters().length : null
|
||||
|
||||
Text {
|
||||
color: infoTitleColor
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 15
|
||||
|
||||
text: comicInfo ? comicInfo.getCharacters()[index] : ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
Layout.topMargin: 25
|
||||
Layout.bottomMargin: 5
|
||||
|
||||
id: main_character_or_team_title
|
||||
color: infoTitleColor
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 18
|
||||
font.bold: true
|
||||
|
||||
text: qsTr("Main character or team")
|
||||
|
||||
visible: comicInfo && comicInfo.mainCharacterOrTeam ? comicInfo.mainCharacterOrTeam.length > 0 : false
|
||||
}
|
||||
|
||||
Text {
|
||||
color: infoTitleColor
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 15
|
||||
|
||||
text: comicInfo && comicInfo.mainCharacterOrTeam ? comicInfo.mainCharacterOrTeam : ""
|
||||
|
||||
visible: comicInfo && comicInfo.mainCharacterOrTeam ? comicInfo.mainCharacterOrTeam.length > 0 : false
|
||||
}
|
||||
|
||||
Text {
|
||||
Layout.topMargin: 25
|
||||
Layout.bottomMargin: 5
|
||||
|
||||
id: teams_title
|
||||
color: infoTitleColor
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 18
|
||||
font.bold: true
|
||||
|
||||
text: qsTr("Teams")
|
||||
|
||||
visible: comicInfo ? comicInfo.getTeams().length > 0 : false
|
||||
}
|
||||
|
||||
|
||||
|
||||
Flow {
|
||||
Layout.fillWidth: true
|
||||
spacing: 20
|
||||
Repeater {
|
||||
id: teams
|
||||
model: comicInfo ? comicInfo.getTeams().length : null
|
||||
|
||||
Text {
|
||||
color: infoTitleColor
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 15
|
||||
|
||||
text: comicInfo ? comicInfo.getTeams()[index] : ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
Layout.topMargin: 25
|
||||
Layout.bottomMargin: 5
|
||||
|
||||
id: locations_title
|
||||
color: infoTitleColor
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 18
|
||||
font.bold: true
|
||||
|
||||
text: qsTr("Locations")
|
||||
|
||||
visible: comicInfo ? comicInfo.getLocations().length > 0 : false
|
||||
}
|
||||
|
||||
Flow {
|
||||
Layout.fillWidth: true
|
||||
spacing: 20
|
||||
Repeater {
|
||||
id: locations
|
||||
model: comicInfo ? comicInfo.getLocations().length : null
|
||||
|
||||
Text {
|
||||
color: infoTitleColor
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 15
|
||||
|
||||
text: comicInfo ? comicInfo.getLocations()[index] : ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
Layout.topMargin: 25
|
||||
Layout.bottomMargin: 5
|
||||
@ -283,7 +433,9 @@ Rectangle {
|
||||
comicInfo.getInkers().length +
|
||||
comicInfo.getColorists().length +
|
||||
comicInfo.getLetterers().length +
|
||||
comicInfo.getCoverArtists().length > 0) : false
|
||||
comicInfo.getCoverArtists().length +
|
||||
comicInfo.getEditors().length +
|
||||
comicInfo.getImprint().length > 0) : false
|
||||
}
|
||||
|
||||
Flow {
|
||||
@ -401,7 +553,7 @@ Rectangle {
|
||||
|
||||
Repeater {
|
||||
id: cover_artist
|
||||
model: comicInfo ? comicInfo.getCoverArtists().length : ""
|
||||
model: comicInfo ? comicInfo.getCoverArtists().length : null
|
||||
Column{
|
||||
Text {
|
||||
color: infoTitleColor
|
||||
@ -420,6 +572,50 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Repeater {
|
||||
id: editors
|
||||
model: comicInfo ? comicInfo.getEditors().length : null
|
||||
Column{
|
||||
Text {
|
||||
color: infoTitleColor
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 15
|
||||
|
||||
text: comicInfo ? comicInfo.getEditors()[index] : ""
|
||||
}
|
||||
|
||||
Text {
|
||||
color: infoTextColor
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 13
|
||||
font.italic: true
|
||||
text: qsTr("editor")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Repeater {
|
||||
id: imprint
|
||||
model: comicInfo ? comicInfo.getImprint().length : null
|
||||
Column{
|
||||
Text {
|
||||
color: infoTitleColor
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 15
|
||||
|
||||
text: comicInfo ? comicInfo.getImprint()[index] : ""
|
||||
}
|
||||
|
||||
Text {
|
||||
color: infoTextColor
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 13
|
||||
font.italic: true
|
||||
text: qsTr("imprint")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
@ -464,6 +660,18 @@ Rectangle {
|
||||
visible: comicInfo ? comicInfo.format ?? false : false
|
||||
}
|
||||
|
||||
Text {
|
||||
id: type
|
||||
|
||||
color: infoTitleColor
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 15
|
||||
|
||||
text: comicInfo ? comicInfo.getTypeString() : ""
|
||||
|
||||
visible: comicInfo ? comicInfo.getTypeString() : false
|
||||
}
|
||||
|
||||
Text {
|
||||
id: color
|
||||
|
||||
@ -476,6 +684,18 @@ Rectangle {
|
||||
visible: comicInfo ? comicInfo.color ?? false : false
|
||||
}
|
||||
|
||||
Text {
|
||||
id: language
|
||||
|
||||
color: infoTitleColor
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 15
|
||||
|
||||
text: comicInfo && comicInfo.languageISO ? comicInfo.languageISO : ""
|
||||
|
||||
visible: comicInfo && comicInfo.languageISO ? comicInfo.languageISO.length > 0 ?? false : false
|
||||
}
|
||||
|
||||
Text {
|
||||
id: age_rating
|
||||
|
||||
@ -488,38 +708,6 @@ Rectangle {
|
||||
visible: comicInfo ? comicInfo.ageRating ?? false : false
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
Layout.topMargin: 25
|
||||
Layout.bottomMargin: 5
|
||||
|
||||
id: characters_title
|
||||
color: infoTitleColor
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 18
|
||||
font.bold: true
|
||||
|
||||
text: qsTr("Characters")
|
||||
|
||||
visible: comicInfo ? comicInfo.getCharacters().length > 0 : false
|
||||
}
|
||||
|
||||
Flow {
|
||||
Layout.fillWidth: true
|
||||
spacing: 20
|
||||
Repeater {
|
||||
id: characters
|
||||
model: comicInfo ? comicInfo.getCharacters().length : null
|
||||
|
||||
Text {
|
||||
color: infoTitleColor
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 15
|
||||
|
||||
text: comicInfo ? comicInfo.getCharacters()[index] : ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
|
@ -131,6 +131,16 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
//is new
|
||||
Rectangle {
|
||||
width: 10
|
||||
height: 10
|
||||
radius: 5
|
||||
anchors { left: coverElement.left; top: coverElement.top; topMargin: 10; leftMargin: 10; }
|
||||
color: "#FFFFCC00"
|
||||
visible: (((new Date() / 1000) - added) < recent_range || ((new Date() / 1000) - updated) < recent_range) && show_recent
|
||||
}
|
||||
|
||||
//border
|
||||
Rectangle {
|
||||
width: coverElement.width
|
||||
|
@ -133,6 +133,16 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
//is new
|
||||
Rectangle {
|
||||
width: 10
|
||||
height: 10
|
||||
radius: 5
|
||||
anchors { left: coverElement.left; top: coverElement.top; topMargin: 10; leftMargin: 10; }
|
||||
color: "#FFFFCC00"
|
||||
visible: (((new Date() / 1000) - added) < recent_range || ((new Date() / 1000) - updated) < recent_range) && show_recent
|
||||
}
|
||||
|
||||
//border
|
||||
Rectangle {
|
||||
width: coverElement.width
|
||||
|
@ -280,6 +280,16 @@ SplitView {
|
||||
|
||||
}
|
||||
|
||||
//is new
|
||||
Rectangle {
|
||||
width: 10
|
||||
height: 10
|
||||
radius: 5
|
||||
anchors { left: coverElement.left; top: coverElement.top; topMargin: 5; leftMargin: 5; }
|
||||
color: "#FFFFCC00"
|
||||
visible: (((new Date() / 1000) - added_date) < recent_range) && show_recent
|
||||
}
|
||||
|
||||
//border
|
||||
Rectangle {
|
||||
width: coverElement.width
|
||||
@ -489,8 +499,7 @@ SplitView {
|
||||
font.pixelSize: 21
|
||||
wrapMode: Text.WordWrap
|
||||
|
||||
text: currentComic.getTitleIncludingNumber()
|
||||
}
|
||||
text: currentComic ? currentComic.getTitleIncludingNumber() : "" }
|
||||
|
||||
Flow {
|
||||
spacing: 0
|
||||
@ -523,6 +532,33 @@ SplitView {
|
||||
visible : currentComicInfo.number ? true : false
|
||||
}
|
||||
|
||||
Text {
|
||||
id: currentComicInfoArc
|
||||
color: currentComicDetailsFlowView.infoFlowTextColor
|
||||
font: currentComicDetailsFlowView.infoFont
|
||||
text: currentComicInfo.getStoryArcInfoString()
|
||||
rightPadding: 20
|
||||
visible : currentComicInfo.getStoryArcInfoString().length > 0
|
||||
}
|
||||
|
||||
Text {
|
||||
id: currentComicInfoAlternate
|
||||
color: currentComicDetailsFlowView.infoFlowTextColor
|
||||
font: currentComicDetailsFlowView.infoFont
|
||||
text: currentComicInfo.getAlternateSeriesString()
|
||||
rightPadding: 20
|
||||
visible : currentComicInfo.getStoryArcInfoString().length > 0
|
||||
}
|
||||
|
||||
Text {
|
||||
id: currentComicInfoSeriesGroup
|
||||
color: currentComicDetailsFlowView.infoFlowTextColor
|
||||
font: currentComicDetailsFlowView.infoFont
|
||||
text: currentComicInfo.seriesGroup ? currentComicInfo.seriesGroup : ""
|
||||
rightPadding: 20
|
||||
visible: currentComicInfo.seriesGroup ? true : false
|
||||
}
|
||||
|
||||
Text {
|
||||
id: currentComicInfoGenre
|
||||
color: currentComicDetailsFlowView.infoFlowTextColor
|
||||
|
@ -283,6 +283,16 @@ SplitView {
|
||||
|
||||
}
|
||||
|
||||
//is new
|
||||
Rectangle {
|
||||
width: 10
|
||||
height: 10
|
||||
radius: 5
|
||||
anchors { left: coverElement.left; top: coverElement.top; topMargin: 5; leftMargin: 5; }
|
||||
color: "#FFFFCC00"
|
||||
visible: (((new Date() / 1000) - added_date) < recent_range) && show_recent
|
||||
}
|
||||
|
||||
//border
|
||||
Rectangle {
|
||||
width: coverElement.width
|
||||
@ -493,7 +503,7 @@ SplitView {
|
||||
font.pixelSize: 21
|
||||
wrapMode: Text.WordWrap
|
||||
|
||||
text: currentComic.getTitleIncludingNumber()
|
||||
text: currentComic?.getTitleIncludingNumber() ?? ""
|
||||
}
|
||||
|
||||
Flow {
|
||||
@ -527,6 +537,33 @@ SplitView {
|
||||
visible : currentComicInfo.number ? true : false
|
||||
}
|
||||
|
||||
Text {
|
||||
id: currentComicInfoArc
|
||||
color: currentComicDetailsFlowView.infoFlowTextColor
|
||||
font: currentComicDetailsFlowView.infoFont
|
||||
text: currentComicInfo.getStoryArcInfoString()
|
||||
rightPadding: 20
|
||||
visible : currentComicInfo.getStoryArcInfoString().length > 0
|
||||
}
|
||||
|
||||
Text {
|
||||
id: currentComicInfoAlternate
|
||||
color: currentComicDetailsFlowView.infoFlowTextColor
|
||||
font: currentComicDetailsFlowView.infoFont
|
||||
text: currentComicInfo.getAlternateSeriesString()
|
||||
rightPadding: 20
|
||||
visible : currentComicInfo.getStoryArcInfoString().length > 0
|
||||
}
|
||||
|
||||
Text {
|
||||
id: currentComicInfoSeriesGroup
|
||||
color: currentComicDetailsFlowView.infoFlowTextColor
|
||||
font: currentComicDetailsFlowView.infoFont
|
||||
text: currentComicInfo.seriesGroup ? currentComicInfo.seriesGroup : ""
|
||||
rightPadding: 20
|
||||
visible: currentComicInfo.seriesGroup ? true : false
|
||||
}
|
||||
|
||||
Text {
|
||||
id: currentComicInfoGenre
|
||||
color: currentComicDetailsFlowView.infoFlowTextColor
|
||||
|
35
YACReaderLibrary/recent_visibility_coordinator.cpp
Normal file
35
YACReaderLibrary/recent_visibility_coordinator.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
|
||||
#include "recent_visibility_coordinator.h"
|
||||
|
||||
#include "yacreader_global_gui.h"
|
||||
|
||||
RecentVisibilityCoordinator::RecentVisibilityCoordinator(QSettings *settings, FolderModel *folderModel, FolderContentView *folderContentView, ComicModel *comicModel)
|
||||
: QObject(), settings(settings), folderModel(folderModel), folderContentView(folderContentView), comicModel(comicModel)
|
||||
{
|
||||
updateVisibility();
|
||||
updateTimeRange();
|
||||
}
|
||||
|
||||
void RecentVisibilityCoordinator::toggleVisibility(bool visibility)
|
||||
{
|
||||
settings->setValue(DISPLAY_RECENTLY_INDICATOR, visibility);
|
||||
|
||||
updateVisibility();
|
||||
}
|
||||
|
||||
void RecentVisibilityCoordinator::updateTimeRange()
|
||||
{
|
||||
auto days = settings->value(NUM_DAYS_TO_CONSIDER_RECENT, 1).toInt();
|
||||
folderModel->setRecentRange(days);
|
||||
folderContentView->setRecentRange(days);
|
||||
comicModel->setRecentRange(days);
|
||||
}
|
||||
|
||||
void RecentVisibilityCoordinator::updateVisibility()
|
||||
{
|
||||
auto visibility = settings->value(DISPLAY_RECENTLY_INDICATOR, true).toBool();
|
||||
|
||||
folderModel->setShowRecent(visibility);
|
||||
folderContentView->setShowRecent(visibility);
|
||||
comicModel->setShowRecent(visibility);
|
||||
}
|
30
YACReaderLibrary/recent_visibility_coordinator.h
Normal file
30
YACReaderLibrary/recent_visibility_coordinator.h
Normal file
@ -0,0 +1,30 @@
|
||||
|
||||
#ifndef RECENT_VISIBILITY_COORDINATOR_H
|
||||
#define RECENT_VISIBILITY_COORDINATOR_H
|
||||
|
||||
#include <QtCore>
|
||||
|
||||
#include "folder_model.h"
|
||||
#include "comic_model.h"
|
||||
#include "folder_content_view.h"
|
||||
|
||||
class RecentVisibilityCoordinator : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit RecentVisibilityCoordinator(QSettings *settings, FolderModel *folderModel, FolderContentView *folderContentView, ComicModel *comicModel);
|
||||
|
||||
public slots:
|
||||
void toggleVisibility(bool visibility);
|
||||
void updateTimeRange();
|
||||
|
||||
private:
|
||||
QSettings *settings;
|
||||
FolderModel *folderModel;
|
||||
FolderContentView *folderContentView;
|
||||
ComicModel *comicModel;
|
||||
|
||||
void updateVisibility();
|
||||
};
|
||||
|
||||
#endif // RECENT_VISIBILITY_COORDINATOR_H
|
@ -6,8 +6,8 @@ QString YACReaderServerDataHelper::folderToYSFormat(const qulonglong libraryId,
|
||||
.arg(libraryId)
|
||||
.arg(folder.id)
|
||||
.arg(folder.name)
|
||||
.arg(folder.getNumChildren())
|
||||
.arg(folder.getFirstChildHash());
|
||||
.arg(folder.numChildren)
|
||||
.arg(folder.firstChildHash);
|
||||
}
|
||||
|
||||
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["library_id"] = QString::number(libraryId);
|
||||
json["folder_name"] = folder.name;
|
||||
json["num_children"] = folder.getNumChildren();
|
||||
json["first_comic_hash"] = folder.getFirstChildHash();
|
||||
json["num_children"] = folder.numChildren;
|
||||
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;
|
||||
}
|
||||
@ -47,14 +54,18 @@ QJsonObject YACReaderServerDataHelper::comicToJSON(const qulonglong libraryId, c
|
||||
json["file_name"] = comic.name;
|
||||
json["file_size"] = QString::number(comic.getFileSize());
|
||||
json["hash"] = comic.info.hash;
|
||||
json["cover_page"] = comic.info.coverPage.toInt(); // 9.13
|
||||
json["current_page"] = comic.info.currentPage;
|
||||
json["num_pages"] = comic.info.numPages.toInt();
|
||||
json["read"] = comic.info.read;
|
||||
json["cover_size_ratio"] = comic.info.coverSizeRatio.toFloat();
|
||||
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["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;
|
||||
}
|
||||
@ -70,6 +81,39 @@ QJsonObject YACReaderServerDataHelper::fullComicToJSON(const qulonglong libraryI
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "xml_info_parser.h"
|
||||
|
||||
#include "yacreader_global.h"
|
||||
|
||||
#include <QtCore>
|
||||
|
||||
bool isValidText(const QString &string)
|
||||
@ -57,7 +59,7 @@ void consolidateDate(ComicInfo &info)
|
||||
|
||||
auto year = info.year.isNull() ? 0 : info.year.toInt();
|
||||
auto month = info.month.isNull() ? 1 : info.month.toInt();
|
||||
auto day = info.date.isNull() ? 1 : info.date.toInt();
|
||||
auto day = info.day.isNull() ? 1 : info.day.toInt();
|
||||
|
||||
info.date = QString("%1/%2/%3").arg(day).arg(month).arg(year);
|
||||
}
|
||||
@ -65,6 +67,7 @@ void consolidateDate(ComicInfo &info)
|
||||
bool tryValues(QXmlStreamReader &reader, ComicInfo &info)
|
||||
{
|
||||
std::map<QString, QVariant &> stringValues = {
|
||||
{ "Number", info.number },
|
||||
{ "Title", info.title },
|
||||
{ "Volume", info.volume },
|
||||
{ "StoryArc", info.storyArc },
|
||||
@ -74,16 +77,23 @@ bool tryValues(QXmlStreamReader &reader, ComicInfo &info)
|
||||
{ "AgeRating", info.ageRating },
|
||||
{ "Summary", info.synopsis },
|
||||
{ "Notes", info.notes },
|
||||
{ "Editor", info.editor },
|
||||
{ "Imprint", info.imprint },
|
||||
{ "Series", info.series },
|
||||
{ "AlternateSeries", info.alternateSeries },
|
||||
{ "AlternateNumber", info.alternateNumber },
|
||||
{ "LanguageISO", info.languageISO },
|
||||
{ "SeriesGroup", info.seriesGroup },
|
||||
{ "MainCharacterOrTeam", info.mainCharacterOrTeam },
|
||||
{ "Review", info.review },
|
||||
};
|
||||
|
||||
std::map<QString, QVariant &> forcedNumbers = {
|
||||
{ "Number", info.number },
|
||||
{ "Count", info.count },
|
||||
{ "AlternateNumber", info.arcNumber },
|
||||
{ "AlternateCount", info.arcCount },
|
||||
{ "AlternateCount", info.alternateCount },
|
||||
{ "Day", info.day },
|
||||
{ "Month", info.month },
|
||||
{ "Year", info.year }
|
||||
{ "Year", info.year },
|
||||
};
|
||||
|
||||
std::map<QString, QVariant &> multiValuedStrings = {
|
||||
@ -93,7 +103,9 @@ bool tryValues(QXmlStreamReader &reader, ComicInfo &info)
|
||||
{ "Colorist", info.colorist },
|
||||
{ "Letterer", info.letterer },
|
||||
{ "CoverArtist", info.coverArtist },
|
||||
{ "Characters", info.characters }
|
||||
{ "Characters", info.characters },
|
||||
{ "Teams", info.teams },
|
||||
{ "Locations", info.locations }
|
||||
};
|
||||
|
||||
for (auto &pair : stringValues) {
|
||||
@ -130,16 +142,17 @@ bool tryValues(QXmlStreamReader &reader, ComicInfo &info)
|
||||
if (reader.name() == QString("Manga")) {
|
||||
auto string = reader.readElementText();
|
||||
if (isValidText(string)) {
|
||||
if (string == "Yes" || string == "YesAndRightToLeft") {
|
||||
info.manga = true;
|
||||
if (string == "Yes" || string == "YesAndRightToLeft") { // there was a breaking change in ComicInfo 2.0, Yes means now WesterManga reading style, but old info stills means manga
|
||||
info.type = QVariant::fromValue(YACReader::FileType::Manga);
|
||||
} else if (string == "No") {
|
||||
info.manga = false;
|
||||
info.type = QVariant::fromValue(YACReader::FileType::Comic);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO, check if the url is actually a comic vine link
|
||||
if (reader.name() == QString("Web")) {
|
||||
auto string = reader.readElementText();
|
||||
if (isValidText(string)) {
|
||||
@ -166,7 +179,7 @@ bool YACReader::parseXMLIntoInfo(const QByteArray &xmlRawData, ComicInfo &info)
|
||||
|
||||
while (reader.readNextStartElement()) {
|
||||
if (tryValues(reader, info)) {
|
||||
someDataWasParsed = true;
|
||||
someDataWasParsed = true | someDataWasParsed;
|
||||
} else {
|
||||
if (reader.name() != QString("ComicInfo")) {
|
||||
reader.skipCurrentElement();
|
||||
|
@ -45,7 +45,7 @@ YACReaderContentViewsManager::YACReaderContentViewsManager(QSettings *settings,
|
||||
doComicsViewConnections();
|
||||
|
||||
comicsViewStack->addWidget(comicsViewTransition = new ComicsViewTransition());
|
||||
comicsViewStack->addWidget(folderContentView = new FolderContentView());
|
||||
comicsViewStack->addWidget(folderContentView = new FolderContentView(parent->toogleShowRecentIndicatorAction));
|
||||
comicsViewStack->addWidget(emptyLabelWidget = new EmptyLabelWidget());
|
||||
comicsViewStack->addWidget(emptySpecialList = new EmptySpecialListWidget());
|
||||
comicsViewStack->addWidget(emptyReadingList = new EmptyReadingListWidget());
|
||||
|
@ -91,4 +91,26 @@ void YACReaderFoldersViewItemDeletegate::paint(QPainter *painter, const QStyleOp
|
||||
}
|
||||
|
||||
QStyledItemDelegate::paint(painter, option, index);
|
||||
|
||||
auto showRecent = index.data(FolderModel::ShowRecentRole).toBool();
|
||||
|
||||
if (showRecent) {
|
||||
auto now = QDateTime::currentSecsSinceEpoch();
|
||||
auto added = index.data(FolderModel::AddedRole).toLongLong();
|
||||
auto updated = index.data(FolderModel::UpdatedRole).toLongLong();
|
||||
auto daysInSeconds = index.data(FolderModel::RecentRangeRole).toLongLong();
|
||||
|
||||
if (now - added < daysInSeconds || now - updated < daysInSeconds) {
|
||||
painter->save();
|
||||
painter->setRenderHint(QPainter::Antialiasing);
|
||||
#ifdef Q_OS_MAC
|
||||
painter->setBrush(QBrush(QColor(85, 95, 127)));
|
||||
#else
|
||||
painter->setBrush(QBrush(QColor(237, 197, 24)));
|
||||
#endif
|
||||
painter->setPen(QPen(QBrush(), 0));
|
||||
painter->drawEllipse(option.rect.x() + 13, option.rect.y() + 2, 7, 7);
|
||||
painter->restore();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "comic_db.h"
|
||||
|
||||
#include "yacreader_global.h"
|
||||
|
||||
#include <QVariant>
|
||||
#include <QFileInfo>
|
||||
|
||||
@ -118,6 +120,51 @@ QString ComicDB::toTXT()
|
||||
if (!info.lastTimeOpened.isNull())
|
||||
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;
|
||||
}
|
||||
|
||||
@ -169,6 +216,35 @@ QString ComicDB::getTitleIncludingNumber() const
|
||||
return getTitleOrFileName();
|
||||
}
|
||||
|
||||
QString ComicDB::getInfoTitle() const
|
||||
{
|
||||
if (!info.number.isNull() && !info.title.isNull() && !info.series.isNull())
|
||||
return "#" + info.number.toString() + " - " + info.title.toString() + " (" + info.series.toString() + ")";
|
||||
|
||||
if (!info.title.isNull() && !info.series.isNull())
|
||||
return info.title.toString() + " (" + info.series.toString() + ")";
|
||||
|
||||
if (!info.number.isNull() && !info.title.isNull())
|
||||
return "#" + info.number.toString() + " - " + info.title.toString();
|
||||
|
||||
if (!info.number.isNull() && !info.series.isNull())
|
||||
return "#" + info.number.toString() + " - " + info.series.toString();
|
||||
|
||||
if (!info.number.isNull())
|
||||
return "#" + info.number.toString() + " - " + getTitleOrFileName();
|
||||
|
||||
if (!info.title.isNull() && !info.series.isNull())
|
||||
return info.title.toString() + " (" + info.series.toString() + ")";
|
||||
|
||||
if (!info.title.isNull())
|
||||
return info.title.toString();
|
||||
|
||||
if (!info.series.isNull())
|
||||
return info.series.toString();
|
||||
|
||||
return QFileInfo(path).fileName();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// COMIC_INFO-------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -238,6 +314,22 @@ void ComicInfo::deleteMetadata()
|
||||
characters = 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();
|
||||
}
|
||||
// the default operator= should work
|
||||
@ -292,135 +384,25 @@ ComicInfo &ComicInfo::operator=(const ComicInfo &comicInfo)
|
||||
coverSizeRatio = comicInfo.coverSizeRatio;
|
||||
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;
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
if (cover.isNull()) {
|
||||
@ -485,6 +467,24 @@ QStringList ComicInfo::getCoverArtists()
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
QStringList ComicInfo::getEditors()
|
||||
{
|
||||
if (editor.toString().length() > 0) {
|
||||
return editor.toString().split("\n");
|
||||
}
|
||||
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
QStringList ComicInfo::getImprint()
|
||||
{
|
||||
if (imprint.toString().length() > 0) {
|
||||
return imprint.toString().split("\n");
|
||||
}
|
||||
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
QStringList ComicInfo::getCharacters()
|
||||
{
|
||||
if (characters.toString().length() > 0) {
|
||||
@ -494,6 +494,75 @@ QStringList ComicInfo::getCharacters()
|
||||
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();
|
||||
}
|
||||
|
||||
QString ComicInfo::getTypeString()
|
||||
{
|
||||
switch (type.value<YACReader::FileType>()) {
|
||||
case YACReader::FileType::Comic:
|
||||
return "Comic";
|
||||
case YACReader::FileType::Manga:
|
||||
return "Manga";
|
||||
case YACReader::FileType::WesternManga:
|
||||
return "Western Manga";
|
||||
case YACReader::FileType::WebComic:
|
||||
return "Web Comic";
|
||||
case YACReader::FileType::Yonkoma:
|
||||
return "4-Koma";
|
||||
}
|
||||
}
|
||||
|
||||
QString ComicInfo::getStoryArcInfoString()
|
||||
{
|
||||
if (arcNumber.toString().length() > 0 && arcCount.toString().length() > 0 && storyArc.toString().length() > 0) {
|
||||
return "(" + arcNumber.toString() + "/" + arcCount.toString() + ") " + storyArc.toString();
|
||||
}
|
||||
|
||||
if (arcNumber.toString().length() > 0 && storyArc.toString().length() > 0) {
|
||||
return "(" + arcNumber.toString() + ") " + storyArc.toString();
|
||||
}
|
||||
|
||||
return storyArc.toString().length() > 0 ? storyArc.toString() : "";
|
||||
}
|
||||
|
||||
QString ComicInfo::getAlternateSeriesString()
|
||||
{
|
||||
if (alternateNumber.toString().length() > 0 && alternateCount.toString().length() > 0 && alternateSeries.toString().length() > 0) {
|
||||
return "(" + alternateNumber.toString() + "/" + alternateCount.toString() + ") " + alternateSeries.toString();
|
||||
}
|
||||
|
||||
if (alternateNumber.toString().length() > 0 && alternateSeries.toString().length() > 0) {
|
||||
return "(" + alternateNumber.toString() + ") " + alternateSeries.toString();
|
||||
}
|
||||
|
||||
return alternateSeries.toString().length() > 0 ? alternateSeries.toString() : "";
|
||||
}
|
||||
|
||||
void ComicInfo::setRead(bool r)
|
||||
{
|
||||
if (r != read) {
|
||||
@ -599,6 +668,24 @@ QDataStream &operator<<(QDataStream &stream, const ComicInfo &comicInfo)
|
||||
stream << comicInfo.coverSizeRatio;
|
||||
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;
|
||||
}
|
||||
|
||||
@ -661,5 +748,23 @@ QDataStream &operator>>(QDataStream &stream, ComicInfo &comicInfo)
|
||||
stream >> comicInfo.coverSizeRatio;
|
||||
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;
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ public:
|
||||
QString hash;
|
||||
bool existOnDb;
|
||||
|
||||
int rating;
|
||||
int rating; // TODO_METADATA: change to float
|
||||
|
||||
bool hasBeenOpened;
|
||||
|
||||
@ -52,13 +52,13 @@ public:
|
||||
QVariant coverPage; // int
|
||||
QVariant numPages; // int
|
||||
|
||||
QVariant number; // int
|
||||
QVariant number; // string (changed in 9.13 from int)
|
||||
QVariant isBis; // bool
|
||||
QVariant count; // int
|
||||
|
||||
QVariant volume; // string
|
||||
QVariant storyArc; // string
|
||||
QVariant arcNumber; // int
|
||||
QVariant arcNumber; // string (changed in 9.13 from int)
|
||||
QVariant arcCount; // int
|
||||
|
||||
QVariant genere; // string
|
||||
@ -80,7 +80,7 @@ public:
|
||||
QVariant format; // string
|
||||
QVariant color; // bool
|
||||
QVariant ageRating; // string
|
||||
QVariant manga; // bool
|
||||
[[deprecated("use type instead")]] QVariant manga; // bool
|
||||
|
||||
QVariant synopsis; // string
|
||||
QVariant characters; // string
|
||||
@ -94,38 +94,21 @@ public:
|
||||
QVariant coverSizeRatio; // h/w
|
||||
QVariant originalCoverSize; // string "WxH"
|
||||
|
||||
/*void setTitle(QVariant value);
|
||||
|
||||
void setCoverPage(QVariant value);
|
||||
void setNumPages(QVariant value);
|
||||
|
||||
void setNumber(QVariant value);
|
||||
void setIsBis(QVariant value);
|
||||
void setCount(QVariant value);
|
||||
|
||||
void setVolume(QVariant value);
|
||||
void setStoryArc(QVariant value);
|
||||
void setArcNumber(QVariant value);
|
||||
void setArcCount(QVariant value);
|
||||
|
||||
void setGenere(QVariant value);
|
||||
|
||||
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);*/
|
||||
QVariant added; // integer/date
|
||||
QVariant type; // enum
|
||||
QVariant editor; // string
|
||||
QVariant imprint; // string
|
||||
QVariant teams; // string/list
|
||||
QVariant locations; // string/list
|
||||
QVariant series; // string
|
||||
QVariant alternateSeries; // string
|
||||
QVariant alternateNumber; // string
|
||||
QVariant alternateCount; // int
|
||||
QVariant languageISO; // string
|
||||
QVariant seriesGroup; // string
|
||||
QVariant mainCharacterOrTeam; // string
|
||||
QVariant review; // string
|
||||
QVariant tags; // string/list
|
||||
|
||||
QPixmap getCover(const QString &basePath);
|
||||
|
||||
@ -135,9 +118,21 @@ public:
|
||||
Q_INVOKABLE QStringList getColorists();
|
||||
Q_INVOKABLE QStringList getLetterers();
|
||||
Q_INVOKABLE QStringList getCoverArtists();
|
||||
Q_INVOKABLE QStringList getEditors();
|
||||
Q_INVOKABLE QStringList getImprint();
|
||||
|
||||
Q_INVOKABLE QStringList getCharacters();
|
||||
|
||||
Q_INVOKABLE QStringList getTeams();
|
||||
Q_INVOKABLE QStringList getLocations();
|
||||
|
||||
Q_INVOKABLE QStringList getTags();
|
||||
|
||||
Q_INVOKABLE QString getTypeString();
|
||||
|
||||
Q_INVOKABLE QString getStoryArcInfoString();
|
||||
Q_INVOKABLE QString getAlternateSeriesString();
|
||||
|
||||
friend QDataStream &operator<<(QDataStream &stream, const ComicInfo &comicInfo);
|
||||
|
||||
friend QDataStream &operator>>(QDataStream &stream, ComicInfo &comicInfo);
|
||||
@ -206,11 +201,27 @@ public:
|
||||
Q_PROPERTY(QVariant coverSizeRatio MEMBER coverSizeRatio 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
|
||||
bool isFavorite;
|
||||
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 setRating(int r);
|
||||
void setFavorite(bool f);
|
||||
@ -248,6 +259,7 @@ public:
|
||||
Q_INVOKABLE qulonglong getFileSize() const;
|
||||
|
||||
Q_INVOKABLE QString getTitleIncludingNumber() const;
|
||||
Q_INVOKABLE QString getInfoTitle() const;
|
||||
|
||||
QString toTXT();
|
||||
|
||||
|
@ -20,7 +20,19 @@ Folder::Folder(qulonglong folderId, qulonglong parentId, const QString &folderNa
|
||||
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),
|
||||
knownId(true),
|
||||
numChildren(-1)
|
||||
@ -32,6 +44,12 @@ Folder::Folder(qulonglong folderId, qulonglong parentId, const QString &folderNa
|
||||
this->completed = completed;
|
||||
this->finished = finished;
|
||||
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)
|
||||
@ -51,6 +69,9 @@ Folder &Folder::operator=(const Folder &other)
|
||||
this->numChildren = other.numChildren;
|
||||
this->firstChildHash = other.firstChildHash;
|
||||
this->customImage = other.customImage;
|
||||
this->type = other.type;
|
||||
this->added = other.added;
|
||||
this->updated = other.updated;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define __FOLDER_H
|
||||
|
||||
#include "library_item.h"
|
||||
#include "yacreader_global.h"
|
||||
|
||||
#include <QList>
|
||||
|
||||
@ -11,9 +12,33 @@ public:
|
||||
bool knownParent;
|
||||
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(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 Folder &folder);
|
||||
Folder &operator=(const Folder &other);
|
||||
@ -33,75 +58,6 @@ public:
|
||||
{
|
||||
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
|
||||
|
@ -7,6 +7,7 @@ int naturalCompare(const QString &s1, const QString &s2, Qt::CaseSensitivity cas
|
||||
QCollator c;
|
||||
c.setCaseSensitivity(caseSensitivity);
|
||||
c.setNumericMode(true);
|
||||
c.setIgnorePunctuation(false);
|
||||
return c.compare(s1, s2);
|
||||
}
|
||||
bool naturalSortLessThanCS(const QString &left, const QString &right)
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include <QMetaType>
|
||||
#include <QAbstractItemModel>
|
||||
|
||||
#define VERSION "9.12.0"
|
||||
#define VERSION "9.13.0"
|
||||
|
||||
#define IMPORT_COMIC_INFO_XML_METADATA "IMPORT_COMIC_INFO_XML_METADATA"
|
||||
|
||||
@ -51,6 +51,14 @@ enum LabelColors {
|
||||
YDark
|
||||
};
|
||||
|
||||
enum class FileType : int {
|
||||
Comic = 0,
|
||||
Manga,
|
||||
WesternManga,
|
||||
WebComic, // continuous vertical reading
|
||||
Yonkoma, // 4Koma
|
||||
};
|
||||
|
||||
struct OpenComicSource {
|
||||
enum Source {
|
||||
Folder = 0,
|
||||
@ -76,5 +84,6 @@ void iterate(const QModelIndex &index,
|
||||
|
||||
Q_DECLARE_METATYPE(YACReader::OpenComicSource::Source)
|
||||
Q_DECLARE_METATYPE(YACReader::OpenComicSource)
|
||||
Q_DECLARE_METATYPE(YACReader::FileType)
|
||||
|
||||
#endif
|
||||
|
@ -71,6 +71,8 @@
|
||||
#define BLUR_RADIUS_BACKGROUND_IMAGE_IN_GRID_VIEW "BLUR_RADIUS_BACKGROUND_IMAGE_IN_GRID_VIEW"
|
||||
#define USE_SELECTED_COMIC_COVER_AS_BACKGROUND_IMAGE_IN_GRID_VIEW "USE_SELECTED_COMIC_COVER_AS_BACKGROUND_IMAGE_IN_GRID_VIEW"
|
||||
#define DISPLAY_CONTINUE_READING_IN_GRID_VIEW "DISPLAY_CONTINUE_READING_IN_GRID_VIEW"
|
||||
#define DISPLAY_RECENTLY_INDICATOR "DISPLAY_RECENTLY_INDICATOR"
|
||||
#define NUM_DAYS_TO_CONSIDER_RECENT "NUM_DAYS_TO_CONSIDER_RECENT"
|
||||
|
||||
namespace YACReader {
|
||||
|
||||
|
@ -46,19 +46,16 @@ YACReader::WhatsNewDialog::WhatsNewDialog(QWidget *parent)
|
||||
"color:#858585;");
|
||||
|
||||
auto text = new QLabel();
|
||||
text->setText("Update to add support for remote search through the server:<br/>"
|
||||
text->setText("New metadata support and better search engine:<br/>"
|
||||
"<br/>"
|
||||
"<span style=\"font-weight:600\">YACReaderLibrary</span><br/>"
|
||||
" • Fix scroll in grid views when using Qt6 builds.<br/>"
|
||||
" • Fix deleting metadata from comics, it also deleted the number of pages info.<br/>"
|
||||
" • Do not accept empty values for the server port in the server settings dialog.<br/>"
|
||||
" • New way of generating QR codes.<br/>"
|
||||
"<br/>"
|
||||
"<span style=\"font-weight:600\">YACReaderLibraryServer</span><br/>"
|
||||
" • Print scannable QR code at server start.<br/>"
|
||||
"<br/>"
|
||||
"<span style=\"font-weight:600\">Server</span><br/>"
|
||||
" • New search API that exposes the search engine. This will be used by the upcoming updates for the iOS & Android apps.<br/>"
|
||||
" • Avoid showing stale information in the server config dialog by updating the connection information when the dialog is opened.<br/>"
|
||||
" • Add new metadata support, it improves compatibility with ComicInfo.xml.<br/>"
|
||||
" • Add support for showing a 'recently added/updated' indicator.<br/>"
|
||||
" • Improved comic metadata dialog.<br/>"
|
||||
" • Add textual tags support that can be queried through the search engine.<br/>"
|
||||
" • Make '=' in the search engine work as ':' does.<br/>"
|
||||
" • Add new operators to the search engine: exact match ==, <, >, <=, >=.<br/>"
|
||||
"<br/>"
|
||||
"I hope you enjoy the new update. Please, if you like YACReader consider to become a patron in <a href=\"https://www.patreon.com/yacreader\" style=\"color:#E8B800;\">Patreon</a> "
|
||||
"or donate some money using <a href=\"https://www.paypal.com/donate?business=5TAMNQCDDMVP8&item_name=Support+YACReader\" style=\"color:#E8B800;\">Pay-Pal</a> and help keeping the project alive. "
|
||||
|
BIN
images/comics_view_toolbar/showRecentIndicator.svg
Normal file
BIN
images/comics_view_toolbar/showRecentIndicator.svg
Normal file
Binary file not shown.
After Width: | Height: | Size: 278 B |
@ -51,6 +51,9 @@ public:
|
||||
#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_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 TOGGLE_FULL_SCREEN_ACTION_YL "TOGGLE_FULL_SCREEN_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_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_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_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 RESET_COMIC_RATING_ACTION_YL "RESET_COMIC_RATING_ACTION_YL"
|
||||
#define SELECT_ALL_COMICS_ACTION_YL "SELECT_ALL_COMICS_ACTION_YL"
|
||||
@ -91,6 +97,7 @@ public:
|
||||
#define RENAME_LIST_ACTION_YL "RENAME_LIST_ACTION_YL"
|
||||
#define ADD_TO_FAVORITES_ACTION_YL "ADD_TO_FAVORITES_ACTION_YL"
|
||||
#define SAVE_COVERS_TO_ACTION_YL "SAVE_COVERS_TO_ACTION_YL"
|
||||
#define SHOW_HIDE_RECENT_INDICATOR_ACTION_YL "SHOW_HIDE_RECENT_INDICATOR_ACTION_YL"
|
||||
// COMMANDS YACReaderLibrary
|
||||
|
||||
// ACTION NAMES YACReader
|
||||
|
Loading…
Reference in New Issue
Block a user