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
|
### YACReaderLibrary
|
||||||
* Avoid showing stale information in the server config dialog by updating the connection information when the dialog is opened.
|
* 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
|
## 9.12
|
||||||
|
|
||||||
|
@ -1575,7 +1575,7 @@ void MainWindowViewer::sendComic()
|
|||||||
auto client = new YACReaderLocalClient;
|
auto client = new YACReaderLocalClient;
|
||||||
|
|
||||||
connect(client, &YACReaderLocalClient::finished, client, &YACReaderLocalClient::deleteLater);
|
connect(client, &YACReaderLocalClient::finished, client, &YACReaderLocalClient::deleteLater);
|
||||||
currentComicDB.info.lastTimeOpened = QDateTime::currentMSecsSinceEpoch() / 1000;
|
currentComicDB.info.lastTimeOpened = QDateTime::currentSecsSinceEpoch();
|
||||||
|
|
||||||
viewer->updateComic(currentComicDB);
|
viewer->updateComic(currentComicDB);
|
||||||
|
|
||||||
|
@ -85,6 +85,7 @@ HEADERS += comic_flow.h \
|
|||||||
library_creator.h \
|
library_creator.h \
|
||||||
library_window.h \
|
library_window.h \
|
||||||
add_library_dialog.h \
|
add_library_dialog.h \
|
||||||
|
recent_visibility_coordinator.h \
|
||||||
rename_library_dialog.h \
|
rename_library_dialog.h \
|
||||||
properties_dialog.h \
|
properties_dialog.h \
|
||||||
options_dialog.h \
|
options_dialog.h \
|
||||||
@ -171,6 +172,7 @@ SOURCES += comic_flow.cpp \
|
|||||||
library_window.cpp \
|
library_window.cpp \
|
||||||
main.cpp \
|
main.cpp \
|
||||||
add_library_dialog.cpp \
|
add_library_dialog.cpp \
|
||||||
|
recent_visibility_coordinator.cpp \
|
||||||
rename_library_dialog.cpp \
|
rename_library_dialog.cpp \
|
||||||
properties_dialog.cpp \
|
properties_dialog.cpp \
|
||||||
options_dialog.cpp \
|
options_dialog.cpp \
|
||||||
|
@ -90,7 +90,7 @@ ClassicComicsView::ClassicComicsView(QWidget *parent)
|
|||||||
hideFlowViewAction->setText(tr("Hide comic flow"));
|
hideFlowViewAction->setText(tr("Hide comic flow"));
|
||||||
hideFlowViewAction->setData(HIDE_COMIC_VIEW_ACTION_YL);
|
hideFlowViewAction->setData(HIDE_COMIC_VIEW_ACTION_YL);
|
||||||
hideFlowViewAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(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->setCheckable(true);
|
||||||
hideFlowViewAction->setChecked(false);
|
hideFlowViewAction->setChecked(false);
|
||||||
|
|
||||||
@ -120,9 +120,7 @@ void ClassicComicsView::setToolBar(QToolBar *toolBar)
|
|||||||
static_cast<QVBoxLayout *>(comics->layout())->insertWidget(0, toolBar);
|
static_cast<QVBoxLayout *>(comics->layout())->insertWidget(0, toolBar);
|
||||||
this->toolbar = toolBar;
|
this->toolbar = toolBar;
|
||||||
|
|
||||||
toolBarStretch = new YACReaderToolBarStretch(this);
|
startSeparatorAction = toolBar->addSeparator();
|
||||||
|
|
||||||
toolBarStretchAction = toolBar->addWidget(toolBarStretch);
|
|
||||||
toolBar->addAction(hideFlowViewAction);
|
toolBar->addAction(hideFlowViewAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -343,7 +341,7 @@ void ClassicComicsView::removeItemsFromFlow(const QModelIndex &parent, int from,
|
|||||||
|
|
||||||
void ClassicComicsView::closeEvent(QCloseEvent *event)
|
void ClassicComicsView::closeEvent(QCloseEvent *event)
|
||||||
{
|
{
|
||||||
toolbar->removeAction(toolBarStretchAction);
|
toolbar->removeAction(startSeparatorAction);
|
||||||
toolbar->removeAction(hideFlowViewAction);
|
toolbar->removeAction(hideFlowViewAction);
|
||||||
|
|
||||||
saveTableHeadersStatus();
|
saveTableHeadersStatus();
|
||||||
|
@ -54,8 +54,6 @@ protected slots:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
YACReaderTableView *tableView;
|
YACReaderTableView *tableView;
|
||||||
YACReaderToolBarStretch *toolBarStretch;
|
|
||||||
QAction *toolBarStretchAction;
|
|
||||||
QToolBar *toolbar;
|
QToolBar *toolbar;
|
||||||
QWidget *comics;
|
QWidget *comics;
|
||||||
QSplitter *sVertical;
|
QSplitter *sVertical;
|
||||||
@ -63,6 +61,7 @@ private:
|
|||||||
QSettings *settings;
|
QSettings *settings;
|
||||||
void closeEvent(QCloseEvent *event) override;
|
void closeEvent(QCloseEvent *event) override;
|
||||||
QAction *hideFlowViewAction;
|
QAction *hideFlowViewAction;
|
||||||
|
QAction *startSeparatorAction;
|
||||||
|
|
||||||
QStackedWidget *stack;
|
QStackedWidget *stack;
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
|
$$PWD/comic_vine_json_parser.h \
|
||||||
comic_vine/comic_vine_dialog.h \
|
comic_vine/comic_vine_dialog.h \
|
||||||
comic_vine/comic_vine_client.h \
|
comic_vine/comic_vine_client.h \
|
||||||
comic_vine/scraper_lineedit.h \
|
comic_vine/scraper_lineedit.h \
|
||||||
@ -24,6 +25,7 @@ HEADERS += \
|
|||||||
$$PWD/comic_vine_all_volume_comics_retriever.h
|
$$PWD/comic_vine_all_volume_comics_retriever.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
|
$$PWD/comic_vine_json_parser.cpp \
|
||||||
comic_vine/comic_vine_dialog.cpp \
|
comic_vine/comic_vine_dialog.cpp \
|
||||||
comic_vine/comic_vine_client.cpp \
|
comic_vine/comic_vine_client.cpp \
|
||||||
comic_vine/scraper_lineedit.cpp \
|
comic_vine/scraper_lineedit.cpp \
|
||||||
|
@ -10,12 +10,11 @@
|
|||||||
#include <QtWidgets>
|
#include <QtWidgets>
|
||||||
#include <QtConcurrent/QtConcurrentRun>
|
#include <QtConcurrent/QtConcurrentRun>
|
||||||
#include "data_base_management.h"
|
#include "data_base_management.h"
|
||||||
#include <QJsonDocument>
|
|
||||||
#include <QJsonParseError>
|
|
||||||
#include <QSqlDatabase>
|
#include <QSqlDatabase>
|
||||||
|
|
||||||
#include "yacreader_busy_widget.h"
|
#include "yacreader_busy_widget.h"
|
||||||
#include "comic_vine_client.h"
|
#include "comic_vine_client.h"
|
||||||
|
#include "comic_vine_json_parser.h"
|
||||||
#include "scraper_lineedit.h"
|
#include "scraper_lineedit.h"
|
||||||
#include "title_header.h"
|
#include "title_header.h"
|
||||||
#include "series_question.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
|
QByteArray result = comicVineClient->getComicDetail(p.second, error, timeout); // TODO check timeOut or Connection error
|
||||||
if (error || timeout)
|
if (error || timeout)
|
||||||
continue; // TODO
|
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;
|
comic.info.comicVineID = p.second;
|
||||||
comics.push_back(comic);
|
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;
|
comic.info.comicVineID = comicId;
|
||||||
setLoadingMessage(tr("Retrieving tags for : %1").arg(comics[currentIndex].getFileName()));
|
setLoadingMessage(tr("Retrieving tags for : %1").arg(comics[currentIndex].getFileName()));
|
||||||
QString connectionName = "";
|
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()
|
void ComicVineDialog::toggleSkipButton()
|
||||||
{
|
{
|
||||||
if (mode == SingleComicInList)
|
if (mode == SingleComicInList)
|
||||||
|
@ -58,16 +58,11 @@ protected slots:
|
|||||||
void showSelectComic(const QString &json);
|
void showSelectComic(const QString &json);
|
||||||
void showSortVolumeComics(const QString &json);
|
void showSortVolumeComics(const QString &json);
|
||||||
void queryTimeOut();
|
void queryTimeOut();
|
||||||
ComicDB parseComicInfo(ComicDB &comic, const QString &json, int count, const QString &publisher);
|
|
||||||
void setLoadingMessage(const QString &message);
|
void setLoadingMessage(const QString &message);
|
||||||
void goToNextComic();
|
void goToNextComic();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void clearState();
|
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();
|
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"
|
#include "QsLog.h"
|
||||||
|
|
||||||
ComicModel::ComicModel(QObject *parent)
|
ComicModel::ComicModel(QObject *parent)
|
||||||
: QAbstractItemModel(parent)
|
: QAbstractItemModel(parent), showRecent(false), recentDays(1)
|
||||||
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
ComicModel::ComicModel(QSqlQuery &sqlquery, QObject *parent)
|
ComicModel::ComicModel(QSqlQuery &sqlquery, QObject *parent)
|
||||||
: QAbstractItemModel(parent)
|
: QAbstractItemModel(parent), showRecent(false), recentDays(1)
|
||||||
{
|
{
|
||||||
setupModelData(sqlquery);
|
setupModelData(sqlquery);
|
||||||
}
|
}
|
||||||
@ -239,6 +240,10 @@ QHash<int, QByteArray> ComicModel::roleNames() const
|
|||||||
roles[CoverPathRole] = "cover_path";
|
roles[CoverPathRole] = "cover_path";
|
||||||
roles[PublicationDate] = "date";
|
roles[PublicationDate] = "date";
|
||||||
roles[ReadableTitle] = "readable_title";
|
roles[ReadableTitle] = "readable_title";
|
||||||
|
roles[AddedRole] = "added_date";
|
||||||
|
roles[TypeRole] = "type";
|
||||||
|
roles[ShowRecentRole] = "show_recent";
|
||||||
|
roles[RecentRangeRole] = "recent_range";
|
||||||
|
|
||||||
return roles;
|
return roles;
|
||||||
}
|
}
|
||||||
@ -301,6 +306,14 @@ QVariant ComicModel::data(const QModelIndex &index, int role) const
|
|||||||
return item->data(Id);
|
return item->data(Id);
|
||||||
else if (role == PublicationDateRole)
|
else if (role == PublicationDateRole)
|
||||||
return QVariant(localizedDate(item->data(PublicationDate).toString()));
|
return QVariant(localizedDate(item->data(PublicationDate).toString()));
|
||||||
|
else if (role == AddedRole)
|
||||||
|
return item->data(Added);
|
||||||
|
else if (role == TypeRole)
|
||||||
|
return item->data(Type);
|
||||||
|
else if (role == ShowRecentRole)
|
||||||
|
return showRecent;
|
||||||
|
else if (role == ComicModel::RecentRangeRole)
|
||||||
|
return recentDays * 86400;
|
||||||
|
|
||||||
if (role != Qt::DisplayRole)
|
if (role != Qt::DisplayRole)
|
||||||
return QVariant();
|
return QVariant();
|
||||||
@ -443,6 +456,8 @@ QStringList ComicModel::getPaths(const QString &_source)
|
|||||||
return paths;
|
return paths;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define COMIC_MODEL_QUERY_FIELDS "ci.number,ci.title,c.fileName,ci.numPages,c.id,c.parentId,c.path,ci.hash,ci.read,ci.isBis,ci.currentPage,ci.rating,ci.hasBeenOpened,ci.date,ci.added,ci.type"
|
||||||
|
|
||||||
void ComicModel::setupFolderModelData(unsigned long long int folderId, const QString &databasePath)
|
void ComicModel::setupFolderModelData(unsigned long long int folderId, const QString &databasePath)
|
||||||
{
|
{
|
||||||
enableResorting = false;
|
enableResorting = false;
|
||||||
@ -458,7 +473,7 @@ void ComicModel::setupFolderModelData(unsigned long long int folderId, const QSt
|
|||||||
{
|
{
|
||||||
QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath);
|
QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath);
|
||||||
QSqlQuery selectQuery(db);
|
QSqlQuery selectQuery(db);
|
||||||
selectQuery.prepare("SELECT ci.number,ci.title,c.fileName,ci.numPages,c.id,c.parentId,c.path,ci.hash,ci.read,ci.isBis,ci.currentPage,ci.rating,ci.hasBeenOpened,ci.date "
|
selectQuery.prepare("SELECT " COMIC_MODEL_QUERY_FIELDS " "
|
||||||
"FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) "
|
"FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) "
|
||||||
"WHERE c.parentId = :parentId");
|
"WHERE c.parentId = :parentId");
|
||||||
selectQuery.bindValue(":parentId", folderId);
|
selectQuery.bindValue(":parentId", folderId);
|
||||||
@ -485,7 +500,7 @@ void ComicModel::setupLabelModelData(unsigned long long parentLabel, const QStri
|
|||||||
{
|
{
|
||||||
QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath);
|
QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath);
|
||||||
QSqlQuery selectQuery(db);
|
QSqlQuery selectQuery(db);
|
||||||
selectQuery.prepare("SELECT ci.number,ci.title,c.fileName,ci.numPages,c.id,c.parentId,c.path,ci.hash,ci.read,ci.isBis,ci.currentPage,ci.rating,ci.hasBeenOpened,ci.date "
|
selectQuery.prepare("SELECT " COMIC_MODEL_QUERY_FIELDS " "
|
||||||
"FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) "
|
"FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) "
|
||||||
"INNER JOIN comic_label cl ON (c.id == cl.comic_id) "
|
"INNER JOIN comic_label cl ON (c.id == cl.comic_id) "
|
||||||
"WHERE cl.label_id = :parentLabelId "
|
"WHERE cl.label_id = :parentLabelId "
|
||||||
@ -529,7 +544,7 @@ void ComicModel::setupReadingListModelData(unsigned long long parentReadingList,
|
|||||||
|
|
||||||
foreach (qulonglong id, ids) {
|
foreach (qulonglong id, ids) {
|
||||||
QSqlQuery selectQuery(db);
|
QSqlQuery selectQuery(db);
|
||||||
selectQuery.prepare("SELECT ci.number,ci.title,c.fileName,ci.numPages,c.id,c.parentId,c.path,ci.hash,ci.read,ci.isBis,ci.currentPage,ci.rating,ci.hasBeenOpened,ci.date "
|
selectQuery.prepare("SELECT " COMIC_MODEL_QUERY_FIELDS " "
|
||||||
"FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) "
|
"FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) "
|
||||||
"INNER JOIN comic_reading_list crl ON (c.id == crl.comic_id) "
|
"INNER JOIN comic_reading_list crl ON (c.id == crl.comic_id) "
|
||||||
"WHERE crl.reading_list_id = :parentReadingList "
|
"WHERE crl.reading_list_id = :parentReadingList "
|
||||||
@ -566,7 +581,7 @@ void ComicModel::setupFavoritesModelData(const QString &databasePath)
|
|||||||
{
|
{
|
||||||
QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath);
|
QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath);
|
||||||
QSqlQuery selectQuery(db);
|
QSqlQuery selectQuery(db);
|
||||||
selectQuery.prepare("SELECT ci.number,ci.title,c.fileName,ci.numPages,c.id,c.parentId,c.path,ci.hash,ci.read,ci.isBis,ci.currentPage,ci.rating,ci.hasBeenOpened,ci.date "
|
selectQuery.prepare("SELECT " COMIC_MODEL_QUERY_FIELDS " "
|
||||||
"FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) "
|
"FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) "
|
||||||
"INNER JOIN comic_default_reading_list cdrl ON (c.id == cdrl.comic_id) "
|
"INNER JOIN comic_default_reading_list cdrl ON (c.id == cdrl.comic_id) "
|
||||||
"WHERE cdrl.default_reading_list_id = :parentDefaultListId "
|
"WHERE cdrl.default_reading_list_id = :parentDefaultListId "
|
||||||
@ -595,7 +610,7 @@ void ComicModel::setupReadingModelData(const QString &databasePath)
|
|||||||
{
|
{
|
||||||
QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath);
|
QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath);
|
||||||
QSqlQuery selectQuery(db);
|
QSqlQuery selectQuery(db);
|
||||||
selectQuery.prepare("SELECT ci.number,ci.title,c.fileName,ci.numPages,c.id,c.parentId,c.path,ci.hash,ci.read,ci.isBis,ci.currentPage,ci.rating,ci.hasBeenOpened,ci.date "
|
selectQuery.prepare("SELECT " COMIC_MODEL_QUERY_FIELDS " "
|
||||||
"FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) "
|
"FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) "
|
||||||
"WHERE ci.hasBeenOpened = 1 AND ci.read = 0 "
|
"WHERE ci.hasBeenOpened = 1 AND ci.read = 0 "
|
||||||
"ORDER BY ci.lastTimeOpened DESC");
|
"ORDER BY ci.lastTimeOpened DESC");
|
||||||
@ -652,7 +667,7 @@ void ComicModel::setupModelData(QSqlQuery &sqlquery)
|
|||||||
return naturalSortLessThanCI(c1->data(ComicModel::FileName).toString(), c2->data(ComicModel::FileName).toString());
|
return naturalSortLessThanCI(c1->data(ComicModel::FileName).toString(), c2->data(ComicModel::FileName).toString());
|
||||||
} else {
|
} else {
|
||||||
if (c1->data(ComicModel::Number).isNull() == false && c2->data(ComicModel::Number).isNull() == false) {
|
if (c1->data(ComicModel::Number).isNull() == false && c2->data(ComicModel::Number).isNull() == false) {
|
||||||
return c1->data(ComicModel::Number).toInt() < c2->data(ComicModel::Number).toInt();
|
return naturalSortLessThanCI(c1->data(ComicModel::Number).toString(), c2->data(ComicModel::Number).toString());
|
||||||
} else {
|
} else {
|
||||||
return c2->data(ComicModel::Number).isNull();
|
return c2->data(ComicModel::Number).isNull();
|
||||||
}
|
}
|
||||||
@ -794,7 +809,7 @@ QVector<YACReaderComicReadStatus> ComicModel::setComicsRead(QList<QModelIndex> l
|
|||||||
return getReadList();
|
return getReadList();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ComicModel::setComicsManga(QList<QModelIndex> list, bool isManga)
|
void ComicModel::setComicsType(QList<QModelIndex> list, FileType type)
|
||||||
{
|
{
|
||||||
QString connectionName = "";
|
QString connectionName = "";
|
||||||
{
|
{
|
||||||
@ -803,7 +818,7 @@ void ComicModel::setComicsManga(QList<QModelIndex> list, bool isManga)
|
|||||||
foreach (QModelIndex mi, list) {
|
foreach (QModelIndex mi, list) {
|
||||||
bool found;
|
bool found;
|
||||||
ComicDB c = DBHelper::loadComic(_data.value(mi.row())->data(ComicModel::Id).toULongLong(), db, found);
|
ComicDB c = DBHelper::loadComic(_data.value(mi.row())->data(ComicModel::Id).toULongLong(), db, found);
|
||||||
c.info.manga = isManga;
|
c.info.type = QVariant::fromValue(type);
|
||||||
DBHelper::update(&(c.info), db);
|
DBHelper::update(&(c.info), db);
|
||||||
}
|
}
|
||||||
db.commit();
|
db.commit();
|
||||||
@ -1122,6 +1137,26 @@ bool ComicModel::isFavorite(const QModelIndex &index)
|
|||||||
return isFavorite;
|
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)
|
void ComicModel::updateRating(int rating, QModelIndex mi)
|
||||||
{
|
{
|
||||||
ComicDB comic = getComic(mi);
|
ComicDB comic = getComic(mi);
|
||||||
|
@ -31,11 +31,13 @@ public:
|
|||||||
Path = 6,
|
Path = 6,
|
||||||
Hash = 7,
|
Hash = 7,
|
||||||
ReadColumn = 8,
|
ReadColumn = 8,
|
||||||
IsBis = 9,
|
IsBis = 9, // TODO_METADATA: Remove this column
|
||||||
CurrentPage = 10,
|
CurrentPage = 10,
|
||||||
Rating = 11,
|
Rating = 11,
|
||||||
HasBeenOpened = 12,
|
HasBeenOpened = 12,
|
||||||
PublicationDate = 13,
|
PublicationDate = 13,
|
||||||
|
Added = 14,
|
||||||
|
Type = 15,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Roles {
|
enum Roles {
|
||||||
@ -55,6 +57,10 @@ public:
|
|||||||
CoverPathRole,
|
CoverPathRole,
|
||||||
PublicationDateRole,
|
PublicationDateRole,
|
||||||
ReadableTitle,
|
ReadableTitle,
|
||||||
|
AddedRole,
|
||||||
|
TypeRole,
|
||||||
|
ShowRecentRole,
|
||||||
|
RecentRangeRole,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Mode {
|
enum Mode {
|
||||||
@ -107,7 +113,7 @@ public:
|
|||||||
// setComicInfoForAllComics(); --> inserta la información común a todos los cómics de una sola vez.
|
// setComicInfoForAllComics(); --> inserta la información común a todos los cómics de una sola vez.
|
||||||
// setComicInfoForSelectedComis(QList<QModelIndex> list); -->inserta la información común para los comics seleccionados
|
// setComicInfoForSelectedComis(QList<QModelIndex> list); -->inserta la información común para los comics seleccionados
|
||||||
QVector<YACReaderComicReadStatus> setComicsRead(QList<QModelIndex> list, YACReaderComicReadStatus read);
|
QVector<YACReaderComicReadStatus> setComicsRead(QList<QModelIndex> list, YACReaderComicReadStatus read);
|
||||||
void setComicsManga(QList<QModelIndex> list, bool isManga);
|
void setComicsType(QList<QModelIndex> list, FileType type);
|
||||||
qint64 asignNumbers(QList<QModelIndex> list, int startingNumber);
|
qint64 asignNumbers(QList<QModelIndex> list, int startingNumber);
|
||||||
// void remove(ComicDB * comic, int row);
|
// void remove(ComicDB * comic, int row);
|
||||||
void removeInTransaction(int row);
|
void removeInTransaction(int row);
|
||||||
@ -135,6 +141,9 @@ public:
|
|||||||
ComicModel::Mode getMode() { return mode; }
|
ComicModel::Mode getMode() { return mode; }
|
||||||
unsigned long long int getSourceId() { return sourceId; }
|
unsigned long long int getSourceId() { return sourceId; }
|
||||||
|
|
||||||
|
void setShowRecent(bool visible);
|
||||||
|
void setRecentRange(int days);
|
||||||
|
|
||||||
QHash<int, QByteArray> roleNames() const override;
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
@ -164,6 +173,9 @@ private:
|
|||||||
qulonglong sourceId;
|
qulonglong sourceId;
|
||||||
QString localizedDate(const QString &dbDate) const;
|
QString localizedDate(const QString &dbDate) const;
|
||||||
|
|
||||||
|
bool showRecent;
|
||||||
|
qlonglong recentDays;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void isEmpty();
|
void isEmpty();
|
||||||
void searchNumResults(int);
|
void searchNumResults(int);
|
||||||
|
@ -64,23 +64,29 @@ static QString fields = "title,"
|
|||||||
//"coverSizeRatio," cover may have changed since the info was exported...
|
//"coverSizeRatio," cover may have changed since the info was exported...
|
||||||
//"originalCoverSize," // h/w
|
//"originalCoverSize," // h/w
|
||||||
// new 9.8 fields
|
// new 9.8 fields
|
||||||
"manga";
|
"manga,"
|
||||||
|
// new 9.13 fields
|
||||||
|
"added,"
|
||||||
|
"type,"
|
||||||
|
"editor,"
|
||||||
|
"imprint,"
|
||||||
|
"teams,"
|
||||||
|
"locations,"
|
||||||
|
"series,"
|
||||||
|
"alternateSeries,"
|
||||||
|
"alternateNumber,"
|
||||||
|
"alternateCount,"
|
||||||
|
"languageISO,"
|
||||||
|
"seriesGroup,"
|
||||||
|
"mainCharacterOrTeam,"
|
||||||
|
"review,"
|
||||||
|
"tags";
|
||||||
|
|
||||||
DataBaseManagement::DataBaseManagement()
|
DataBaseManagement::DataBaseManagement()
|
||||||
: QObject(), dataBasesList()
|
: QObject(), dataBasesList()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/*TreeModel * DataBaseManagement::newTreeModel(QString path)
|
|
||||||
{
|
|
||||||
//la consulta se ejecuta...
|
|
||||||
QSqlQuery selectQuery(loadDatabase(path));
|
|
||||||
selectQuery.setForwardOnly(true);
|
|
||||||
selectQuery.exec("select * from folder order by parentId,name");
|
|
||||||
//selectQuery.finish();
|
|
||||||
return new TreeModel(selectQuery);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
QSqlDatabase DataBaseManagement::createDatabase(QString name, QString path)
|
QSqlDatabase DataBaseManagement::createDatabase(QString name, QString path)
|
||||||
{
|
{
|
||||||
return createDatabase(QDir::cleanPath(path) + "/" + name + ".ydb");
|
return createDatabase(QDir::cleanPath(path) + "/" + name + ".ydb");
|
||||||
@ -102,12 +108,12 @@ QSqlDatabase DataBaseManagement::createDatabase(QString dest)
|
|||||||
// pragma.finish();
|
// pragma.finish();
|
||||||
DataBaseManagement::createTables(db);
|
DataBaseManagement::createTables(db);
|
||||||
|
|
||||||
QSqlQuery query("INSERT INTO folder (parentId, name, path) "
|
QSqlQuery insertRootQuery(db);
|
||||||
"VALUES (1,'root', '/')",
|
insertRootQuery.prepare("INSERT INTO folder (parentId, name, path, added) "
|
||||||
db);
|
"VALUES (1, 'root', '/', :added)");
|
||||||
|
insertRootQuery.bindValue(":added", QDateTime::currentSecsSinceEpoch());
|
||||||
|
insertRootQuery.exec();
|
||||||
}
|
}
|
||||||
// query.finish();
|
|
||||||
// db.close();
|
|
||||||
|
|
||||||
return db;
|
return db;
|
||||||
}
|
}
|
||||||
@ -156,13 +162,13 @@ bool DataBaseManagement::createTables(QSqlDatabase &database)
|
|||||||
"coverPage INTEGER DEFAULT 1,"
|
"coverPage INTEGER DEFAULT 1,"
|
||||||
"numPages INTEGER,"
|
"numPages INTEGER,"
|
||||||
|
|
||||||
"number INTEGER,"
|
"number TEXT," // changed to text from INTEGER (9.13)
|
||||||
"isBis BOOLEAN,"
|
"isBis BOOLEAN,"
|
||||||
"count INTEGER,"
|
"count INTEGER,"
|
||||||
|
|
||||||
"volume TEXT,"
|
"volume TEXT,"
|
||||||
"storyArc TEXT,"
|
"storyArc TEXT,"
|
||||||
"arcNumber INTEGER,"
|
"arcNumber TEXT," // changed to text from INTEGER (9.13)
|
||||||
"arcCount INTEGER,"
|
"arcCount INTEGER,"
|
||||||
|
|
||||||
"genere TEXT,"
|
"genere TEXT,"
|
||||||
@ -174,11 +180,11 @@ bool DataBaseManagement::createTables(QSqlDatabase &database)
|
|||||||
"letterer TEXT,"
|
"letterer TEXT,"
|
||||||
"coverArtist TEXT,"
|
"coverArtist TEXT,"
|
||||||
|
|
||||||
"date TEXT," // dd/mm/yyyy --> se mostrará en 3 campos diferentes
|
"date TEXT," // publication date dd/mm/yyyy --> se mostrará en 3 campos diferentes
|
||||||
"publisher TEXT,"
|
"publisher TEXT,"
|
||||||
"format TEXT,"
|
"format TEXT,"
|
||||||
"color BOOLEAN,"
|
"color BOOLEAN,"
|
||||||
"ageRating BOOLEAN," // this is actually a string (TEXT), funny thing is that the current implementation works
|
"ageRating TEXT,"
|
||||||
|
|
||||||
"synopsis TEXT,"
|
"synopsis TEXT,"
|
||||||
"characters TEXT,"
|
"characters TEXT,"
|
||||||
@ -190,7 +196,7 @@ bool DataBaseManagement::createTables(QSqlDatabase &database)
|
|||||||
// new 7.0 fields
|
// new 7.0 fields
|
||||||
|
|
||||||
"hasBeenOpened BOOLEAN DEFAULT 0,"
|
"hasBeenOpened BOOLEAN DEFAULT 0,"
|
||||||
"rating INTEGER DEFAULT 0,"
|
"rating INTEGER DEFAULT 0," // TODO_METADATA change type to REAL with two decimals
|
||||||
"currentPage INTEGER DEFAULT 1, "
|
"currentPage INTEGER DEFAULT 1, "
|
||||||
"bookmark1 INTEGER DEFAULT -1, "
|
"bookmark1 INTEGER DEFAULT -1, "
|
||||||
"bookmark2 INTEGER DEFAULT -1, "
|
"bookmark2 INTEGER DEFAULT -1, "
|
||||||
@ -205,8 +211,23 @@ bool DataBaseManagement::createTables(QSqlDatabase &database)
|
|||||||
"coverSizeRatio REAL,"
|
"coverSizeRatio REAL,"
|
||||||
"originalCoverSize STRING," // h/w
|
"originalCoverSize STRING," // h/w
|
||||||
// new 9.8 fields
|
// new 9.8 fields
|
||||||
"manga BOOLEAN DEFAULT 0"
|
"manga BOOLEAN DEFAULT 0," // deprecated 9.13
|
||||||
|
// new 9.13 fields
|
||||||
|
"added INTEGER,"
|
||||||
|
"type INTEGER DEFAULT 0," // 0 = comic, 1 = manga, 2 = manga left to right, 3 = webcomic, 4 = 4koma
|
||||||
|
"editor TEXT,"
|
||||||
|
"imprint TEXT,"
|
||||||
|
"teams TEXT,"
|
||||||
|
"locations TEXT,"
|
||||||
|
"series TEXT,"
|
||||||
|
"alternateSeries TEXT,"
|
||||||
|
"alternateNumber TEXT,"
|
||||||
|
"alternateCount INTEGER,"
|
||||||
|
"languageISO TEXT,"
|
||||||
|
"seriesGroup TEXT,"
|
||||||
|
"mainCharacterOrTeam TEXT,"
|
||||||
|
"review TEXT,"
|
||||||
|
"tags TEXT"
|
||||||
")");
|
")");
|
||||||
success = success && queryComicInfo.exec();
|
success = success && queryComicInfo.exec();
|
||||||
// queryComicInfo.finish();
|
// queryComicInfo.finish();
|
||||||
@ -226,7 +247,11 @@ bool DataBaseManagement::createTables(QSqlDatabase &database)
|
|||||||
"firstChildHash TEXT,"
|
"firstChildHash TEXT,"
|
||||||
"customImage TEXT,"
|
"customImage TEXT,"
|
||||||
// new 9.8 fields
|
// new 9.8 fields
|
||||||
"manga BOOLEAN DEFAULT 0,"
|
"manga BOOLEAN DEFAULT 0," // deprecated 9.13
|
||||||
|
// new 9.13 fields
|
||||||
|
"type INTEGER DEFAULT 0," // 0 = comic, 1 = manga, 2 = manga left to right, 3 = webcomic, 4 = 4koma
|
||||||
|
"added INTEGER,"
|
||||||
|
"updated INTEGER," // updated when the folder gets new content
|
||||||
"FOREIGN KEY(parentId) REFERENCES folder(id) ON DELETE CASCADE)");
|
"FOREIGN KEY(parentId) REFERENCES folder(id) ON DELETE CASCADE)");
|
||||||
success = success && queryFolder.exec();
|
success = success && queryFolder.exec();
|
||||||
|
|
||||||
@ -460,7 +485,25 @@ bool DataBaseManagement::importComicsInfo(QString source, QString dest)
|
|||||||
//--
|
//--
|
||||||
|
|
||||||
// new 9.8 fields
|
// new 9.8 fields
|
||||||
"manga = :manga"
|
"manga = :manga,"
|
||||||
|
|
||||||
|
// new 9.13 fields
|
||||||
|
"added = :added,"
|
||||||
|
"type = :type," // 0 = comic, 1 = manga, 2 = manga left to right, 3 = webcomic,
|
||||||
|
"editor = :editor,"
|
||||||
|
"imprint = :imprint,"
|
||||||
|
"teams = :teams,"
|
||||||
|
"locations = :locations,"
|
||||||
|
"series = :series,"
|
||||||
|
"alternateSeries = :alternateSeries,"
|
||||||
|
"alternateNumber = :alternateNumber,"
|
||||||
|
"alternateCount = :alternateCount,"
|
||||||
|
"languageISO = :languageISO,"
|
||||||
|
"seriesGroup = :seriesGroup,"
|
||||||
|
"mainCharacterOrTeam = :mainCharacterOrTeam,"
|
||||||
|
"review = :review,"
|
||||||
|
"tags = :tags"
|
||||||
|
|
||||||
//--
|
//--
|
||||||
" WHERE hash = :hash ");
|
" WHERE hash = :hash ");
|
||||||
|
|
||||||
@ -496,6 +539,21 @@ bool DataBaseManagement::importComicsInfo(QString source, QString dest)
|
|||||||
"comicVineID,"
|
"comicVineID,"
|
||||||
"lastTimeOpened,"
|
"lastTimeOpened,"
|
||||||
"coverSizeRatio,"
|
"coverSizeRatio,"
|
||||||
|
"manga,"
|
||||||
|
"added,"
|
||||||
|
"type,"
|
||||||
|
"editor,"
|
||||||
|
"imprint,"
|
||||||
|
"teams,"
|
||||||
|
"locations,"
|
||||||
|
"series,"
|
||||||
|
"alternateSeries,"
|
||||||
|
"alternateNumber,"
|
||||||
|
"alternateCount,"
|
||||||
|
"languageISO,"
|
||||||
|
"seriesGroup,"
|
||||||
|
"mainCharacterOrTeam,"
|
||||||
|
"review,"
|
||||||
"hash)"
|
"hash)"
|
||||||
|
|
||||||
"VALUES (:title,"
|
"VALUES (:title,"
|
||||||
@ -539,6 +597,23 @@ bool DataBaseManagement::importComicsInfo(QString source, QString dest)
|
|||||||
":coverSizeRatio,"
|
":coverSizeRatio,"
|
||||||
":originalCoverSize,"
|
":originalCoverSize,"
|
||||||
|
|
||||||
|
":manga,"
|
||||||
|
":added,"
|
||||||
|
":type,"
|
||||||
|
":editor,"
|
||||||
|
":imprint,"
|
||||||
|
":teams,"
|
||||||
|
":locations,"
|
||||||
|
":series,"
|
||||||
|
":alternateSeries,"
|
||||||
|
":alternateNumber,"
|
||||||
|
":alternateCount,"
|
||||||
|
":languageISO,"
|
||||||
|
":seriesGroup,"
|
||||||
|
":mainCharacterOrTeam,"
|
||||||
|
":review,"
|
||||||
|
":tags,"
|
||||||
|
|
||||||
":hash )");
|
":hash )");
|
||||||
|
|
||||||
QSqlRecord record = newInfo.record();
|
QSqlRecord record = newInfo.record();
|
||||||
@ -596,6 +671,8 @@ bool DataBaseManagement::importComicsInfo(QString source, QString dest)
|
|||||||
|
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: update fields
|
||||||
// TODO fix these bindings
|
// TODO fix these bindings
|
||||||
void DataBaseManagement::bindValuesFromRecord(const QSqlRecord &record, QSqlQuery &query)
|
void DataBaseManagement::bindValuesFromRecord(const QSqlRecord &record, QSqlQuery &query)
|
||||||
{
|
{
|
||||||
@ -654,6 +731,22 @@ void DataBaseManagement::bindValuesFromRecord(const QSqlRecord &record, QSqlQuer
|
|||||||
bindValue("coverSizeRatio", record, query);
|
bindValue("coverSizeRatio", record, query);
|
||||||
bindValue("originalCoverSize", record, query);
|
bindValue("originalCoverSize", record, query);
|
||||||
|
|
||||||
|
bindValue("added", record, query);
|
||||||
|
bindValue("type", record, query);
|
||||||
|
bindValue("editor", record, query);
|
||||||
|
bindValue("imprint", record, query);
|
||||||
|
bindValue("teams", record, query);
|
||||||
|
bindValue("locations", record, query);
|
||||||
|
bindValue("series", record, query);
|
||||||
|
bindValue("alternateSeries", record, query);
|
||||||
|
bindValue("alternateNumber", record, query);
|
||||||
|
bindValue("alternateCount", record, query);
|
||||||
|
bindValue("languageISO", record, query);
|
||||||
|
bindValue("seriesGroup", record, query);
|
||||||
|
bindValue("mainCharacterOrTeam", record, query);
|
||||||
|
bindValue("review", record, query);
|
||||||
|
bindValue("tags", record, query);
|
||||||
|
|
||||||
bindValue("hash", record, query);
|
bindValue("hash", record, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -757,6 +850,7 @@ bool DataBaseManagement::updateToCurrentVersion(const QString &path)
|
|||||||
bool pre8 = false;
|
bool pre8 = false;
|
||||||
bool pre9_5 = false;
|
bool pre9_5 = false;
|
||||||
bool pre9_8 = false;
|
bool pre9_8 = false;
|
||||||
|
bool pre9_13 = false;
|
||||||
|
|
||||||
QString fullPath = path + "/library.ydb";
|
QString fullPath = path + "/library.ydb";
|
||||||
|
|
||||||
@ -770,6 +864,8 @@ bool DataBaseManagement::updateToCurrentVersion(const QString &path)
|
|||||||
pre9_5 = true;
|
pre9_5 = true;
|
||||||
if (compareVersions(DataBaseManagement::checkValidDB(fullPath), "9.8.0") < 0)
|
if (compareVersions(DataBaseManagement::checkValidDB(fullPath), "9.8.0") < 0)
|
||||||
pre9_8 = true;
|
pre9_8 = true;
|
||||||
|
if (compareVersions(DataBaseManagement::checkValidDB(fullPath), "9.13.0") < 0)
|
||||||
|
pre9_13 = true;
|
||||||
|
|
||||||
QString connectionName = "";
|
QString connectionName = "";
|
||||||
bool returnValue = false;
|
bool returnValue = false;
|
||||||
@ -895,6 +991,53 @@ bool DataBaseManagement::updateToCurrentVersion(const QString &path)
|
|||||||
returnValue = returnValue && successAddingColumns;
|
returnValue = returnValue && successAddingColumns;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pre9_13) {
|
||||||
|
{ // comic_info
|
||||||
|
QStringList columnDefs;
|
||||||
|
columnDefs << "added INTEGER";
|
||||||
|
columnDefs << "type INTEGER DEFAULT 0"; // 0 = comic, 1 = manga, 2 = manga left to right, 3 = webcomic,
|
||||||
|
columnDefs << "editor TEXT";
|
||||||
|
columnDefs << "imprint TEXT";
|
||||||
|
columnDefs << "teams TEXT";
|
||||||
|
columnDefs << "locations TEXT";
|
||||||
|
columnDefs << "series TEXT";
|
||||||
|
columnDefs << "alternateSeries TEXT";
|
||||||
|
columnDefs << "alternateNumber TEXT";
|
||||||
|
columnDefs << "alternateCount INTEGER";
|
||||||
|
columnDefs << "languageISO TEXT";
|
||||||
|
columnDefs << "seriesGroup TEXT";
|
||||||
|
columnDefs << "mainCharacterOrTeam TEXT";
|
||||||
|
columnDefs << "review TEXT";
|
||||||
|
columnDefs << "tags TEXT";
|
||||||
|
bool successAddingColumns = addColumns("comic_info", columnDefs, db);
|
||||||
|
returnValue = returnValue && successAddingColumns;
|
||||||
|
|
||||||
|
QSqlQuery updateTypeQueryToManga(db);
|
||||||
|
updateTypeQueryToManga.prepare("UPDATE comic_info SET type = manga");
|
||||||
|
bool successMigratingManga = updateTypeQueryToManga.exec();
|
||||||
|
returnValue = returnValue && successMigratingManga;
|
||||||
|
|
||||||
|
QSqlQuery updateNumberQueryToBis(db);
|
||||||
|
updateNumberQueryToBis.prepare("UPDATE comic_info SET number = number + 0.5 WHERE isBis = 1");
|
||||||
|
bool successMigratingBis = updateNumberQueryToBis.exec();
|
||||||
|
returnValue = returnValue && successMigratingBis;
|
||||||
|
}
|
||||||
|
{ // folder
|
||||||
|
QStringList columnDefs;
|
||||||
|
columnDefs << "added INTEGER";
|
||||||
|
columnDefs << "updated INTEGER";
|
||||||
|
columnDefs << "type INTEGER DEFAULT 0";
|
||||||
|
|
||||||
|
bool successAddingColumns = addColumns("folder", columnDefs, db);
|
||||||
|
returnValue = returnValue && successAddingColumns;
|
||||||
|
|
||||||
|
QSqlQuery updateTypeQueryToManga(db);
|
||||||
|
updateTypeQueryToManga.prepare("UPDATE folder SET type = manga");
|
||||||
|
bool successMigratingManga = updateTypeQueryToManga.exec();
|
||||||
|
returnValue = returnValue && successMigratingManga;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
connectionName = db.connectionName();
|
connectionName = db.connectionName();
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,6 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
DataBaseManagement();
|
DataBaseManagement();
|
||||||
// TreeModel * newTreeModel(QString path);
|
|
||||||
// crea una base de datos y todas sus tablas
|
// crea una base de datos y todas sus tablas
|
||||||
static QSqlDatabase createDatabase(QString name, QString path);
|
static QSqlDatabase createDatabase(QString name, QString path);
|
||||||
static QSqlDatabase createDatabase(QString dest);
|
static QSqlDatabase createDatabase(QString dest);
|
||||||
|
@ -6,8 +6,6 @@
|
|||||||
#include "db_helper.h"
|
#include "db_helper.h"
|
||||||
#include "qnaturalsorting.h"
|
#include "qnaturalsorting.h"
|
||||||
#include "yacreader_global_gui.h"
|
#include "yacreader_global_gui.h"
|
||||||
#include "QsLog.h"
|
|
||||||
#include "query_parser.h"
|
|
||||||
|
|
||||||
#include <QtGui>
|
#include <QtGui>
|
||||||
|
|
||||||
@ -54,21 +52,19 @@ void drawMacOSXFinishedFolderIcon()
|
|||||||
#define ROOT 1
|
#define ROOT 1
|
||||||
|
|
||||||
FolderModel::FolderModel(QObject *parent)
|
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)
|
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;
|
QList<QVariant> rootData;
|
||||||
rootData << "root"; // id 0, padre 0, title "root" (el id, y el id del padre van a ir en la clase TreeItem)
|
rootData << "root"; // id 1, parent 1, title "root"
|
||||||
rootItem = new FolderItem(rootData);
|
rootItem = new FolderItem(rootData);
|
||||||
rootItem->id = ROOT;
|
rootItem->id = ROOT;
|
||||||
rootItem->parentItem = nullptr;
|
rootItem->parentItem = nullptr;
|
||||||
setupModelData(sqlquery, rootItem);
|
setupModelData(sqlquery, rootItem);
|
||||||
// sqlquery.finish();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FolderModel::~FolderModel()
|
FolderModel::~FolderModel()
|
||||||
@ -98,7 +94,13 @@ QHash<int, QByteArray> FolderModel::roleNames() const
|
|||||||
roles[IdRole] = "id";
|
roles[IdRole] = "id";
|
||||||
roles[MangaRole] = "is_manga";
|
roles[MangaRole] = "is_manga";
|
||||||
roles[CoverPathRole] = "cover_path";
|
roles[CoverPathRole] = "cover_path";
|
||||||
roles[FolderName] = "name";
|
roles[FolderNameRole] = "name";
|
||||||
|
roles[NumChildrenRole] = "num_children";
|
||||||
|
roles[TypeRole] = "type";
|
||||||
|
roles[AddedRole] = "added";
|
||||||
|
roles[UpdatedRole] = "updated";
|
||||||
|
roles[ShowRecentRole] = "show_recent";
|
||||||
|
roles[RecentRangeRole] = "recent_range";
|
||||||
|
|
||||||
return roles;
|
return roles;
|
||||||
}
|
}
|
||||||
@ -150,7 +152,7 @@ QVariant FolderModel::data(const QModelIndex &index, int role) const
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (role == FolderModel::FolderName) {
|
if (role == FolderModel::FolderNameRole) {
|
||||||
return item->data(FolderModel::Name);
|
return item->data(FolderModel::Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,6 +171,24 @@ QVariant FolderModel::data(const QModelIndex &index, int role) const
|
|||||||
if (role == FolderModel::CoverPathRole)
|
if (role == FolderModel::CoverPathRole)
|
||||||
return getCoverUrlPathForComicHash(item->data(FirstChildHash).toString());
|
return getCoverUrlPathForComicHash(item->data(FirstChildHash).toString());
|
||||||
|
|
||||||
|
if (role == FolderModel::NumChildrenRole)
|
||||||
|
return item->data(NumChildren);
|
||||||
|
|
||||||
|
if (role == FolderModel::TypeRole)
|
||||||
|
return item->data(Type);
|
||||||
|
|
||||||
|
if (role == FolderModel::AddedRole)
|
||||||
|
return item->data(Added);
|
||||||
|
|
||||||
|
if (role == FolderModel::UpdatedRole)
|
||||||
|
return item->data(Updated);
|
||||||
|
|
||||||
|
if (role == FolderModel::ShowRecentRole)
|
||||||
|
return showRecent;
|
||||||
|
|
||||||
|
if (role == FolderModel::RecentRangeRole)
|
||||||
|
return recentDays * 86400;
|
||||||
|
|
||||||
if (role != Qt::DisplayRole)
|
if (role != Qt::DisplayRole)
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
|
||||||
@ -183,7 +203,8 @@ Qt::ItemFlags FolderModel::flags(const QModelIndex &index) const
|
|||||||
return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDropEnabled | Qt::ItemIsDragEnabled;
|
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
|
int role) const
|
||||||
{
|
{
|
||||||
if (rootItem == nullptr) {
|
if (rootItem == nullptr) {
|
||||||
@ -323,65 +344,39 @@ void FolderModel::setupModelData(QSqlQuery &sqlquery, FolderItem *parent)
|
|||||||
int manga = record.indexOf("manga");
|
int manga = record.indexOf("manga");
|
||||||
int id = record.indexOf("id");
|
int id = record.indexOf("id");
|
||||||
int parentId = record.indexOf("parentId");
|
int parentId = record.indexOf("parentId");
|
||||||
|
int numChildren = record.indexOf("numChildren");
|
||||||
int firstChildHash = record.indexOf("firstChildHash");
|
int firstChildHash = record.indexOf("firstChildHash");
|
||||||
|
int customImage = record.indexOf("customImage");
|
||||||
|
int type = record.indexOf("type");
|
||||||
|
int added = record.indexOf("added");
|
||||||
|
int updated = record.indexOf("updated");
|
||||||
|
|
||||||
while (sqlquery.next()) {
|
while (sqlquery.next()) {
|
||||||
QList<QVariant> data;
|
QList<QVariant> data;
|
||||||
|
|
||||||
data << sqlquery.value(name).toString();
|
data << sqlquery.value(name);
|
||||||
data << sqlquery.value(path).toString();
|
data << sqlquery.value(path);
|
||||||
data << sqlquery.value(finished).toBool();
|
data << sqlquery.value(finished);
|
||||||
data << sqlquery.value(completed).toBool();
|
data << sqlquery.value(completed);
|
||||||
data << sqlquery.value(manga).toBool();
|
data << sqlquery.value(manga);
|
||||||
data << sqlquery.value(firstChildHash).toString();
|
data << sqlquery.value(numChildren);
|
||||||
|
data << sqlquery.value(firstChildHash);
|
||||||
|
data << sqlquery.value(customImage);
|
||||||
|
data << sqlquery.value(type);
|
||||||
|
data << sqlquery.value(added);
|
||||||
|
data << sqlquery.value(updated);
|
||||||
|
|
||||||
auto item = new FolderItem(data);
|
auto item = new FolderItem(data);
|
||||||
|
|
||||||
item->id = sqlquery.value(id).toULongLong();
|
item->id = sqlquery.value(id).toULongLong();
|
||||||
// la inserci<63>n de hijos se hace de forma ordenada
|
// la inserci<63>n de hijos se hace de forma ordenada
|
||||||
FolderItem *parent = items.value(sqlquery.value(parentId).toULongLong());
|
FolderItem *parent = items.value(sqlquery.value(parentId).toULongLong());
|
||||||
// if(parent !=0) //TODO if parent==0 the parent of item was removed from the DB and delete on cascade didn't work, ERROR.
|
|
||||||
parent->appendChild(item);
|
parent->appendChild(item);
|
||||||
// se a<>ade el item al map, de forma que se pueda encontrar como padre en siguientes iteraciones
|
// se a<>ade el item al map, de forma que se pueda encontrar como padre en siguientes iteraciones
|
||||||
items.insert(item->id, item);
|
items.insert(item->id, item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FolderModel::updateFolderModelData(QSqlQuery &sqlquery, FolderItem *parent)
|
|
||||||
{
|
|
||||||
Q_UNUSED(parent);
|
|
||||||
|
|
||||||
QSqlRecord record = sqlquery.record();
|
|
||||||
|
|
||||||
int name = record.indexOf("name");
|
|
||||||
int path = record.indexOf("path");
|
|
||||||
int finished = record.indexOf("finished");
|
|
||||||
int completed = record.indexOf("completed");
|
|
||||||
int manga = record.indexOf("manga");
|
|
||||||
int id = record.indexOf("id");
|
|
||||||
int parentId = record.indexOf("parentId");
|
|
||||||
int firstChildHash = record.indexOf("firstChildHash");
|
|
||||||
|
|
||||||
while (sqlquery.next()) {
|
|
||||||
QList<QVariant> data;
|
|
||||||
|
|
||||||
data << sqlquery.value(name).toString();
|
|
||||||
data << sqlquery.value(path).toString();
|
|
||||||
data << sqlquery.value(finished).toBool();
|
|
||||||
data << sqlquery.value(completed).toBool();
|
|
||||||
data << sqlquery.value(manga).toBool();
|
|
||||||
data << sqlquery.value(firstChildHash).toString();
|
|
||||||
auto item = new FolderItem(data);
|
|
||||||
|
|
||||||
item->id = sqlquery.value(id).toULongLong();
|
|
||||||
// la inserci<63>n de hijos se hace de forma ordenada
|
|
||||||
FolderItem *parent = items.value(sqlquery.value(parentId).toULongLong());
|
|
||||||
if (parent != 0) // TODO if parent==0 the parent of item was removed from the DB and delete on cascade didn't work, ERROR.
|
|
||||||
parent->appendChild(item);
|
|
||||||
// se a<>ade el item al map, de forma que se pueda encontrar como padre en siguientes iteraciones
|
|
||||||
items.insert(item->id, item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString FolderModel::getDatabase()
|
QString FolderModel::getDatabase()
|
||||||
{
|
{
|
||||||
return _databasePath;
|
return _databasePath;
|
||||||
@ -406,7 +401,7 @@ void FolderModel::updateFolderCompletedStatus(const QModelIndexList &list, bool
|
|||||||
|
|
||||||
if (!isSubfolder) {
|
if (!isSubfolder) {
|
||||||
Folder f = DBHelper::loadFolder(item->id, db);
|
Folder f = DBHelper::loadFolder(item->id, db);
|
||||||
f.setCompleted(status);
|
f.completed = status;
|
||||||
DBHelper::update(f, db);
|
DBHelper::update(f, db);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -415,7 +410,7 @@ void FolderModel::updateFolderCompletedStatus(const QModelIndexList &list, bool
|
|||||||
}
|
}
|
||||||
QSqlDatabase::removeDatabase(connectionName);
|
QSqlDatabase::removeDatabase(connectionName);
|
||||||
|
|
||||||
emit dataChanged(index(list.first().row(), FolderModel::Name), index(list.last().row(), FolderModel::FirstChildHash));
|
emit dataChanged(index(list.first().row(), FolderModel::Name), index(list.last().row(), FolderModel::Updated));
|
||||||
}
|
}
|
||||||
|
|
||||||
void FolderModel::updateFolderFinishedStatus(const QModelIndexList &list, bool status)
|
void FolderModel::updateFolderFinishedStatus(const QModelIndexList &list, bool status)
|
||||||
@ -430,7 +425,7 @@ void FolderModel::updateFolderFinishedStatus(const QModelIndexList &list, bool s
|
|||||||
|
|
||||||
if (!isSubfolder) {
|
if (!isSubfolder) {
|
||||||
Folder f = DBHelper::loadFolder(item->id, db);
|
Folder f = DBHelper::loadFolder(item->id, db);
|
||||||
f.setFinished(status);
|
f.finished = status;
|
||||||
DBHelper::update(f, db);
|
DBHelper::update(f, db);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -439,10 +434,10 @@ void FolderModel::updateFolderFinishedStatus(const QModelIndexList &list, bool s
|
|||||||
}
|
}
|
||||||
QSqlDatabase::removeDatabase(connectionName);
|
QSqlDatabase::removeDatabase(connectionName);
|
||||||
|
|
||||||
emit dataChanged(index(list.first().row(), FolderModel::Name), index(list.last().row(), FolderModel::FirstChildHash));
|
emit dataChanged(index(list.first().row(), FolderModel::Name), index(list.last().row(), FolderModel::Updated));
|
||||||
}
|
}
|
||||||
|
|
||||||
void FolderModel::updateFolderManga(const QModelIndexList &list, bool manga)
|
void FolderModel::updateFolderType(const QModelIndexList &list, YACReader::FileType type)
|
||||||
{
|
{
|
||||||
QString connectionName = "";
|
QString connectionName = "";
|
||||||
{
|
{
|
||||||
@ -451,19 +446,19 @@ void FolderModel::updateFolderManga(const QModelIndexList &list, bool manga)
|
|||||||
foreach (QModelIndex mi, list) {
|
foreach (QModelIndex mi, list) {
|
||||||
auto item = static_cast<FolderItem *>(mi.internalPointer());
|
auto item = static_cast<FolderItem *>(mi.internalPointer());
|
||||||
|
|
||||||
std::function<void(FolderItem *, bool)> setManga;
|
std::function<void(FolderItem *, YACReader::FileType)> setType;
|
||||||
setManga = [&setManga](FolderItem *item, bool manga) -> void {
|
setType = [&setType](FolderItem *item, YACReader::FileType type) -> void {
|
||||||
item->setData(FolderModel::Manga, manga);
|
item->setData(FolderModel::Type, QVariant::fromValue(type));
|
||||||
|
|
||||||
for (auto child : item->children()) {
|
for (auto child : item->children()) {
|
||||||
setManga(child, manga);
|
setType(child, type);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
setManga(item, manga);
|
setType(item, type);
|
||||||
|
|
||||||
if (!isSubfolder) {
|
if (!isSubfolder) {
|
||||||
DBHelper::updateFolderTreeManga(item->id, db, manga);
|
DBHelper::updateFolderTreeType(item->id, db, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
db.commit();
|
db.commit();
|
||||||
@ -471,7 +466,7 @@ void FolderModel::updateFolderManga(const QModelIndexList &list, bool manga)
|
|||||||
}
|
}
|
||||||
QSqlDatabase::removeDatabase(connectionName);
|
QSqlDatabase::removeDatabase(connectionName);
|
||||||
|
|
||||||
emit dataChanged(index(list.first().row(), FolderModel::Name), index(list.last().row(), FolderModel::FirstChildHash));
|
emit dataChanged(index(list.first().row(), FolderModel::Name), index(list.last().row(), FolderModel::Updated));
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList FolderModel::getSubfoldersNames(const QModelIndex &mi)
|
QStringList FolderModel::getSubfoldersNames(const QModelIndex &mi)
|
||||||
@ -552,7 +547,13 @@ Folder FolderModel::getFolder(const QModelIndex &mi)
|
|||||||
folderItem->parent()->data(Columns::Path).toString() + "/" + name,
|
folderItem->parent()->data(Columns::Path).toString() + "/" + name,
|
||||||
folderItem->data(Columns::Completed).toBool(),
|
folderItem->data(Columns::Completed).toBool(),
|
||||||
folderItem->data(Columns::Finished).toBool(),
|
folderItem->data(Columns::Finished).toBool(),
|
||||||
folderItem->data(Columns::Manga).toBool());
|
folderItem->data(Columns::Manga).toBool(),
|
||||||
|
folderItem->data(Columns::NumChildren).toInt(),
|
||||||
|
folderItem->data(Columns::FirstChildHash).toString(),
|
||||||
|
folderItem->data(Columns::CustomImage).toString(),
|
||||||
|
folderItem->data(Columns::Type).value<YACReader::FileType>(),
|
||||||
|
folderItem->data(Columns::Added).toLongLong(),
|
||||||
|
folderItem->data(Columns::Updated).toLongLong());
|
||||||
|
|
||||||
return folder;
|
return folder;
|
||||||
}
|
}
|
||||||
@ -589,74 +590,6 @@ QModelIndex FolderModel::getIndexFromFolder(const Folder &folder, const QModelIn
|
|||||||
return QModelIndex();
|
return QModelIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FolderModel::fetchMoreFromDB(const QModelIndex &parent)
|
|
||||||
{
|
|
||||||
FolderItem *item;
|
|
||||||
if (parent.isValid())
|
|
||||||
item = static_cast<FolderItem *>(parent.internalPointer());
|
|
||||||
else
|
|
||||||
item = rootItem;
|
|
||||||
|
|
||||||
// Remove all children
|
|
||||||
if (item->childCount() > 0) {
|
|
||||||
beginRemoveRows(parent, 0, item->childCount() - 1);
|
|
||||||
item->clearChildren();
|
|
||||||
endRemoveRows();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString connectionName = "";
|
|
||||||
{
|
|
||||||
QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath);
|
|
||||||
|
|
||||||
QList<FolderItem *> items;
|
|
||||||
QList<FolderItem *> nextLevelItems;
|
|
||||||
|
|
||||||
QSqlQuery selectQuery(db);
|
|
||||||
selectQuery.prepare("select * from folder where id <> 1 and parentId = :parentId order by parentId,name");
|
|
||||||
|
|
||||||
items << item;
|
|
||||||
bool firstLevelUpdated = false;
|
|
||||||
while (items.size() > 0) {
|
|
||||||
nextLevelItems.clear();
|
|
||||||
foreach (FolderItem *item, items) {
|
|
||||||
QLOG_DEBUG() << "ID " << item->id;
|
|
||||||
selectQuery.bindValue(":parentId", item->id);
|
|
||||||
|
|
||||||
selectQuery.exec();
|
|
||||||
|
|
||||||
if (!firstLevelUpdated) {
|
|
||||||
// NO size support
|
|
||||||
int numResults = 0;
|
|
||||||
while (selectQuery.next())
|
|
||||||
numResults++;
|
|
||||||
|
|
||||||
if (!selectQuery.seek(-1))
|
|
||||||
selectQuery.exec();
|
|
||||||
// END no size support
|
|
||||||
|
|
||||||
beginInsertRows(parent, 0, numResults - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateFolderModelData(selectQuery, item);
|
|
||||||
|
|
||||||
if (!firstLevelUpdated) {
|
|
||||||
endInsertRows();
|
|
||||||
firstLevelUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
nextLevelItems << item->children();
|
|
||||||
}
|
|
||||||
|
|
||||||
items.clear();
|
|
||||||
items = nextLevelItems;
|
|
||||||
}
|
|
||||||
connectionName = db.connectionName();
|
|
||||||
}
|
|
||||||
QLOG_DEBUG() << "item->childCount()-1" << item->childCount() - 1;
|
|
||||||
|
|
||||||
QSqlDatabase::removeDatabase(connectionName);
|
|
||||||
}
|
|
||||||
|
|
||||||
QModelIndex FolderModel::addFolderAtParent(const QString &folderName, const QModelIndex &parent)
|
QModelIndex FolderModel::addFolderAtParent(const QString &folderName, const QModelIndex &parent)
|
||||||
{
|
{
|
||||||
FolderItem *parentItem;
|
FolderItem *parentItem;
|
||||||
@ -670,7 +603,9 @@ QModelIndex FolderModel::addFolderAtParent(const QString &folderName, const QMod
|
|||||||
newFolder.name = folderName;
|
newFolder.name = folderName;
|
||||||
newFolder.parentId = parentItem->id;
|
newFolder.parentId = parentItem->id;
|
||||||
newFolder.path = parentItem->data(Columns::Path).toString() + "/" + folderName;
|
newFolder.path = parentItem->data(Columns::Path).toString() + "/" + folderName;
|
||||||
newFolder.setManga(parentItem->data(Columns::Manga).toBool());
|
newFolder.manga = parentItem->data(Columns::Manga).toBool();
|
||||||
|
newFolder.type = parentItem->data(Columns::Type).value<YACReader::FileType>();
|
||||||
|
|
||||||
QString connectionName = "";
|
QString connectionName = "";
|
||||||
{
|
{
|
||||||
QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath);
|
QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath);
|
||||||
@ -687,7 +622,13 @@ QModelIndex FolderModel::addFolderAtParent(const QString &folderName, const QMod
|
|||||||
data << newFolder.path;
|
data << newFolder.path;
|
||||||
data << false; // finished
|
data << false; // finished
|
||||||
data << true; // completed
|
data << true; // completed
|
||||||
data << newFolder.isManga();
|
data << newFolder.manga;
|
||||||
|
data << 0; // numChildren
|
||||||
|
data << QVariant(); // first child hash, new folder is empty
|
||||||
|
data << QVariant(); // custom cover
|
||||||
|
data << QVariant::fromValue(newFolder.type);
|
||||||
|
data << newFolder.added;
|
||||||
|
data << newFolder.updated;
|
||||||
|
|
||||||
auto item = new FolderItem(data);
|
auto item = new FolderItem(data);
|
||||||
item->id = newFolder.id;
|
item->id = newFolder.id;
|
||||||
@ -708,6 +649,26 @@ QUrl FolderModel::getCoverUrlPathForComicHash(const QString &hash) const
|
|||||||
return QUrl("file:" + _databasePath + "/covers/" + hash + ".jpg");
|
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)
|
void FolderModel::deleteFolder(const QModelIndex &mi)
|
||||||
{
|
{
|
||||||
beginRemoveRows(mi.parent(), mi.row(), mi.row());
|
beginRemoveRows(mi.parent(), mi.row(), mi.row());
|
||||||
|
@ -66,13 +66,10 @@ public:
|
|||||||
void setupModelData(QString path);
|
void setupModelData(QString path);
|
||||||
QString getDatabase();
|
QString getDatabase();
|
||||||
QString getFolderPath(const QModelIndex &folder);
|
QString getFolderPath(const QModelIndex &folder);
|
||||||
// QModelIndex indexFromItem(FolderItem * item, int column);
|
|
||||||
|
|
||||||
// bool isFilterEnabled(){return filterEnabled;};
|
|
||||||
|
|
||||||
void updateFolderCompletedStatus(const QModelIndexList &list, bool status);
|
void updateFolderCompletedStatus(const QModelIndexList &list, bool status);
|
||||||
void updateFolderFinishedStatus(const QModelIndexList &list, bool status);
|
void updateFolderFinishedStatus(const QModelIndexList &list, bool status);
|
||||||
void updateFolderManga(const QModelIndexList &list, bool manga);
|
void updateFolderType(const QModelIndexList &list, YACReader::FileType type);
|
||||||
|
|
||||||
QStringList getSubfoldersNames(const QModelIndex &mi);
|
QStringList getSubfoldersNames(const QModelIndex &mi);
|
||||||
FolderModel *getSubfoldersModel(const QModelIndex &mi);
|
FolderModel *getSubfoldersModel(const QModelIndex &mi);
|
||||||
@ -80,28 +77,40 @@ public:
|
|||||||
Folder getFolder(const QModelIndex &mi);
|
Folder getFolder(const QModelIndex &mi);
|
||||||
QModelIndex getIndexFromFolder(const Folder &folder, const QModelIndex &parent = QModelIndex());
|
QModelIndex getIndexFromFolder(const Folder &folder, const QModelIndex &parent = QModelIndex());
|
||||||
|
|
||||||
void fetchMoreFromDB(const QModelIndex &parent);
|
|
||||||
|
|
||||||
QModelIndex addFolderAtParent(const QString &folderName, const QModelIndex &parent);
|
QModelIndex addFolderAtParent(const QString &folderName, const QModelIndex &parent);
|
||||||
|
|
||||||
Q_INVOKABLE QUrl getCoverUrlPathForComicHash(const QString &hash) const;
|
Q_INVOKABLE QUrl getCoverUrlPathForComicHash(const QString &hash) const;
|
||||||
|
|
||||||
|
void setShowRecent(bool showRecent);
|
||||||
|
void setRecentRange(int days);
|
||||||
|
|
||||||
enum Columns {
|
enum Columns {
|
||||||
Name = 0,
|
Name = 0,
|
||||||
Path = 1,
|
Path,
|
||||||
Finished = 2,
|
Finished,
|
||||||
Completed = 3,
|
Completed,
|
||||||
Manga = 4,
|
Manga, // deprecated
|
||||||
FirstChildHash = 5
|
NumChildren,
|
||||||
}; // id INTEGER PRIMARY KEY, parentId INTEGER NOT NULL, name TEXT NOT NULL, path TEXT NOT NULL
|
FirstChildHash,
|
||||||
|
CustomImage,
|
||||||
|
Type, // FileType
|
||||||
|
Added,
|
||||||
|
Updated,
|
||||||
|
};
|
||||||
|
|
||||||
enum Roles {
|
enum Roles {
|
||||||
FinishedRole = Qt::UserRole + 1,
|
FinishedRole = Qt::UserRole + 1,
|
||||||
CompletedRole,
|
CompletedRole,
|
||||||
IdRole,
|
IdRole,
|
||||||
MangaRole,
|
MangaRole, // deprecated
|
||||||
CoverPathRole,
|
CoverPathRole,
|
||||||
FolderName,
|
FolderNameRole,
|
||||||
|
NumChildrenRole,
|
||||||
|
TypeRole,
|
||||||
|
AddedRole,
|
||||||
|
UpdatedRole,
|
||||||
|
ShowRecentRole,
|
||||||
|
RecentRangeRole,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool isSubfolder;
|
bool isSubfolder;
|
||||||
@ -112,9 +121,7 @@ public slots:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void fullSetup(QSqlQuery &sqlquery, FolderItem *parent);
|
void fullSetup(QSqlQuery &sqlquery, FolderItem *parent);
|
||||||
|
|
||||||
void setupModelData(QSqlQuery &sqlquery, FolderItem *parent);
|
void setupModelData(QSqlQuery &sqlquery, FolderItem *parent);
|
||||||
void updateFolderModelData(QSqlQuery &sqlquery, FolderItem *parent);
|
|
||||||
|
|
||||||
FolderItem *rootItem; // el árbol
|
FolderItem *rootItem; // el árbol
|
||||||
QMap<unsigned long long int, FolderItem *> items; // relación entre folders
|
QMap<unsigned long long int, FolderItem *> items; // relación entre folders
|
||||||
@ -123,6 +130,9 @@ private:
|
|||||||
|
|
||||||
QIcon folderIcon;
|
QIcon folderIcon;
|
||||||
QIcon folderFinishedIcon;
|
QIcon folderFinishedIcon;
|
||||||
|
|
||||||
|
bool showRecent;
|
||||||
|
qlonglong recentDays;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -17,6 +17,14 @@ Token QueryLexer::next()
|
|||||||
case '(':
|
case '(':
|
||||||
case ')':
|
case ')':
|
||||||
return single(Token::Type::opcode);
|
return single(Token::Type::opcode);
|
||||||
|
case ':':
|
||||||
|
return single(Token::Type::equal);
|
||||||
|
case '=':
|
||||||
|
return equal();
|
||||||
|
case '<':
|
||||||
|
return minor();
|
||||||
|
case '>':
|
||||||
|
return major();
|
||||||
case '"':
|
case '"':
|
||||||
return quotedWord();
|
return quotedWord();
|
||||||
default:
|
default:
|
||||||
@ -44,7 +52,7 @@ Token QueryLexer::word()
|
|||||||
auto start = index;
|
auto start = index;
|
||||||
get();
|
get();
|
||||||
auto current = peek();
|
auto current = peek();
|
||||||
while (current != '\0' && !isSpace(current) && current != '"' && current != '(' && current != ')') {
|
while (current != '\0' && !isSpace(current) && current != '"' && current != '(' && current != ')' && current != ':' && current != '=' && current != '<' && current != '>') {
|
||||||
get();
|
get();
|
||||||
current = peek();
|
current = peek();
|
||||||
}
|
}
|
||||||
@ -70,6 +78,45 @@ Token QueryLexer::quotedWord()
|
|||||||
return Token(Token::Type::eof);
|
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)
|
bool QueryLexer::isSpace(char c)
|
||||||
{
|
{
|
||||||
switch (c) {
|
switch (c) {
|
||||||
|
@ -11,6 +11,12 @@ public:
|
|||||||
opcode,
|
opcode,
|
||||||
word,
|
word,
|
||||||
quotedWord,
|
quotedWord,
|
||||||
|
equal, // =
|
||||||
|
exactEqual, // ==
|
||||||
|
minor,
|
||||||
|
major,
|
||||||
|
minorOrEqual,
|
||||||
|
majorOrEqual,
|
||||||
undefined
|
undefined
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -50,6 +56,9 @@ private:
|
|||||||
Token single(Token::Type type);
|
Token single(Token::Type type);
|
||||||
Token word();
|
Token word();
|
||||||
Token quotedWord();
|
Token quotedWord();
|
||||||
|
Token minor();
|
||||||
|
Token major();
|
||||||
|
Token equal();
|
||||||
|
|
||||||
bool isSpace(char c);
|
bool isSpace(char c);
|
||||||
};
|
};
|
||||||
|
@ -5,19 +5,25 @@
|
|||||||
#include <numeric>
|
#include <numeric>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include <QsLog.h>
|
||||||
|
|
||||||
const std::map<QueryParser::FieldType, std::vector<std::string>> QueryParser::fieldNames {
|
const std::map<QueryParser::FieldType, std::vector<std::string>> QueryParser::fieldNames {
|
||||||
{ FieldType::numeric, { "numpages", "number", "count", "arcnumber", "arccount" } },
|
// TODO_METADATA support dates
|
||||||
{ FieldType::text, { "title", "volume", "storyarc", "genere", "writer", "penciller", "inker", "colorist", "letterer", "coverartist", "publisher", "format", "agerating", "synopsis", "characters", "notes" } },
|
{ FieldType::numeric, { "numpages", "count", "arccount", "alternateCount", "rating" } },
|
||||||
{ FieldType::boolean, { "isbis", "color", "read", "manga" } },
|
{ 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::date, { "date" } },
|
{ FieldType::boolean, { "color", "read", "edited", "hasBeenOpened" } },
|
||||||
|
{ FieldType::date, { "date", "added", "lastTimeOpened" } },
|
||||||
{ FieldType::filename, { "filename" } },
|
{ FieldType::filename, { "filename" } },
|
||||||
{ FieldType::folder, { "folder" } },
|
{ FieldType::folder, { "folder" } },
|
||||||
{ FieldType::booleanFolder, { "completed", "finished" } },
|
{ FieldType::booleanFolder, { "completed", "finished" } },
|
||||||
|
{ FieldType::enumField, { "type" } },
|
||||||
|
{ FieldType::enumFieldFolder, { "foldertype" } }
|
||||||
};
|
};
|
||||||
|
|
||||||
int QueryParser::TreeNode::buildSqlString(std::string &sqlString, int bindPosition) const
|
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;
|
++bindPosition;
|
||||||
if (toLower(children[0].t) == "all") {
|
if (toLower(children[0].t) == "all") {
|
||||||
sqlString += "(";
|
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(c.filename) LIKE UPPER(:bindPosition" + std::to_string(bindPosition) + ") OR ";
|
||||||
sqlString += "UPPER(f.name) LIKE UPPER(:bindPosition" + std::to_string(bindPosition) + ")) ";
|
sqlString += "UPPER(f.name) LIKE UPPER(:bindPosition" + std::to_string(bindPosition) + ")) ";
|
||||||
} else if (isIn(fieldType(children[0].t), { FieldType::numeric, FieldType::boolean })) {
|
} else if (isIn(fieldType(children[0].t), { FieldType::numeric })) {
|
||||||
|
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) + " ";
|
sqlString += "ci." + children[0].t + " = :bindPosition" + std::to_string(bindPosition) + " ";
|
||||||
} else if (fieldType(children[0].t) == FieldType::filename) {
|
} else if (fieldType(children[0].t) == FieldType::filename) {
|
||||||
sqlString += "(UPPER(c." + children[0].t + ") LIKE UPPER(:bindPosition" + std::to_string(bindPosition) + ")) ";
|
sqlString += "(UPPER(c." + children[0].t + ") LIKE UPPER(:bindPosition" + std::to_string(bindPosition) + ")) ";
|
||||||
@ -34,8 +48,23 @@ int QueryParser::TreeNode::buildSqlString(std::string &sqlString, int bindPositi
|
|||||||
sqlString += "(UPPER(f.name) LIKE UPPER(:bindPosition" + std::to_string(bindPosition) + ")) ";
|
sqlString += "(UPPER(f.name) LIKE UPPER(:bindPosition" + std::to_string(bindPosition) + ")) ";
|
||||||
} else if (fieldType(children[0].t) == FieldType::booleanFolder) {
|
} else if (fieldType(children[0].t) == FieldType::booleanFolder) {
|
||||||
sqlString += "f." + children[0].t + " = :bindPosition" + std::to_string(bindPosition) + " ";
|
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 {
|
} 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") {
|
} else if (t == "not") {
|
||||||
sqlString += "(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
|
int QueryParser::TreeNode::bindValues(QSqlQuery &selectQuery, int bindPosition) const
|
||||||
{
|
{
|
||||||
if (t == "token") {
|
if (t == "expression") {
|
||||||
std::string bind_string(":bindPosition" + std::to_string(++bindPosition));
|
std::string bind_string(":bindPosition" + std::to_string(++bindPosition));
|
||||||
if (isIn(fieldType(children[0].t), { FieldType::numeric })) {
|
if (isIn(fieldType(children[0].t), { FieldType::numeric })) {
|
||||||
selectQuery.bindValue(QString::fromStdString(bind_string), std::stoi(children[1].t));
|
selectQuery.bindValue(QString::fromStdString(bind_string), std::stoi(children[1].t));
|
||||||
@ -67,8 +96,30 @@ int QueryParser::TreeNode::bindValues(QSqlQuery &selectQuery, int bindPosition)
|
|||||||
} else {
|
} else {
|
||||||
selectQuery.bindValue(QString::fromStdString(bind_string), std::stoi(value));
|
selectQuery.bindValue(QString::fromStdString(bind_string), std::stoi(value));
|
||||||
}
|
}
|
||||||
|
} else if ((isIn(fieldType(children[0].t), { FieldType::enumField, 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 {
|
} 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") {
|
} else if (t == "not") {
|
||||||
bindPosition = children[0].bindValues(selectQuery, bindPosition);
|
bindPosition = children[0].bindValues(selectQuery, bindPosition);
|
||||||
@ -151,6 +202,16 @@ void QueryParser::advance()
|
|||||||
currentToken = lexer.next();
|
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)
|
QueryParser::FieldType QueryParser::fieldType(const std::string &str)
|
||||||
{
|
{
|
||||||
for (const auto &names : fieldNames) {
|
for (const auto &names : fieldNames) {
|
||||||
@ -223,25 +284,39 @@ QueryParser::TreeNode QueryParser::locationExpression()
|
|||||||
if (!isIn(tokenType(), { Token::Type::word, Token::Type::quotedWord })) {
|
if (!isIn(tokenType(), { Token::Type::word, Token::Type::quotedWord })) {
|
||||||
throw std::invalid_argument("Invalid syntax. Expected a lookup name or a word");
|
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();
|
return baseToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
QueryParser::TreeNode QueryParser::baseToken()
|
QueryParser::TreeNode QueryParser::baseToken()
|
||||||
{
|
{
|
||||||
if (tokenType() == Token::Type::quotedWord) {
|
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 (tokenType() == Token::Type::word) {
|
||||||
|
return TreeNode("expression", { TreeNode("all", {}), TreeNode(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, ":"), {}) });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return TreeNode("token", { TreeNode("all", {}), TreeNode(join(words, ":"), {}) });
|
return TreeNode("expression", { TreeNode("all", {}), TreeNode(token(true), {}) });
|
||||||
}
|
}
|
||||||
|
@ -9,8 +9,8 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <list>
|
#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_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.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_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,
|
* 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 ]
|
* and_expression ::= not_expression [ [ 'and' ] and_expression ]
|
||||||
* not_expression ::= [ 'not' ] location_expression
|
* not_expression ::= [ 'not' ] location_expression
|
||||||
* location_expression ::= base_token | ( '(' or_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:
|
* Usage Example:
|
||||||
* QSqlQuery selectQuery(db);
|
* QSqlQuery selectQuery(db);
|
||||||
@ -47,9 +49,10 @@ public:
|
|||||||
struct TreeNode {
|
struct TreeNode {
|
||||||
std::string t;
|
std::string t;
|
||||||
std::vector<TreeNode> children;
|
std::vector<TreeNode> children;
|
||||||
|
std::string expOperator;
|
||||||
|
|
||||||
explicit TreeNode(std::string t, std::vector<TreeNode> children)
|
explicit TreeNode(std::string t, std::vector<TreeNode> children, std::string expOperator = "")
|
||||||
: t(t), children(children)
|
: t(t), children(children), expOperator(expOperator)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,6 +81,8 @@ private:
|
|||||||
return std::find(v.begin(), v.end(), e) != v.end();
|
return std::find(v.begin(), v.end(), e) != v.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isOperatorToken(Token::Type type);
|
||||||
|
|
||||||
enum class FieldType { unknown,
|
enum class FieldType { unknown,
|
||||||
numeric,
|
numeric,
|
||||||
text,
|
text,
|
||||||
@ -85,7 +90,9 @@ private:
|
|||||||
date,
|
date,
|
||||||
folder,
|
folder,
|
||||||
booleanFolder,
|
booleanFolder,
|
||||||
filename };
|
filename,
|
||||||
|
enumField,
|
||||||
|
enumFieldFolder };
|
||||||
static FieldType fieldType(const std::string &str);
|
static FieldType fieldType(const std::string &str);
|
||||||
|
|
||||||
static std::string join(const QStringList &strings, const std::string &delim);
|
static std::string join(const QStringList &strings, const std::string &delim);
|
||||||
@ -95,6 +102,7 @@ private:
|
|||||||
TreeNode andExpression();
|
TreeNode andExpression();
|
||||||
TreeNode notExpression();
|
TreeNode notExpression();
|
||||||
TreeNode locationExpression();
|
TreeNode locationExpression();
|
||||||
|
TreeNode expression();
|
||||||
TreeNode baseToken();
|
TreeNode baseToken();
|
||||||
|
|
||||||
static const std::map<FieldType, std::vector<std::string>> fieldNames;
|
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);
|
return naturalSortLessThanCI(c1->name, c2->name);
|
||||||
} else {
|
} else {
|
||||||
if (c1->info.number.isNull() == false && c2->info.number.isNull() == false) {
|
if (c1->info.number.isNull() == false && c2->info.number.isNull() == false) {
|
||||||
return c1->info.number.toInt() < c2->info.number.toInt();
|
return naturalSortLessThanCI(c1->info.number.toString(), c2->info.number.toString());
|
||||||
} else {
|
} else {
|
||||||
return c2->info.number.isNull();
|
return c2->info.number.isNull();
|
||||||
}
|
}
|
||||||
@ -637,9 +637,28 @@ void DBHelper::update(ComicInfo *comicInfo, QSqlDatabase &db)
|
|||||||
//--
|
//--
|
||||||
|
|
||||||
// new 9.8 fields
|
// new 9.8 fields
|
||||||
"manga = :manga"
|
"manga = :manga,"
|
||||||
//--
|
//--
|
||||||
" WHERE id = :id ");
|
|
||||||
|
// new 9.13 fields
|
||||||
|
"added = :added,"
|
||||||
|
"type = :type,"
|
||||||
|
"editor = :editor,"
|
||||||
|
"imprint = :imprint,"
|
||||||
|
"teams = :teams,"
|
||||||
|
"locations = :locations,"
|
||||||
|
"series = :series,"
|
||||||
|
"alternateSeries = :alternateSeries,"
|
||||||
|
"alternateNumber = :alternateNumber,"
|
||||||
|
"alternateCount = :alternateCount,"
|
||||||
|
"languageISO = :languageISO,"
|
||||||
|
"seriesGroup = :seriesGroup,"
|
||||||
|
"mainCharacterOrTeam = :mainCharacterOrTeam,"
|
||||||
|
"review = :review,"
|
||||||
|
"tags = :tags"
|
||||||
|
|
||||||
|
//--
|
||||||
|
" WHERE id = :id");
|
||||||
|
|
||||||
updateComicInfo.bindValue(":title", comicInfo->title);
|
updateComicInfo.bindValue(":title", comicInfo->title);
|
||||||
|
|
||||||
@ -698,7 +717,28 @@ void DBHelper::update(ComicInfo *comicInfo, QSqlDatabase &db)
|
|||||||
updateComicInfo.bindValue(":coverSizeRatio", comicInfo->coverSizeRatio);
|
updateComicInfo.bindValue(":coverSizeRatio", comicInfo->coverSizeRatio);
|
||||||
updateComicInfo.bindValue(":originalCoverSize", comicInfo->originalCoverSize);
|
updateComicInfo.bindValue(":originalCoverSize", comicInfo->originalCoverSize);
|
||||||
|
|
||||||
|
updateComicInfo.bindValue(":added", comicInfo->added);
|
||||||
|
auto intType = static_cast<int>(comicInfo->type.value<YACReader::FileType>());
|
||||||
|
updateComicInfo.bindValue(":type", intType);
|
||||||
|
updateComicInfo.bindValue(":editor", comicInfo->editor);
|
||||||
|
updateComicInfo.bindValue(":imprint", comicInfo->imprint);
|
||||||
|
updateComicInfo.bindValue(":teams", comicInfo->teams);
|
||||||
|
updateComicInfo.bindValue(":locations", comicInfo->locations);
|
||||||
|
updateComicInfo.bindValue(":series", comicInfo->series);
|
||||||
|
updateComicInfo.bindValue(":alternateSeries", comicInfo->alternateSeries);
|
||||||
|
updateComicInfo.bindValue(":alternateNumber", comicInfo->alternateNumber);
|
||||||
|
updateComicInfo.bindValue(":alternateCount", comicInfo->alternateCount);
|
||||||
|
updateComicInfo.bindValue(":languageISO", comicInfo->languageISO);
|
||||||
|
updateComicInfo.bindValue(":seriesGroup", comicInfo->seriesGroup);
|
||||||
|
updateComicInfo.bindValue(":mainCharacterOrTeam", comicInfo->mainCharacterOrTeam);
|
||||||
|
updateComicInfo.bindValue(":review", comicInfo->review);
|
||||||
|
updateComicInfo.bindValue(":tags", comicInfo->tags);
|
||||||
|
|
||||||
updateComicInfo.exec();
|
updateComicInfo.exec();
|
||||||
|
|
||||||
|
QLOG_INFO() << updateComicInfo.lastError().databaseText();
|
||||||
|
QLOG_INFO() << updateComicInfo.lastError().text();
|
||||||
|
QLOG_INFO() << updateComicInfo.lastQuery();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DBHelper::updateRead(ComicInfo *comicInfo, QSqlDatabase &db)
|
void DBHelper::updateRead(ComicInfo *comicInfo, QSqlDatabase &db)
|
||||||
@ -718,12 +758,10 @@ void DBHelper::update(const Folder &folder, QSqlDatabase &db)
|
|||||||
QSqlQuery updateFolderInfo(db);
|
QSqlQuery updateFolderInfo(db);
|
||||||
updateFolderInfo.prepare("UPDATE folder SET "
|
updateFolderInfo.prepare("UPDATE folder SET "
|
||||||
"finished = :finished, "
|
"finished = :finished, "
|
||||||
"completed = :completed, "
|
"completed = :completed "
|
||||||
"manga = :manga "
|
|
||||||
"WHERE id = :id ");
|
"WHERE id = :id ");
|
||||||
updateFolderInfo.bindValue(":finished", folder.isFinished() ? 1 : 0);
|
updateFolderInfo.bindValue(":finished", folder.finished ? 1 : 0);
|
||||||
updateFolderInfo.bindValue(":completed", folder.isCompleted() ? 1 : 0);
|
updateFolderInfo.bindValue(":completed", folder.completed ? 1 : 0);
|
||||||
updateFolderInfo.bindValue(":manga", folder.isManga() ? 1 : 0);
|
|
||||||
updateFolderInfo.bindValue(":id", folder.id);
|
updateFolderInfo.bindValue(":id", folder.id);
|
||||||
updateFolderInfo.exec();
|
updateFolderInfo.exec();
|
||||||
}
|
}
|
||||||
@ -762,7 +800,7 @@ Folder DBHelper::updateChildrenInfo(qulonglong folderId, QSqlDatabase &db)
|
|||||||
} else {
|
} else {
|
||||||
for (auto item : updatedSubfolders) {
|
for (auto item : updatedSubfolders) {
|
||||||
auto f = static_cast<Folder *>(item);
|
auto f = static_cast<Folder *>(item);
|
||||||
auto firstChildHash = f->getFirstChildHash();
|
auto firstChildHash = f->firstChildHash;
|
||||||
if (!firstChildHash.isEmpty()) {
|
if (!firstChildHash.isEmpty()) {
|
||||||
coverHash = firstChildHash;
|
coverHash = firstChildHash;
|
||||||
break;
|
break;
|
||||||
@ -770,16 +808,16 @@ Folder DBHelper::updateChildrenInfo(qulonglong folderId, QSqlDatabase &db)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
folder.setNumChildren(subfolders.count() + comics.count());
|
folder.numChildren = subfolders.count() + comics.count();
|
||||||
folder.setFirstChildHash(coverHash);
|
folder.firstChildHash = coverHash;
|
||||||
|
|
||||||
QSqlQuery updateFolderInfo(db);
|
QSqlQuery updateFolderInfo(db);
|
||||||
updateFolderInfo.prepare("UPDATE folder SET "
|
updateFolderInfo.prepare("UPDATE folder SET "
|
||||||
"numChildren = :numChildren, "
|
"numChildren = :numChildren, "
|
||||||
"firstChildHash = :firstChildHash "
|
"firstChildHash = :firstChildHash "
|
||||||
"WHERE id = :id ");
|
"WHERE id = :id ");
|
||||||
updateFolderInfo.bindValue(":numChildren", folder.getNumChildren());
|
updateFolderInfo.bindValue(":numChildren", folder.numChildren);
|
||||||
updateFolderInfo.bindValue(":firstChildHash", folder.getFirstChildHash());
|
updateFolderInfo.bindValue(":firstChildHash", folder.firstChildHash);
|
||||||
updateFolderInfo.bindValue(":id", folderId);
|
updateFolderInfo.bindValue(":id", folderId);
|
||||||
updateFolderInfo.exec();
|
updateFolderInfo.exec();
|
||||||
|
|
||||||
@ -854,7 +892,7 @@ void DBHelper::updateReadingRemoteProgress(const ComicInfo &comicInfo, QSqlDatab
|
|||||||
updateComicInfo.bindValue(":read", comicInfo.read ? 1 : 0);
|
updateComicInfo.bindValue(":read", comicInfo.read ? 1 : 0);
|
||||||
updateComicInfo.bindValue(":currentPage", comicInfo.currentPage);
|
updateComicInfo.bindValue(":currentPage", comicInfo.currentPage);
|
||||||
updateComicInfo.bindValue(":hasBeenOpened", comicInfo.hasBeenOpened ? 1 : 0);
|
updateComicInfo.bindValue(":hasBeenOpened", comicInfo.hasBeenOpened ? 1 : 0);
|
||||||
updateComicInfo.bindValue(":lastTimeOpened", QDateTime::currentMSecsSinceEpoch() / 1000);
|
updateComicInfo.bindValue(":lastTimeOpened", QDateTime::currentSecsSinceEpoch());
|
||||||
updateComicInfo.bindValue(":id", comicInfo.id);
|
updateComicInfo.bindValue(":id", comicInfo.id);
|
||||||
updateComicInfo.bindValue(":rating", comicInfo.rating);
|
updateComicInfo.bindValue(":rating", comicInfo.rating);
|
||||||
updateComicInfo.exec();
|
updateComicInfo.exec();
|
||||||
@ -1067,7 +1105,7 @@ void DBHelper::updateFromRemoteClientWithHash(const QList<ComicInfo> &comics)
|
|||||||
updateComicInfo.bindValue(":read", info.read ? 1 : 0);
|
updateComicInfo.bindValue(":read", info.read ? 1 : 0);
|
||||||
updateComicInfo.bindValue(":currentPage", info.currentPage);
|
updateComicInfo.bindValue(":currentPage", info.currentPage);
|
||||||
updateComicInfo.bindValue(":hasBeenOpened", info.hasBeenOpened ? 1 : 0);
|
updateComicInfo.bindValue(":hasBeenOpened", info.hasBeenOpened ? 1 : 0);
|
||||||
updateComicInfo.bindValue(":lastTimeOpened", QDateTime::currentMSecsSinceEpoch() / 1000);
|
updateComicInfo.bindValue(":lastTimeOpened", QDateTime::currentSecsSinceEpoch());
|
||||||
updateComicInfo.bindValue(":id", info.id);
|
updateComicInfo.bindValue(":id", info.id);
|
||||||
updateComicInfo.bindValue(":rating", info.rating);
|
updateComicInfo.bindValue(":rating", info.rating);
|
||||||
updateComicInfo.exec();
|
updateComicInfo.exec();
|
||||||
@ -1194,12 +1232,16 @@ void DBHelper::updateComicsInfo(QList<ComicDB> &comics, const QString &databaseP
|
|||||||
// inserts
|
// inserts
|
||||||
qulonglong DBHelper::insert(Folder *folder, QSqlDatabase &db)
|
qulonglong DBHelper::insert(Folder *folder, QSqlDatabase &db)
|
||||||
{
|
{
|
||||||
|
auto added = QDateTime::currentSecsSinceEpoch();
|
||||||
|
folder->added = added;
|
||||||
|
|
||||||
QSqlQuery query(db);
|
QSqlQuery query(db);
|
||||||
query.prepare("INSERT INTO folder (parentId, name, path) "
|
query.prepare("INSERT INTO folder (parentId, name, path, added) "
|
||||||
"VALUES (:parentId, :name, :path)");
|
"VALUES (:parentId, :name, :path, :added)");
|
||||||
query.bindValue(":parentId", folder->parentId);
|
query.bindValue(":parentId", folder->parentId);
|
||||||
query.bindValue(":name", folder->name);
|
query.bindValue(":name", folder->name);
|
||||||
query.bindValue(":path", folder->path);
|
query.bindValue(":path", folder->path);
|
||||||
|
query.bindValue(":added", added);
|
||||||
query.exec();
|
query.exec();
|
||||||
|
|
||||||
return query.lastInsertId().toULongLong();
|
return query.lastInsertId().toULongLong();
|
||||||
@ -1207,16 +1249,21 @@ qulonglong DBHelper::insert(Folder *folder, QSqlDatabase &db)
|
|||||||
|
|
||||||
qulonglong DBHelper::insert(ComicDB *comic, QSqlDatabase &db, bool insertAllInfo)
|
qulonglong DBHelper::insert(ComicDB *comic, QSqlDatabase &db, bool insertAllInfo)
|
||||||
{
|
{
|
||||||
|
auto added = QDateTime::currentSecsSinceEpoch();
|
||||||
|
|
||||||
if (!comic->info.existOnDb) {
|
if (!comic->info.existOnDb) {
|
||||||
QSqlQuery comicInfoInsert(db);
|
QSqlQuery comicInfoInsert(db);
|
||||||
comicInfoInsert.prepare("INSERT INTO comic_info (hash,numPages,coverSizeRatio,originalCoverSize) "
|
|
||||||
"VALUES (:hash,:numPages,:coverSizeRatio,:originalCoverSize)");
|
comicInfoInsert.prepare("INSERT INTO comic_info (hash,numPages,coverSizeRatio,originalCoverSize,added) "
|
||||||
|
"VALUES (:hash,:numPages,:coverSizeRatio,:originalCoverSize,:added)");
|
||||||
comicInfoInsert.bindValue(":hash", comic->info.hash);
|
comicInfoInsert.bindValue(":hash", comic->info.hash);
|
||||||
comicInfoInsert.bindValue(":numPages", comic->info.numPages);
|
comicInfoInsert.bindValue(":numPages", comic->info.numPages);
|
||||||
comicInfoInsert.bindValue(":coverSizeRatio", comic->info.coverSizeRatio);
|
comicInfoInsert.bindValue(":coverSizeRatio", comic->info.coverSizeRatio);
|
||||||
comicInfoInsert.bindValue(":originalCoverSize", comic->info.originalCoverSize);
|
comicInfoInsert.bindValue(":originalCoverSize", comic->info.originalCoverSize);
|
||||||
|
comicInfoInsert.bindValue(":added", added);
|
||||||
comicInfoInsert.exec();
|
comicInfoInsert.exec();
|
||||||
comic->info.id = comicInfoInsert.lastInsertId().toULongLong();
|
comic->info.id = comicInfoInsert.lastInsertId().toULongLong();
|
||||||
|
comic->info.added = added;
|
||||||
comic->_hasCover = false;
|
comic->_hasCover = false;
|
||||||
|
|
||||||
if (insertAllInfo) {
|
if (insertAllInfo) {
|
||||||
@ -1234,6 +1281,14 @@ qulonglong DBHelper::insert(ComicDB *comic, QSqlDatabase &db, bool insertAllInfo
|
|||||||
query.bindValue(":path", comic->path);
|
query.bindValue(":path", comic->path);
|
||||||
query.exec();
|
query.exec();
|
||||||
|
|
||||||
|
QSqlQuery updateFolder(db);
|
||||||
|
updateFolder.prepare("UPDATE folder SET "
|
||||||
|
"updated = :updated "
|
||||||
|
"WHERE id = :id ");
|
||||||
|
updateFolder.bindValue(":updated", added);
|
||||||
|
updateFolder.bindValue(":id", comic->parentId);
|
||||||
|
updateFolder.exec();
|
||||||
|
|
||||||
return query.lastInsertId().toULongLong();
|
return query.lastInsertId().toULongLong();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1342,6 +1397,7 @@ void DBHelper::insertComicsInReadingList(const QList<ComicDB> &comicsList, qulon
|
|||||||
|
|
||||||
db.commit();
|
db.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// queries
|
// queries
|
||||||
QList<LibraryItem *> DBHelper::getFoldersFromParent(qulonglong parentId, QSqlDatabase &db, bool sort)
|
QList<LibraryItem *> DBHelper::getFoldersFromParent(qulonglong parentId, QSqlDatabase &db, bool sort)
|
||||||
{
|
{
|
||||||
@ -1356,20 +1412,33 @@ QList<LibraryItem *> DBHelper::getFoldersFromParent(qulonglong parentId, QSqlDat
|
|||||||
|
|
||||||
int name = record.indexOf("name");
|
int name = record.indexOf("name");
|
||||||
int path = record.indexOf("path");
|
int path = record.indexOf("path");
|
||||||
|
int finished = record.indexOf("finished");
|
||||||
|
int completed = record.indexOf("completed");
|
||||||
|
int manga = record.indexOf("manga");
|
||||||
int id = record.indexOf("id");
|
int id = record.indexOf("id");
|
||||||
int numChildren = record.indexOf("numChildren");
|
int numChildren = record.indexOf("numChildren");
|
||||||
int firstChildHash = record.indexOf("firstChildHash");
|
int firstChildHash = record.indexOf("firstChildHash");
|
||||||
int customImage = record.indexOf("customImage");
|
int customImage = record.indexOf("customImage");
|
||||||
|
int type = record.indexOf("type");
|
||||||
|
int added = record.indexOf("added");
|
||||||
|
int updated = record.indexOf("updated");
|
||||||
|
|
||||||
Folder *currentItem;
|
Folder *currentItem;
|
||||||
while (selectQuery.next()) {
|
while (selectQuery.next()) {
|
||||||
// TODO sort by sort indicator and name
|
// TODO sort by sort indicator and name
|
||||||
currentItem = new Folder(selectQuery.value(id).toULongLong(), parentId, selectQuery.value(name).toString(), selectQuery.value(path).toString());
|
currentItem = new Folder(selectQuery.value(id).toULongLong(), parentId, selectQuery.value(name).toString(), selectQuery.value(path).toString());
|
||||||
|
|
||||||
if (!selectQuery.value(numChildren).isNull() && selectQuery.value(numChildren).isValid())
|
currentItem->finished = selectQuery.value(finished).toBool();
|
||||||
currentItem->setNumChildren(selectQuery.value(numChildren).toInt());
|
currentItem->completed = selectQuery.value(completed).toBool();
|
||||||
currentItem->setFirstChildHash(selectQuery.value(firstChildHash).toString());
|
if (!selectQuery.value(numChildren).isNull() && selectQuery.value(numChildren).isValid()) {
|
||||||
currentItem->setCustomImage(selectQuery.value(customImage).toString());
|
currentItem->numChildren = selectQuery.value(numChildren).toInt();
|
||||||
|
}
|
||||||
|
currentItem->firstChildHash = selectQuery.value(firstChildHash).toString();
|
||||||
|
currentItem->customImage = selectQuery.value(customImage).toString();
|
||||||
|
currentItem->manga = selectQuery.value(manga).toBool();
|
||||||
|
currentItem->type = selectQuery.value(type).value<YACReader::FileType>();
|
||||||
|
currentItem->added = selectQuery.value(added).toLongLong();
|
||||||
|
currentItem->updated = selectQuery.value(updated).toLongLong();
|
||||||
|
|
||||||
int lessThan = 0;
|
int lessThan = 0;
|
||||||
|
|
||||||
@ -1524,21 +1593,21 @@ QList<Label> DBHelper::getLabels(qulonglong libraryId)
|
|||||||
return labels;
|
return labels;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DBHelper::updateFolderTreeManga(qulonglong id, QSqlDatabase &db, bool manga)
|
void DBHelper::updateFolderTreeType(qulonglong id, QSqlDatabase &db, YACReader::FileType type)
|
||||||
{
|
{
|
||||||
QSqlQuery updateFolderQuery(db);
|
QSqlQuery updateFolderQuery(db);
|
||||||
updateFolderQuery.prepare("UPDATE folder "
|
updateFolderQuery.prepare("UPDATE folder "
|
||||||
"SET manga = :manga "
|
"SET type = :type "
|
||||||
"WHERE id = :id");
|
"WHERE id = :id");
|
||||||
updateFolderQuery.bindValue(":manga", manga ? 1 : 0);
|
updateFolderQuery.bindValue(":type", static_cast<int>(type));
|
||||||
updateFolderQuery.bindValue(":id", id);
|
updateFolderQuery.bindValue(":id", id);
|
||||||
updateFolderQuery.exec();
|
updateFolderQuery.exec();
|
||||||
|
|
||||||
QSqlQuery updateComicInfo(db);
|
QSqlQuery updateComicInfo(db);
|
||||||
updateComicInfo.prepare("UPDATE comic_info "
|
updateComicInfo.prepare("UPDATE comic_info "
|
||||||
"SET manga = :manga "
|
"SET type = :type "
|
||||||
"WHERE id IN (SELECT ci.id FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) WHERE c.parentId = :parentId)");
|
"WHERE id IN (SELECT ci.id FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) WHERE c.parentId = :parentId)");
|
||||||
updateComicInfo.bindValue(":manga", manga ? 1 : 0);
|
updateComicInfo.bindValue(":type", static_cast<int>(type));
|
||||||
updateComicInfo.bindValue(":parentId", id);
|
updateComicInfo.bindValue(":parentId", id);
|
||||||
updateComicInfo.exec();
|
updateComicInfo.exec();
|
||||||
|
|
||||||
@ -1550,24 +1619,49 @@ void DBHelper::updateFolderTreeManga(qulonglong id, QSqlDatabase &db, bool manga
|
|||||||
int childFolderIdPos = getSubFoldersQuery.record().indexOf("id");
|
int childFolderIdPos = getSubFoldersQuery.record().indexOf("id");
|
||||||
|
|
||||||
while (getSubFoldersQuery.next()) {
|
while (getSubFoldersQuery.next()) {
|
||||||
updateFolderTreeManga(getSubFoldersQuery.value(childFolderIdPos).toULongLong(), db, manga);
|
updateFolderTreeType(getSubFoldersQuery.value(childFolderIdPos).toULongLong(), db, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// loads
|
|
||||||
Folder DBHelper::loadFolder(qulonglong id, QSqlDatabase &db)
|
Folder DBHelper::loadFolder(qulonglong id, QSqlDatabase &db)
|
||||||
{
|
{
|
||||||
Folder folder;
|
|
||||||
|
|
||||||
QSqlQuery query(db);
|
QSqlQuery query(db);
|
||||||
query.prepare("SELECT * FROM folder WHERE id = :id");
|
query.prepare("SELECT * FROM folder WHERE id = :id");
|
||||||
query.bindValue(":id", id);
|
query.bindValue(":id", id);
|
||||||
query.exec();
|
query.exec();
|
||||||
|
|
||||||
|
Folder folder;
|
||||||
|
|
||||||
folder.id = id;
|
folder.id = id;
|
||||||
folder.parentId = 0;
|
folder.parentId = 0;
|
||||||
|
|
||||||
|
DBHelper::readFolderFromQuery(folder, query);
|
||||||
|
|
||||||
|
return folder;
|
||||||
|
}
|
||||||
|
|
||||||
|
Folder DBHelper::loadFolder(const QString &folderName, qulonglong parentId, QSqlDatabase &db)
|
||||||
|
{
|
||||||
|
QSqlQuery query(db);
|
||||||
|
query.prepare("SELECT * FROM folder WHERE parentId = :parentId AND name = :folderName");
|
||||||
|
query.bindValue(":parentId", parentId);
|
||||||
|
query.bindValue(":folderName", folderName);
|
||||||
|
query.exec();
|
||||||
|
|
||||||
|
Folder folder;
|
||||||
|
|
||||||
|
folder.parentId = parentId;
|
||||||
|
|
||||||
|
DBHelper::readFolderFromQuery(folder, query);
|
||||||
|
|
||||||
|
return folder;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DBHelper::readFolderFromQuery(Folder &folder, QSqlQuery &query)
|
||||||
|
{
|
||||||
QSqlRecord record = query.record();
|
QSqlRecord record = query.record();
|
||||||
|
|
||||||
|
int id = record.indexOf("id");
|
||||||
int parentId = record.indexOf("parentId");
|
int parentId = record.indexOf("parentId");
|
||||||
int name = record.indexOf("name");
|
int name = record.indexOf("name");
|
||||||
int path = record.indexOf("path");
|
int path = record.indexOf("path");
|
||||||
@ -1577,74 +1671,36 @@ Folder DBHelper::loadFolder(qulonglong id, QSqlDatabase &db)
|
|||||||
int numChildren = record.indexOf("numChildren");
|
int numChildren = record.indexOf("numChildren");
|
||||||
int firstChildHash = record.indexOf("firstChildHash");
|
int firstChildHash = record.indexOf("firstChildHash");
|
||||||
int customImage = record.indexOf("customImage");
|
int customImage = record.indexOf("customImage");
|
||||||
|
int type = record.indexOf("type");
|
||||||
|
int added = record.indexOf("added");
|
||||||
|
int updated = record.indexOf("updated");
|
||||||
|
|
||||||
if (query.next()) {
|
if (query.next()) {
|
||||||
|
folder.id = query.value(id).toULongLong();
|
||||||
folder.parentId = query.value(parentId).toULongLong();
|
folder.parentId = query.value(parentId).toULongLong();
|
||||||
folder.name = query.value(name).toString();
|
folder.name = query.value(name).toString();
|
||||||
folder.path = query.value(path).toString();
|
folder.path = query.value(path).toString();
|
||||||
folder.knownId = true;
|
folder.knownId = true;
|
||||||
|
|
||||||
// new 7.1
|
// new 7.1
|
||||||
folder.setFinished(query.value(finished).toBool());
|
folder.finished = query.value(finished).toBool();
|
||||||
folder.setCompleted(query.value(completed).toBool());
|
folder.completed = query.value(completed).toBool();
|
||||||
|
|
||||||
// new 9.5
|
// new 9.5
|
||||||
if (!query.value(numChildren).isNull() && query.value(numChildren).isValid())
|
if (!query.value(numChildren).isNull() && query.value(numChildren).isValid()) {
|
||||||
folder.setNumChildren(query.value(numChildren).toInt());
|
folder.numChildren = query.value(numChildren).toInt();
|
||||||
folder.setFirstChildHash(query.value(firstChildHash).toString());
|
}
|
||||||
folder.setCustomImage(query.value(customImage).toString());
|
folder.firstChildHash = query.value(firstChildHash).toString();
|
||||||
|
folder.customImage = query.value(customImage).toString();
|
||||||
|
|
||||||
// new 9.8
|
// new 9.8
|
||||||
folder.setManga(query.value(manga).toBool());
|
folder.manga = query.value(manga).toBool();
|
||||||
|
|
||||||
|
// new 9.13
|
||||||
|
folder.type = query.value(type).value<YACReader::FileType>();
|
||||||
|
folder.added = query.value(added).toLongLong();
|
||||||
|
folder.updated = query.value(updated).toLongLong();
|
||||||
}
|
}
|
||||||
|
|
||||||
return folder;
|
|
||||||
}
|
|
||||||
|
|
||||||
Folder DBHelper::loadFolder(const QString &folderName, qulonglong parentId, QSqlDatabase &db)
|
|
||||||
{
|
|
||||||
Folder folder;
|
|
||||||
|
|
||||||
QSqlQuery query(db);
|
|
||||||
query.prepare("SELECT * FROM folder WHERE parentId = :parentId AND name = :folderName");
|
|
||||||
query.bindValue(":parentId", parentId);
|
|
||||||
query.bindValue(":folderName", folderName);
|
|
||||||
query.exec();
|
|
||||||
|
|
||||||
QSqlRecord record = query.record();
|
|
||||||
|
|
||||||
int id = record.indexOf("id");
|
|
||||||
int name = record.indexOf("name");
|
|
||||||
int path = record.indexOf("path");
|
|
||||||
int finished = record.indexOf("finished");
|
|
||||||
int completed = record.indexOf("completed");
|
|
||||||
int manga = record.indexOf("manga");
|
|
||||||
int numChildren = record.indexOf("numChildren");
|
|
||||||
int firstChildHash = record.indexOf("firstChildHash");
|
|
||||||
int customImage = record.indexOf("customImage");
|
|
||||||
|
|
||||||
folder.parentId = parentId;
|
|
||||||
if (query.next()) {
|
|
||||||
folder.id = query.value(id).toULongLong();
|
|
||||||
folder.name = query.value(name).toString();
|
|
||||||
folder.path = query.value(path).toString();
|
|
||||||
folder.knownId = true;
|
|
||||||
|
|
||||||
// new 7.1
|
|
||||||
folder.setFinished(query.value(finished).toBool());
|
|
||||||
folder.setCompleted(query.value(completed).toBool());
|
|
||||||
|
|
||||||
// new 9.5
|
|
||||||
if (!query.value(numChildren).isNull() && query.value(numChildren).isValid())
|
|
||||||
folder.setNumChildren(query.value(numChildren).toInt());
|
|
||||||
folder.setFirstChildHash(query.value(firstChildHash).toString());
|
|
||||||
folder.setCustomImage(query.value(customImage).toString());
|
|
||||||
|
|
||||||
// new 9.8
|
|
||||||
folder.setManga(query.value(manga).toBool());
|
|
||||||
}
|
|
||||||
|
|
||||||
return folder;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ComicDB DBHelper::loadComic(qulonglong id, QSqlDatabase &db, bool &found)
|
ComicDB DBHelper::loadComic(qulonglong id, QSqlDatabase &db, bool &found)
|
||||||
@ -1776,6 +1832,22 @@ ComicInfo DBHelper::getComicInfoFromQuery(QSqlQuery &query, const QString &idKey
|
|||||||
int coverSizeRatio = record.indexOf("coverSizeRatio");
|
int coverSizeRatio = record.indexOf("coverSizeRatio");
|
||||||
int originalCoverSize = record.indexOf("originalCoverSize");
|
int originalCoverSize = record.indexOf("originalCoverSize");
|
||||||
|
|
||||||
|
int added = record.indexOf("added");
|
||||||
|
int type = record.indexOf("type");
|
||||||
|
int editor = record.indexOf("editor");
|
||||||
|
int imprint = record.indexOf("imprint");
|
||||||
|
int teams = record.indexOf("teams");
|
||||||
|
int locations = record.indexOf("locations");
|
||||||
|
int series = record.indexOf("series");
|
||||||
|
int alternateSeries = record.indexOf("alternateSeries");
|
||||||
|
int alternateNumber = record.indexOf("alternateNumber");
|
||||||
|
int alternateCount = record.indexOf("alternateCount");
|
||||||
|
int languageISO = record.indexOf("languageISO");
|
||||||
|
int seriesGroup = record.indexOf("seriesGroup");
|
||||||
|
int mainCharacterOrTeam = record.indexOf("mainCharacterOrTeam");
|
||||||
|
int review = record.indexOf("review");
|
||||||
|
int tags = record.indexOf("tags");
|
||||||
|
|
||||||
ComicInfo comicInfo;
|
ComicInfo comicInfo;
|
||||||
|
|
||||||
comicInfo.hash = query.value(hash).toString();
|
comicInfo.hash = query.value(hash).toString();
|
||||||
@ -1840,6 +1912,24 @@ ComicInfo DBHelper::getComicInfoFromQuery(QSqlQuery &query, const QString &idKey
|
|||||||
comicInfo.manga = query.value(manga);
|
comicInfo.manga = query.value(manga);
|
||||||
//--
|
//--
|
||||||
|
|
||||||
|
// new 9.13 fields
|
||||||
|
comicInfo.added = query.value(added);
|
||||||
|
comicInfo.type = query.value(type);
|
||||||
|
comicInfo.editor = query.value(editor);
|
||||||
|
comicInfo.imprint = query.value(imprint);
|
||||||
|
comicInfo.teams = query.value(teams);
|
||||||
|
comicInfo.locations = query.value(locations);
|
||||||
|
comicInfo.series = query.value(series);
|
||||||
|
comicInfo.alternateSeries = query.value(alternateSeries);
|
||||||
|
comicInfo.alternateNumber = query.value(alternateNumber);
|
||||||
|
comicInfo.alternateCount = query.value(alternateCount);
|
||||||
|
comicInfo.languageISO = query.value(languageISO);
|
||||||
|
comicInfo.seriesGroup = query.value(seriesGroup);
|
||||||
|
comicInfo.mainCharacterOrTeam = query.value(mainCharacterOrTeam);
|
||||||
|
comicInfo.review = query.value(review);
|
||||||
|
comicInfo.tags = query.value(tags);
|
||||||
|
//--
|
||||||
|
|
||||||
comicInfo.existOnDb = true;
|
comicInfo.existOnDb = true;
|
||||||
|
|
||||||
return comicInfo;
|
return comicInfo;
|
||||||
|
@ -65,7 +65,7 @@ public:
|
|||||||
static void update(ComicDB *comics, QSqlDatabase &db);
|
static void update(ComicDB *comics, QSqlDatabase &db);
|
||||||
static void update(ComicInfo *comicInfo, QSqlDatabase &db);
|
static void update(ComicInfo *comicInfo, QSqlDatabase &db);
|
||||||
static void updateRead(ComicInfo *comicInfo, QSqlDatabase &db);
|
static void updateRead(ComicInfo *comicInfo, QSqlDatabase &db);
|
||||||
static void update(const Folder &folder, QSqlDatabase &db);
|
static void update(const Folder &folder, QSqlDatabase &db); // only for finished/completed fields
|
||||||
static void propagateFolderUpdatesToParent(const Folder &folder, QSqlDatabase &db);
|
static void propagateFolderUpdatesToParent(const Folder &folder, QSqlDatabase &db);
|
||||||
static Folder updateChildrenInfo(qulonglong folderId, QSqlDatabase &db);
|
static Folder updateChildrenInfo(qulonglong folderId, QSqlDatabase &db);
|
||||||
static void updateChildrenInfo(QSqlDatabase &db);
|
static void updateChildrenInfo(QSqlDatabase &db);
|
||||||
@ -89,11 +89,12 @@ public:
|
|||||||
static QList<LibraryItem *> getComicsFromParent(qulonglong parentId, QSqlDatabase &db, bool sort = true);
|
static QList<LibraryItem *> getComicsFromParent(qulonglong parentId, QSqlDatabase &db, bool sort = true);
|
||||||
static QList<Label> getLabels(qulonglong libraryId);
|
static QList<Label> getLabels(qulonglong libraryId);
|
||||||
|
|
||||||
static void updateFolderTreeManga(qulonglong id, QSqlDatabase &db, bool manga);
|
static void updateFolderTreeType(qulonglong id, QSqlDatabase &db, YACReader::FileType type);
|
||||||
|
|
||||||
// load
|
// load
|
||||||
static Folder loadFolder(qulonglong id, QSqlDatabase &db);
|
static Folder loadFolder(qulonglong id, QSqlDatabase &db);
|
||||||
static Folder loadFolder(const QString &folderName, qulonglong parentId, QSqlDatabase &db);
|
static Folder loadFolder(const QString &folderName, qulonglong parentId, QSqlDatabase &db);
|
||||||
|
static void readFolderFromQuery(Folder &folder, QSqlQuery &query);
|
||||||
static ComicDB loadComic(qulonglong id, QSqlDatabase &db, bool &found);
|
static ComicDB loadComic(qulonglong id, QSqlDatabase &db, bool &found);
|
||||||
static ComicDB loadComic(QString cname, QString cpath, QString chash, QSqlDatabase &database);
|
static ComicDB loadComic(QString cname, QString cpath, QString chash, QSqlDatabase &database);
|
||||||
static ComicInfo loadComicInfo(QString hash, QSqlDatabase &db);
|
static ComicInfo loadComicInfo(QString hash, QSqlDatabase &db);
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
using namespace YACReader;
|
using namespace YACReader;
|
||||||
|
|
||||||
FolderContentView::FolderContentView(QWidget *parent)
|
FolderContentView::FolderContentView(QAction *toogleRecentVisibilityAction, QWidget *parent)
|
||||||
: QWidget { parent }, parent(QModelIndex()), comicModel(new ComicModel()), folderModel(new FolderModel())
|
: QWidget { parent }, parent(QModelIndex()), comicModel(new ComicModel()), folderModel(new FolderModel())
|
||||||
{
|
{
|
||||||
qmlRegisterType<FolderModel>("com.yacreader.FolderModel", 1, 0, "FolderModel");
|
qmlRegisterType<FolderModel>("com.yacreader.FolderModel", 1, 0, "FolderModel");
|
||||||
@ -59,7 +59,11 @@ FolderContentView::FolderContentView(QWidget *parent)
|
|||||||
connect(coverSizeSlider, &QAbstractSlider::valueChanged, this, &FolderContentView::setCoversSize);
|
connect(coverSizeSlider, &QAbstractSlider::valueChanged, this, &FolderContentView::setCoversSize);
|
||||||
|
|
||||||
toolbar = new QToolBar();
|
toolbar = new QToolBar();
|
||||||
|
toolbar->setStyleSheet("QToolBar {border: none;}");
|
||||||
|
toolbar->setIconSize(QSize(18, 18));
|
||||||
toolbar->addWidget(new YACReaderToolBarStretch);
|
toolbar->addWidget(new YACReaderToolBarStretch);
|
||||||
|
toolbar->addAction(toogleRecentVisibilityAction);
|
||||||
|
toolbar->addSeparator();
|
||||||
toolbar->addWidget(coverSizeSliderWidget);
|
toolbar->addWidget(coverSizeSliderWidget);
|
||||||
|
|
||||||
auto l = new QVBoxLayout;
|
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)
|
void FolderContentView::openFolder(int index)
|
||||||
{
|
{
|
||||||
emit subfolderSelected(this->parent, index);
|
emit subfolderSelected(this->parent, index);
|
||||||
|
@ -19,10 +19,12 @@ class FolderContentView : public QWidget
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit FolderContentView(QWidget *parent = nullptr);
|
explicit FolderContentView(QAction *toogleRecentVisibilityAction, QWidget *parent = nullptr);
|
||||||
void setModel(const QModelIndex &parent, FolderModel *model);
|
void setModel(const QModelIndex &parent, FolderModel *model);
|
||||||
void setContinueReadingModel(ComicModel *model);
|
void setContinueReadingModel(ComicModel *model);
|
||||||
void reloadContinueReadingModel();
|
void reloadContinueReadingModel();
|
||||||
|
void setShowRecent(bool visible);
|
||||||
|
void setRecentRange(int days);
|
||||||
|
|
||||||
FolderModel *currentFolderModel() { return folderModel; }
|
FolderModel *currentFolderModel() { return folderModel; }
|
||||||
signals:
|
signals:
|
||||||
|
@ -170,7 +170,6 @@ GridComicsView::~GridComicsView()
|
|||||||
|
|
||||||
void GridComicsView::createCoverSizeSliderWidget()
|
void GridComicsView::createCoverSizeSliderWidget()
|
||||||
{
|
{
|
||||||
toolBarStretch = new YACReaderToolBarStretch(this);
|
|
||||||
coverSizeSliderWidget = new QWidget(this);
|
coverSizeSliderWidget = new QWidget(this);
|
||||||
coverSizeSliderWidget->setFixedWidth(200);
|
coverSizeSliderWidget->setFixedWidth(200);
|
||||||
coverSizeSlider = new QSlider();
|
coverSizeSlider = new QSlider();
|
||||||
@ -206,7 +205,7 @@ void GridComicsView::setToolBar(QToolBar *toolBar)
|
|||||||
|
|
||||||
createCoverSizeSliderWidget();
|
createCoverSizeSliderWidget();
|
||||||
|
|
||||||
toolBarStretchAction = toolBar->addWidget(toolBarStretch);
|
startSeparatorAction = toolBar->addSeparator();
|
||||||
toolBar->addAction(showInfoAction);
|
toolBar->addAction(showInfoAction);
|
||||||
showInfoSeparatorAction = toolBar->addSeparator();
|
showInfoSeparatorAction = toolBar->addSeparator();
|
||||||
coverSizeSliderAction = toolBar->addWidget(coverSizeSliderWidget);
|
coverSizeSliderAction = toolBar->addWidget(coverSizeSliderWidget);
|
||||||
@ -553,7 +552,7 @@ void GridComicsView::setShowMarks(bool show)
|
|||||||
|
|
||||||
void GridComicsView::closeEvent(QCloseEvent *event)
|
void GridComicsView::closeEvent(QCloseEvent *event)
|
||||||
{
|
{
|
||||||
toolbar->removeAction(toolBarStretchAction);
|
toolbar->removeAction(startSeparatorAction);
|
||||||
toolbar->removeAction(showInfoAction);
|
toolbar->removeAction(showInfoAction);
|
||||||
toolbar->removeAction(showInfoSeparatorAction);
|
toolbar->removeAction(showInfoSeparatorAction);
|
||||||
toolbar->removeAction(coverSizeSliderAction);
|
toolbar->removeAction(coverSizeSliderAction);
|
||||||
|
@ -97,13 +97,12 @@ signals:
|
|||||||
private:
|
private:
|
||||||
QSettings *settings;
|
QSettings *settings;
|
||||||
QToolBar *toolbar;
|
QToolBar *toolbar;
|
||||||
YACReaderToolBarStretch *toolBarStretch;
|
|
||||||
QAction *toolBarStretchAction;
|
|
||||||
QWidget *coverSizeSliderWidget;
|
QWidget *coverSizeSliderWidget;
|
||||||
QSlider *coverSizeSlider;
|
QSlider *coverSizeSlider;
|
||||||
QAction *coverSizeSliderAction;
|
QAction *coverSizeSliderAction;
|
||||||
QAction *showInfoAction;
|
QAction *showInfoAction;
|
||||||
QAction *showInfoSeparatorAction;
|
QAction *showInfoSeparatorAction;
|
||||||
|
QAction *startSeparatorAction;
|
||||||
|
|
||||||
bool filterEnabled;
|
bool filterEnabled;
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
<file>../images/comics_view_toolbar/show_comic_info.svg</file>
|
<file>../images/comics_view_toolbar/show_comic_info.svg</file>
|
||||||
<file>../images/comics_view_toolbar/setManga.svg</file>
|
<file>../images/comics_view_toolbar/setManga.svg</file>
|
||||||
<file>../images/comics_view_toolbar/setNormal.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/defaultCover.png</file>
|
||||||
<file>../images/edit.png</file>
|
<file>../images/edit.png</file>
|
||||||
<file>../images/empty_current_readings.png</file>
|
<file>../images/empty_current_readings.png</file>
|
||||||
|
@ -232,7 +232,8 @@ qulonglong LibraryCreator::insertFolders()
|
|||||||
for (i = _currentPathFolders.begin(); i != _currentPathFolders.end(); ++i) {
|
for (i = _currentPathFolders.begin(); i != _currentPathFolders.end(); ++i) {
|
||||||
if (!(i->knownId)) {
|
if (!(i->knownId)) {
|
||||||
i->setFather(currentId);
|
i->setFather(currentId);
|
||||||
i->setManga(currentParent.isManga());
|
i->manga = currentParent.manga;
|
||||||
|
i->type = currentParent.type;
|
||||||
currentId = DBHelper::insert(&(*i), _database); // insertFolder(currentId,*i);
|
currentId = DBHelper::insert(&(*i), _database); // insertFolder(currentId,*i);
|
||||||
i->setId(currentId);
|
i->setId(currentId);
|
||||||
} else {
|
} else {
|
||||||
@ -325,7 +326,8 @@ void LibraryCreator::insertComic(const QString &relativePath, const QFileInfo &f
|
|||||||
}
|
}
|
||||||
|
|
||||||
comic.parentId = _currentPathFolders.last().id;
|
comic.parentId = _currentPathFolders.last().id;
|
||||||
comic.info.manga = _currentPathFolders.last().isManga();
|
comic.info.manga = _currentPathFolders.last().manga;
|
||||||
|
comic.info.type = QVariant::fromValue(_currentPathFolders.last().type); // TODO_METADATA test this
|
||||||
|
|
||||||
DBHelper::insert(&comic, _database, parsed);
|
DBHelper::insert(&comic, _database, parsed);
|
||||||
}
|
}
|
||||||
@ -539,14 +541,24 @@ void LibraryCreator::update(QDir dirS)
|
|||||||
} else // same file
|
} else // same file
|
||||||
{
|
{
|
||||||
if (fileInfoS.isFile() && !fileInfoD->isDir()) {
|
if (fileInfoS.isFile() && !fileInfoD->isDir()) {
|
||||||
// TODO comprobar fechas + tamaño
|
// TODO_METADATA use added,
|
||||||
// if(fileInfoS.lastModified()>fileInfoD.lastModified())
|
// if added < modified, do something
|
||||||
//{
|
|
||||||
// dirD.mkpath(_target+(QDir::cleanPath(fileInfoS.absolutePath()).remove(_source)));
|
// copy metadata to avoid loosing it if the imported comics doesn't have it.
|
||||||
// emit(coverExtracted(QDir::cleanPath(fileInfoS.absoluteFilePath()).remove(_source)));
|
|
||||||
// ThumbnailCreator tc(QDir::cleanPath(fileInfoS.absoluteFilePath()),_target+(QDir::cleanPath(fileInfoS.absoluteFilePath()).remove(_source))+".jpg");
|
// DBHelper::removeFromDB(fileInfoD, _database);
|
||||||
// tc.create();
|
// #ifdef Q_OS_MAC
|
||||||
// }
|
// QStringList src = _source.split("/");
|
||||||
|
// QString filePath = fileInfoS.absoluteFilePath();
|
||||||
|
// QStringList fp = filePath.split("/");
|
||||||
|
// for (int i = 0; i < src.count(); i++) {
|
||||||
|
// fp.removeFirst();
|
||||||
|
// }
|
||||||
|
// QString path = "/" + fp.join("/");
|
||||||
|
// #else
|
||||||
|
// QString path = QDir::cleanPath(fileInfoS.absoluteFilePath()).remove(_source);
|
||||||
|
// #endif
|
||||||
|
// insertComic(path, fileInfoS);
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
j++;
|
j++;
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#include "library_window.h"
|
#include "library_window.h"
|
||||||
#include "custom_widgets.h"
|
|
||||||
#include "folder_item.h"
|
#include "folder_item.h"
|
||||||
|
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
@ -31,7 +30,6 @@
|
|||||||
#include "library_creator.h"
|
#include "library_creator.h"
|
||||||
#include "package_manager.h"
|
#include "package_manager.h"
|
||||||
#include "xml_info_library_scanner.h"
|
#include "xml_info_library_scanner.h"
|
||||||
#include "comic_flow_widget.h"
|
|
||||||
#include "create_library_dialog.h"
|
#include "create_library_dialog.h"
|
||||||
#include "rename_library_dialog.h"
|
#include "rename_library_dialog.h"
|
||||||
#include "properties_dialog.h"
|
#include "properties_dialog.h"
|
||||||
@ -45,9 +43,7 @@
|
|||||||
#include "server_config_dialog.h"
|
#include "server_config_dialog.h"
|
||||||
#include "comic_model.h"
|
#include "comic_model.h"
|
||||||
#include "yacreader_tool_bar_stretch.h"
|
#include "yacreader_tool_bar_stretch.h"
|
||||||
#include "yacreader_table_view.h"
|
|
||||||
|
|
||||||
#include "yacreader_dark_menu.h"
|
|
||||||
#include "yacreader_titled_toolbar.h"
|
#include "yacreader_titled_toolbar.h"
|
||||||
#include "yacreader_main_toolbar.h"
|
#include "yacreader_main_toolbar.h"
|
||||||
|
|
||||||
@ -87,6 +83,8 @@
|
|||||||
|
|
||||||
#include "library_comic_opener.h"
|
#include "library_comic_opener.h"
|
||||||
|
|
||||||
|
#include "recent_visibility_coordinator.h"
|
||||||
|
|
||||||
#include "QsLog.h"
|
#include "QsLog.h"
|
||||||
|
|
||||||
#include "yacreader_http_server.h"
|
#include "yacreader_http_server.h"
|
||||||
@ -204,6 +202,8 @@ void LibraryWindow::setupUI()
|
|||||||
createToolBars();
|
createToolBars();
|
||||||
createMenus();
|
createMenus();
|
||||||
|
|
||||||
|
setupCoordinators();
|
||||||
|
|
||||||
navigationController = new YACReaderNavigationController(this, contentViewsManager);
|
navigationController = new YACReaderNavigationController(this, contentViewsManager);
|
||||||
|
|
||||||
createConnections();
|
createConnections();
|
||||||
@ -222,24 +222,6 @@ void LibraryWindow::setupUI()
|
|||||||
trayIconController = new TrayIconController(settings, this);
|
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()
|
void LibraryWindow::doLayout()
|
||||||
{
|
{
|
||||||
// LAYOUT ELEMENTS------------------------------------------------------------
|
// LAYOUT ELEMENTS------------------------------------------------------------
|
||||||
@ -461,6 +443,7 @@ void LibraryWindow::setUpShortcutsManagement()
|
|||||||
editShortcutsDialog->addActionsGroup("Visualization", QIcon(":/images/shortcuts_group_visualization.svg"),
|
editShortcutsDialog->addActionsGroup("Visualization", QIcon(":/images/shortcuts_group_visualization.svg"),
|
||||||
tmpList = QList<QAction *>()
|
tmpList = QList<QAction *>()
|
||||||
<< showHideMarksAction
|
<< showHideMarksAction
|
||||||
|
<< toogleShowRecentIndicatorAction
|
||||||
#ifndef Q_OS_MAC
|
#ifndef Q_OS_MAC
|
||||||
<< toggleFullScreenAction
|
<< toggleFullScreenAction
|
||||||
#endif
|
#endif
|
||||||
@ -485,6 +468,11 @@ void LibraryWindow::doModels()
|
|||||||
listsModelProxy = new ReadingListModelProxy(this);
|
listsModelProxy = new ReadingListModelProxy(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LibraryWindow::setupCoordinators()
|
||||||
|
{
|
||||||
|
recentVisibilityCoordinator = new RecentVisibilityCoordinator(settings, foldersModel, contentViewsManager->folderContentView, comicsModel);
|
||||||
|
}
|
||||||
|
|
||||||
void LibraryWindow::createActions()
|
void LibraryWindow::createActions()
|
||||||
{
|
{
|
||||||
backAction = new QAction(this);
|
backAction = new QAction(this);
|
||||||
@ -587,25 +575,34 @@ void LibraryWindow::createActions()
|
|||||||
setAsNonReadAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SET_AS_NON_READ_ACTION_YL));
|
setAsNonReadAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SET_AS_NON_READ_ACTION_YL));
|
||||||
setAsNonReadAction->setIcon(QIcon(":/images/comics_view_toolbar/setUnread.svg"));
|
setAsNonReadAction->setIcon(QIcon(":/images/comics_view_toolbar/setUnread.svg"));
|
||||||
|
|
||||||
setMangaAction = new QAction(tr("Set as manga"), this);
|
setMangaAction = new QAction(tr("manga"), this);
|
||||||
setMangaAction->setToolTip(tr("Set issue as manga"));
|
setMangaAction->setToolTip(tr("Set issue as manga"));
|
||||||
setMangaAction->setData(SET_AS_MANGA_ACTION_YL);
|
setMangaAction->setData(SET_AS_MANGA_ACTION_YL);
|
||||||
setMangaAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SET_AS_MANGA_ACTION_YL));
|
setMangaAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SET_AS_MANGA_ACTION_YL));
|
||||||
setMangaAction->setIcon(QIcon(":/images/comics_view_toolbar/setManga.svg"));
|
setMangaAction->setIcon(QIcon(":/images/comics_view_toolbar/setManga.svg"));
|
||||||
|
|
||||||
setNormalAction = new QAction(tr("Set as normal"), this);
|
setNormalAction = new QAction(tr("comic"), this);
|
||||||
setNormalAction->setToolTip(tr("Set issue as normal"));
|
setNormalAction->setToolTip(tr("Set issue as normal"));
|
||||||
setNormalAction->setData(SET_AS_NORMAL_ACTION_YL);
|
setNormalAction->setData(SET_AS_NORMAL_ACTION_YL);
|
||||||
setNormalAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SET_AS_NORMAL_ACTION_YL));
|
setNormalAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SET_AS_NORMAL_ACTION_YL));
|
||||||
setNormalAction->setIcon(QIcon(":/images/comics_view_toolbar/setNormal.svg"));
|
setNormalAction->setIcon(QIcon(":/images/comics_view_toolbar/setNormal.svg"));
|
||||||
|
|
||||||
/*setAllAsReadAction = new QAction(tr("Set all as read"),this);
|
setWesternMangaAction = new QAction(tr("western manga"), this);
|
||||||
setAllAsReadAction->setToolTip(tr("Set all comics as read"));
|
setWesternMangaAction->setToolTip(tr("Set issue as western manga"));
|
||||||
setAllAsReadAction->setIcon(QIcon(":/images/comics_view_toolbar/setAllRead.png"));
|
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);
|
setWebComicAction = new QAction(tr("web comic"), this);
|
||||||
setAllAsNonReadAction->setToolTip(tr("Set all comics as unread"));
|
setWebComicAction->setToolTip(tr("Set issue as web comic"));
|
||||||
setAllAsNonReadAction->setIcon(QIcon(":/images/comics_view_toolbar/setAllUnread.png"));*/
|
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 = new QAction(tr("Show/Hide marks"), this);
|
||||||
showHideMarksAction->setToolTip(tr("Show or hide read marks"));
|
showHideMarksAction->setToolTip(tr("Show or hide read marks"));
|
||||||
@ -614,6 +611,15 @@ void LibraryWindow::createActions()
|
|||||||
showHideMarksAction->setCheckable(true);
|
showHideMarksAction->setCheckable(true);
|
||||||
showHideMarksAction->setIcon(QIcon(":/images/comics_view_toolbar/showMarks.svg"));
|
showHideMarksAction->setIcon(QIcon(":/images/comics_view_toolbar/showMarks.svg"));
|
||||||
showHideMarksAction->setChecked(true);
|
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
|
#ifndef Q_OS_MAC
|
||||||
toggleFullScreenAction = new QAction(tr("Fullscreen mode on/off"), this);
|
toggleFullScreenAction = new QAction(tr("Fullscreen mode on/off"), this);
|
||||||
toggleFullScreenAction->setToolTip(tr("Fullscreen mode on/off"));
|
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));
|
setFolderAsUnreadAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SET_FOLDER_AS_UNREAD_ACTION_YL));
|
||||||
|
|
||||||
setFolderAsMangaAction = new QAction(this);
|
setFolderAsMangaAction = new QAction(this);
|
||||||
setFolderAsMangaAction->setText(tr("Set as manga"));
|
setFolderAsMangaAction->setText(tr("manga"));
|
||||||
setFolderAsMangaAction->setData(SET_FOLDER_AS_MANGA_ACTION_YL);
|
setFolderAsMangaAction->setData(SET_FOLDER_AS_MANGA_ACTION_YL);
|
||||||
setFolderAsMangaAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SET_FOLDER_AS_MANGA_ACTION_YL));
|
setFolderAsMangaAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SET_FOLDER_AS_MANGA_ACTION_YL));
|
||||||
|
|
||||||
setFolderAsNormalAction = new QAction(this);
|
setFolderAsNormalAction = new QAction(this);
|
||||||
setFolderAsNormalAction->setText(tr("Set as comic"));
|
setFolderAsNormalAction->setText(tr("comic"));
|
||||||
setFolderAsNormalAction->setData(SET_FOLDER_AS_NORMAL_ACTION_YL);
|
setFolderAsNormalAction->setData(SET_FOLDER_AS_NORMAL_ACTION_YL);
|
||||||
setFolderAsNormalAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SET_FOLDER_AS_NORMAL_ACTION_YL));
|
setFolderAsNormalAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SET_FOLDER_AS_NORMAL_ACTION_YL));
|
||||||
|
|
||||||
|
setFolderAsWesternMangaAction = new QAction(this);
|
||||||
|
setFolderAsWesternMangaAction->setText(tr("western manga (left to right)"));
|
||||||
|
setFolderAsWesternMangaAction->setData(SET_FOLDER_AS_WESTERN_MANGA_ACTION_YL);
|
||||||
|
setFolderAsWesternMangaAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SET_FOLDER_AS_WESTERN_MANGA_ACTION_YL));
|
||||||
|
|
||||||
|
setFolderAsWebComicAction = new QAction(this);
|
||||||
|
setFolderAsWebComicAction->setText(tr("web comic"));
|
||||||
|
setFolderAsWebComicAction->setData(SET_FOLDER_AS_WEB_COMIC_ACTION_YL);
|
||||||
|
setFolderAsWebComicAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SET_FOLDER_AS_WEB_COMIC_ACTION_YL));
|
||||||
|
|
||||||
|
setFolderAsYonkomaAction = new QAction(this);
|
||||||
|
setFolderAsYonkomaAction->setText(tr("yonkoma"));
|
||||||
|
setFolderAsYonkomaAction->setData(SET_FOLDER_AS_YONKOMA_ACTION_YL);
|
||||||
|
setFolderAsYonkomaAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SET_FOLDER_AS_YONKOMA_ACTION_YL));
|
||||||
|
|
||||||
//----
|
//----
|
||||||
|
|
||||||
openContainingFolderComicAction = new QAction(this);
|
openContainingFolderComicAction = new QAction(this);
|
||||||
@ -867,6 +888,9 @@ void LibraryWindow::createActions()
|
|||||||
this->addAction(setFolderAsUnreadAction);
|
this->addAction(setFolderAsUnreadAction);
|
||||||
this->addAction(setFolderAsMangaAction);
|
this->addAction(setFolderAsMangaAction);
|
||||||
this->addAction(setFolderAsNormalAction);
|
this->addAction(setFolderAsNormalAction);
|
||||||
|
this->addAction(setFolderAsWesternMangaAction);
|
||||||
|
this->addAction(setFolderAsWebComicAction);
|
||||||
|
this->addAction(setFolderAsYonkomaAction);
|
||||||
this->addAction(deleteMetadataAction);
|
this->addAction(deleteMetadataAction);
|
||||||
this->addAction(rescanXMLFromCurrentFolderAction);
|
this->addAction(rescanXMLFromCurrentFolderAction);
|
||||||
#ifndef Q_OS_MAC
|
#ifndef Q_OS_MAC
|
||||||
@ -891,6 +915,9 @@ void LibraryWindow::disableComicsActions(bool disabled)
|
|||||||
setAsNonReadAction->setDisabled(disabled);
|
setAsNonReadAction->setDisabled(disabled);
|
||||||
setNormalAction->setDisabled(disabled);
|
setNormalAction->setDisabled(disabled);
|
||||||
setMangaAction->setDisabled(disabled);
|
setMangaAction->setDisabled(disabled);
|
||||||
|
setWebComicAction->setDisabled(disabled);
|
||||||
|
setWesternMangaAction->setDisabled(disabled);
|
||||||
|
setYonkomaAction->setDisabled(disabled);
|
||||||
// setAllAsReadAction->setDisabled(disabled);
|
// setAllAsReadAction->setDisabled(disabled);
|
||||||
// setAllAsNonReadAction->setDisabled(disabled);
|
// setAllAsNonReadAction->setDisabled(disabled);
|
||||||
showHideMarksAction->setDisabled(disabled);
|
showHideMarksAction->setDisabled(disabled);
|
||||||
@ -1001,21 +1028,31 @@ void LibraryWindow::createToolBars()
|
|||||||
editInfoToolBar->addSeparator();
|
editInfoToolBar->addSeparator();
|
||||||
|
|
||||||
editInfoToolBar->addAction(setAsReadAction);
|
editInfoToolBar->addAction(setAsReadAction);
|
||||||
// editInfoToolBar->addAction(setAllAsReadAction);
|
|
||||||
editInfoToolBar->addAction(setAsNonReadAction);
|
editInfoToolBar->addAction(setAsNonReadAction);
|
||||||
// editInfoToolBar->addAction(setAllAsNonReadAction);
|
|
||||||
|
|
||||||
editInfoToolBar->addAction(showHideMarksAction);
|
editInfoToolBar->addAction(showHideMarksAction);
|
||||||
|
|
||||||
editInfoToolBar->addSeparator();
|
editInfoToolBar->addSeparator();
|
||||||
|
|
||||||
editInfoToolBar->addAction(setNormalAction);
|
auto setTypeToolButton = new QToolButton();
|
||||||
editInfoToolBar->addAction(setMangaAction);
|
setTypeToolButton->addAction(setNormalAction);
|
||||||
|
setTypeToolButton->addAction(setMangaAction);
|
||||||
|
setTypeToolButton->addAction(setWesternMangaAction);
|
||||||
|
setTypeToolButton->addAction(setWebComicAction);
|
||||||
|
setTypeToolButton->addAction(setYonkomaAction);
|
||||||
|
setTypeToolButton->setPopupMode(QToolButton::InstantPopup);
|
||||||
|
setTypeToolButton->setDefaultAction(setNormalAction);
|
||||||
|
editInfoToolBar->addWidget(setTypeToolButton);
|
||||||
|
|
||||||
editInfoToolBar->addSeparator();
|
editInfoToolBar->addSeparator();
|
||||||
|
|
||||||
editInfoToolBar->addAction(deleteComicsAction);
|
editInfoToolBar->addAction(deleteComicsAction);
|
||||||
|
|
||||||
|
auto toolBarStretch = new YACReaderToolBarStretch(this);
|
||||||
|
editInfoToolBar->addWidget(toolBarStretch);
|
||||||
|
|
||||||
|
editInfoToolBar->addAction(toogleShowRecentIndicatorAction);
|
||||||
|
|
||||||
contentViewsManager->comicsView->setToolBar(editInfoToolBar);
|
contentViewsManager->comicsView->setToolBar(editInfoToolBar);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1037,8 +1074,11 @@ void LibraryWindow::createMenus()
|
|||||||
foldersView->addAction(setFolderAsUnreadAction);
|
foldersView->addAction(setFolderAsUnreadAction);
|
||||||
YACReader::addSperator(foldersView);
|
YACReader::addSperator(foldersView);
|
||||||
|
|
||||||
foldersView->addAction(setFolderAsMangaAction);
|
|
||||||
foldersView->addAction(setFolderAsNormalAction);
|
foldersView->addAction(setFolderAsNormalAction);
|
||||||
|
foldersView->addAction(setFolderAsMangaAction);
|
||||||
|
foldersView->addAction(setFolderAsWesternMangaAction);
|
||||||
|
foldersView->addAction(setFolderAsWebComicAction);
|
||||||
|
foldersView->addAction(setFolderAsYonkomaAction);
|
||||||
|
|
||||||
selectedLibrary->addAction(updateLibraryAction);
|
selectedLibrary->addAction(updateLibraryAction);
|
||||||
selectedLibrary->addAction(renameLibraryAction);
|
selectedLibrary->addAction(renameLibraryAction);
|
||||||
@ -1093,8 +1133,11 @@ void LibraryWindow::createMenus()
|
|||||||
folderMenu->addAction(setFolderAsReadAction);
|
folderMenu->addAction(setFolderAsReadAction);
|
||||||
folderMenu->addAction(setFolderAsUnreadAction);
|
folderMenu->addAction(setFolderAsUnreadAction);
|
||||||
folderMenu->addSeparator();
|
folderMenu->addSeparator();
|
||||||
foldersView->addAction(setFolderAsMangaAction);
|
|
||||||
foldersView->addAction(setFolderAsNormalAction);
|
foldersView->addAction(setFolderAsNormalAction);
|
||||||
|
foldersView->addAction(setFolderAsMangaAction);
|
||||||
|
foldersView->addAction(setFolderAsWesternMangaAction);
|
||||||
|
foldersView->addAction(setFolderAsWebComicAction);
|
||||||
|
foldersView->addAction(setFolderAsYonkomaAction);
|
||||||
|
|
||||||
// comic
|
// comic
|
||||||
QMenu *comicMenu = new QMenu(tr("Comic"));
|
QMenu *comicMenu = new QMenu(tr("Comic"));
|
||||||
@ -1133,7 +1176,7 @@ void LibraryWindow::createConnections()
|
|||||||
connect(libraryCreator, &LibraryCreator::comicAdded, importWidget, &ImportWidget::newComic);
|
connect(libraryCreator, &LibraryCreator::comicAdded, importWidget, &ImportWidget::newComic);
|
||||||
// libraryCreator errors
|
// libraryCreator errors
|
||||||
connect(libraryCreator, &LibraryCreator::failedCreatingDB, this, &LibraryWindow::manageCreatingError);
|
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::showRootWidget);
|
||||||
connect(xmlInfoLibraryScanner, &QThread::finished, this, &LibraryWindow::reloadCurrentFolderComicsContent);
|
connect(xmlInfoLibraryScanner, &QThread::finished, this, &LibraryWindow::reloadCurrentFolderComicsContent);
|
||||||
@ -1185,10 +1228,22 @@ void LibraryWindow::createConnections()
|
|||||||
connect(openLibraryAction, &QAction::triggered, this, &LibraryWindow::showAddLibrary);
|
connect(openLibraryAction, &QAction::triggered, this, &LibraryWindow::showAddLibrary);
|
||||||
connect(setAsReadAction, &QAction::triggered, this, &LibraryWindow::setCurrentComicReaded);
|
connect(setAsReadAction, &QAction::triggered, this, &LibraryWindow::setCurrentComicReaded);
|
||||||
connect(setAsNonReadAction, &QAction::triggered, this, &LibraryWindow::setCurrentComicUnreaded);
|
connect(setAsNonReadAction, &QAction::triggered, this, &LibraryWindow::setCurrentComicUnreaded);
|
||||||
connect(setNormalAction, &QAction::triggered, this, &LibraryWindow::setSelectedComicsAsNormal);
|
|
||||||
connect(setMangaAction, &QAction::triggered, this, &LibraryWindow::setSelectedComicsAsManga);
|
connect(setNormalAction, &QAction::triggered, this, [=]() {
|
||||||
// connect(setAllAsReadAction,SIGNAL(triggered()),this,SLOT(setComicsReaded()));
|
setSelectedComicsType(FileType::Comic);
|
||||||
// connect(setAllAsNonReadAction,SIGNAL(triggered()),this,SLOT(setComicsUnreaded()));
|
});
|
||||||
|
connect(setMangaAction, &QAction::triggered, this, [=]() {
|
||||||
|
setSelectedComicsType(FileType::Manga);
|
||||||
|
});
|
||||||
|
connect(setWesternMangaAction, &QAction::triggered, this, [=]() {
|
||||||
|
setSelectedComicsType(FileType::WesternManga);
|
||||||
|
});
|
||||||
|
connect(setWebComicAction, &QAction::triggered, this, [=]() {
|
||||||
|
setSelectedComicsType(FileType::WebComic);
|
||||||
|
});
|
||||||
|
connect(setYonkomaAction, &QAction::triggered, this, [=]() {
|
||||||
|
setSelectedComicsType(FileType::Yonkoma);
|
||||||
|
});
|
||||||
|
|
||||||
// comicsInfoManagement
|
// comicsInfoManagement
|
||||||
connect(exportComicsInfoAction, &QAction::triggered, this, &LibraryWindow::showExportComicsInfo);
|
connect(exportComicsInfoAction, &QAction::triggered, this, &LibraryWindow::showExportComicsInfo);
|
||||||
@ -1241,8 +1296,22 @@ void LibraryWindow::createConnections()
|
|||||||
connect(setFolderAsReadAction, &QAction::triggered, this, &LibraryWindow::setFolderAsRead);
|
connect(setFolderAsReadAction, &QAction::triggered, this, &LibraryWindow::setFolderAsRead);
|
||||||
connect(setFolderAsUnreadAction, &QAction::triggered, this, &LibraryWindow::setFolderAsUnread);
|
connect(setFolderAsUnreadAction, &QAction::triggered, this, &LibraryWindow::setFolderAsUnread);
|
||||||
connect(openContainingFolderAction, &QAction::triggered, this, &LibraryWindow::openContainingFolder);
|
connect(openContainingFolderAction, &QAction::triggered, this, &LibraryWindow::openContainingFolder);
|
||||||
connect(setFolderAsMangaAction, &QAction::triggered, this, &LibraryWindow::setFolderAsManga);
|
|
||||||
connect(setFolderAsNormalAction, &QAction::triggered, this, &LibraryWindow::setFolderAsNormal);
|
connect(setFolderAsMangaAction, &QAction::triggered, this, [=]() {
|
||||||
|
setFolderType(FileType::Manga);
|
||||||
|
});
|
||||||
|
connect(setFolderAsNormalAction, &QAction::triggered, this, [=]() {
|
||||||
|
setFolderType(FileType::Comic);
|
||||||
|
});
|
||||||
|
connect(setFolderAsWesternMangaAction, &QAction::triggered, this, [=]() {
|
||||||
|
setFolderType(FileType::WesternManga);
|
||||||
|
});
|
||||||
|
connect(setFolderAsWebComicAction, &QAction::triggered, this, [=]() {
|
||||||
|
setFolderType(FileType::WebComic);
|
||||||
|
});
|
||||||
|
connect(setFolderAsYonkomaAction, &QAction::triggered, this, [=]() {
|
||||||
|
setFolderType(FileType::Yonkoma);
|
||||||
|
});
|
||||||
|
|
||||||
connect(resetComicRatingAction, &QAction::triggered, this, &LibraryWindow::resetComicRating);
|
connect(resetComicRatingAction, &QAction::triggered, this, &LibraryWindow::resetComicRating);
|
||||||
|
|
||||||
@ -1288,6 +1357,8 @@ void LibraryWindow::createConnections()
|
|||||||
// upgrade library
|
// upgrade library
|
||||||
connect(this, &LibraryWindow::libraryUpgraded, this, &LibraryWindow::loadLibrary, Qt::QueuedConnection);
|
connect(this, &LibraryWindow::libraryUpgraded, this, &LibraryWindow::loadLibrary, Qt::QueuedConnection);
|
||||||
connect(this, &LibraryWindow::errorUpgradingLibrary, this, &LibraryWindow::showErrorUpgradingLibrary, Qt::QueuedConnection);
|
connect(this, &LibraryWindow::errorUpgradingLibrary, this, &LibraryWindow::showErrorUpgradingLibrary, Qt::QueuedConnection);
|
||||||
|
|
||||||
|
connect(toogleShowRecentIndicatorAction, &QAction::toggled, recentVisibilityCoordinator, &RecentVisibilityCoordinator::toggleVisibility);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LibraryWindow::showErrorUpgradingLibrary(const QString &path)
|
void LibraryWindow::showErrorUpgradingLibrary(const QString &path)
|
||||||
@ -1582,12 +1653,18 @@ void LibraryWindow::reloadAfterCopyMove(const QModelIndex &mi)
|
|||||||
{
|
{
|
||||||
if (getCurrentFolderIndex() == mi) {
|
if (getCurrentFolderIndex() == mi) {
|
||||||
auto item = static_cast<FolderItem *>(mi.internalPointer());
|
auto item = static_cast<FolderItem *>(mi.internalPointer());
|
||||||
auto id = item->id;
|
|
||||||
foldersModel->reload(mi);
|
|
||||||
auto newMi = foldersModel->index(id);
|
|
||||||
|
|
||||||
foldersView->setCurrentIndex(foldersModelProxy->mapFromSource(newMi));
|
if (item == nullptr) {
|
||||||
navigationController->loadFolderInfo(newMi);
|
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();
|
enableNeededActions();
|
||||||
@ -1779,8 +1856,13 @@ void LibraryWindow::showComicsViewContextMenu(const QPoint &point)
|
|||||||
menu.addAction(setAsReadAction);
|
menu.addAction(setAsReadAction);
|
||||||
menu.addAction(setAsNonReadAction);
|
menu.addAction(setAsNonReadAction);
|
||||||
menu.addSeparator();
|
menu.addSeparator();
|
||||||
menu.addAction(setNormalAction);
|
auto typeMenu = new QMenu(tr("Set type"));
|
||||||
menu.addAction(setMangaAction);
|
menu.addMenu(typeMenu);
|
||||||
|
typeMenu->addAction(setNormalAction);
|
||||||
|
typeMenu->addAction(setMangaAction);
|
||||||
|
typeMenu->addAction(setWesternMangaAction);
|
||||||
|
typeMenu->addAction(setWebComicAction);
|
||||||
|
typeMenu->addAction(setYonkomaAction);
|
||||||
menu.addSeparator();
|
menu.addSeparator();
|
||||||
menu.addAction(deleteMetadataAction);
|
menu.addAction(deleteMetadataAction);
|
||||||
menu.addSeparator();
|
menu.addSeparator();
|
||||||
@ -1817,8 +1899,13 @@ void LibraryWindow::showComicsItemContextMenu(const QPoint &point)
|
|||||||
menu.addAction(setAsReadAction);
|
menu.addAction(setAsReadAction);
|
||||||
menu.addAction(setAsNonReadAction);
|
menu.addAction(setAsNonReadAction);
|
||||||
menu.addSeparator();
|
menu.addSeparator();
|
||||||
menu.addAction(setNormalAction);
|
auto typeMenu = new QMenu(tr("Set type"));
|
||||||
menu.addAction(setMangaAction);
|
menu.addMenu(typeMenu);
|
||||||
|
typeMenu->addAction(setNormalAction);
|
||||||
|
typeMenu->addAction(setMangaAction);
|
||||||
|
typeMenu->addAction(setWesternMangaAction);
|
||||||
|
typeMenu->addAction(setWebComicAction);
|
||||||
|
typeMenu->addAction(setYonkomaAction);
|
||||||
menu.addSeparator();
|
menu.addSeparator();
|
||||||
menu.addAction(deleteMetadataAction);
|
menu.addAction(deleteMetadataAction);
|
||||||
menu.addSeparator();
|
menu.addSeparator();
|
||||||
@ -1857,30 +1944,43 @@ void LibraryWindow::showGridFoldersContextMenu(QPoint point, Folder folder)
|
|||||||
setFolderAsUnreadAction->setText(tr("Set as unread"));
|
setFolderAsUnreadAction->setText(tr("Set as unread"));
|
||||||
|
|
||||||
auto setFolderAsMangaAction = new QAction();
|
auto setFolderAsMangaAction = new QAction();
|
||||||
setFolderAsMangaAction->setText(tr("Set as manga"));
|
setFolderAsMangaAction->setText(tr("manga"));
|
||||||
|
|
||||||
auto setFolderAsNormalAction = new QAction();
|
auto setFolderAsNormalAction = new QAction();
|
||||||
setFolderAsNormalAction->setText(tr("Set as comic"));
|
setFolderAsNormalAction->setText(tr("comic"));
|
||||||
|
|
||||||
|
auto setFolderAsWesternMangaAction = new QAction();
|
||||||
|
setFolderAsMangaAction->setText(tr("manga (or left to right)"));
|
||||||
|
|
||||||
|
auto setFolderAsWebComicAction = new QAction();
|
||||||
|
setFolderAsNormalAction->setText(tr("web comic"));
|
||||||
|
|
||||||
|
auto setFolderAs4KomaAction = new QAction();
|
||||||
|
setFolderAsMangaAction->setText(tr("4koma (or top to botom"));
|
||||||
|
|
||||||
menu.addAction(openContainingFolderAction);
|
menu.addAction(openContainingFolderAction);
|
||||||
menu.addAction(updateFolderAction);
|
menu.addAction(updateFolderAction);
|
||||||
menu.addSeparator();
|
menu.addSeparator();
|
||||||
menu.addAction(rescanLibraryForXMLInfoAction);
|
menu.addAction(rescanLibraryForXMLInfoAction);
|
||||||
menu.addSeparator();
|
menu.addSeparator();
|
||||||
if (folder.isCompleted())
|
if (folder.completed)
|
||||||
menu.addAction(setFolderAsNotCompletedAction);
|
menu.addAction(setFolderAsNotCompletedAction);
|
||||||
else
|
else
|
||||||
menu.addAction(setFolderAsCompletedAction);
|
menu.addAction(setFolderAsCompletedAction);
|
||||||
menu.addSeparator();
|
menu.addSeparator();
|
||||||
if (folder.isFinished())
|
if (folder.finished)
|
||||||
menu.addAction(setFolderAsUnreadAction);
|
menu.addAction(setFolderAsUnreadAction);
|
||||||
else
|
else
|
||||||
menu.addAction(setFolderAsReadAction);
|
menu.addAction(setFolderAsReadAction);
|
||||||
menu.addSeparator();
|
menu.addSeparator();
|
||||||
if (folder.isManga())
|
|
||||||
menu.addAction(setFolderAsNormalAction);
|
auto typeMenu = new QMenu(tr("Set type"));
|
||||||
else
|
menu.addMenu(typeMenu);
|
||||||
menu.addAction(setFolderAsMangaAction);
|
typeMenu->addAction(setFolderAsNormalAction);
|
||||||
|
typeMenu->addAction(setFolderAsMangaAction);
|
||||||
|
typeMenu->addAction(setFolderAsWesternMangaAction);
|
||||||
|
typeMenu->addAction(setFolderAsWebComicAction);
|
||||||
|
typeMenu->addAction(setFolderAs4KomaAction);
|
||||||
|
|
||||||
auto subfolderModel = contentViewsManager->folderContentView->currentFolderModel();
|
auto subfolderModel = contentViewsManager->folderContentView->currentFolderModel();
|
||||||
|
|
||||||
@ -1910,12 +2010,24 @@ void LibraryWindow::showGridFoldersContextMenu(QPoint point, Folder folder)
|
|||||||
subfolderModel->updateFolderFinishedStatus(QModelIndexList() << subfolderModel->getIndexFromFolder(folder), false);
|
subfolderModel->updateFolderFinishedStatus(QModelIndexList() << subfolderModel->getIndexFromFolder(folder), false);
|
||||||
});
|
});
|
||||||
connect(setFolderAsMangaAction, &QAction::triggered, this, [=]() {
|
connect(setFolderAsMangaAction, &QAction::triggered, this, [=]() {
|
||||||
foldersModel->updateFolderManga(QModelIndexList() << foldersModel->getIndexFromFolder(folder), true);
|
foldersModel->updateFolderType(QModelIndexList() << foldersModel->getIndexFromFolder(folder), FileType::Manga);
|
||||||
subfolderModel->updateFolderManga(QModelIndexList() << subfolderModel->getIndexFromFolder(folder), true);
|
subfolderModel->updateFolderType(QModelIndexList() << foldersModel->getIndexFromFolder(folder), FileType::Manga);
|
||||||
});
|
});
|
||||||
connect(setFolderAsNormalAction, &QAction::triggered, this, [=]() {
|
connect(setFolderAsNormalAction, &QAction::triggered, this, [=]() {
|
||||||
foldersModel->updateFolderManga(QModelIndexList() << foldersModel->getIndexFromFolder(folder), false);
|
foldersModel->updateFolderType(QModelIndexList() << foldersModel->getIndexFromFolder(folder), FileType::Comic);
|
||||||
subfolderModel->updateFolderManga(QModelIndexList() << subfolderModel->getIndexFromFolder(folder), false);
|
subfolderModel->updateFolderType(QModelIndexList() << foldersModel->getIndexFromFolder(folder), FileType::Comic);
|
||||||
|
});
|
||||||
|
connect(setFolderAsWesternMangaAction, &QAction::triggered, this, [=]() {
|
||||||
|
foldersModel->updateFolderType(QModelIndexList() << foldersModel->getIndexFromFolder(folder), FileType::WesternManga);
|
||||||
|
subfolderModel->updateFolderType(QModelIndexList() << foldersModel->getIndexFromFolder(folder), FileType::WesternManga);
|
||||||
|
});
|
||||||
|
connect(setFolderAsWebComicAction, &QAction::triggered, this, [=]() {
|
||||||
|
foldersModel->updateFolderType(QModelIndexList() << foldersModel->getIndexFromFolder(folder), FileType::WebComic);
|
||||||
|
subfolderModel->updateFolderType(QModelIndexList() << foldersModel->getIndexFromFolder(folder), FileType::WebComic);
|
||||||
|
});
|
||||||
|
connect(setFolderAs4KomaAction, &QAction::triggered, this, [=]() {
|
||||||
|
foldersModel->updateFolderType(QModelIndexList() << foldersModel->getIndexFromFolder(folder), FileType::Yonkoma);
|
||||||
|
subfolderModel->updateFolderType(QModelIndexList() << foldersModel->getIndexFromFolder(folder), FileType::Yonkoma);
|
||||||
});
|
});
|
||||||
|
|
||||||
menu.exec(contentViewsManager->folderContentView->mapToGlobal(point));
|
menu.exec(contentViewsManager->folderContentView->mapToGlobal(point));
|
||||||
@ -2091,14 +2203,9 @@ void LibraryWindow::setCurrentComicUnreaded()
|
|||||||
this->setCurrentComicsStatusReaded(YACReader::Unread);
|
this->setCurrentComicsStatusReaded(YACReader::Unread);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LibraryWindow::setSelectedComicsAsNormal()
|
void LibraryWindow::setSelectedComicsType(FileType type)
|
||||||
{
|
{
|
||||||
comicsModel->setComicsManga(getSelectedComics(), false);
|
comicsModel->setComicsType(getSelectedComics(), type);
|
||||||
}
|
|
||||||
|
|
||||||
void LibraryWindow::setSelectedComicsAsManga()
|
|
||||||
{
|
|
||||||
comicsModel->setComicsManga(getSelectedComics(), true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LibraryWindow::createLibrary()
|
void LibraryWindow::createLibrary()
|
||||||
@ -2109,7 +2216,7 @@ void LibraryWindow::createLibrary()
|
|||||||
|
|
||||||
void LibraryWindow::create(QString source, QString dest, QString name)
|
void LibraryWindow::create(QString source, QString dest, QString name)
|
||||||
{
|
{
|
||||||
QLOG_INFO() << QString("About to create a library from '%1' to '%2' with name '%3'").arg(source).arg(dest).arg(name);
|
QLOG_INFO() << QString("About to create a library from '%1' to '%2' with name '%3'").arg(source, dest, name);
|
||||||
libraryCreator->createLibrary(source, dest);
|
libraryCreator->createLibrary(source, dest);
|
||||||
libraryCreator->start();
|
libraryCreator->start();
|
||||||
_lastAdded = name;
|
_lastAdded = name;
|
||||||
@ -2625,14 +2732,9 @@ void LibraryWindow::setFolderAsUnread()
|
|||||||
foldersModel->updateFolderFinishedStatus(QModelIndexList() << foldersModelProxy->mapToSource(foldersView->currentIndex()), false);
|
foldersModel->updateFolderFinishedStatus(QModelIndexList() << foldersModelProxy->mapToSource(foldersView->currentIndex()), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LibraryWindow::setFolderAsManga()
|
void LibraryWindow::setFolderType(FileType type)
|
||||||
{
|
{
|
||||||
foldersModel->updateFolderManga(QModelIndexList() << foldersModelProxy->mapToSource(foldersView->currentIndex()), true);
|
foldersModel->updateFolderType(QModelIndexList() << foldersModelProxy->mapToSource(foldersView->currentIndex()), type);
|
||||||
}
|
|
||||||
|
|
||||||
void LibraryWindow::setFolderAsNormal()
|
|
||||||
{
|
|
||||||
foldersModel->updateFolderManga(QModelIndexList() << foldersModelProxy->mapToSource(foldersView->currentIndex()), false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LibraryWindow::exportLibrary(QString destPath)
|
void LibraryWindow::exportLibrary(QString destPath)
|
||||||
@ -2654,6 +2756,8 @@ void LibraryWindow::reloadOptions()
|
|||||||
contentViewsManager->comicsView->updateConfig(settings);
|
contentViewsManager->comicsView->updateConfig(settings);
|
||||||
|
|
||||||
trayIconController->updateIconVisibility();
|
trayIconController->updateIconVisibility();
|
||||||
|
|
||||||
|
recentVisibilityCoordinator->updateTimeRange();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString LibraryWindow::currentPath()
|
QString LibraryWindow::currentPath()
|
||||||
@ -2872,10 +2976,9 @@ void LibraryWindow::showFoldersContextMenu(const QPoint &point)
|
|||||||
|
|
||||||
bool isCompleted = sourceMI.data(FolderModel::CompletedRole).toBool();
|
bool isCompleted = sourceMI.data(FolderModel::CompletedRole).toBool();
|
||||||
bool isRead = sourceMI.data(FolderModel::FinishedRole).toBool();
|
bool isRead = sourceMI.data(FolderModel::FinishedRole).toBool();
|
||||||
bool isManga = sourceMI.data(FolderModel::MangaRole).toBool();
|
|
||||||
|
|
||||||
QMenu menu;
|
QMenu menu;
|
||||||
// QMenu * folderMenu = new QMenu(tr("Folder"));
|
|
||||||
menu.addAction(openContainingFolderAction);
|
menu.addAction(openContainingFolderAction);
|
||||||
menu.addAction(updateFolderAction);
|
menu.addAction(updateFolderAction);
|
||||||
menu.addSeparator(); //-------------------------------
|
menu.addSeparator(); //-------------------------------
|
||||||
@ -2891,10 +2994,13 @@ void LibraryWindow::showFoldersContextMenu(const QPoint &point)
|
|||||||
else
|
else
|
||||||
menu.addAction(setFolderAsReadAction);
|
menu.addAction(setFolderAsReadAction);
|
||||||
menu.addSeparator(); //-------------------------------
|
menu.addSeparator(); //-------------------------------
|
||||||
if (isManga)
|
auto typeMenu = new QMenu(tr("Set type"));
|
||||||
menu.addAction(setFolderAsNormalAction);
|
menu.addMenu(typeMenu);
|
||||||
else
|
typeMenu->addAction(setFolderAsNormalAction);
|
||||||
menu.addAction(setFolderAsMangaAction);
|
typeMenu->addAction(setFolderAsMangaAction);
|
||||||
|
typeMenu->addAction(setFolderAsWesternMangaAction);
|
||||||
|
typeMenu->addAction(setFolderAsWebComicAction);
|
||||||
|
typeMenu->addAction(setFolderAsYonkomaAction);
|
||||||
|
|
||||||
menu.exec(foldersView->mapToGlobal(point));
|
menu.exec(foldersView->mapToGlobal(point));
|
||||||
}
|
}
|
||||||
|
@ -81,6 +81,7 @@ class YACReaderHistoryController;
|
|||||||
class EmptyLabelWidget;
|
class EmptyLabelWidget;
|
||||||
class EmptySpecialListWidget;
|
class EmptySpecialListWidget;
|
||||||
class EmptyReadingListWidget;
|
class EmptyReadingListWidget;
|
||||||
|
class RecentVisibilityCoordinator;
|
||||||
|
|
||||||
namespace YACReader {
|
namespace YACReader {
|
||||||
class TrayIconController;
|
class TrayIconController;
|
||||||
@ -197,8 +198,12 @@ public:
|
|||||||
//--
|
//--
|
||||||
QAction *setFolderAsReadAction;
|
QAction *setFolderAsReadAction;
|
||||||
QAction *setFolderAsUnreadAction;
|
QAction *setFolderAsUnreadAction;
|
||||||
|
//--
|
||||||
QAction *setFolderAsMangaAction;
|
QAction *setFolderAsMangaAction;
|
||||||
QAction *setFolderAsNormalAction;
|
QAction *setFolderAsNormalAction;
|
||||||
|
QAction *setFolderAsWesternMangaAction;
|
||||||
|
QAction *setFolderAsWebComicAction;
|
||||||
|
QAction *setFolderAsYonkomaAction;
|
||||||
|
|
||||||
QAction *openContainingFolderComicAction;
|
QAction *openContainingFolderComicAction;
|
||||||
QAction *setAsReadAction;
|
QAction *setAsReadAction;
|
||||||
@ -206,13 +211,16 @@ public:
|
|||||||
|
|
||||||
QAction *setMangaAction;
|
QAction *setMangaAction;
|
||||||
QAction *setNormalAction;
|
QAction *setNormalAction;
|
||||||
|
QAction *setWesternMangaAction;
|
||||||
|
QAction *setWebComicAction;
|
||||||
|
QAction *setYonkomaAction;
|
||||||
|
|
||||||
// QAction * setAllAsReadAction;
|
|
||||||
// QAction * setAllAsNonReadAction;
|
|
||||||
QAction *showHideMarksAction;
|
QAction *showHideMarksAction;
|
||||||
QAction *getInfoAction; // comic vine
|
QAction *getInfoAction; // comic vine
|
||||||
QAction *resetComicRatingAction;
|
QAction *resetComicRatingAction;
|
||||||
|
|
||||||
|
QAction *toogleShowRecentIndicatorAction;
|
||||||
|
|
||||||
// edit info actions
|
// edit info actions
|
||||||
QAction *selectAllComicsAction;
|
QAction *selectAllComicsAction;
|
||||||
QAction *editSelectedComicsAction;
|
QAction *editSelectedComicsAction;
|
||||||
@ -259,10 +267,6 @@ public:
|
|||||||
QString _lastAdded;
|
QString _lastAdded;
|
||||||
QString _sourceLastAdded;
|
QString _sourceLastAdded;
|
||||||
|
|
||||||
// QModelIndex _rootIndex;
|
|
||||||
// QModelIndex _rootIndexCV;
|
|
||||||
// QModelIndex updateDestination;
|
|
||||||
|
|
||||||
quint64 _comicIdEdited;
|
quint64 _comicIdEdited;
|
||||||
|
|
||||||
enum NavigationStatus {
|
enum NavigationStatus {
|
||||||
@ -283,6 +287,7 @@ public:
|
|||||||
void doDialogs();
|
void doDialogs();
|
||||||
void setUpShortcutsManagement();
|
void setUpShortcutsManagement();
|
||||||
void doModels();
|
void doModels();
|
||||||
|
void setupCoordinators();
|
||||||
|
|
||||||
// ACTIONS MANAGEMENT
|
// ACTIONS MANAGEMENT
|
||||||
void disableComicsActions(bool disabled);
|
void disableComicsActions(bool disabled);
|
||||||
@ -291,9 +296,6 @@ public:
|
|||||||
void disableFoldersActions(bool disabled);
|
void disableFoldersActions(bool disabled);
|
||||||
|
|
||||||
void disableAllActions();
|
void disableAllActions();
|
||||||
// void disableActions();
|
|
||||||
// void enableActions();
|
|
||||||
// void enableLibraryActions();
|
|
||||||
|
|
||||||
QString currentPath();
|
QString currentPath();
|
||||||
QString currentFolderPath();
|
QString currentFolderPath();
|
||||||
@ -340,8 +342,7 @@ public slots:
|
|||||||
void setFolderAsCompleted();
|
void setFolderAsCompleted();
|
||||||
void setFolderAsRead();
|
void setFolderAsRead();
|
||||||
void setFolderAsUnread();
|
void setFolderAsUnread();
|
||||||
void setFolderAsManga();
|
void setFolderType(FileType type);
|
||||||
void setFolderAsNormal();
|
|
||||||
void openContainingFolderComic();
|
void openContainingFolderComic();
|
||||||
void deleteCurrentLibrary();
|
void deleteCurrentLibrary();
|
||||||
void removeLibrary();
|
void removeLibrary();
|
||||||
@ -368,8 +369,7 @@ public slots:
|
|||||||
void setCurrentComicsStatusReaded(YACReaderComicReadStatus readStatus);
|
void setCurrentComicsStatusReaded(YACReaderComicReadStatus readStatus);
|
||||||
void setCurrentComicReaded();
|
void setCurrentComicReaded();
|
||||||
void setCurrentComicUnreaded();
|
void setCurrentComicUnreaded();
|
||||||
void setSelectedComicsAsNormal();
|
void setSelectedComicsType(FileType type);
|
||||||
void setSelectedComicsAsManga();
|
|
||||||
void showExportComicsInfo();
|
void showExportComicsInfo();
|
||||||
void showImportComicsInfo();
|
void showImportComicsInfo();
|
||||||
void asignNumbers();
|
void asignNumbers();
|
||||||
@ -450,6 +450,8 @@ private:
|
|||||||
TrayIconController *trayIconController;
|
TrayIconController *trayIconController;
|
||||||
ComicQueryResultProcessor comicQueryResultProcessor;
|
ComicQueryResultProcessor comicQueryResultProcessor;
|
||||||
std::unique_ptr<FolderQueryResultProcessor> folderQueryResultProcessor;
|
std::unique_ptr<FolderQueryResultProcessor> folderQueryResultProcessor;
|
||||||
|
|
||||||
|
RecentVisibilityCoordinator *recentVisibilityCoordinator;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -86,6 +86,18 @@ OptionsDialog::OptionsDialog(QWidget *parent)
|
|||||||
comicInfoXMLBoxLayout->addWidget(comicInfoXMLCheckbox);
|
comicInfoXMLBoxLayout->addWidget(comicInfoXMLCheckbox);
|
||||||
comicInfoXMLBox->setLayout(comicInfoXMLBoxLayout);
|
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
|
// grid view background config
|
||||||
useBackgroundImageCheck = new QCheckBox(tr("Enable background image"));
|
useBackgroundImageCheck = new QCheckBox(tr("Enable background image"));
|
||||||
|
|
||||||
@ -152,6 +164,7 @@ OptionsDialog::OptionsDialog(QWidget *parent)
|
|||||||
generalLayout->addWidget(shortcutsBox);
|
generalLayout->addWidget(shortcutsBox);
|
||||||
generalLayout->addWidget(apiKeyBox);
|
generalLayout->addWidget(apiKeyBox);
|
||||||
generalLayout->addWidget(comicInfoXMLBox);
|
generalLayout->addWidget(comicInfoXMLBox);
|
||||||
|
generalLayout->addWidget(recentlyAddedBox);
|
||||||
generalLayout->addStretch();
|
generalLayout->addStretch();
|
||||||
|
|
||||||
tabWidget->addTab(generalW, tr("General"));
|
tabWidget->addTab(generalW, tr("General"));
|
||||||
@ -163,8 +176,6 @@ OptionsDialog::OptionsDialog(QWidget *parent)
|
|||||||
layout->addWidget(tabWidget);
|
layout->addWidget(tabWidget);
|
||||||
layout->addLayout(buttons);
|
layout->addLayout(buttons);
|
||||||
setLayout(layout);
|
setLayout(layout);
|
||||||
// restoreOptions(settings); //load options
|
|
||||||
// resize(200,0);
|
|
||||||
setModal(true);
|
setModal(true);
|
||||||
setWindowTitle(tr("Options"));
|
setWindowTitle(tr("Options"));
|
||||||
|
|
||||||
@ -187,6 +198,8 @@ void OptionsDialog::restoreOptions(QSettings *settings)
|
|||||||
|
|
||||||
comicInfoXMLCheckbox->setChecked(settings->value(IMPORT_COMIC_INFO_XML_METADATA, false).toBool());
|
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();
|
bool useBackgroundImage = settings->value(USE_BACKGROUND_IMAGE_IN_GRID_VIEW, true).toBool();
|
||||||
|
|
||||||
useBackgroundImageCheck->setChecked(useBackgroundImage);
|
useBackgroundImageCheck->setChecked(useBackgroundImage);
|
||||||
@ -237,6 +250,15 @@ void OptionsDialog::useCurrentComicCoverCheckClicked(bool checked)
|
|||||||
emit optionsChanged();
|
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()
|
void OptionsDialog::resetToDefaults()
|
||||||
{
|
{
|
||||||
settings->setValue(OPACITY_BACKGROUND_IMAGE_IN_GRID_VIEW, 0.2);
|
settings->setValue(OPACITY_BACKGROUND_IMAGE_IN_GRID_VIEW, 0.2);
|
||||||
|
@ -24,6 +24,7 @@ private slots:
|
|||||||
void backgroundImageOpacitySliderChanged(int value);
|
void backgroundImageOpacitySliderChanged(int value);
|
||||||
void backgroundImageBlurRadiusSliderChanged(int value);
|
void backgroundImageBlurRadiusSliderChanged(int value);
|
||||||
void useCurrentComicCoverCheckClicked(bool checked);
|
void useCurrentComicCoverCheckClicked(bool checked);
|
||||||
|
void numDaysToConsiderRecentChanged(int value);
|
||||||
void resetToDefaults();
|
void resetToDefaults();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -38,6 +39,8 @@ private:
|
|||||||
QCheckBox *trayIconCheckbox;
|
QCheckBox *trayIconCheckbox;
|
||||||
QCheckBox *startToTrayCheckbox;
|
QCheckBox *startToTrayCheckbox;
|
||||||
QCheckBox *comicInfoXMLCheckbox;
|
QCheckBox *comicInfoXMLCheckbox;
|
||||||
|
QSlider *recentIntervalSlider;
|
||||||
|
QLabel *numDaysLabel;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -31,6 +31,7 @@ PropertiesDialog::PropertiesDialog(QWidget *parent)
|
|||||||
createPublishingBox();
|
createPublishingBox();
|
||||||
createButtonBox();
|
createButtonBox();
|
||||||
createPlotBox();
|
createPlotBox();
|
||||||
|
createNotesBox(); // review, notes, tags
|
||||||
|
|
||||||
createTabBar();
|
createTabBar();
|
||||||
auto rootLayout = new QGridLayout;
|
auto rootLayout = new QGridLayout;
|
||||||
@ -80,9 +81,10 @@ void PropertiesDialog::createTabBar()
|
|||||||
{
|
{
|
||||||
tabBar = new QTabWidget;
|
tabBar = new QTabWidget;
|
||||||
tabBar->addTab(generalInfoBox, tr("General info"));
|
tabBar->addTab(generalInfoBox, tr("General info"));
|
||||||
|
tabBar->addTab(plotBox, tr("Plot"));
|
||||||
tabBar->addTab(authorsBox, tr("Authors"));
|
tabBar->addTab(authorsBox, tr("Authors"));
|
||||||
tabBar->addTab(publishingBox, tr("Publishing"));
|
tabBar->addTab(publishingBox, tr("Publishing"));
|
||||||
tabBar->addTab(plotBox, tr("Plot"));
|
tabBar->addTab(notesBox, tr("Notes"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertiesDialog::createCoverBox()
|
void PropertiesDialog::createCoverBox()
|
||||||
@ -140,38 +142,44 @@ void PropertiesDialog::createGeneralInfoBox()
|
|||||||
|
|
||||||
generalInfoLayout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
|
generalInfoLayout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
|
||||||
generalInfoLayout->setRowWrapPolicy(QFormLayout::WrapAllRows);
|
generalInfoLayout->setRowWrapPolicy(QFormLayout::WrapAllRows);
|
||||||
|
generalInfoLayout->addRow(tr("Series:"), series = new YACReaderFieldEdit());
|
||||||
generalInfoLayout->addRow(tr("Title:"), title = new YACReaderFieldEdit());
|
generalInfoLayout->addRow(tr("Title:"), title = new YACReaderFieldEdit());
|
||||||
|
|
||||||
auto number = new QHBoxLayout;
|
auto number = new QHBoxLayout;
|
||||||
number->addWidget(numberEdit = new YACReaderFieldEdit());
|
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(new QLabel(tr("of:")));
|
||||||
number->addWidget(countEdit = new YACReaderFieldEdit());
|
number->addWidget(countEdit = new YACReaderFieldEdit());
|
||||||
countValidator.setBottom(0);
|
countValidator.setBottom(0);
|
||||||
countEdit->setValidator(&countValidator);
|
countEdit->setValidator(&countValidator);
|
||||||
number->addStretch(1);
|
number->addStretch(1);
|
||||||
/*generalInfoLayout->addRow(tr("&Issue number:"), );
|
|
||||||
generalInfoLayout->addRow(tr("&Bis:"), );*/
|
|
||||||
generalInfoLayout->addRow(tr("Issue number:"), number);
|
generalInfoLayout->addRow(tr("Issue number:"), number);
|
||||||
|
|
||||||
generalInfoLayout->addRow(tr("Volume:"), volumeEdit = new YACReaderFieldEdit());
|
generalInfoLayout->addRow(tr("Volume:"), volumeEdit = new YACReaderFieldEdit());
|
||||||
|
|
||||||
auto arc = new QHBoxLayout;
|
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(new QLabel(tr("Arc number:")));
|
||||||
arc->addWidget(arcNumberEdit = new YACReaderFieldEdit());
|
arc->addWidget(arcNumberEdit = new YACReaderFieldEdit());
|
||||||
arcNumberValidator.setBottom(0);
|
|
||||||
arcNumberEdit->setValidator(&arcNumberValidator);
|
|
||||||
arc->addWidget(new QLabel(tr("of:")));
|
arc->addWidget(new QLabel(tr("of:")));
|
||||||
arc->addWidget(arcCountEdit = new YACReaderFieldEdit());
|
arc->addWidget(arcCountEdit = new YACReaderFieldEdit());
|
||||||
arcCountValidator.setBottom(0);
|
arcCountValidator.setBottom(0);
|
||||||
arcCountEdit->setValidator(&arcCountValidator);
|
arcCountEdit->setValidator(&arcCountValidator);
|
||||||
arc->addStretch(1);
|
|
||||||
generalInfoLayout->addRow(tr("Story arc:"), arc);
|
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("Genre:"), genereEdit = new YACReaderFieldEdit());
|
||||||
|
|
||||||
generalInfoLayout->addRow(tr("Size:"), size = new QLabel("size"));
|
generalInfoLayout->addRow(tr("Size:"), size = new QLabel("size"));
|
||||||
@ -221,9 +229,20 @@ void PropertiesDialog::createAuthorsBox()
|
|||||||
vr3->addWidget(coverArtist = new YACReaderFieldPlainTextEdit());
|
vr3->addWidget(coverArtist = new YACReaderFieldPlainTextEdit());
|
||||||
h3->addLayout(vr3);
|
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(h1);
|
||||||
authorsLayout->addLayout(h2);
|
authorsLayout->addLayout(h2);
|
||||||
authorsLayout->addLayout(h3);
|
authorsLayout->addLayout(h3);
|
||||||
|
authorsLayout->addLayout(h4);
|
||||||
authorsLayout->addStretch(1);
|
authorsLayout->addStretch(1);
|
||||||
authorsBox->setLayout(authorsLayout);
|
authorsBox->setLayout(authorsLayout);
|
||||||
}
|
}
|
||||||
@ -257,7 +276,16 @@ void PropertiesDialog::createPublishingBox()
|
|||||||
publishingLayout->addRow(tr("Format:"), formatEdit = new YACReaderFieldEdit());
|
publishingLayout->addRow(tr("Format:"), formatEdit = new YACReaderFieldEdit());
|
||||||
publishingLayout->addRow(tr("Color/BW:"), colorCheck = new QCheckBox());
|
publishingLayout->addRow(tr("Color/BW:"), colorCheck = new QCheckBox());
|
||||||
publishingLayout->addRow(tr("Age rating:"), ageRatingEdit = new YACReaderFieldEdit());
|
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);
|
publishingBox->setLayout(publishingLayout);
|
||||||
}
|
}
|
||||||
@ -266,17 +294,61 @@ void PropertiesDialog::createPlotBox()
|
|||||||
{
|
{
|
||||||
plotBox = new QWidget;
|
plotBox = new QWidget;
|
||||||
|
|
||||||
auto plotLayout = new QFormLayout;
|
auto plotLayout = new QVBoxLayout;
|
||||||
plotLayout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
|
|
||||||
|
|
||||||
plotLayout->setRowWrapPolicy(QFormLayout::WrapAllRows);
|
auto h1 = new QHBoxLayout;
|
||||||
plotLayout->addRow(tr("Synopsis:"), synopsis = new YACReaderFieldPlainTextEdit());
|
auto vl1 = new QVBoxLayout;
|
||||||
plotLayout->addRow(tr("Characters:"), characters = new YACReaderFieldPlainTextEdit());
|
vl1->addWidget(new QLabel(tr("Synopsis:")));
|
||||||
plotLayout->addRow(tr("Notes:"), notes = new YACReaderFieldPlainTextEdit());
|
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);
|
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()
|
void PropertiesDialog::createButtonBox()
|
||||||
{
|
{
|
||||||
buttonBox = new QDialogButtonBox;
|
buttonBox = new QDialogButtonBox;
|
||||||
@ -362,6 +434,8 @@ QImage blurred(const QImage &image, const QRect &rect, int radius, bool alphaOnl
|
|||||||
|
|
||||||
void PropertiesDialog::loadComic(ComicDB &comic)
|
void PropertiesDialog::loadComic(ComicDB &comic)
|
||||||
{
|
{
|
||||||
|
if (!comic.info.series.isNull())
|
||||||
|
series->setText(comic.info.series.toString());
|
||||||
if (!comic.info.title.isNull())
|
if (!comic.info.title.isNull())
|
||||||
title->setText(comic.info.title.toString());
|
title->setText(comic.info.title.toString());
|
||||||
if (!comic.info.comicVineID.isNull()) {
|
if (!comic.info.comicVineID.isNull()) {
|
||||||
@ -401,8 +475,6 @@ void PropertiesDialog::loadComic(ComicDB &comic)
|
|||||||
|
|
||||||
if (!comic.info.number.isNull())
|
if (!comic.info.number.isNull())
|
||||||
numberEdit->setText(comic.info.number.toString());
|
numberEdit->setText(comic.info.number.toString());
|
||||||
if (!comic.info.isBis.isNull())
|
|
||||||
isBisCheck->setChecked(comic.info.isBis.toBool());
|
|
||||||
if (!comic.info.count.isNull())
|
if (!comic.info.count.isNull())
|
||||||
countEdit->setText(comic.info.count.toString());
|
countEdit->setText(comic.info.count.toString());
|
||||||
|
|
||||||
@ -414,6 +486,14 @@ void PropertiesDialog::loadComic(ComicDB &comic)
|
|||||||
arcNumberEdit->setText(comic.info.arcNumber.toString());
|
arcNumberEdit->setText(comic.info.arcNumber.toString());
|
||||||
if (!comic.info.arcCount.isNull())
|
if (!comic.info.arcCount.isNull())
|
||||||
arcCountEdit->setText(comic.info.arcCount.toString());
|
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())
|
if (!comic.info.genere.isNull())
|
||||||
genereEdit->setText(comic.info.genere.toString());
|
genereEdit->setText(comic.info.genere.toString());
|
||||||
@ -430,6 +510,10 @@ void PropertiesDialog::loadComic(ComicDB &comic)
|
|||||||
letterer->setPlainText(comic.info.letterer.toString());
|
letterer->setPlainText(comic.info.letterer.toString());
|
||||||
if (!comic.info.coverArtist.isNull())
|
if (!comic.info.coverArtist.isNull())
|
||||||
coverArtist->setPlainText(comic.info.coverArtist.toString());
|
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");
|
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
|
else
|
||||||
colorCheck->setCheckState(Qt::PartiallyChecked);
|
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())
|
if (!comic.info.ageRating.isNull())
|
||||||
ageRatingEdit->setText(comic.info.ageRating.toString());
|
ageRatingEdit->setText(comic.info.ageRating.toString());
|
||||||
@ -461,8 +548,19 @@ void PropertiesDialog::loadComic(ComicDB &comic)
|
|||||||
synopsis->setPlainText(comic.info.synopsis.toString());
|
synopsis->setPlainText(comic.info.synopsis.toString());
|
||||||
if (!comic.info.characters.isNull())
|
if (!comic.info.characters.isNull())
|
||||||
characters->setPlainText(comic.info.characters.toString());
|
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())
|
if (!comic.info.notes.isNull())
|
||||||
notes->setPlainText(comic.info.notes.toString());
|
notes->setPlainText(comic.info.notes.toString());
|
||||||
|
if (!comic.info.tags.isNull())
|
||||||
|
tags->setPlainText(comic.info.tags.toString());
|
||||||
|
|
||||||
this->setWindowTitle(tr("Edit comic information"));
|
this->setWindowTitle(tr("Edit comic information"));
|
||||||
setCover(comic.info.getCover(basePath));
|
setCover(comic.info.getCover(basePath));
|
||||||
@ -503,6 +601,9 @@ void PropertiesDialog::setComics(QList<ComicDB> comics)
|
|||||||
|
|
||||||
QList<ComicDB>::iterator itr;
|
QList<ComicDB>::iterator itr;
|
||||||
for (itr = ++comics.begin(); itr != comics.end(); 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())
|
if (itr->info.title.isNull() || itr->info.title.toString() != title->text())
|
||||||
title->clear();
|
title->clear();
|
||||||
|
|
||||||
@ -516,8 +617,15 @@ void PropertiesDialog::setComics(QList<ComicDB> comics)
|
|||||||
if (itr->info.arcCount.isNull() || itr->info.arcCount.toString() != storyArcEdit->text())
|
if (itr->info.arcCount.isNull() || itr->info.arcCount.toString() != storyArcEdit->text())
|
||||||
arcCountEdit->clear();
|
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())
|
if (itr->info.genere.isNull() || itr->info.genere.toString() != genereEdit->text())
|
||||||
genereEdit->clear();
|
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())
|
if (itr->info.writer.isNull() || itr->info.writer.toString() != writer->toPlainText())
|
||||||
writer->clear();
|
writer->clear();
|
||||||
@ -531,6 +639,10 @@ void PropertiesDialog::setComics(QList<ComicDB> comics)
|
|||||||
letterer->clear();
|
letterer->clear();
|
||||||
if (itr->info.coverArtist.isNull() || itr->info.coverArtist.toString() != coverArtist->toPlainText())
|
if (itr->info.coverArtist.isNull() || itr->info.coverArtist.toString() != coverArtist->toPlainText())
|
||||||
coverArtist->clear();
|
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()) {
|
if (itr->info.date.isNull()) {
|
||||||
dayEdit->clear();
|
dayEdit->clear();
|
||||||
@ -552,8 +664,16 @@ void PropertiesDialog::setComics(QList<ComicDB> comics)
|
|||||||
formatEdit->clear();
|
formatEdit->clear();
|
||||||
if (itr->info.color.isNull() || itr->info.color.toBool() != colorCheck->isChecked())
|
if (itr->info.color.isNull() || itr->info.color.toBool() != colorCheck->isChecked())
|
||||||
colorCheck->setCheckState(Qt::PartiallyChecked);
|
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())
|
if (itr->info.ageRating.isNull() || itr->info.ageRating.toString() != ageRatingEdit->text())
|
||||||
ageRatingEdit->clear();
|
ageRatingEdit->clear();
|
||||||
|
|
||||||
@ -561,8 +681,19 @@ void PropertiesDialog::setComics(QList<ComicDB> comics)
|
|||||||
synopsis->clear();
|
synopsis->clear();
|
||||||
if (itr->info.characters.isNull() || itr->info.characters.toString() != characters->toPlainText())
|
if (itr->info.characters.isNull() || itr->info.characters.toString() != characters->toPlainText())
|
||||||
characters->clear();
|
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())
|
if (itr->info.notes.isNull() || itr->info.notes.toString() != notes->toPlainText())
|
||||||
notes->clear();
|
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)
|
void PropertiesDialog::setCover(const QPixmap &coverI)
|
||||||
{
|
{
|
||||||
coverImage = coverI.scaledToHeight(444, Qt::SmoothTransformation);
|
coverImage = coverI.scaledToHeight(575, Qt::SmoothTransformation);
|
||||||
|
|
||||||
cover->setPixmap(coverImage);
|
cover->setPixmap(coverImage);
|
||||||
}
|
}
|
||||||
@ -642,6 +773,12 @@ void PropertiesDialog::save()
|
|||||||
for (itr = begin; itr != end; itr++) {
|
for (itr = begin; itr != end; itr++) {
|
||||||
bool edited = false;
|
bool edited = false;
|
||||||
|
|
||||||
|
if (series->isModified()) {
|
||||||
|
auto seriesString = series->text();
|
||||||
|
itr->info.series = seriesString.isEmpty() ? QVariant() : series->text();
|
||||||
|
edited = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (title->isModified()) {
|
if (title->isModified()) {
|
||||||
auto titleString = title->text();
|
auto titleString = title->text();
|
||||||
itr->info.title = titleString.isEmpty() ? QVariant() : title->text();
|
itr->info.title = titleString.isEmpty() ? QVariant() : title->text();
|
||||||
@ -654,8 +791,6 @@ void PropertiesDialog::save()
|
|||||||
edited = true;
|
edited = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*if(comic.info.numPages != NULL)
|
|
||||||
numPagesEdit->setText(QString::number(*comic.info.numPages));*/
|
|
||||||
if (sequentialEditing)
|
if (sequentialEditing)
|
||||||
if (numberEdit->isModified()) {
|
if (numberEdit->isModified()) {
|
||||||
if (numberEdit->text().isEmpty())
|
if (numberEdit->text().isEmpty())
|
||||||
@ -664,11 +799,6 @@ void PropertiesDialog::save()
|
|||||||
itr->info.number = numberEdit->text();
|
itr->info.number = numberEdit->text();
|
||||||
edited = true;
|
edited = true;
|
||||||
}
|
}
|
||||||
if (sequentialEditing)
|
|
||||||
if (!itr->info.isBis.isNull() || isBisCheck->isChecked()) {
|
|
||||||
itr->info.isBis = isBisCheck->isChecked();
|
|
||||||
edited = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (countEdit->isModified()) {
|
if (countEdit->isModified()) {
|
||||||
itr->info.count = countEdit->text();
|
itr->info.count = countEdit->text();
|
||||||
@ -693,6 +823,23 @@ void PropertiesDialog::save()
|
|||||||
edited = true;
|
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()) {
|
if (genereEdit->isModified()) {
|
||||||
itr->info.genere = genereEdit->text();
|
itr->info.genere = genereEdit->text();
|
||||||
edited = true;
|
edited = true;
|
||||||
@ -722,6 +869,14 @@ void PropertiesDialog::save()
|
|||||||
itr->info.coverArtist = coverArtist->toPlainText();
|
itr->info.coverArtist = coverArtist->toPlainText();
|
||||||
edited = true;
|
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()) {
|
if (dayEdit->isModified() || monthEdit->isModified() || yearEdit->isModified()) {
|
||||||
itr->info.date = dayEdit->text() + "/" + monthEdit->text() + "/" + yearEdit->text();
|
itr->info.date = dayEdit->text() + "/" + monthEdit->text() + "/" + yearEdit->text();
|
||||||
@ -740,8 +895,13 @@ void PropertiesDialog::save()
|
|||||||
edited = true;
|
edited = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mangaCheck->checkState() != Qt::PartiallyChecked) {
|
if (typeCombo->currentIndex() != -1 && itr->info.type.toInt() != typeCombo->currentIndex()) {
|
||||||
itr->info.manga = mangaCheck->isChecked();
|
itr->info.type = typeCombo->currentIndex();
|
||||||
|
edited = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (languageEdit->isModified()) {
|
||||||
|
itr->info.languageISO = languageEdit->text();
|
||||||
edited = true;
|
edited = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -754,14 +914,40 @@ void PropertiesDialog::save()
|
|||||||
itr->info.synopsis = synopsis->toPlainText();
|
itr->info.synopsis = synopsis->toPlainText();
|
||||||
edited = true;
|
edited = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (characters->document()->isModified()) {
|
if (characters->document()->isModified()) {
|
||||||
itr->info.characters = characters->toPlainText();
|
itr->info.characters = characters->toPlainText();
|
||||||
edited = true;
|
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()) {
|
if (notes->document()->isModified()) {
|
||||||
itr->info.notes = notes->toPlainText();
|
itr->info.notes = notes->toPlainText();
|
||||||
edited = true;
|
edited = true;
|
||||||
}
|
}
|
||||||
|
if (tags->document()->isModified()) {
|
||||||
|
itr->info.tags = tags->toPlainText();
|
||||||
|
edited = true;
|
||||||
|
}
|
||||||
|
|
||||||
itr->info.edited = edited;
|
itr->info.edited = edited;
|
||||||
}
|
}
|
||||||
@ -829,10 +1015,10 @@ void PropertiesDialog::setDisableUniqueValues(bool disabled)
|
|||||||
coverPageEdit->clear();
|
coverPageEdit->clear();
|
||||||
numberEdit->setDisabled(disabled);
|
numberEdit->setDisabled(disabled);
|
||||||
numberEdit->clear();
|
numberEdit->clear();
|
||||||
isBisCheck->setDisabled(disabled);
|
|
||||||
isBisCheck->setChecked(false);
|
|
||||||
arcNumberEdit->setDisabled(disabled);
|
arcNumberEdit->setDisabled(disabled);
|
||||||
arcNumberEdit->clear();
|
arcNumberEdit->clear();
|
||||||
|
alternateNumberEdit->setDisabled(disabled);
|
||||||
|
alternateNumberEdit->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertiesDialog::closeEvent(QCloseEvent *e)
|
void PropertiesDialog::closeEvent(QCloseEvent *e)
|
||||||
@ -841,9 +1027,7 @@ void PropertiesDialog::closeEvent(QCloseEvent *e)
|
|||||||
title->clear();
|
title->clear();
|
||||||
title->setModified(false);
|
title->setModified(false);
|
||||||
coverPageEdit->clear();
|
coverPageEdit->clear();
|
||||||
// numPagesEdit->setText(QString::number(*comic.info.numPages));
|
|
||||||
numberEdit->clear();
|
numberEdit->clear();
|
||||||
isBisCheck->setChecked(false);
|
|
||||||
countEdit->clear();
|
countEdit->clear();
|
||||||
volumeEdit->clear();
|
volumeEdit->clear();
|
||||||
storyArcEdit->clear();
|
storyArcEdit->clear();
|
||||||
@ -862,12 +1046,27 @@ void PropertiesDialog::closeEvent(QCloseEvent *e)
|
|||||||
publisherEdit->clear();
|
publisherEdit->clear();
|
||||||
formatEdit->clear();
|
formatEdit->clear();
|
||||||
colorCheck->setCheckState(Qt::PartiallyChecked);
|
colorCheck->setCheckState(Qt::PartiallyChecked);
|
||||||
mangaCheck->setChecked(false);
|
|
||||||
ageRatingEdit->clear();
|
ageRatingEdit->clear();
|
||||||
synopsis->clear();
|
synopsis->clear();
|
||||||
characters->clear();
|
characters->clear();
|
||||||
notes->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);
|
setDisableUniqueValues(false);
|
||||||
|
|
||||||
tabBar->setCurrentIndex(0);
|
tabBar->setCurrentIndex(0);
|
||||||
|
@ -15,6 +15,7 @@ class YACReaderFieldEdit;
|
|||||||
class YACReaderFieldPlainTextEdit;
|
class YACReaderFieldPlainTextEdit;
|
||||||
class QDialogButtonBox;
|
class QDialogButtonBox;
|
||||||
class QCheckBox;
|
class QCheckBox;
|
||||||
|
class QComboBox;
|
||||||
// class YACReaderBusyWidget;
|
// class YACReaderBusyWidget;
|
||||||
class QToolButton;
|
class QToolButton;
|
||||||
|
|
||||||
@ -36,6 +37,7 @@ private:
|
|||||||
QScrollArea *sa;
|
QScrollArea *sa;
|
||||||
|
|
||||||
QWidget *generalInfoBox;
|
QWidget *generalInfoBox;
|
||||||
|
YACReaderFieldEdit *series;
|
||||||
YACReaderFieldEdit *title;
|
YACReaderFieldEdit *title;
|
||||||
YACReaderFieldEdit *numPagesEdit;
|
YACReaderFieldEdit *numPagesEdit;
|
||||||
QLabel *size;
|
QLabel *size;
|
||||||
@ -46,7 +48,6 @@ private:
|
|||||||
|
|
||||||
YACReaderFieldEdit *numberEdit;
|
YACReaderFieldEdit *numberEdit;
|
||||||
QIntValidator numberValidator;
|
QIntValidator numberValidator;
|
||||||
QCheckBox *isBisCheck;
|
|
||||||
YACReaderFieldEdit *countEdit;
|
YACReaderFieldEdit *countEdit;
|
||||||
QIntValidator countValidator;
|
QIntValidator countValidator;
|
||||||
|
|
||||||
@ -57,6 +58,12 @@ private:
|
|||||||
YACReaderFieldEdit *arcCountEdit;
|
YACReaderFieldEdit *arcCountEdit;
|
||||||
QIntValidator arcCountValidator;
|
QIntValidator arcCountValidator;
|
||||||
|
|
||||||
|
YACReaderFieldEdit *alternateSeriesEdit;
|
||||||
|
YACReaderFieldEdit *alternateNumberEdit;
|
||||||
|
YACReaderFieldEdit *alternateCountEdit;
|
||||||
|
|
||||||
|
YACReaderFieldEdit *seriesGroupEdit;
|
||||||
|
|
||||||
YACReaderFieldEdit *genereEdit;
|
YACReaderFieldEdit *genereEdit;
|
||||||
|
|
||||||
YACReaderFieldPlainTextEdit *writer;
|
YACReaderFieldPlainTextEdit *writer;
|
||||||
@ -65,6 +72,8 @@ private:
|
|||||||
YACReaderFieldPlainTextEdit *colorist;
|
YACReaderFieldPlainTextEdit *colorist;
|
||||||
YACReaderFieldPlainTextEdit *letterer;
|
YACReaderFieldPlainTextEdit *letterer;
|
||||||
YACReaderFieldPlainTextEdit *coverArtist;
|
YACReaderFieldPlainTextEdit *coverArtist;
|
||||||
|
YACReaderFieldPlainTextEdit *editor;
|
||||||
|
YACReaderFieldPlainTextEdit *imprint;
|
||||||
|
|
||||||
YACReaderFieldEdit *dayEdit;
|
YACReaderFieldEdit *dayEdit;
|
||||||
QIntValidator dayValidator;
|
QIntValidator dayValidator;
|
||||||
@ -76,11 +85,14 @@ private:
|
|||||||
YACReaderFieldEdit *formatEdit;
|
YACReaderFieldEdit *formatEdit;
|
||||||
QCheckBox *colorCheck;
|
QCheckBox *colorCheck;
|
||||||
YACReaderFieldEdit *ageRatingEdit;
|
YACReaderFieldEdit *ageRatingEdit;
|
||||||
QCheckBox *mangaCheck;
|
QComboBox *typeCombo;
|
||||||
|
YACReaderFieldEdit *languageEdit;
|
||||||
|
|
||||||
YACReaderFieldPlainTextEdit *synopsis;
|
YACReaderFieldPlainTextEdit *synopsis;
|
||||||
YACReaderFieldPlainTextEdit *characters;
|
YACReaderFieldPlainTextEdit *characters;
|
||||||
YACReaderFieldPlainTextEdit *notes;
|
YACReaderFieldPlainTextEdit *teams;
|
||||||
|
YACReaderFieldPlainTextEdit *locations;
|
||||||
|
YACReaderFieldEdit *mainCharacterOrTeamEdit;
|
||||||
|
|
||||||
QWidget *authorsBox;
|
QWidget *authorsBox;
|
||||||
|
|
||||||
@ -88,6 +100,12 @@ private:
|
|||||||
|
|
||||||
QWidget *plotBox;
|
QWidget *plotBox;
|
||||||
|
|
||||||
|
QWidget *notesBox;
|
||||||
|
|
||||||
|
YACReaderFieldPlainTextEdit *review;
|
||||||
|
YACReaderFieldPlainTextEdit *notes;
|
||||||
|
YACReaderFieldPlainTextEdit *tags;
|
||||||
|
|
||||||
QDialogButtonBox *buttonBox;
|
QDialogButtonBox *buttonBox;
|
||||||
QPushButton *closeButton;
|
QPushButton *closeButton;
|
||||||
QPushButton *saveButton;
|
QPushButton *saveButton;
|
||||||
@ -107,6 +125,7 @@ private:
|
|||||||
void createAuthorsBox();
|
void createAuthorsBox();
|
||||||
void createPublishingBox();
|
void createPublishingBox();
|
||||||
void createPlotBox();
|
void createPlotBox();
|
||||||
|
void createNotesBox();
|
||||||
|
|
||||||
void createButtonBox();
|
void createButtonBox();
|
||||||
|
|
||||||
|
@ -140,7 +140,7 @@ Rectangle {
|
|||||||
font.pixelSize: mainContainer.compact ? 18 : 21;
|
font.pixelSize: mainContainer.compact ? 18 : 21;
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
|
|
||||||
text: comic ? comic.getTitleIncludingNumber() ?? "" : ""
|
text: comic ? comic.getInfoTitle() ?? "" : ""
|
||||||
}
|
}
|
||||||
|
|
||||||
RowLayout
|
RowLayout
|
||||||
@ -202,6 +202,33 @@ Rectangle {
|
|||||||
visible : comicInfo ? comicInfo.number ?? false : false
|
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 {
|
Text {
|
||||||
id: genre
|
id: genre
|
||||||
color: infoColor
|
color: infoColor
|
||||||
@ -266,6 +293,129 @@ Rectangle {
|
|||||||
textFormat: Text.RichText
|
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 {
|
Text {
|
||||||
Layout.topMargin: 25
|
Layout.topMargin: 25
|
||||||
Layout.bottomMargin: 5
|
Layout.bottomMargin: 5
|
||||||
@ -283,7 +433,9 @@ Rectangle {
|
|||||||
comicInfo.getInkers().length +
|
comicInfo.getInkers().length +
|
||||||
comicInfo.getColorists().length +
|
comicInfo.getColorists().length +
|
||||||
comicInfo.getLetterers().length +
|
comicInfo.getLetterers().length +
|
||||||
comicInfo.getCoverArtists().length > 0) : false
|
comicInfo.getCoverArtists().length +
|
||||||
|
comicInfo.getEditors().length +
|
||||||
|
comicInfo.getImprint().length > 0) : false
|
||||||
}
|
}
|
||||||
|
|
||||||
Flow {
|
Flow {
|
||||||
@ -401,7 +553,7 @@ Rectangle {
|
|||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
id: cover_artist
|
id: cover_artist
|
||||||
model: comicInfo ? comicInfo.getCoverArtists().length : ""
|
model: comicInfo ? comicInfo.getCoverArtists().length : null
|
||||||
Column{
|
Column{
|
||||||
Text {
|
Text {
|
||||||
color: infoTitleColor
|
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 {
|
Text {
|
||||||
@ -464,6 +660,18 @@ Rectangle {
|
|||||||
visible: comicInfo ? comicInfo.format ?? false : false
|
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 {
|
Text {
|
||||||
id: color
|
id: color
|
||||||
|
|
||||||
@ -476,6 +684,18 @@ Rectangle {
|
|||||||
visible: comicInfo ? comicInfo.color ?? false : false
|
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 {
|
Text {
|
||||||
id: age_rating
|
id: age_rating
|
||||||
|
|
||||||
@ -488,38 +708,6 @@ Rectangle {
|
|||||||
visible: comicInfo ? comicInfo.ageRating ?? false : false
|
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 {
|
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
|
//border
|
||||||
Rectangle {
|
Rectangle {
|
||||||
width: coverElement.width
|
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
|
//border
|
||||||
Rectangle {
|
Rectangle {
|
||||||
width: coverElement.width
|
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
|
//border
|
||||||
Rectangle {
|
Rectangle {
|
||||||
width: coverElement.width
|
width: coverElement.width
|
||||||
@ -489,8 +499,7 @@ SplitView {
|
|||||||
font.pixelSize: 21
|
font.pixelSize: 21
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
|
|
||||||
text: currentComic.getTitleIncludingNumber()
|
text: currentComic ? currentComic.getTitleIncludingNumber() : "" }
|
||||||
}
|
|
||||||
|
|
||||||
Flow {
|
Flow {
|
||||||
spacing: 0
|
spacing: 0
|
||||||
@ -523,6 +532,33 @@ SplitView {
|
|||||||
visible : currentComicInfo.number ? true : false
|
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 {
|
Text {
|
||||||
id: currentComicInfoGenre
|
id: currentComicInfoGenre
|
||||||
color: currentComicDetailsFlowView.infoFlowTextColor
|
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
|
//border
|
||||||
Rectangle {
|
Rectangle {
|
||||||
width: coverElement.width
|
width: coverElement.width
|
||||||
@ -493,7 +503,7 @@ SplitView {
|
|||||||
font.pixelSize: 21
|
font.pixelSize: 21
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
|
|
||||||
text: currentComic.getTitleIncludingNumber()
|
text: currentComic?.getTitleIncludingNumber() ?? ""
|
||||||
}
|
}
|
||||||
|
|
||||||
Flow {
|
Flow {
|
||||||
@ -527,6 +537,33 @@ SplitView {
|
|||||||
visible : currentComicInfo.number ? true : false
|
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 {
|
Text {
|
||||||
id: currentComicInfoGenre
|
id: currentComicInfoGenre
|
||||||
color: currentComicDetailsFlowView.infoFlowTextColor
|
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(libraryId)
|
||||||
.arg(folder.id)
|
.arg(folder.id)
|
||||||
.arg(folder.name)
|
.arg(folder.name)
|
||||||
.arg(folder.getNumChildren())
|
.arg(folder.numChildren)
|
||||||
.arg(folder.getFirstChildHash());
|
.arg(folder.firstChildHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString YACReaderServerDataHelper::comicToYSFormat(const qulonglong libraryId, const ComicDB &comic)
|
QString YACReaderServerDataHelper::comicToYSFormat(const qulonglong libraryId, const ComicDB &comic)
|
||||||
@ -31,8 +31,15 @@ QJsonObject YACReaderServerDataHelper::folderToJSON(const qulonglong libraryId,
|
|||||||
json["id"] = QString::number(folder.id);
|
json["id"] = QString::number(folder.id);
|
||||||
json["library_id"] = QString::number(libraryId);
|
json["library_id"] = QString::number(libraryId);
|
||||||
json["folder_name"] = folder.name;
|
json["folder_name"] = folder.name;
|
||||||
json["num_children"] = folder.getNumChildren();
|
json["num_children"] = folder.numChildren;
|
||||||
json["first_comic_hash"] = folder.getFirstChildHash();
|
json["first_comic_hash"] = folder.firstChildHash;
|
||||||
|
// 9.13
|
||||||
|
json["finished"] = folder.finished;
|
||||||
|
json["completed"] = folder.completed;
|
||||||
|
json["custom_image"] = folder.customImage;
|
||||||
|
json["file_type"] = static_cast<typename std::underlying_type<YACReader::FileType>::type>(folder.type);
|
||||||
|
json["added"] = folder.added;
|
||||||
|
json["updated"] = folder.updated;
|
||||||
|
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
@ -47,14 +54,18 @@ QJsonObject YACReaderServerDataHelper::comicToJSON(const qulonglong libraryId, c
|
|||||||
json["file_name"] = comic.name;
|
json["file_name"] = comic.name;
|
||||||
json["file_size"] = QString::number(comic.getFileSize());
|
json["file_size"] = QString::number(comic.getFileSize());
|
||||||
json["hash"] = comic.info.hash;
|
json["hash"] = comic.info.hash;
|
||||||
|
json["cover_page"] = comic.info.coverPage.toInt(); // 9.13
|
||||||
json["current_page"] = comic.info.currentPage;
|
json["current_page"] = comic.info.currentPage;
|
||||||
json["num_pages"] = comic.info.numPages.toInt();
|
json["num_pages"] = comic.info.numPages.toInt();
|
||||||
json["read"] = comic.info.read;
|
json["read"] = comic.info.read;
|
||||||
json["cover_size_ratio"] = comic.info.coverSizeRatio.toFloat();
|
json["cover_size_ratio"] = comic.info.coverSizeRatio.toFloat();
|
||||||
json["title"] = comic.info.title.toString();
|
json["title"] = comic.info.title.toString();
|
||||||
json["number"] = comic.info.number.toInt();
|
json["number"] = comic.info.number.toInt(); // 9.13 legacy, kept for compatibility with old clients
|
||||||
|
json["universal_number"] = comic.info.number.toString(); // 9.13, text based number
|
||||||
json["last_time_opened"] = comic.info.lastTimeOpened.toLongLong();
|
json["last_time_opened"] = comic.info.lastTimeOpened.toLongLong();
|
||||||
json["manga"] = comic.info.manga.toBool();
|
auto type = comic.info.type.value<YACReader::FileType>();
|
||||||
|
json["manga"] = type == YACReader::FileType::Manga; // legacy, kept for compatibility with old clients
|
||||||
|
json["file_type"] = comic.info.type.toInt(); // 9.13
|
||||||
|
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
@ -70,6 +81,39 @@ QJsonObject YACReaderServerDataHelper::fullComicToJSON(const qulonglong libraryI
|
|||||||
|
|
||||||
json["synopsis"] = comic.info.synopsis.toString();
|
json["synopsis"] = comic.info.synopsis.toString();
|
||||||
|
|
||||||
|
// 9.13
|
||||||
|
json["count"] = comic.info.count.toInt();
|
||||||
|
json["story_arc"] = comic.info.storyArc.toString();
|
||||||
|
json["arc_number"] = comic.info.arcNumber.toString();
|
||||||
|
json["arc_count"] = comic.info.arcCount.toInt();
|
||||||
|
json["writer"] = comic.info.writer.toString();
|
||||||
|
json["penciller"] = comic.info.penciller.toString();
|
||||||
|
json["inker"] = comic.info.inker.toString();
|
||||||
|
json["colorist"] = comic.info.colorist.toString();
|
||||||
|
json["letterer"] = comic.info.letterer.toString();
|
||||||
|
json["cover_artist"] = comic.info.coverArtist.toString();
|
||||||
|
json["publisher"] = comic.info.publisher.toString();
|
||||||
|
json["format"] = comic.info.format.toString();
|
||||||
|
json["color"] = comic.info.color.toBool();
|
||||||
|
json["age_rating"] = comic.info.ageRating.toString();
|
||||||
|
json["editor"] = comic.info.editor.toString();
|
||||||
|
json["characters"] = comic.info.characters.toString();
|
||||||
|
json["notes"] = comic.info.notes.toString();
|
||||||
|
json["added"] = comic.info.added.toLongLong();
|
||||||
|
json["editor"] = comic.info.editor.toString();
|
||||||
|
json["imprint"] = comic.info.imprint.toString();
|
||||||
|
json["teams"] = comic.info.teams.toString();
|
||||||
|
json["locations"] = comic.info.locations.toString();
|
||||||
|
json["series"] = comic.info.series.toString();
|
||||||
|
json["alternate_series"] = comic.info.alternateSeries.toString();
|
||||||
|
json["alternate_number"] = comic.info.alternateNumber.toString();
|
||||||
|
json["alternate_count"] = comic.info.alternateCount.toInt();
|
||||||
|
json["language_iso"] = comic.info.languageISO.toString();
|
||||||
|
json["series_group"] = comic.info.seriesGroup.toString();
|
||||||
|
json["main_character_or_team"] = comic.info.mainCharacterOrTeam.toString();
|
||||||
|
json["review"] = comic.info.review.toString();
|
||||||
|
json["tags"] = comic.info.tags.toString();
|
||||||
|
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "xml_info_parser.h"
|
#include "xml_info_parser.h"
|
||||||
|
|
||||||
|
#include "yacreader_global.h"
|
||||||
|
|
||||||
#include <QtCore>
|
#include <QtCore>
|
||||||
|
|
||||||
bool isValidText(const QString &string)
|
bool isValidText(const QString &string)
|
||||||
@ -57,7 +59,7 @@ void consolidateDate(ComicInfo &info)
|
|||||||
|
|
||||||
auto year = info.year.isNull() ? 0 : info.year.toInt();
|
auto year = info.year.isNull() ? 0 : info.year.toInt();
|
||||||
auto month = info.month.isNull() ? 1 : info.month.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);
|
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)
|
bool tryValues(QXmlStreamReader &reader, ComicInfo &info)
|
||||||
{
|
{
|
||||||
std::map<QString, QVariant &> stringValues = {
|
std::map<QString, QVariant &> stringValues = {
|
||||||
|
{ "Number", info.number },
|
||||||
{ "Title", info.title },
|
{ "Title", info.title },
|
||||||
{ "Volume", info.volume },
|
{ "Volume", info.volume },
|
||||||
{ "StoryArc", info.storyArc },
|
{ "StoryArc", info.storyArc },
|
||||||
@ -74,16 +77,23 @@ bool tryValues(QXmlStreamReader &reader, ComicInfo &info)
|
|||||||
{ "AgeRating", info.ageRating },
|
{ "AgeRating", info.ageRating },
|
||||||
{ "Summary", info.synopsis },
|
{ "Summary", info.synopsis },
|
||||||
{ "Notes", info.notes },
|
{ "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 = {
|
std::map<QString, QVariant &> forcedNumbers = {
|
||||||
{ "Number", info.number },
|
|
||||||
{ "Count", info.count },
|
{ "Count", info.count },
|
||||||
{ "AlternateNumber", info.arcNumber },
|
{ "AlternateCount", info.alternateCount },
|
||||||
{ "AlternateCount", info.arcCount },
|
|
||||||
{ "Day", info.day },
|
{ "Day", info.day },
|
||||||
{ "Month", info.month },
|
{ "Month", info.month },
|
||||||
{ "Year", info.year }
|
{ "Year", info.year },
|
||||||
};
|
};
|
||||||
|
|
||||||
std::map<QString, QVariant &> multiValuedStrings = {
|
std::map<QString, QVariant &> multiValuedStrings = {
|
||||||
@ -93,7 +103,9 @@ bool tryValues(QXmlStreamReader &reader, ComicInfo &info)
|
|||||||
{ "Colorist", info.colorist },
|
{ "Colorist", info.colorist },
|
||||||
{ "Letterer", info.letterer },
|
{ "Letterer", info.letterer },
|
||||||
{ "CoverArtist", info.coverArtist },
|
{ "CoverArtist", info.coverArtist },
|
||||||
{ "Characters", info.characters }
|
{ "Characters", info.characters },
|
||||||
|
{ "Teams", info.teams },
|
||||||
|
{ "Locations", info.locations }
|
||||||
};
|
};
|
||||||
|
|
||||||
for (auto &pair : stringValues) {
|
for (auto &pair : stringValues) {
|
||||||
@ -130,16 +142,17 @@ bool tryValues(QXmlStreamReader &reader, ComicInfo &info)
|
|||||||
if (reader.name() == QString("Manga")) {
|
if (reader.name() == QString("Manga")) {
|
||||||
auto string = reader.readElementText();
|
auto string = reader.readElementText();
|
||||||
if (isValidText(string)) {
|
if (isValidText(string)) {
|
||||||
if (string == "Yes" || string == "YesAndRightToLeft") {
|
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.manga = true;
|
info.type = QVariant::fromValue(YACReader::FileType::Manga);
|
||||||
} else if (string == "No") {
|
} else if (string == "No") {
|
||||||
info.manga = false;
|
info.type = QVariant::fromValue(YACReader::FileType::Comic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO, check if the url is actually a comic vine link
|
||||||
if (reader.name() == QString("Web")) {
|
if (reader.name() == QString("Web")) {
|
||||||
auto string = reader.readElementText();
|
auto string = reader.readElementText();
|
||||||
if (isValidText(string)) {
|
if (isValidText(string)) {
|
||||||
@ -166,7 +179,7 @@ bool YACReader::parseXMLIntoInfo(const QByteArray &xmlRawData, ComicInfo &info)
|
|||||||
|
|
||||||
while (reader.readNextStartElement()) {
|
while (reader.readNextStartElement()) {
|
||||||
if (tryValues(reader, info)) {
|
if (tryValues(reader, info)) {
|
||||||
someDataWasParsed = true;
|
someDataWasParsed = true | someDataWasParsed;
|
||||||
} else {
|
} else {
|
||||||
if (reader.name() != QString("ComicInfo")) {
|
if (reader.name() != QString("ComicInfo")) {
|
||||||
reader.skipCurrentElement();
|
reader.skipCurrentElement();
|
||||||
|
@ -45,7 +45,7 @@ YACReaderContentViewsManager::YACReaderContentViewsManager(QSettings *settings,
|
|||||||
doComicsViewConnections();
|
doComicsViewConnections();
|
||||||
|
|
||||||
comicsViewStack->addWidget(comicsViewTransition = new ComicsViewTransition());
|
comicsViewStack->addWidget(comicsViewTransition = new ComicsViewTransition());
|
||||||
comicsViewStack->addWidget(folderContentView = new FolderContentView());
|
comicsViewStack->addWidget(folderContentView = new FolderContentView(parent->toogleShowRecentIndicatorAction));
|
||||||
comicsViewStack->addWidget(emptyLabelWidget = new EmptyLabelWidget());
|
comicsViewStack->addWidget(emptyLabelWidget = new EmptyLabelWidget());
|
||||||
comicsViewStack->addWidget(emptySpecialList = new EmptySpecialListWidget());
|
comicsViewStack->addWidget(emptySpecialList = new EmptySpecialListWidget());
|
||||||
comicsViewStack->addWidget(emptyReadingList = new EmptyReadingListWidget());
|
comicsViewStack->addWidget(emptyReadingList = new EmptyReadingListWidget());
|
||||||
|
@ -91,4 +91,26 @@ void YACReaderFoldersViewItemDeletegate::paint(QPainter *painter, const QStyleOp
|
|||||||
}
|
}
|
||||||
|
|
||||||
QStyledItemDelegate::paint(painter, option, index);
|
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 "comic_db.h"
|
||||||
|
|
||||||
|
#include "yacreader_global.h"
|
||||||
|
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
|
|
||||||
@ -118,6 +120,51 @@ QString ComicDB::toTXT()
|
|||||||
if (!info.lastTimeOpened.isNull())
|
if (!info.lastTimeOpened.isNull())
|
||||||
txt.append(QString("lastTimeOpened:%1\r\n").arg(info.lastTimeOpened.toULongLong()));
|
txt.append(QString("lastTimeOpened:%1\r\n").arg(info.lastTimeOpened.toULongLong()));
|
||||||
|
|
||||||
|
if (!info.added.isNull())
|
||||||
|
txt.append(QString("added:%1\r\n").arg(info.added.toULongLong()));
|
||||||
|
|
||||||
|
if (!info.type.isNull())
|
||||||
|
txt.append(QString("type:%1\r\n").arg(info.type.toInt()));
|
||||||
|
|
||||||
|
if (!info.editor.isNull())
|
||||||
|
txt.append(QString("editor:%1\r\n").arg(info.editor.toString()));
|
||||||
|
|
||||||
|
if (!info.imprint.isNull())
|
||||||
|
txt.append(QString("imprint:%1\r\n").arg(info.imprint.toString()));
|
||||||
|
|
||||||
|
if (!info.teams.isNull())
|
||||||
|
txt.append(QString("teams:%1\r\n").arg(info.teams.toString()));
|
||||||
|
|
||||||
|
if (!info.locations.isNull())
|
||||||
|
txt.append(QString("locations:%1\r\n").arg(info.locations.toString()));
|
||||||
|
|
||||||
|
if (!info.series.isNull())
|
||||||
|
txt.append(QString("series:%1\r\n").arg(info.series.toString()));
|
||||||
|
|
||||||
|
if (!info.alternateSeries.isNull())
|
||||||
|
txt.append(QString("alternateSeries:%1\r\n").arg(info.alternateSeries.toString()));
|
||||||
|
|
||||||
|
if (!info.alternateNumber.isNull())
|
||||||
|
txt.append(QString("alternateNumber:%1\r\n").arg(info.alternateNumber.toString()));
|
||||||
|
|
||||||
|
if (!info.alternateCount.isNull())
|
||||||
|
txt.append(QString("alternateCount:%1\r\n").arg(info.alternateCount.toString()));
|
||||||
|
|
||||||
|
if (!info.languageISO.isNull())
|
||||||
|
txt.append(QString("languageISO:%1\r\n").arg(info.languageISO.toString()));
|
||||||
|
|
||||||
|
if (!info.seriesGroup.isNull())
|
||||||
|
txt.append(QString("seriesGroup:%1\r\n").arg(info.seriesGroup.toString()));
|
||||||
|
|
||||||
|
if (!info.mainCharacterOrTeam.isNull())
|
||||||
|
txt.append(QString("mainCharacterOrTeam:%1\r\n").arg(info.mainCharacterOrTeam.toString()));
|
||||||
|
|
||||||
|
if (!info.review.isNull())
|
||||||
|
txt.append(QString("review:%1\r\n").arg(info.review.toString()));
|
||||||
|
|
||||||
|
if (!info.tags.isNull())
|
||||||
|
txt.append(QString("tags:%1\r\n").arg(info.tags.toString()));
|
||||||
|
|
||||||
return txt;
|
return txt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,6 +216,35 @@ QString ComicDB::getTitleIncludingNumber() const
|
|||||||
return getTitleOrFileName();
|
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-------------------------------------------------------------------
|
// COMIC_INFO-------------------------------------------------------------------
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -238,6 +314,22 @@ void ComicInfo::deleteMetadata()
|
|||||||
characters = QVariant();
|
characters = QVariant();
|
||||||
notes = QVariant();
|
notes = QVariant();
|
||||||
|
|
||||||
|
// type = QVariant(); reset or not???
|
||||||
|
editor = QVariant();
|
||||||
|
imprint = QVariant();
|
||||||
|
teams = QVariant();
|
||||||
|
locations = QVariant();
|
||||||
|
series = QVariant();
|
||||||
|
alternateSeries = QVariant();
|
||||||
|
alternateNumber = QVariant();
|
||||||
|
alternateCount = QVariant();
|
||||||
|
languageISO = QVariant();
|
||||||
|
seriesGroup = QVariant();
|
||||||
|
mainCharacterOrTeam = QVariant();
|
||||||
|
review = QVariant();
|
||||||
|
|
||||||
|
// tags = QVariant(); reset or not???
|
||||||
|
|
||||||
comicVineID = QVariant();
|
comicVineID = QVariant();
|
||||||
}
|
}
|
||||||
// the default operator= should work
|
// the default operator= should work
|
||||||
@ -292,135 +384,25 @@ ComicInfo &ComicInfo::operator=(const ComicInfo &comicInfo)
|
|||||||
coverSizeRatio = comicInfo.coverSizeRatio;
|
coverSizeRatio = comicInfo.coverSizeRatio;
|
||||||
originalCoverSize = comicInfo.originalCoverSize;
|
originalCoverSize = comicInfo.originalCoverSize;
|
||||||
|
|
||||||
|
added = comicInfo.added;
|
||||||
|
type = comicInfo.type;
|
||||||
|
editor = comicInfo.editor;
|
||||||
|
imprint = comicInfo.imprint;
|
||||||
|
teams = comicInfo.teams;
|
||||||
|
locations = comicInfo.locations;
|
||||||
|
series = comicInfo.series;
|
||||||
|
alternateSeries = comicInfo.alternateSeries;
|
||||||
|
alternateNumber = comicInfo.alternateNumber;
|
||||||
|
alternateCount = comicInfo.alternateCount;
|
||||||
|
languageISO = comicInfo.languageISO;
|
||||||
|
seriesGroup = comicInfo.seriesGroup;
|
||||||
|
mainCharacterOrTeam = comicInfo.mainCharacterOrTeam;
|
||||||
|
review = comicInfo.review;
|
||||||
|
tags = comicInfo.tags;
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set fields
|
|
||||||
/*
|
|
||||||
void ComicInfo::setTitle(QString value)
|
|
||||||
{
|
|
||||||
setValue(title,value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ComicInfo::setCoverPage(int value)
|
|
||||||
{
|
|
||||||
setValue(coverPage,value);
|
|
||||||
}
|
|
||||||
void ComicInfo::setNumPages(int value)
|
|
||||||
{
|
|
||||||
setValue(numPages,value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ComicInfo::setNumber(int value)
|
|
||||||
{
|
|
||||||
setValue(number,value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ComicInfo::setIsBis(bool value)
|
|
||||||
{
|
|
||||||
setValue(isBis,value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ComicInfo::setCount(int value)
|
|
||||||
{
|
|
||||||
setValue(count,value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ComicInfo::setVolume(QString value)
|
|
||||||
{
|
|
||||||
setValue(volume,value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ComicInfo::setStoryArc(QString value)
|
|
||||||
{
|
|
||||||
setValue(storyArc,value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ComicInfo::setArcNumber(int value)
|
|
||||||
{
|
|
||||||
setValue(arcNumber,value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ComicInfo::setArcCount(int value)
|
|
||||||
{
|
|
||||||
setValue(arcCount,value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ComicInfo::setGenere(QString value)
|
|
||||||
{
|
|
||||||
setValue(genere,value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ComicInfo::setWriter(QString value)
|
|
||||||
{
|
|
||||||
setValue(writer,value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ComicInfo::setPenciller(QString value)
|
|
||||||
{
|
|
||||||
setValue(penciller,value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ComicInfo::setInker(QString value)
|
|
||||||
{
|
|
||||||
setValue(inker,value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ComicInfo::setColorist(QString value)
|
|
||||||
{
|
|
||||||
setValue(colorist,value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ComicInfo::setLetterer(QString value)
|
|
||||||
{
|
|
||||||
setValue(letterer,value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ComicInfo::setCoverArtist(QString value)
|
|
||||||
{
|
|
||||||
setValue(coverArtist,value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ComicInfo::setDate(QString value)
|
|
||||||
{
|
|
||||||
setValue(date,value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ComicInfo::setPublisher(QString value)
|
|
||||||
{
|
|
||||||
setValue(publisher,value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ComicInfo::setFormat(QString value)
|
|
||||||
{
|
|
||||||
setValue(format,value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ComicInfo::setColor(bool value)
|
|
||||||
{
|
|
||||||
setValue(color,value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ComicInfo::setAgeRating(QString value)
|
|
||||||
{
|
|
||||||
setValue(ageRating,value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ComicInfo::setSynopsis(QString value)
|
|
||||||
{
|
|
||||||
setValue(synopsis,value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ComicInfo::setCharacters(QString value)
|
|
||||||
{
|
|
||||||
setValue(characters,value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ComicInfo::setNotes(QString value)
|
|
||||||
{
|
|
||||||
setValue(notes,value);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
QPixmap ComicInfo::getCover(const QString &basePath)
|
QPixmap ComicInfo::getCover(const QString &basePath)
|
||||||
{
|
{
|
||||||
if (cover.isNull()) {
|
if (cover.isNull()) {
|
||||||
@ -485,6 +467,24 @@ QStringList ComicInfo::getCoverArtists()
|
|||||||
return QStringList();
|
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()
|
QStringList ComicInfo::getCharacters()
|
||||||
{
|
{
|
||||||
if (characters.toString().length() > 0) {
|
if (characters.toString().length() > 0) {
|
||||||
@ -494,6 +494,75 @@ QStringList ComicInfo::getCharacters()
|
|||||||
return QStringList();
|
return QStringList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList ComicInfo::getTeams()
|
||||||
|
{
|
||||||
|
if (teams.toString().length() > 0) {
|
||||||
|
return teams.toString().split("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return QStringList();
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList ComicInfo::getLocations()
|
||||||
|
{
|
||||||
|
if (locations.toString().length() > 0) {
|
||||||
|
return locations.toString().split("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return QStringList();
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList ComicInfo::getTags()
|
||||||
|
{
|
||||||
|
if (tags.toString().length() > 0) {
|
||||||
|
return tags.toString().split("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return QStringList();
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
void ComicInfo::setRead(bool r)
|
||||||
{
|
{
|
||||||
if (r != read) {
|
if (r != read) {
|
||||||
@ -599,6 +668,24 @@ QDataStream &operator<<(QDataStream &stream, const ComicInfo &comicInfo)
|
|||||||
stream << comicInfo.coverSizeRatio;
|
stream << comicInfo.coverSizeRatio;
|
||||||
stream << comicInfo.originalCoverSize;
|
stream << comicInfo.originalCoverSize;
|
||||||
|
|
||||||
|
stream << comicInfo.added;
|
||||||
|
stream << comicInfo.type;
|
||||||
|
stream << comicInfo.added;
|
||||||
|
stream << comicInfo.type;
|
||||||
|
stream << comicInfo.editor;
|
||||||
|
stream << comicInfo.imprint;
|
||||||
|
stream << comicInfo.teams;
|
||||||
|
stream << comicInfo.locations;
|
||||||
|
stream << comicInfo.series;
|
||||||
|
stream << comicInfo.alternateSeries;
|
||||||
|
stream << comicInfo.alternateNumber;
|
||||||
|
stream << comicInfo.alternateCount;
|
||||||
|
stream << comicInfo.languageISO;
|
||||||
|
stream << comicInfo.seriesGroup;
|
||||||
|
stream << comicInfo.mainCharacterOrTeam;
|
||||||
|
stream << comicInfo.review;
|
||||||
|
stream << comicInfo.tags;
|
||||||
|
|
||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -661,5 +748,23 @@ QDataStream &operator>>(QDataStream &stream, ComicInfo &comicInfo)
|
|||||||
stream >> comicInfo.coverSizeRatio;
|
stream >> comicInfo.coverSizeRatio;
|
||||||
stream >> comicInfo.originalCoverSize;
|
stream >> comicInfo.originalCoverSize;
|
||||||
|
|
||||||
|
stream >> comicInfo.added;
|
||||||
|
stream >> comicInfo.type;
|
||||||
|
stream >> comicInfo.added;
|
||||||
|
stream >> comicInfo.type;
|
||||||
|
stream >> comicInfo.editor;
|
||||||
|
stream >> comicInfo.imprint;
|
||||||
|
stream >> comicInfo.teams;
|
||||||
|
stream >> comicInfo.locations;
|
||||||
|
stream >> comicInfo.series;
|
||||||
|
stream >> comicInfo.alternateSeries;
|
||||||
|
stream >> comicInfo.alternateNumber;
|
||||||
|
stream >> comicInfo.alternateCount;
|
||||||
|
stream >> comicInfo.languageISO;
|
||||||
|
stream >> comicInfo.seriesGroup;
|
||||||
|
stream >> comicInfo.mainCharacterOrTeam;
|
||||||
|
stream >> comicInfo.review;
|
||||||
|
stream >> comicInfo.tags;
|
||||||
|
|
||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ public:
|
|||||||
QString hash;
|
QString hash;
|
||||||
bool existOnDb;
|
bool existOnDb;
|
||||||
|
|
||||||
int rating;
|
int rating; // TODO_METADATA: change to float
|
||||||
|
|
||||||
bool hasBeenOpened;
|
bool hasBeenOpened;
|
||||||
|
|
||||||
@ -52,13 +52,13 @@ public:
|
|||||||
QVariant coverPage; // int
|
QVariant coverPage; // int
|
||||||
QVariant numPages; // int
|
QVariant numPages; // int
|
||||||
|
|
||||||
QVariant number; // int
|
QVariant number; // string (changed in 9.13 from int)
|
||||||
QVariant isBis; // bool
|
QVariant isBis; // bool
|
||||||
QVariant count; // int
|
QVariant count; // int
|
||||||
|
|
||||||
QVariant volume; // string
|
QVariant volume; // string
|
||||||
QVariant storyArc; // string
|
QVariant storyArc; // string
|
||||||
QVariant arcNumber; // int
|
QVariant arcNumber; // string (changed in 9.13 from int)
|
||||||
QVariant arcCount; // int
|
QVariant arcCount; // int
|
||||||
|
|
||||||
QVariant genere; // string
|
QVariant genere; // string
|
||||||
@ -80,7 +80,7 @@ public:
|
|||||||
QVariant format; // string
|
QVariant format; // string
|
||||||
QVariant color; // bool
|
QVariant color; // bool
|
||||||
QVariant ageRating; // string
|
QVariant ageRating; // string
|
||||||
QVariant manga; // bool
|
[[deprecated("use type instead")]] QVariant manga; // bool
|
||||||
|
|
||||||
QVariant synopsis; // string
|
QVariant synopsis; // string
|
||||||
QVariant characters; // string
|
QVariant characters; // string
|
||||||
@ -94,38 +94,21 @@ public:
|
|||||||
QVariant coverSizeRatio; // h/w
|
QVariant coverSizeRatio; // h/w
|
||||||
QVariant originalCoverSize; // string "WxH"
|
QVariant originalCoverSize; // string "WxH"
|
||||||
|
|
||||||
/*void setTitle(QVariant value);
|
QVariant added; // integer/date
|
||||||
|
QVariant type; // enum
|
||||||
void setCoverPage(QVariant value);
|
QVariant editor; // string
|
||||||
void setNumPages(QVariant value);
|
QVariant imprint; // string
|
||||||
|
QVariant teams; // string/list
|
||||||
void setNumber(QVariant value);
|
QVariant locations; // string/list
|
||||||
void setIsBis(QVariant value);
|
QVariant series; // string
|
||||||
void setCount(QVariant value);
|
QVariant alternateSeries; // string
|
||||||
|
QVariant alternateNumber; // string
|
||||||
void setVolume(QVariant value);
|
QVariant alternateCount; // int
|
||||||
void setStoryArc(QVariant value);
|
QVariant languageISO; // string
|
||||||
void setArcNumber(QVariant value);
|
QVariant seriesGroup; // string
|
||||||
void setArcCount(QVariant value);
|
QVariant mainCharacterOrTeam; // string
|
||||||
|
QVariant review; // string
|
||||||
void setGenere(QVariant value);
|
QVariant tags; // string/list
|
||||||
|
|
||||||
void setWriter(QVariant value);
|
|
||||||
void setPenciller(QVariant value);
|
|
||||||
void setInker(QVariant value);
|
|
||||||
void setColorist(QVariant value);
|
|
||||||
void setLetterer(QVariant value);
|
|
||||||
void setCoverArtist(QVariant value);
|
|
||||||
|
|
||||||
void setDate(QVariant value);
|
|
||||||
void setPublisher(QVariant value);
|
|
||||||
void setFormat(QVariant value);
|
|
||||||
void setColor(QVariant value);
|
|
||||||
void setAgeRating(QVariant value);
|
|
||||||
|
|
||||||
void setSynopsis(QVariant value);
|
|
||||||
void setCharacters(QVariant value);
|
|
||||||
void setNotes(QVariant value);*/
|
|
||||||
|
|
||||||
QPixmap getCover(const QString &basePath);
|
QPixmap getCover(const QString &basePath);
|
||||||
|
|
||||||
@ -135,9 +118,21 @@ public:
|
|||||||
Q_INVOKABLE QStringList getColorists();
|
Q_INVOKABLE QStringList getColorists();
|
||||||
Q_INVOKABLE QStringList getLetterers();
|
Q_INVOKABLE QStringList getLetterers();
|
||||||
Q_INVOKABLE QStringList getCoverArtists();
|
Q_INVOKABLE QStringList getCoverArtists();
|
||||||
|
Q_INVOKABLE QStringList getEditors();
|
||||||
|
Q_INVOKABLE QStringList getImprint();
|
||||||
|
|
||||||
Q_INVOKABLE QStringList getCharacters();
|
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, const ComicInfo &comicInfo);
|
||||||
|
|
||||||
friend QDataStream &operator>>(QDataStream &stream, ComicInfo &comicInfo);
|
friend QDataStream &operator>>(QDataStream &stream, ComicInfo &comicInfo);
|
||||||
@ -206,11 +201,27 @@ public:
|
|||||||
Q_PROPERTY(QVariant coverSizeRatio MEMBER coverSizeRatio CONSTANT)
|
Q_PROPERTY(QVariant coverSizeRatio MEMBER coverSizeRatio CONSTANT)
|
||||||
Q_PROPERTY(QVariant originalCoverSize MEMBER originalCoverSize CONSTANT)
|
Q_PROPERTY(QVariant originalCoverSize MEMBER originalCoverSize CONSTANT)
|
||||||
|
|
||||||
|
Q_PROPERTY(QVariant added MEMBER added CONSTANT)
|
||||||
|
Q_PROPERTY(QVariant type MEMBER type CONSTANT)
|
||||||
|
Q_PROPERTY(QVariant editor MEMBER editor CONSTANT)
|
||||||
|
Q_PROPERTY(QVariant imprint MEMBER imprint CONSTANT)
|
||||||
|
Q_PROPERTY(QVariant teams MEMBER teams CONSTANT)
|
||||||
|
Q_PROPERTY(QVariant locations MEMBER locations CONSTANT)
|
||||||
|
Q_PROPERTY(QVariant series MEMBER series CONSTANT)
|
||||||
|
Q_PROPERTY(QVariant alternateSeries MEMBER alternateSeries CONSTANT)
|
||||||
|
Q_PROPERTY(QVariant alternateNumber MEMBER alternateNumber CONSTANT)
|
||||||
|
Q_PROPERTY(QVariant alternateCount MEMBER alternateCount CONSTANT)
|
||||||
|
Q_PROPERTY(QVariant languageISO MEMBER languageISO CONSTANT)
|
||||||
|
Q_PROPERTY(QVariant seriesGroup MEMBER seriesGroup CONSTANT)
|
||||||
|
Q_PROPERTY(QVariant mainCharacterOrTeam MEMBER mainCharacterOrTeam CONSTANT)
|
||||||
|
Q_PROPERTY(QVariant review MEMBER review CONSTANT)
|
||||||
|
Q_PROPERTY(QVariant tags MEMBER tags CONSTANT)
|
||||||
|
|
||||||
//-new properties, not loaded from the DB automatically
|
//-new properties, not loaded from the DB automatically
|
||||||
bool isFavorite;
|
bool isFavorite;
|
||||||
Q_PROPERTY(bool isFavorite MEMBER isFavorite WRITE setFavorite NOTIFY favoriteChanged)
|
Q_PROPERTY(bool isFavorite MEMBER isFavorite WRITE setFavorite NOTIFY favoriteChanged)
|
||||||
|
|
||||||
// setters, used in QML only by now
|
// setters, used in QML only for now
|
||||||
void setRead(bool r);
|
void setRead(bool r);
|
||||||
void setRating(int r);
|
void setRating(int r);
|
||||||
void setFavorite(bool f);
|
void setFavorite(bool f);
|
||||||
@ -248,6 +259,7 @@ public:
|
|||||||
Q_INVOKABLE qulonglong getFileSize() const;
|
Q_INVOKABLE qulonglong getFileSize() const;
|
||||||
|
|
||||||
Q_INVOKABLE QString getTitleIncludingNumber() const;
|
Q_INVOKABLE QString getTitleIncludingNumber() const;
|
||||||
|
Q_INVOKABLE QString getInfoTitle() const;
|
||||||
|
|
||||||
QString toTXT();
|
QString toTXT();
|
||||||
|
|
||||||
|
@ -20,7 +20,19 @@ Folder::Folder(qulonglong folderId, qulonglong parentId, const QString &folderNa
|
|||||||
this->path = folderPath;
|
this->path = folderPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
Folder::Folder(qulonglong folderId, qulonglong parentId, const QString &folderName, const QString &folderPath, bool completed, bool finished, bool manga)
|
Folder::Folder(qulonglong folderId,
|
||||||
|
qulonglong parentId,
|
||||||
|
const QString &folderName,
|
||||||
|
const QString &folderPath,
|
||||||
|
bool completed,
|
||||||
|
bool finished,
|
||||||
|
bool manga,
|
||||||
|
int numChildren,
|
||||||
|
const QString &firstChildHash,
|
||||||
|
const QString &customImage,
|
||||||
|
YACReader::FileType type,
|
||||||
|
qint64 added,
|
||||||
|
qint64 updated)
|
||||||
: knownParent(true),
|
: knownParent(true),
|
||||||
knownId(true),
|
knownId(true),
|
||||||
numChildren(-1)
|
numChildren(-1)
|
||||||
@ -32,6 +44,12 @@ Folder::Folder(qulonglong folderId, qulonglong parentId, const QString &folderNa
|
|||||||
this->completed = completed;
|
this->completed = completed;
|
||||||
this->finished = finished;
|
this->finished = finished;
|
||||||
this->manga = manga;
|
this->manga = manga;
|
||||||
|
this->numChildren = numChildren;
|
||||||
|
this->firstChildHash = firstChildHash;
|
||||||
|
this->customImage = customImage;
|
||||||
|
this->type = type;
|
||||||
|
this->added = added;
|
||||||
|
this->updated = updated;
|
||||||
}
|
}
|
||||||
|
|
||||||
Folder::Folder(const Folder &folder)
|
Folder::Folder(const Folder &folder)
|
||||||
@ -51,6 +69,9 @@ Folder &Folder::operator=(const Folder &other)
|
|||||||
this->numChildren = other.numChildren;
|
this->numChildren = other.numChildren;
|
||||||
this->firstChildHash = other.firstChildHash;
|
this->firstChildHash = other.firstChildHash;
|
||||||
this->customImage = other.customImage;
|
this->customImage = other.customImage;
|
||||||
|
this->type = other.type;
|
||||||
|
this->added = other.added;
|
||||||
|
this->updated = other.updated;
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define __FOLDER_H
|
#define __FOLDER_H
|
||||||
|
|
||||||
#include "library_item.h"
|
#include "library_item.h"
|
||||||
|
#include "yacreader_global.h"
|
||||||
|
|
||||||
#include <QList>
|
#include <QList>
|
||||||
|
|
||||||
@ -11,9 +12,33 @@ public:
|
|||||||
bool knownParent;
|
bool knownParent;
|
||||||
bool knownId;
|
bool knownId;
|
||||||
|
|
||||||
|
bool finished; // finished means read, the user has read all the content in this folder
|
||||||
|
bool completed; // completed means the folder has all the content, e.g. a series got its final issue and the user has collected all of them
|
||||||
|
[[deprecated("use type instead")]] bool manga;
|
||||||
|
|
||||||
|
qint32 numChildren; //-1 for unknown number of children
|
||||||
|
QString firstChildHash; // empty for unknown first child
|
||||||
|
QString customImage; // empty for none custom image
|
||||||
|
|
||||||
|
YACReader::FileType type;
|
||||||
|
qint64 added; // epoch in seconds
|
||||||
|
qint64 updated; // epoch in seconds
|
||||||
|
|
||||||
Folder();
|
Folder();
|
||||||
Folder(qulonglong folderId, qulonglong parentId, const QString &folderName, const QString &folderPath);
|
Folder(qulonglong folderId, qulonglong parentId, const QString &folderName, const QString &folderPath);
|
||||||
Folder(qulonglong folderId, qulonglong parentId, const QString &folderName, const QString &folderPath, bool completed, bool finished, bool manga);
|
Folder(qulonglong folderId,
|
||||||
|
qulonglong parentId,
|
||||||
|
const QString &folderName,
|
||||||
|
const QString &folderPath,
|
||||||
|
bool completed,
|
||||||
|
bool finished,
|
||||||
|
bool manga,
|
||||||
|
int numChildren,
|
||||||
|
const QString &firstChildHash,
|
||||||
|
const QString &customImage,
|
||||||
|
YACReader::FileType type,
|
||||||
|
qint64 added,
|
||||||
|
qint64 updated);
|
||||||
Folder(const QString &folderName, const QString &folderPath);
|
Folder(const QString &folderName, const QString &folderPath);
|
||||||
Folder(const Folder &folder);
|
Folder(const Folder &folder);
|
||||||
Folder &operator=(const Folder &other);
|
Folder &operator=(const Folder &other);
|
||||||
@ -33,75 +58,6 @@ public:
|
|||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool isFinished() const
|
|
||||||
{
|
|
||||||
return finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool isCompleted() const
|
|
||||||
{
|
|
||||||
return completed;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool isManga() const
|
|
||||||
{
|
|
||||||
return manga;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void setFinished(bool b)
|
|
||||||
{
|
|
||||||
finished = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void setCompleted(bool b)
|
|
||||||
{
|
|
||||||
completed = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void setManga(bool b)
|
|
||||||
{
|
|
||||||
manga = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline qint32 getNumChildren() const
|
|
||||||
{
|
|
||||||
return numChildren;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void setNumChildren(const qint32 v)
|
|
||||||
{
|
|
||||||
numChildren = v;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline QString getFirstChildHash() const
|
|
||||||
{
|
|
||||||
return firstChildHash;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void setFirstChildHash(const QString &v)
|
|
||||||
{
|
|
||||||
firstChildHash = v;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline QString getCustomImage() const
|
|
||||||
{
|
|
||||||
return customImage;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void setCustomImage(const QString &s)
|
|
||||||
{
|
|
||||||
customImage = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool finished; // finished means read, the user has read all the content in this folder
|
|
||||||
bool completed; // completed means the folder has all the content, e.g. a series got its final issue and the user has collected all of them
|
|
||||||
bool manga;
|
|
||||||
|
|
||||||
qint32 numChildren; //-1 for unknown number of children
|
|
||||||
QString firstChildHash; // empty for unknown first child
|
|
||||||
QString customImage; // empty for none custom image
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -7,6 +7,7 @@ int naturalCompare(const QString &s1, const QString &s2, Qt::CaseSensitivity cas
|
|||||||
QCollator c;
|
QCollator c;
|
||||||
c.setCaseSensitivity(caseSensitivity);
|
c.setCaseSensitivity(caseSensitivity);
|
||||||
c.setNumericMode(true);
|
c.setNumericMode(true);
|
||||||
|
c.setIgnorePunctuation(false);
|
||||||
return c.compare(s1, s2);
|
return c.compare(s1, s2);
|
||||||
}
|
}
|
||||||
bool naturalSortLessThanCS(const QString &left, const QString &right)
|
bool naturalSortLessThanCS(const QString &left, const QString &right)
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
#include <QMetaType>
|
#include <QMetaType>
|
||||||
#include <QAbstractItemModel>
|
#include <QAbstractItemModel>
|
||||||
|
|
||||||
#define VERSION "9.12.0"
|
#define VERSION "9.13.0"
|
||||||
|
|
||||||
#define IMPORT_COMIC_INFO_XML_METADATA "IMPORT_COMIC_INFO_XML_METADATA"
|
#define IMPORT_COMIC_INFO_XML_METADATA "IMPORT_COMIC_INFO_XML_METADATA"
|
||||||
|
|
||||||
@ -51,6 +51,14 @@ enum LabelColors {
|
|||||||
YDark
|
YDark
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class FileType : int {
|
||||||
|
Comic = 0,
|
||||||
|
Manga,
|
||||||
|
WesternManga,
|
||||||
|
WebComic, // continuous vertical reading
|
||||||
|
Yonkoma, // 4Koma
|
||||||
|
};
|
||||||
|
|
||||||
struct OpenComicSource {
|
struct OpenComicSource {
|
||||||
enum Source {
|
enum Source {
|
||||||
Folder = 0,
|
Folder = 0,
|
||||||
@ -76,5 +84,6 @@ void iterate(const QModelIndex &index,
|
|||||||
|
|
||||||
Q_DECLARE_METATYPE(YACReader::OpenComicSource::Source)
|
Q_DECLARE_METATYPE(YACReader::OpenComicSource::Source)
|
||||||
Q_DECLARE_METATYPE(YACReader::OpenComicSource)
|
Q_DECLARE_METATYPE(YACReader::OpenComicSource)
|
||||||
|
Q_DECLARE_METATYPE(YACReader::FileType)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -71,6 +71,8 @@
|
|||||||
#define BLUR_RADIUS_BACKGROUND_IMAGE_IN_GRID_VIEW "BLUR_RADIUS_BACKGROUND_IMAGE_IN_GRID_VIEW"
|
#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 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_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 {
|
namespace YACReader {
|
||||||
|
|
||||||
|
@ -46,19 +46,16 @@ YACReader::WhatsNewDialog::WhatsNewDialog(QWidget *parent)
|
|||||||
"color:#858585;");
|
"color:#858585;");
|
||||||
|
|
||||||
auto text = new QLabel();
|
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/>"
|
"<br/>"
|
||||||
"<span style=\"font-weight:600\">YACReaderLibrary</span><br/>"
|
"<span style=\"font-weight:600\">YACReaderLibrary</span><br/>"
|
||||||
" • Fix scroll in grid views when using Qt6 builds.<br/>"
|
" • Avoid showing stale information in the server config dialog by updating the connection information when the dialog is opened.<br/>"
|
||||||
" • Fix deleting metadata from comics, it also deleted the number of pages info.<br/>"
|
" • Add new metadata support, it improves compatibility with ComicInfo.xml.<br/>"
|
||||||
" • Do not accept empty values for the server port in the server settings dialog.<br/>"
|
" • Add support for showing a 'recently added/updated' indicator.<br/>"
|
||||||
" • New way of generating QR codes.<br/>"
|
" • Improved comic metadata dialog.<br/>"
|
||||||
"<br/>"
|
" • Add textual tags support that can be queried through the search engine.<br/>"
|
||||||
"<span style=\"font-weight:600\">YACReaderLibraryServer</span><br/>"
|
" • Make '=' in the search engine work as ':' does.<br/>"
|
||||||
" • Print scannable QR code at server start.<br/>"
|
" • Add new operators to the search engine: exact match ==, <, >, <=, >=.<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/>"
|
|
||||||
"<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> "
|
"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. "
|
"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_NON_READ_ACTION_YL "SET_AS_NON_READ_ACTION_YL"
|
||||||
#define SET_AS_MANGA_ACTION_YL "SET_AS_MANGA_ACTION_YL"
|
#define SET_AS_MANGA_ACTION_YL "SET_AS_MANGA_ACTION_YL"
|
||||||
#define SET_AS_NORMAL_ACTION_YL "SET_AS_MANGA_ACTION_YL"
|
#define SET_AS_NORMAL_ACTION_YL "SET_AS_MANGA_ACTION_YL"
|
||||||
|
#define SET_AS_WESTERN_MANGA_ACTION_YL "SET_AS_WESTERN_MANGA_ACTION_YL"
|
||||||
|
#define SET_AS_WEB_COMIC_ACTION_YL "SET_AS_WEB_COMIC_ACTION_YL"
|
||||||
|
#define SET_AS_YONKOMA_ACTION_YL "SET_AS_YONKOMA_ACTION_YL"
|
||||||
#define SHOW_HIDE_MARKS_ACTION_YL "SHOW_HIDE_MARKS_ACTION_YL"
|
#define SHOW_HIDE_MARKS_ACTION_YL "SHOW_HIDE_MARKS_ACTION_YL"
|
||||||
#define TOGGLE_FULL_SCREEN_ACTION_YL "TOGGLE_FULL_SCREEN_ACTION_YL"
|
#define TOGGLE_FULL_SCREEN_ACTION_YL "TOGGLE_FULL_SCREEN_ACTION_YL"
|
||||||
#define HELP_ABOUT_ACTION_YL "HELP_ABOUT_ACTION_YL"
|
#define HELP_ABOUT_ACTION_YL "HELP_ABOUT_ACTION_YL"
|
||||||
@ -66,7 +69,10 @@ public:
|
|||||||
#define SET_FOLDER_AS_READ_ACTION_YL "SET_FOLDER_AS_READ_ACTION_YL"
|
#define SET_FOLDER_AS_READ_ACTION_YL "SET_FOLDER_AS_READ_ACTION_YL"
|
||||||
#define SET_FOLDER_AS_UNREAD_ACTION_YL "SET_FOLDER_AS_UNREAD_ACTION_YL"
|
#define SET_FOLDER_AS_UNREAD_ACTION_YL "SET_FOLDER_AS_UNREAD_ACTION_YL"
|
||||||
#define SET_FOLDER_AS_MANGA_ACTION_YL "SET_FOLDER_AS_MANGA_ACTION_YL"
|
#define SET_FOLDER_AS_MANGA_ACTION_YL "SET_FOLDER_AS_MANGA_ACTION_YL"
|
||||||
|
#define SET_FOLDER_AS_WESTERN_MANGA_ACTION_YL "SET_FOLDER_AS_WESTERN_MANGA_ACTION_YL"
|
||||||
#define SET_FOLDER_AS_NORMAL_ACTION_YL "SET_FOLDER_AS_NORMAL_ACTION_YL"
|
#define SET_FOLDER_AS_NORMAL_ACTION_YL "SET_FOLDER_AS_NORMAL_ACTION_YL"
|
||||||
|
#define SET_FOLDER_AS_WEB_COMIC_ACTION_YL "SET_FOLDER_AS_WEB_COMIC_ACTION_YL"
|
||||||
|
#define SET_FOLDER_AS_YONKOMA_ACTION_YL "SET_FOLDER_AS_YONKOMA_ACTION_YL"
|
||||||
#define OPEN_CONTAINING_FOLDER_COMIC_ACTION_YL "OPEN_CONTAINING_FOLDER_COMIC_ACTION_YL"
|
#define OPEN_CONTAINING_FOLDER_COMIC_ACTION_YL "OPEN_CONTAINING_FOLDER_COMIC_ACTION_YL"
|
||||||
#define RESET_COMIC_RATING_ACTION_YL "RESET_COMIC_RATING_ACTION_YL"
|
#define RESET_COMIC_RATING_ACTION_YL "RESET_COMIC_RATING_ACTION_YL"
|
||||||
#define SELECT_ALL_COMICS_ACTION_YL "SELECT_ALL_COMICS_ACTION_YL"
|
#define SELECT_ALL_COMICS_ACTION_YL "SELECT_ALL_COMICS_ACTION_YL"
|
||||||
@ -91,6 +97,7 @@ public:
|
|||||||
#define RENAME_LIST_ACTION_YL "RENAME_LIST_ACTION_YL"
|
#define RENAME_LIST_ACTION_YL "RENAME_LIST_ACTION_YL"
|
||||||
#define ADD_TO_FAVORITES_ACTION_YL "ADD_TO_FAVORITES_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 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
|
// COMMANDS YACReaderLibrary
|
||||||
|
|
||||||
// ACTION NAMES YACReader
|
// ACTION NAMES YACReader
|
||||||
|
Loading…
Reference in New Issue
Block a user