diff --git a/YACReaderLibrary/YACReaderLibrary.pro b/YACReaderLibrary/YACReaderLibrary.pro index 6e77aca7..ab7c8eef 100644 --- a/YACReaderLibrary/YACReaderLibrary.pro +++ b/YACReaderLibrary/YACReaderLibrary.pro @@ -83,6 +83,7 @@ HEADERS += comic_flow.h \ db/comic_query_result_processor.h \ db/folder_query_result_processor.h \ db/query_lexer.h \ + folder_content_view.h \ initial_comic_info_extractor.h \ library_comic_opener.h \ library_creator.h \ @@ -165,6 +166,7 @@ SOURCES += comic_flow.cpp \ db/comic_query_result_processor.cpp \ db/folder_query_result_processor.cpp \ db/query_lexer.cpp \ + folder_content_view.cpp \ initial_comic_info_extractor.cpp \ library_comic_opener.cpp \ library_creator.cpp \ diff --git a/YACReaderLibrary/folder_content_view.cpp b/YACReaderLibrary/folder_content_view.cpp new file mode 100644 index 00000000..78c9a3b4 --- /dev/null +++ b/YACReaderLibrary/folder_content_view.cpp @@ -0,0 +1,271 @@ +#include "folder_content_view.h" + +#include "folder_model.h" +#include "grid_comics_view.h" +#include "yacreader_global_gui.h" +#include "yacreader_tool_bar_stretch.h" + +#include "QsLog.h" + +#include +#include +#include + +using namespace YACReader; + +FolderContentView::FolderContentView(QWidget *parent) + : QWidget { parent }, parent(QModelIndex()), comicModel(new ComicModel()), folderModel(new FolderModel()) +{ + qmlRegisterType("com.yacreader.FolderModel", 1, 0, "FolderModel"); + + settings = new QSettings(YACReader::getSettingsPath() + "/YACReaderLibrary.ini", QSettings::IniFormat, this); + settings->beginGroup("libraryConfig"); + + view = new QQuickWidget(); + + // QQuickWidget requires rendering into OpenGL framebuffer objects +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + view->quickWindow()->setGraphicsApi(QSGRendererInterface::OpenGL); +#endif + + view->setResizeMode(QQuickWidget::SizeRootObjectToView); + connect( + view, &QQuickWidget::statusChanged, + [=](QQuickWidget::Status status) { + if (status == QQuickWidget::Error) { + QLOG_ERROR() << view->errors(); + } + }); + + coverSizeSliderWidget = new QWidget(this); + coverSizeSliderWidget->setFixedWidth(200); + coverSizeSlider = new QSlider(coverSizeSliderWidget); + coverSizeSlider->setOrientation(Qt::Horizontal); + coverSizeSlider->setRange(YACREADER_MIN_GRID_ZOOM_WIDTH, YACREADER_MAX_GRID_ZOOM_WIDTH); + + auto horizontalLayout = new QHBoxLayout(); + QLabel *smallLabel = new QLabel(); + smallLabel->setPixmap(QPixmap(":/images/comics_view_toolbar/small_size_grid_zoom.png")); + horizontalLayout->addWidget(smallLabel); + horizontalLayout->addWidget(coverSizeSlider, 0, Qt::AlignVCenter); + QLabel *bigLabel = new QLabel(); + bigLabel->setPixmap(QPixmap(":/images/comics_view_toolbar/big_size_grid_zoom.png")); + horizontalLayout->addWidget(bigLabel); + horizontalLayout->addSpacing(10); + horizontalLayout->setContentsMargins(0, 0, 0, 0); + + coverSizeSliderWidget->setLayout(horizontalLayout); + + connect(coverSizeSlider, &QAbstractSlider::valueChanged, this, &FolderContentView::setCoversSize); + + toolbar = new QToolBar(); + toolbar->addWidget(new YACReaderToolBarStretch); + toolbar->addWidget(coverSizeSliderWidget); + + auto l = new QVBoxLayout; + setContentsMargins(0, 0, 0, 0); + l->setContentsMargins(0, 0, 0, 0); + l->setSpacing(0); + l->addWidget(view); + l->addWidget(toolbar); + this->setLayout(l); + + QQmlContext *ctxt = view->rootContext(); + + LibraryUITheme theme; +#ifdef Q_OS_MAC + theme = Light; +#else + theme = Dark; +#endif + + if (theme == Light) { + ctxt->setContextProperty("continueReadingBackgroundColor", "#DDDDDD"); + ctxt->setContextProperty("continueReadingColor", "#000000"); + + ctxt->setContextProperty("backgroundColor", "#F6F6F6"); + ctxt->setContextProperty("cellColor", "#FFFFFF"); + ctxt->setContextProperty("selectedColor", "#FFFFFF"); + ctxt->setContextProperty("selectedBorderColor", "#007AFF"); + ctxt->setContextProperty("borderColor", "#DBDBDB"); + ctxt->setContextProperty("titleColor", "#121212"); + ctxt->setContextProperty("textColor", "#636363"); + // fonts settings + ctxt->setContextProperty("fontSize", 11); + ctxt->setContextProperty("fontFamily", QApplication::font().family()); + ctxt->setContextProperty("fontSpacing", 0.5); + + // info - copy/pasted from info_comics_view TODO create helpers for setting the UI config + ctxt->setContextProperty("infoBackgroundColor", "#FFFFFF"); + ctxt->setContextProperty("topShadow", QUrl()); + ctxt->setContextProperty("infoShadow", "info-shadow-light.png"); + ctxt->setContextProperty("infoIndicator", "info-indicator-light.png"); + + ctxt->setContextProperty("infoTextColor", "#404040"); + ctxt->setContextProperty("infoTitleColor", "#2E2E2E"); + + ctxt->setContextProperty("ratingUnselectedColor", "#DEDEDE"); + ctxt->setContextProperty("ratingSelectedColor", "#2B2B2B"); + + ctxt->setContextProperty("favUncheckedColor", "#DEDEDE"); + ctxt->setContextProperty("favCheckedColor", "#E84852"); + + ctxt->setContextProperty("readTickUncheckedColor", "#DEDEDE"); + ctxt->setContextProperty("readTickCheckedColor", "#E84852"); + } else { + ctxt->setContextProperty("continueReadingBackgroundColor", "#88000000"); + ctxt->setContextProperty("continueReadingColor", "#FFFFFF"); + + ctxt->setContextProperty("backgroundColor", "#2A2A2A"); + ctxt->setContextProperty("cellColor", "#212121"); + ctxt->setContextProperty("selectedColor", "#121212"); + ctxt->setContextProperty("selectedBorderColor", "#121212"); + ctxt->setContextProperty("borderColor", "#121212"); + ctxt->setContextProperty("titleColor", "#FFFFFF"); + ctxt->setContextProperty("textColor", "#A8A8A8"); + ctxt->setContextProperty("dropShadow", QVariant(false)); + // fonts settings + int fontSize = QApplication::font().pointSize(); + if (fontSize == -1) + fontSize = QApplication::font().pixelSize(); + ctxt->setContextProperty("fontSize", fontSize); + ctxt->setContextProperty("fontFamily", QApplication::font().family()); + ctxt->setContextProperty("fontSpacing", 0.5); + + // info - copy/pasted from info_comics_view TODO create helpers for setting the UI config + ctxt->setContextProperty("infoBackgroundColor", "#2E2E2E"); + ctxt->setContextProperty("topShadow", "info-top-shadow.png"); + ctxt->setContextProperty("infoShadow", "info-shadow.png"); + ctxt->setContextProperty("infoIndicator", "info-indicator.png"); + + ctxt->setContextProperty("infoTextColor", "#B0B0B0"); + ctxt->setContextProperty("infoTitleColor", "#FFFFFF"); + + ctxt->setContextProperty("ratingUnselectedColor", "#1C1C1C"); + ctxt->setContextProperty("ratingSelectedColor", "#FFFFFF"); + + ctxt->setContextProperty("favUncheckedColor", "#1C1C1C"); + ctxt->setContextProperty("favCheckedColor", "#E84852"); + + ctxt->setContextProperty("readTickUncheckedColor", "#1C1C1C"); + ctxt->setContextProperty("readTickCheckedColor", "#E84852"); + } + + updateCoversSizeInContext(YACREADER_MIN_COVER_WIDTH, ctxt); + + ctxt->setContextProperty("comicsList", comicModel.get()); + ctxt->setContextProperty("foldersList", folderModel); + + ctxt->setContextProperty("showCurrentComic", QVariant(false)); + + ctxt->setContextProperty("openHelper", this); + ctxt->setContextProperty("contextMenuHelper", this); + + view->setSource(QUrl("qrc:/qml/FolderContentView.qml")); +} + +void FolderContentView::setModel(const QModelIndex &parent, FolderModel *model) +{ + this->parent = parent; + QQmlContext *ctxt = view->rootContext(); + + ctxt->setContextProperty("foldersList", model); + + // when the root folder is set, FolderModel just returns itself in `getSubfoldersModel`, I need to measure the performance of create a deep copy... + if (folderModel->isSubfolder) { + delete folderModel; + } + folderModel = model; + + auto grid = view->rootObject()->findChild(QStringLiteral("grid")); + + if (grid != nullptr) { + grid->setProperty("currentIndex", 0); + } +} + +void FolderContentView::setContinueReadingModel(ComicModel *model) +{ + QQmlContext *ctxt = view->rootContext(); + + ctxt->setContextProperty("comicsList", model); + this->comicModel.reset(model); + + auto list = view->rootObject()->findChild(QStringLiteral("list")); + + if (list != nullptr) { + list->setProperty("currentIndex", 0); + } +} + +void FolderContentView::openFolder(int index) +{ + emit subfolderSelected(this->parent, index); +} + +void FolderContentView::openComicFromContinueReadingList(int index) +{ + auto comic = comicModel->getComic(comicModel->index(index, 0)); + emit openComic(comic, ComicModel::Folder); +} + +void FolderContentView::requestedFolderContextMenu(QPoint point, int index) +{ + auto folder = folderModel->getFolder(folderModel->index(index, 0)); + emit openFolderContextMenu(point, folder); +} + +void FolderContentView::requestedContinueReadingComicContextMenu(QPoint point, int index) +{ + auto comic = comicModel->getComic(comicModel->index(index, 0)); + emit openContinueReadingComicContextMenu(point, comic); +} + +void FolderContentView::updateCoversSizeInContext(int width, QQmlContext *ctxt) +{ + int cellBottomMarging = 8 * (1 + 2 * (1 - (float(YACREADER_MAX_GRID_ZOOM_WIDTH - width) / (YACREADER_MAX_GRID_ZOOM_WIDTH - YACREADER_MIN_GRID_ZOOM_WIDTH)))); + + ctxt->setContextProperty("cellCustomHeight", ((width * YACREADER_MAX_COVER_HEIGHT) / YACREADER_MIN_COVER_WIDTH) + 51 + cellBottomMarging); + ctxt->setContextProperty("cellCustomWidth", (width * YACREADER_MIN_CELL_CUSTOM_WIDTH) / YACREADER_MIN_COVER_WIDTH); + + ctxt->setContextProperty("itemWidth", width); + ctxt->setContextProperty("itemHeight", ((width * YACREADER_MAX_COVER_HEIGHT) / YACREADER_MIN_COVER_WIDTH) + 51); + + ctxt->setContextProperty("coverWidth", width); + ctxt->setContextProperty("coverHeight", (width * YACREADER_MAX_COVER_HEIGHT) / YACREADER_MIN_COVER_WIDTH); +} + +void FolderContentView::setCoversSize(int width) +{ + QQmlContext *ctxt = view->rootContext(); + + auto grid = view->rootObject()->findChild(QStringLiteral("grid")); + + if (grid != 0) { + QVariant cellCustomWidth = (width * YACREADER_MIN_CELL_CUSTOM_WIDTH) / YACREADER_MIN_GRID_ZOOM_WIDTH; + QMetaObject::invokeMethod(grid, "calculateCellWidths", + Q_ARG(QVariant, cellCustomWidth)); + } + + updateCoversSizeInContext(width, ctxt); + + settings->setValue(COMICS_GRID_COVER_SIZES, coverSizeSlider->value()); +} + +void FolderContentView::showEvent(QShowEvent *event) +{ + QWidget::showEvent(event); + + int coverSize = settings->value(COMICS_GRID_COVER_SIZES, YACREADER_MIN_COVER_WIDTH).toInt(); + + coverSizeSlider->setValue(coverSize); + setCoversSize(coverSize); +} + +void FolderContentView::dragEnterEvent(QDragEnterEvent *event) +{ +} + +void FolderContentView::dropEvent(QDropEvent *event) +{ +} diff --git a/YACReaderLibrary/folder_content_view.h b/YACReaderLibrary/folder_content_view.h new file mode 100644 index 00000000..56adc699 --- /dev/null +++ b/YACReaderLibrary/folder_content_view.h @@ -0,0 +1,70 @@ +#ifndef FOLDERCONTENTVIEW_H +#define FOLDERCONTENTVIEW_H + +#include + +#include "comic_model.h" + +#include "folder.h" +#include "comic_db.h" + +class FolderModel; +class ComicModel; +class YACReaderToolBarStretch; + +class QQuickWidget; +class QQmlContext; + +class FolderContentView : public QWidget +{ + Q_OBJECT +public: + explicit FolderContentView(QWidget *parent = nullptr); + void setModel(const QModelIndex &parent, FolderModel *model); + void setContinueReadingModel(ComicModel *model); + +signals: + void subfolderSelected(QModelIndex, int); + void openComic(const ComicDB &comic, const ComicModel::Mode mode); + + // Drops + void copyComicsToCurrentFolder(QList>); + void moveComicsToCurrentFolder(QList>); + + void openFolderContextMenu(QPoint point, Folder folder); + void openContinueReadingComicContextMenu(QPoint point, ComicDB comic); + +protected slots: + // void onItemClicked(const QModelIndex &mi); + void updateCoversSizeInContext(int width, QQmlContext *ctxt); + void setCoversSize(int width); + virtual void showEvent(QShowEvent *event) override; + void openFolder(int index); + void openComicFromContinueReadingList(int index); + void requestedFolderContextMenu(QPoint point, int index); + void requestedContinueReadingComicContextMenu(QPoint point, int index); + +protected: + QQuickWidget *view; + QModelIndex parent; + + std::unique_ptr comicModel; + FolderModel *folderModel; + + // Drop to import + void dragEnterEvent(QDragEnterEvent *event) override; + void dropEvent(QDropEvent *event) override; + +private: + QSettings *settings; + QToolBar *toolbar; + YACReaderToolBarStretch *toolBarStretch; + QAction *toolBarStretchAction; + QWidget *coverSizeSliderWidget; + QSlider *coverSizeSlider; + QAction *coverSizeSliderAction; + QAction *showInfoAction; + QAction *showInfoSeparatorAction; +}; + +#endif // FOLDERCONTENTVIEW_H diff --git a/YACReaderLibrary/grid_comics_view.cpp b/YACReaderLibrary/grid_comics_view.cpp index 0e262345..4ec4ff87 100644 --- a/YACReaderLibrary/grid_comics_view.cpp +++ b/YACReaderLibrary/grid_comics_view.cpp @@ -14,22 +14,6 @@ #include "yacreader_comic_info_helper.h" #include "current_comic_view_helper.h" -// values relative to visible cells -const unsigned int YACREADER_MIN_GRID_ZOOM_WIDTH = 156; -const unsigned int YACREADER_MAX_GRID_ZOOM_WIDTH = 312; - -// GridView cells -const unsigned int YACREADER_MIN_CELL_CUSTOM_HEIGHT = 295; -const unsigned int YACREADER_MIN_CELL_CUSTOM_WIDTH = 185; - -// Covers -const unsigned int YACREADER_MAX_COVER_HEIGHT = 236; -const unsigned int YACREADER_MIN_COVER_WIDTH = YACREADER_MIN_GRID_ZOOM_WIDTH; - -// visible cells (realCell in qml), grid cells size is used to create faux inner margings -const unsigned int YACREADER_MIN_ITEM_HEIGHT = YACREADER_MAX_COVER_HEIGHT + 51; // 51 is the height of the bottom rectangle used for title and other info -const unsigned int YACREADER_MIN_ITEM_WIDTH = YACREADER_MIN_COVER_WIDTH; - GridComicsView::GridComicsView(QWidget *parent) : ComicsView(parent), filterEnabled(false) { @@ -422,6 +406,8 @@ void GridComicsView::setCoversSize(int width) } updateCoversSizeInContext(width, ctxt); + + settings->setValue(COMICS_GRID_COVER_SIZES, coverSizeSlider->value()); } void GridComicsView::updateCoversSizeInContext(int width, QQmlContext *ctxt) diff --git a/YACReaderLibrary/grid_comics_view.h b/YACReaderLibrary/grid_comics_view.h index 7d7455e7..158ebc6a 100644 --- a/YACReaderLibrary/grid_comics_view.h +++ b/YACReaderLibrary/grid_comics_view.h @@ -16,6 +16,22 @@ class YACReaderToolBarStretch; class YACReaderComicsSelectionHelper; class YACReaderComicInfoHelper; +// values relative to visible cells +const unsigned int YACREADER_MIN_GRID_ZOOM_WIDTH = 156; +const unsigned int YACREADER_MAX_GRID_ZOOM_WIDTH = 312; + +// GridView cells +const unsigned int YACREADER_MIN_CELL_CUSTOM_HEIGHT = 295; +const unsigned int YACREADER_MIN_CELL_CUSTOM_WIDTH = 185; + +// Covers +const unsigned int YACREADER_MAX_COVER_HEIGHT = 236; +const unsigned int YACREADER_MIN_COVER_WIDTH = YACREADER_MIN_GRID_ZOOM_WIDTH; + +// visible cells (realCell in qml), grid cells size is used to create faux inner margings +const unsigned int YACREADER_MIN_ITEM_HEIGHT = YACREADER_MAX_COVER_HEIGHT + 51; // 51 is the height of the bottom rectangle used for title and other info +const unsigned int YACREADER_MIN_ITEM_WIDTH = YACREADER_MIN_COVER_WIDTH; + class GridComicsView : public ComicsView { Q_OBJECT