mirror of
https://github.com/YACReader/yacreader
synced 2025-06-04 01:28:55 -04:00
Merge pull request #475 from YACReader/custom_comic_covers
This commit is contained in:
commit
a4ab11d44d
@ -16,7 +16,11 @@ Version counting is based on semantic versioning (Major.Feature.Patch)
|
|||||||
* New setting in Comic Vine scraper to force exact volume matches.
|
* New setting in Comic Vine scraper to force exact volume matches.
|
||||||
* Better default search query in the Comic Vine scraper.
|
* Better default search query in the Comic Vine scraper.
|
||||||
* Improved navigation in Comic Vine scraper, including keeping the current query around to make edits and refined searches easier.
|
* Improved navigation in Comic Vine scraper, including keeping the current query around to make edits and refined searches easier.
|
||||||
* Add support for adding custom covers for folders using the context menu.
|
* Add support for custom covers for any folder using the context menu.
|
||||||
|
* The edit cover buttons now support looping through pages, going forward from the last returns to the first, and going backward from the first jumps to the last.
|
||||||
|
* Add support for custom covers for comics using the edit metadata dialog, you can use a pick file button or drag&drop an image into the cover view in the dialog.
|
||||||
|
* Covers can be set in bulk for various comics at once.
|
||||||
|
* New button to reset to the default cover of a comic.
|
||||||
|
|
||||||
### YACReaderLibraryServer
|
### YACReaderLibraryServer
|
||||||
* Log libraries validation when the app starts.
|
* Log libraries validation when the app starts.
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
<file>../images/flow4.png</file>
|
<file>../images/flow4.png</file>
|
||||||
<file>../images/flow5.png</file>
|
<file>../images/flow5.png</file>
|
||||||
<file>../images/glowLine.png</file>
|
<file>../images/glowLine.png</file>
|
||||||
|
<file>../images/loadCustomCover.svg</file>
|
||||||
<file>../images/hiddenCovers.png</file>
|
<file>../images/hiddenCovers.png</file>
|
||||||
<file>../images/icon-new.svg</file>
|
<file>../images/icon-new.svg</file>
|
||||||
<file>../images/iconLibrary.png</file>
|
<file>../images/iconLibrary.png</file>
|
||||||
@ -70,6 +71,7 @@
|
|||||||
<file>../images/previousCoverPage.png</file>
|
<file>../images/previousCoverPage.png</file>
|
||||||
<file>../images/readingRibbon.png</file>
|
<file>../images/readingRibbon.png</file>
|
||||||
<file>../images/readRibbon.png</file>
|
<file>../images/readRibbon.png</file>
|
||||||
|
<file>../images/resetCover.svg</file>
|
||||||
<file>../images/searching_icon.png</file>
|
<file>../images/searching_icon.png</file>
|
||||||
<file>../images/serverConfigBackground.png</file>
|
<file>../images/serverConfigBackground.png</file>
|
||||||
<file>../images/shortcuts_group_comics.svg</file>
|
<file>../images/shortcuts_group_comics.svg</file>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "library_window.h"
|
#include "library_window.h"
|
||||||
|
|
||||||
#include "yacreader_global.h"
|
#include "yacreader_global.h"
|
||||||
|
#include "yacreader_global_gui.h"
|
||||||
|
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QSplitter>
|
#include <QSplitter>
|
||||||
@ -2313,12 +2314,7 @@ void LibraryWindow::setFolderCover()
|
|||||||
|
|
||||||
void LibraryWindow::setCustomFolderCover(Folder folder)
|
void LibraryWindow::setCustomFolderCover(Folder folder)
|
||||||
{
|
{
|
||||||
QString supportedImageFormatsString;
|
auto customCoverPath = YACReader::imageFileLoader(this);
|
||||||
for (const QByteArray &format : QImageReader::supportedImageFormats()) {
|
|
||||||
supportedImageFormatsString += QString("*.%1 ").arg(QString(format));
|
|
||||||
}
|
|
||||||
|
|
||||||
QString customCoverPath = QFileDialog::getOpenFileName(this, tr("Select custom cover"), QDir::homePath(), tr("Images (%1)").arg(supportedImageFormatsString));
|
|
||||||
if (!customCoverPath.isEmpty()) {
|
if (!customCoverPath.isEmpty()) {
|
||||||
QImage cover(customCoverPath);
|
QImage cover(customCoverPath);
|
||||||
if (cover.isNull()) {
|
if (cover.isNull()) {
|
||||||
|
@ -1,10 +1,14 @@
|
|||||||
#include "properties_dialog.h"
|
#include "properties_dialog.h"
|
||||||
|
|
||||||
|
#include "yacreader_global_gui.h"
|
||||||
|
|
||||||
|
#include "cover_utils.h"
|
||||||
#include "data_base_management.h"
|
#include "data_base_management.h"
|
||||||
#include "initial_comic_info_extractor.h"
|
#include "initial_comic_info_extractor.h"
|
||||||
#include "yacreader_field_edit.h"
|
#include "yacreader_field_edit.h"
|
||||||
#include "yacreader_field_plain_text_edit.h"
|
#include "yacreader_field_plain_text_edit.h"
|
||||||
#include "db_helper.h"
|
#include "db_helper.h"
|
||||||
|
#include "yacreader_cover_label.h"
|
||||||
|
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
@ -36,7 +40,8 @@ PropertiesDialog::PropertiesDialog(QWidget *parent)
|
|||||||
createTabBar();
|
createTabBar();
|
||||||
auto rootLayout = new QGridLayout;
|
auto rootLayout = new QGridLayout;
|
||||||
|
|
||||||
cover = new QLabel();
|
cover = new YACReader::CoverLabel();
|
||||||
|
connect(cover, &YACReader::CoverLabel::imageDropped, this, &PropertiesDialog::loadCustomCoverImageFromPath);
|
||||||
|
|
||||||
mainLayout = new QGridLayout;
|
mainLayout = new QGridLayout;
|
||||||
mainLayout->addWidget(tabBar, 0, 0);
|
mainLayout->addWidget(tabBar, 0, 0);
|
||||||
@ -102,11 +107,23 @@ void PropertiesDialog::createCoverBox()
|
|||||||
|
|
||||||
showPreviousCoverPageButton = new QToolButton();
|
showPreviousCoverPageButton = new QToolButton();
|
||||||
showPreviousCoverPageButton->setIcon(QIcon(":/images/previousCoverPage.png"));
|
showPreviousCoverPageButton->setIcon(QIcon(":/images/previousCoverPage.png"));
|
||||||
|
showPreviousCoverPageButton->setToolTip(tr("Load previous page as cover"));
|
||||||
showPreviousCoverPageButton->setStyleSheet("QToolButton {border:none;}");
|
showPreviousCoverPageButton->setStyleSheet("QToolButton {border:none;}");
|
||||||
showNextCoverPageButton = new QToolButton();
|
showNextCoverPageButton = new QToolButton();
|
||||||
showNextCoverPageButton->setIcon(QIcon(":/images/nextCoverPage.png"));
|
showNextCoverPageButton->setIcon(QIcon(":/images/nextCoverPage.png"));
|
||||||
|
showNextCoverPageButton->setToolTip(tr("Load next page as cover"));
|
||||||
showNextCoverPageButton->setStyleSheet("QToolButton {border:none;}");
|
showNextCoverPageButton->setStyleSheet("QToolButton {border:none;}");
|
||||||
|
|
||||||
|
resetCoverButton = new QToolButton();
|
||||||
|
resetCoverButton->setIcon(QIcon(":/images/resetCover.svg"));
|
||||||
|
resetCoverButton->setToolTip(tr("Reset cover to the default image"));
|
||||||
|
resetCoverButton->setStyleSheet("QToolButton {border:none;}");
|
||||||
|
|
||||||
|
loadCustomCoverImageButton = new QToolButton();
|
||||||
|
loadCustomCoverImageButton->setIcon(QIcon(":/images/loadCustomCover.svg"));
|
||||||
|
loadCustomCoverImageButton->setToolTip(tr("Load custom cover image"));
|
||||||
|
loadCustomCoverImageButton->setStyleSheet("QToolButton {border:none;}");
|
||||||
|
|
||||||
coverPageNumberLabel = new QLabel("-");
|
coverPageNumberLabel = new QLabel("-");
|
||||||
|
|
||||||
coverPageNumberLabel->setStyleSheet("QLabel {color: white; font-weight:bold; font-size:14px;}");
|
coverPageNumberLabel->setStyleSheet("QLabel {color: white; font-weight:bold; font-size:14px;}");
|
||||||
@ -116,6 +133,10 @@ void PropertiesDialog::createCoverBox()
|
|||||||
layout->addWidget(coverPageNumberLabel, 0, Qt::AlignVCenter);
|
layout->addWidget(coverPageNumberLabel, 0, Qt::AlignVCenter);
|
||||||
layout->addSpacing(5);
|
layout->addSpacing(5);
|
||||||
layout->addWidget(showNextCoverPageButton, 0, Qt::AlignVCenter);
|
layout->addWidget(showNextCoverPageButton, 0, Qt::AlignVCenter);
|
||||||
|
layout->addSpacing(5);
|
||||||
|
layout->addWidget(resetCoverButton, 0, Qt::AlignVCenter);
|
||||||
|
layout->addSpacing(5);
|
||||||
|
layout->addWidget(loadCustomCoverImageButton, 0, Qt::AlignVCenter);
|
||||||
|
|
||||||
coverPageEdit->setStyleSheet("QLineEdit {border:none;}");
|
coverPageEdit->setStyleSheet("QLineEdit {border:none;}");
|
||||||
layout->setSpacing(0);
|
layout->setSpacing(0);
|
||||||
@ -132,6 +153,8 @@ void PropertiesDialog::createCoverBox()
|
|||||||
|
|
||||||
connect(showPreviousCoverPageButton, &QAbstractButton::clicked, this, &PropertiesDialog::loadPreviousCover);
|
connect(showPreviousCoverPageButton, &QAbstractButton::clicked, this, &PropertiesDialog::loadPreviousCover);
|
||||||
connect(showNextCoverPageButton, &QAbstractButton::clicked, this, &PropertiesDialog::loadNextCover);
|
connect(showNextCoverPageButton, &QAbstractButton::clicked, this, &PropertiesDialog::loadNextCover);
|
||||||
|
connect(resetCoverButton, &QAbstractButton::clicked, this, &PropertiesDialog::resetCover);
|
||||||
|
connect(loadCustomCoverImageButton, &QAbstractButton::clicked, this, &PropertiesDialog::loadCustomCoverImage);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertiesDialog::createGeneralInfoBox()
|
void PropertiesDialog::createGeneralInfoBox()
|
||||||
@ -434,6 +457,8 @@ QImage blurred(const QImage &image, const QRect &rect, int radius, bool alphaOnl
|
|||||||
|
|
||||||
void PropertiesDialog::loadComic(ComicDB &comic)
|
void PropertiesDialog::loadComic(ComicDB &comic)
|
||||||
{
|
{
|
||||||
|
customCover = QImage();
|
||||||
|
|
||||||
if (!comic.info.series.isNull())
|
if (!comic.info.series.isNull())
|
||||||
series->setText(comic.info.series.toString());
|
series->setText(comic.info.series.toString());
|
||||||
if (!comic.info.title.isNull())
|
if (!comic.info.title.isNull())
|
||||||
@ -456,22 +481,17 @@ void PropertiesDialog::loadComic(ComicDB &comic)
|
|||||||
showPreviousCoverPageButton->setEnabled(true);
|
showPreviousCoverPageButton->setEnabled(true);
|
||||||
showNextCoverPageButton->setEnabled(true);
|
showNextCoverPageButton->setEnabled(true);
|
||||||
|
|
||||||
if (coverPage == 1)
|
|
||||||
showPreviousCoverPageButton->setDisabled(true);
|
|
||||||
if (coverPage == comic.info.numPages.toInt())
|
|
||||||
showNextCoverPageButton->setDisabled(true);
|
|
||||||
|
|
||||||
coverChanged = false;
|
coverChanged = false;
|
||||||
coverBox->show();
|
updateCoverBoxForSingleComic();
|
||||||
|
|
||||||
if (!QFileInfo(basePath + comic.path).exists()) {
|
if (!QFileInfo(basePath + comic.path).exists()) {
|
||||||
QMessageBox::warning(this, tr("Not found"), tr("Comic not found. You should update your library."));
|
QMessageBox::warning(this, tr("Not found"), tr("Comic not found. You should update your library."));
|
||||||
showPreviousCoverPageButton->setDisabled(true);
|
showPreviousCoverPageButton->setDisabled(true);
|
||||||
showNextCoverPageButton->setDisabled(true);
|
showNextCoverPageButton->setDisabled(true);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
coverPageNumberLabel->setText("1");
|
||||||
}
|
}
|
||||||
/*if(comic.info.numPages != NULL)
|
|
||||||
numPagesEdit->setText(QString::number(*comic.info.numPages));*/
|
|
||||||
|
|
||||||
if (!comic.info.number.isNull())
|
if (!comic.info.number.isNull())
|
||||||
numberEdit->setText(comic.info.number.toString());
|
numberEdit->setText(comic.info.number.toString());
|
||||||
@ -581,9 +601,13 @@ void PropertiesDialog::updateButtons()
|
|||||||
|
|
||||||
void PropertiesDialog::setComics(QList<ComicDB> comics)
|
void PropertiesDialog::setComics(QList<ComicDB> comics)
|
||||||
{
|
{
|
||||||
updated = false;
|
|
||||||
sequentialEditing = false;
|
sequentialEditing = false;
|
||||||
|
|
||||||
|
updated = false;
|
||||||
|
currentComicIndex = 0;
|
||||||
|
coverChanged = false;
|
||||||
|
customCover = QImage();
|
||||||
|
|
||||||
this->comics = comics;
|
this->comics = comics;
|
||||||
|
|
||||||
ComicDB comic = comics[0];
|
ComicDB comic = comics[0];
|
||||||
@ -593,7 +617,7 @@ void PropertiesDialog::setComics(QList<ComicDB> comics)
|
|||||||
updateButtons();
|
updateButtons();
|
||||||
|
|
||||||
if (comics.length() > 1) {
|
if (comics.length() > 1) {
|
||||||
coverBox->hide();
|
updateCoverBoxForMultipleComics();
|
||||||
|
|
||||||
setDisableUniqueValues(true);
|
setDisableUniqueValues(true);
|
||||||
this->setWindowTitle(tr("Edit selected comics information"));
|
this->setWindowTitle(tr("Edit selected comics information"));
|
||||||
@ -700,9 +724,12 @@ void PropertiesDialog::setComics(QList<ComicDB> comics)
|
|||||||
|
|
||||||
void PropertiesDialog::setComicsForSequentialEditing(int currentComicIndex, QList<ComicDB> comics)
|
void PropertiesDialog::setComicsForSequentialEditing(int currentComicIndex, QList<ComicDB> comics)
|
||||||
{
|
{
|
||||||
updated = false;
|
|
||||||
sequentialEditing = true;
|
sequentialEditing = true;
|
||||||
|
|
||||||
|
updated = false;
|
||||||
|
coverChanged = false;
|
||||||
|
customCover = QImage();
|
||||||
|
|
||||||
this->comics = comics;
|
this->comics = comics;
|
||||||
this->currentComicIndex = currentComicIndex;
|
this->currentComicIndex = currentComicIndex;
|
||||||
|
|
||||||
@ -726,6 +753,40 @@ void PropertiesDialog::updateComics()
|
|||||||
DBHelper::update(&(itr->info), db);
|
DBHelper::update(&(itr->info), db);
|
||||||
updated = true;
|
updated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!sequentialEditing && coverChanged) {
|
||||||
|
auto coverPath = LibraryPaths::coverPath(basePath, itr->info.hash);
|
||||||
|
|
||||||
|
if (customCover.isNull()) { // reseted, we need to restore the default cover
|
||||||
|
itr->info.coverPage = QVariant();
|
||||||
|
|
||||||
|
InitialComicInfoExtractor ie(basePath + itr->path, coverPath, 1);
|
||||||
|
ie.extract();
|
||||||
|
|
||||||
|
if (ie.getOriginalCoverSize().second > 0) {
|
||||||
|
itr->info.originalCoverSize = QString("%1x%2").arg(ie.getOriginalCoverSize().first).arg(ie.getOriginalCoverSize().second);
|
||||||
|
itr->info.coverSizeRatio = static_cast<float>(ie.getOriginalCoverSize().first) / ie.getOriginalCoverSize().second;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit coverChangedSignal(*itr);
|
||||||
|
|
||||||
|
DBHelper::update(&(itr->info), db);
|
||||||
|
updated = true;
|
||||||
|
} else {
|
||||||
|
itr->info.coverPage = QVariant();
|
||||||
|
YACReader::saveCover(coverPath, customCover);
|
||||||
|
|
||||||
|
auto width = customCover.width();
|
||||||
|
auto height = customCover.height();
|
||||||
|
itr->info.originalCoverSize = QString("%1x%2").arg(width).arg(height);
|
||||||
|
itr->info.coverSizeRatio = static_cast<float>(width) / height;
|
||||||
|
|
||||||
|
DBHelper::update(&(itr->info), db);
|
||||||
|
updated = true;
|
||||||
|
|
||||||
|
emit coverChangedSignal(*itr);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
db.commit();
|
db.commit();
|
||||||
connectionName = db.connectionName();
|
connectionName = db.connectionName();
|
||||||
@ -739,14 +800,14 @@ void PropertiesDialog::setMultipleCover()
|
|||||||
QPixmap last = lastComic.info.getCover(basePath);
|
QPixmap last = lastComic.info.getCover(basePath);
|
||||||
last = last.scaledToHeight(575, Qt::SmoothTransformation);
|
last = last.scaledToHeight(575, Qt::SmoothTransformation);
|
||||||
|
|
||||||
coverImage = QPixmap::fromImage(blurred(last.toImage(), QRect(0, 0, last.width(), last.height()), 15));
|
auto coverImage = QPixmap::fromImage(blurred(last.toImage(), QRect(0, 0, last.width(), last.height()), 15));
|
||||||
|
|
||||||
cover->setPixmap(coverImage);
|
cover->setPixmap(coverImage);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertiesDialog::setCover(const QPixmap &coverI)
|
void PropertiesDialog::setCover(const QPixmap &coverI)
|
||||||
{
|
{
|
||||||
coverImage = coverI.scaledToHeight(575, Qt::SmoothTransformation);
|
auto coverImage = coverI.scaledToHeight(575, Qt::SmoothTransformation);
|
||||||
|
|
||||||
cover->setPixmap(coverImage);
|
cover->setPixmap(coverImage);
|
||||||
}
|
}
|
||||||
@ -755,13 +816,14 @@ void PropertiesDialog::setFilename(const QString &nameString)
|
|||||||
{
|
{
|
||||||
title->setText(nameString);
|
title->setText(nameString);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertiesDialog::setNumpages(int pagesNum)
|
void PropertiesDialog::setNumpages(int pagesNum)
|
||||||
{
|
{
|
||||||
numPagesEdit->setText(QString::number(pagesNum));
|
numPagesEdit->setText(QString::number(pagesNum));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertiesDialog::setSize(float sizeFloat)
|
void PropertiesDialog::setSize(float sizeFloat)
|
||||||
{
|
{
|
||||||
|
|
||||||
size->setText(QString::number(sizeFloat, 'f', 2) + " MB");
|
size->setText(QString::number(sizeFloat, 'f', 2) + " MB");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -787,7 +849,11 @@ void PropertiesDialog::save()
|
|||||||
|
|
||||||
if (sequentialEditing)
|
if (sequentialEditing)
|
||||||
if (coverChanged) {
|
if (coverChanged) {
|
||||||
itr->info.coverPage = coverPageNumberLabel->text().toInt();
|
if (customCover.isNull()) {
|
||||||
|
itr->info.coverPage = coverPageNumberLabel->text().toInt();
|
||||||
|
} else {
|
||||||
|
itr->info.coverPage = QVariant();
|
||||||
|
}
|
||||||
edited = true;
|
edited = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -955,15 +1021,31 @@ void PropertiesDialog::save()
|
|||||||
if (sequentialEditing) {
|
if (sequentialEditing) {
|
||||||
if (coverChanged) {
|
if (coverChanged) {
|
||||||
auto coverPath = LibraryPaths::coverPath(basePath, comics[currentComicIndex].info.hash);
|
auto coverPath = LibraryPaths::coverPath(basePath, comics[currentComicIndex].info.hash);
|
||||||
InitialComicInfoExtractor ie(basePath + comics[currentComicIndex].path, coverPath, comics[currentComicIndex].info.coverPage.toInt());
|
|
||||||
ie.extract();
|
|
||||||
|
|
||||||
if (ie.getOriginalCoverSize().second > 0) {
|
if (customCover.isNull()) {
|
||||||
comics[currentComicIndex].info.originalCoverSize = QString("%1x%2").arg(ie.getOriginalCoverSize().first).arg(ie.getOriginalCoverSize().second);
|
InitialComicInfoExtractor ie(basePath + comics[currentComicIndex].path, coverPath, comics[currentComicIndex].info.coverPage.toInt());
|
||||||
comics[currentComicIndex].info.coverSizeRatio = static_cast<float>(ie.getOriginalCoverSize().first) / ie.getOriginalCoverSize().second;
|
ie.extract();
|
||||||
|
|
||||||
|
if (ie.getOriginalCoverSize().second > 0) {
|
||||||
|
comics[currentComicIndex].info.originalCoverSize = QString("%1x%2").arg(ie.getOriginalCoverSize().first).arg(ie.getOriginalCoverSize().second);
|
||||||
|
comics[currentComicIndex].info.coverSizeRatio = static_cast<float>(ie.getOriginalCoverSize().first) / ie.getOriginalCoverSize().second;
|
||||||
|
}
|
||||||
|
|
||||||
|
comics[currentComicIndex].info.edited = true;
|
||||||
|
|
||||||
|
emit coverChangedSignal(comics[currentComicIndex]);
|
||||||
|
} else {
|
||||||
|
auto width = customCover.width();
|
||||||
|
auto height = customCover.height();
|
||||||
|
|
||||||
|
comics[currentComicIndex].info.originalCoverSize = QString("%1x%2").arg(width).arg(height);
|
||||||
|
comics[currentComicIndex].info.coverSizeRatio = static_cast<float>(width) / height;
|
||||||
|
|
||||||
|
comics[currentComicIndex].info.edited = true;
|
||||||
|
|
||||||
|
YACReader::saveCover(coverPath, customCover);
|
||||||
|
emit coverChangedSignal(comics[currentComicIndex]);
|
||||||
}
|
}
|
||||||
|
|
||||||
emit coverChangedSignal(comics[currentComicIndex]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1093,48 +1175,87 @@ void PropertiesDialog::updateCoverPageNumberLabel(int n)
|
|||||||
void PropertiesDialog::loadNextCover()
|
void PropertiesDialog::loadNextCover()
|
||||||
{
|
{
|
||||||
int current = coverPageNumberLabel->text().toInt();
|
int current = coverPageNumberLabel->text().toInt();
|
||||||
if (current < comics[currentComicIndex].info.numPages.toInt()) {
|
int next;
|
||||||
updateCoverPageNumberLabel(current + 1);
|
|
||||||
|
|
||||||
InitialComicInfoExtractor ie(basePath + comics[currentComicIndex].path, "", current + 1);
|
if (current == comics[currentComicIndex].info.numPages.toInt())
|
||||||
ie.extract();
|
next = 1;
|
||||||
setCover(ie.getCover());
|
else
|
||||||
repaint();
|
next = current + 1;
|
||||||
|
|
||||||
if ((current + 1) == comics[currentComicIndex].info.numPages.toInt()) {
|
setCoverPage(next);
|
||||||
showNextCoverPageButton->setDisabled(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
showPreviousCoverPageButton->setEnabled(true);
|
coverChanged = next != comics[currentComicIndex].info.coverPage;
|
||||||
if (current + 1 != comics[currentComicIndex].info.coverPage)
|
|
||||||
coverChanged = true;
|
|
||||||
else
|
|
||||||
coverChanged = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertiesDialog::loadPreviousCover()
|
void PropertiesDialog::loadPreviousCover()
|
||||||
{
|
{
|
||||||
int current = coverPageNumberLabel->text().toInt();
|
int current = coverPageNumberLabel->text().toInt();
|
||||||
if (current != 1) {
|
int previous;
|
||||||
updateCoverPageNumberLabel(current - 1);
|
|
||||||
InitialComicInfoExtractor ie(basePath + comics[currentComicIndex].path, "", current - 1);
|
if (current == 1)
|
||||||
|
previous = comics[currentComicIndex].info.numPages.toInt();
|
||||||
|
else
|
||||||
|
previous = current - 1;
|
||||||
|
|
||||||
|
setCoverPage(previous);
|
||||||
|
|
||||||
|
coverChanged = previous != comics[currentComicIndex].info.coverPage.toInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PropertiesDialog::resetCover()
|
||||||
|
{
|
||||||
|
if (sequentialEditing) {
|
||||||
|
setCoverPage(1);
|
||||||
|
coverChanged = true; // it could be that the cover is a custom cover, so we need to always update it
|
||||||
|
} else {
|
||||||
|
InitialComicInfoExtractor ie(basePath + comics.last().path, "", 1);
|
||||||
ie.extract();
|
ie.extract();
|
||||||
setCover(ie.getCover());
|
auto cover = ie.getCover();
|
||||||
repaint();
|
cover = cover.scaledToHeight(575, Qt::SmoothTransformation);
|
||||||
|
|
||||||
if ((current - 1) == 1) {
|
auto coverImage = QPixmap::fromImage(blurred(cover.toImage(), QRect(0, 0, cover.width(), cover.height()), 15));
|
||||||
showPreviousCoverPageButton->setDisabled(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
showNextCoverPageButton->setEnabled(true);
|
this->cover->setPixmap(coverImage);
|
||||||
if (current - 1 != comics[currentComicIndex].info.coverPage.toInt())
|
|
||||||
coverChanged = true;
|
customCover = QImage();
|
||||||
else
|
coverChanged = true;
|
||||||
coverChanged = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PropertiesDialog::loadCustomCoverImage()
|
||||||
|
{
|
||||||
|
auto path = YACReader::imageFileLoader(this);
|
||||||
|
loadCustomCoverImageFromPath(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PropertiesDialog::loadCustomCoverImageFromPath(const QString &path)
|
||||||
|
{
|
||||||
|
if (path.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
customCover = QImage(path);
|
||||||
|
coverChanged = true;
|
||||||
|
|
||||||
|
if (customCover.isNull()) {
|
||||||
|
QMessageBox::warning(this, tr("Invalid cover"), tr("The image is invalid."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setCover(QPixmap::fromImage(customCover));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PropertiesDialog::setCoverPage(int pageNumber)
|
||||||
|
{
|
||||||
|
customCover = QImage();
|
||||||
|
|
||||||
|
updateCoverPageNumberLabel(pageNumber);
|
||||||
|
InitialComicInfoExtractor ie(basePath + comics[currentComicIndex].path, "", pageNumber);
|
||||||
|
ie.extract();
|
||||||
|
setCover(ie.getCover());
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
|
||||||
bool PropertiesDialog::close()
|
bool PropertiesDialog::close()
|
||||||
{
|
{
|
||||||
if (updated) {
|
if (updated) {
|
||||||
@ -1143,3 +1264,17 @@ bool PropertiesDialog::close()
|
|||||||
|
|
||||||
return QDialog::close();
|
return QDialog::close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PropertiesDialog::updateCoverBoxForMultipleComics()
|
||||||
|
{
|
||||||
|
showPreviousCoverPageButton->hide();
|
||||||
|
showNextCoverPageButton->hide();
|
||||||
|
coverPageNumberLabel->hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PropertiesDialog::updateCoverBoxForSingleComic()
|
||||||
|
{
|
||||||
|
showPreviousCoverPageButton->show();
|
||||||
|
showNextCoverPageButton->show();
|
||||||
|
coverPageNumberLabel->show();
|
||||||
|
}
|
||||||
|
@ -19,6 +19,10 @@ class QComboBox;
|
|||||||
// class YACReaderBusyWidget;
|
// class YACReaderBusyWidget;
|
||||||
class QToolButton;
|
class QToolButton;
|
||||||
|
|
||||||
|
namespace YACReader {
|
||||||
|
class CoverLabel;
|
||||||
|
}
|
||||||
|
|
||||||
#include "comic_db.h"
|
#include "comic_db.h"
|
||||||
|
|
||||||
class PropertiesDialog : public QDialog
|
class PropertiesDialog : public QDialog
|
||||||
@ -33,7 +37,7 @@ private:
|
|||||||
QTabWidget *tabBar;
|
QTabWidget *tabBar;
|
||||||
|
|
||||||
QWidget *coverBox;
|
QWidget *coverBox;
|
||||||
QLabel *cover;
|
YACReader::CoverLabel *cover;
|
||||||
QScrollArea *sa;
|
QScrollArea *sa;
|
||||||
|
|
||||||
QWidget *generalInfoBox;
|
QWidget *generalInfoBox;
|
||||||
@ -113,12 +117,13 @@ private:
|
|||||||
QPushButton *previousButton;
|
QPushButton *previousButton;
|
||||||
QPushButton *restoreButton; //??
|
QPushButton *restoreButton; //??
|
||||||
|
|
||||||
QPixmap coverImage;
|
|
||||||
|
|
||||||
QToolButton *showPreviousCoverPageButton;
|
QToolButton *showPreviousCoverPageButton;
|
||||||
QToolButton *showNextCoverPageButton;
|
QToolButton *showNextCoverPageButton;
|
||||||
QLabel *coverPageNumberLabel;
|
QLabel *coverPageNumberLabel;
|
||||||
|
|
||||||
|
QToolButton *resetCoverButton;
|
||||||
|
QToolButton *loadCustomCoverImageButton;
|
||||||
|
|
||||||
void createTabBar();
|
void createTabBar();
|
||||||
void createCoverBox();
|
void createCoverBox();
|
||||||
void createGeneralInfoBox();
|
void createGeneralInfoBox();
|
||||||
@ -144,6 +149,8 @@ private:
|
|||||||
bool updated;
|
bool updated;
|
||||||
QString originalCoverSize;
|
QString originalCoverSize;
|
||||||
|
|
||||||
|
QImage customCover;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PropertiesDialog(QWidget *parent = nullptr);
|
PropertiesDialog(QWidget *parent = nullptr);
|
||||||
QString databasePath;
|
QString databasePath;
|
||||||
@ -170,7 +177,13 @@ public slots:
|
|||||||
void setSize(float size);
|
void setSize(float size);
|
||||||
void loadNextCover();
|
void loadNextCover();
|
||||||
void loadPreviousCover();
|
void loadPreviousCover();
|
||||||
|
void resetCover();
|
||||||
|
void loadCustomCoverImage();
|
||||||
|
void loadCustomCoverImageFromPath(const QString &path);
|
||||||
|
void setCoverPage(int pageNumber);
|
||||||
bool close();
|
bool close();
|
||||||
|
void updateCoverBoxForMultipleComics();
|
||||||
|
void updateCoverBoxForSingleComic();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void coverChangedSignal(const ComicDB &comic);
|
void coverChangedSignal(const ComicDB &comic);
|
||||||
|
@ -404,12 +404,7 @@ ComicInfo &ComicInfo::operator=(const ComicInfo &comicInfo)
|
|||||||
|
|
||||||
QPixmap ComicInfo::getCover(const QString &basePath)
|
QPixmap ComicInfo::getCover(const QString &basePath)
|
||||||
{
|
{
|
||||||
if (cover.isNull()) {
|
return QPixmap(YACReader::LibraryPaths::coverPath(basePath, hash));
|
||||||
cover.load(YACReader::LibraryPaths::coverPath(basePath, hash));
|
|
||||||
}
|
|
||||||
QPixmap c;
|
|
||||||
c.convertFromImage(cover);
|
|
||||||
return c;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList ComicInfo::getWriters()
|
QStringList ComicInfo::getWriters()
|
||||||
|
@ -84,8 +84,6 @@ public:
|
|||||||
|
|
||||||
QVariant comicVineID; // string
|
QVariant comicVineID; // string
|
||||||
|
|
||||||
QImage cover;
|
|
||||||
|
|
||||||
QVariant lastTimeOpened; // integer/date
|
QVariant lastTimeOpened; // integer/date
|
||||||
QVariant coverSizeRatio; // h/w
|
QVariant coverSizeRatio; // h/w
|
||||||
QVariant originalCoverSize; // string "WxH"
|
QVariant originalCoverSize; // string "WxH"
|
||||||
@ -189,8 +187,6 @@ public:
|
|||||||
|
|
||||||
Q_PROPERTY(QVariant comicVineID MEMBER comicVineID CONSTANT)
|
Q_PROPERTY(QVariant comicVineID MEMBER comicVineID CONSTANT)
|
||||||
|
|
||||||
Q_PROPERTY(QImage cover MEMBER cover CONSTANT)
|
|
||||||
|
|
||||||
Q_PROPERTY(QVariant lastTimeOpened MEMBER lastTimeOpened CONSTANT)
|
Q_PROPERTY(QVariant lastTimeOpened MEMBER lastTimeOpened CONSTANT)
|
||||||
|
|
||||||
Q_PROPERTY(QVariant coverSizeRatio MEMBER coverSizeRatio CONSTANT)
|
Q_PROPERTY(QVariant coverSizeRatio MEMBER coverSizeRatio CONSTANT)
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include <QtCore>
|
#include <QtCore>
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
|
#include <QImageReader>
|
||||||
|
#include <QFileDialog>
|
||||||
|
|
||||||
using namespace YACReader;
|
using namespace YACReader;
|
||||||
|
|
||||||
@ -99,3 +101,47 @@ QPixmap YACReader::hdpiPixmap(const QString &file, QSize size)
|
|||||||
{
|
{
|
||||||
return QIcon(file).pixmap(size);
|
return QIcon(file).pixmap(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString YACReader::imageFileLoader(QWidget *parent)
|
||||||
|
{
|
||||||
|
QString supportedImageFormatsString;
|
||||||
|
for (const QByteArray &format : QImageReader::supportedImageFormats()) {
|
||||||
|
supportedImageFormatsString += QString("*.%1 ").arg(QString(format));
|
||||||
|
}
|
||||||
|
|
||||||
|
return QFileDialog::getOpenFileName(parent, QObject::tr("Select custom cover"), QDir::homePath(), QObject::tr("Images (%1)").arg(supportedImageFormatsString));
|
||||||
|
}
|
||||||
|
|
||||||
|
QString YACReader::imagePathFromMimeData(const QMimeData *mimeData)
|
||||||
|
{
|
||||||
|
QString filePath;
|
||||||
|
|
||||||
|
if (mimeData->hasUrls()) {
|
||||||
|
QList<QUrl> urlList = mimeData->urls();
|
||||||
|
|
||||||
|
if (!urlList.isEmpty()) {
|
||||||
|
QUrl url = urlList.first();
|
||||||
|
if (url.isLocalFile()) {
|
||||||
|
filePath = url.toLocalFile();
|
||||||
|
|
||||||
|
QFileInfo fileInfo(filePath);
|
||||||
|
QString extension = fileInfo.suffix().toLower();
|
||||||
|
QList<QByteArray> supportedFormats = QImageReader::supportedImageFormats();
|
||||||
|
bool isSupported = false;
|
||||||
|
|
||||||
|
for (const QByteArray &format : supportedFormats) {
|
||||||
|
if (extension == QString(format).toLower()) {
|
||||||
|
isSupported = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isSupported) {
|
||||||
|
filePath.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return filePath;
|
||||||
|
}
|
||||||
|
@ -112,6 +112,7 @@ QString addExtensionToIconPath(const QString &path);
|
|||||||
QString addExtensionToIconPathInToolbar(const QString &path);
|
QString addExtensionToIconPathInToolbar(const QString &path);
|
||||||
QAction *actionWithCustomIcon(const QIcon &icon, QAction *action);
|
QAction *actionWithCustomIcon(const QIcon &icon, QAction *action);
|
||||||
QPixmap hdpiPixmap(const QString &file, QSize size);
|
QPixmap hdpiPixmap(const QString &file, QSize size);
|
||||||
|
QString imageFileLoader(QWidget *parent);
|
||||||
|
QString imagePathFromMimeData(const QMimeData *mimeData);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -21,7 +21,8 @@ HEADERS += \
|
|||||||
$$PWD/yacreader_library_list_widget.h \
|
$$PWD/yacreader_library_list_widget.h \
|
||||||
$$PWD/yacreader_library_item_widget.h \
|
$$PWD/yacreader_library_item_widget.h \
|
||||||
$$PWD/yacreader_treeview.h \
|
$$PWD/yacreader_treeview.h \
|
||||||
$$PWD/yacreader_busy_widget.h
|
$$PWD/yacreader_busy_widget.h \
|
||||||
|
$$PWD/yacreader_cover_label.h
|
||||||
!CONFIG(no_opengl){
|
!CONFIG(no_opengl){
|
||||||
HEADERS += $$PWD/yacreader_gl_flow_config_widget.h
|
HEADERS += $$PWD/yacreader_gl_flow_config_widget.h
|
||||||
}
|
}
|
||||||
@ -50,8 +51,8 @@ SOURCES += \
|
|||||||
$$PWD/yacreader_library_list_widget.cpp \
|
$$PWD/yacreader_library_list_widget.cpp \
|
||||||
$$PWD/yacreader_library_item_widget.cpp \
|
$$PWD/yacreader_library_item_widget.cpp \
|
||||||
$$PWD/yacreader_treeview.cpp \
|
$$PWD/yacreader_treeview.cpp \
|
||||||
$$PWD/yacreader_busy_widget.cpp
|
$$PWD/yacreader_busy_widget.cpp \
|
||||||
|
$$PWD/yacreader_cover_label.cpp
|
||||||
!CONFIG(no_opengl){
|
!CONFIG(no_opengl){
|
||||||
SOURCES += $$PWD/yacreader_gl_flow_config_widget.cpp
|
SOURCES += $$PWD/yacreader_gl_flow_config_widget.cpp
|
||||||
}
|
}
|
||||||
|
31
custom_widgets/yacreader_cover_label.cpp
Normal file
31
custom_widgets/yacreader_cover_label.cpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#include "yacreader_cover_label.h"
|
||||||
|
#include "yacreader_global_gui.h"
|
||||||
|
|
||||||
|
YACReader::CoverLabel::CoverLabel(QWidget *parent)
|
||||||
|
: QLabel(parent)
|
||||||
|
{
|
||||||
|
setAcceptDrops(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void YACReader::CoverLabel::dragEnterEvent(QDragEnterEvent *event)
|
||||||
|
{
|
||||||
|
if (event->mimeData()->hasUrls() && !YACReader::imagePathFromMimeData(event->mimeData()).isEmpty()) {
|
||||||
|
event->acceptProposedAction();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void YACReader::CoverLabel::dragMoveEvent(QDragMoveEvent *event)
|
||||||
|
{
|
||||||
|
if (event->mimeData()->hasUrls()) {
|
||||||
|
event->acceptProposedAction();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void YACReader::CoverLabel::dropEvent(QDropEvent *event)
|
||||||
|
{
|
||||||
|
QString path = YACReader::imagePathFromMimeData(event->mimeData());
|
||||||
|
if (!path.isEmpty()) {
|
||||||
|
emit imageDropped(path);
|
||||||
|
event->acceptProposedAction();
|
||||||
|
}
|
||||||
|
}
|
29
custom_widgets/yacreader_cover_label.h
Normal file
29
custom_widgets/yacreader_cover_label.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#ifndef DROP_LABEL_H
|
||||||
|
#define DROP_LABEL_H
|
||||||
|
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QDragEnterEvent>
|
||||||
|
#include <QDropEvent>
|
||||||
|
#include <QMimeData>
|
||||||
|
|
||||||
|
namespace YACReader {
|
||||||
|
|
||||||
|
class CoverLabel : public QLabel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit CoverLabel(QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void dragEnterEvent(QDragEnterEvent *event) override;
|
||||||
|
void dragMoveEvent(QDragMoveEvent *event) override;
|
||||||
|
void dropEvent(QDropEvent *event) override;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void imageDropped(const QString &path);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // DROP_LABEL_H
|
11
images/loadCustomCover.svg
Normal file
11
images/loadCustomCover.svg
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg id="Layer_2" data-name="Layer 2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 8">
|
||||||
|
<defs>
|
||||||
|
<style>
|
||||||
|
.cls-1 {
|
||||||
|
fill: #fff;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</defs>
|
||||||
|
<polygon class="cls-1" points="4 3 4 2 2 2 2 3 2 6 6 6 6 3 4 3"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 292 B |
15
images/resetCover.svg
Normal file
15
images/resetCover.svg
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg id="Layer_2" data-name="Layer 2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 8">
|
||||||
|
<defs>
|
||||||
|
<style>
|
||||||
|
.cls-1 {
|
||||||
|
fill: none;
|
||||||
|
stroke: #fff;
|
||||||
|
stroke-miterlimit: 10;
|
||||||
|
stroke-width: 1.5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</defs>
|
||||||
|
<line class="cls-1" x1="2.35" y1="2.29" x2="5.65" y2="5.71"/>
|
||||||
|
<line class="cls-1" x1="5.65" y1="2.29" x2="2.35" y2="5.71"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 434 B |
Loading…
x
Reference in New Issue
Block a user