From 721da42c8cf145e02858cf5c86b3d1fd510dc291 Mon Sep 17 00:00:00 2001 From: luisangelsm Date: Wed, 14 Jan 2026 15:51:32 +0100 Subject: [PATCH] Add toolbar and background theming to YACReader --- YACReader/configuration.cpp | 2 - YACReader/configuration.h | 4 +- YACReader/magnifying_glass.cpp | 6 +- YACReader/main_window_viewer.cpp | 70 +++++++-- YACReader/main_window_viewer.h | 8 +- YACReader/options_dialog.cpp | 14 +- YACReader/options_dialog.h | 2 + YACReader/page_label_widget.cpp | 23 ++- YACReader/page_label_widget.h | 7 +- YACReader/themes/theme.h | 93 ++++++++++++ YACReader/themes/theme_factory.cpp | 223 ++++++++++++++++++++++++++++ YACReader/themes/theme_factory.h | 9 ++ YACReader/themes/themes.pri | 3 + YACReader/viewer.cpp | 24 ++- YACReader/viewer.h | 6 +- YACReader/yacreader_images.qrc | 1 + common/themes/theme_manager.cpp | 3 +- common/yacreader_global_gui.cpp | 5 +- common/yacreader_global_gui.h | 4 +- images/viewer_toolbar/menuArrow.svg | 12 ++ 20 files changed, 482 insertions(+), 37 deletions(-) create mode 100644 YACReader/themes/theme_factory.cpp create mode 100644 YACReader/themes/theme_factory.h create mode 100644 images/viewer_toolbar/menuArrow.svg diff --git a/YACReader/configuration.cpp b/YACReader/configuration.cpp index 15868a8f..93a93d32 100644 --- a/YACReader/configuration.cpp +++ b/YACReader/configuration.cpp @@ -37,8 +37,6 @@ void Configuration::load(QSettings *settings) settings->setValue(MAXIMIZED, false); if (!settings->contains(DOUBLE_PAGE)) settings->setValue(DOUBLE_PAGE, false); - if (!settings->contains(BACKGROUND_COLOR)) - settings->setValue(BACKGROUND_COLOR, QColor(40, 40, 40)); if (!settings->contains(SHOW_TOOLBARS)) settings->setValue(SHOW_TOOLBARS, true); if (!settings->contains(QUICK_NAVI_MODE)) diff --git a/YACReader/configuration.h b/YACReader/configuration.h index 2845b122..b70594bf 100644 --- a/YACReader/configuration.h +++ b/YACReader/configuration.h @@ -85,8 +85,8 @@ public: bool getEnlargeImages() { return settings->value(ENLARGE_IMAGES, true).toBool(); } void setEnlargeImages(bool b) { settings->setValue(ENLARGE_IMAGES, b); } - QColor getBackgroundColor() { return settings->value(BACKGROUND_COLOR).value(); } - void setBackgroundColor(const QColor &color) { settings->value(BACKGROUND_COLOR, color); } + QColor getBackgroundColor(const QColor &color) { return settings->value(BACKGROUND_COLOR, color).value(); } + void setBackgroundColor(const QColor &color) { settings->setValue(BACKGROUND_COLOR, color); } bool getShowToolbars() { return settings->value(SHOW_TOOLBARS).toBool(); } void setShowToolbars(bool b) { settings->setValue(SHOW_TOOLBARS, b); } bool getShowInformation() { return settings->value(SHOW_INFO, false).toBool(); } diff --git a/YACReader/magnifying_glass.cpp b/YACReader/magnifying_glass.cpp index 05c919be..3c166ff3 100644 --- a/YACReader/magnifying_glass.cpp +++ b/YACReader/magnifying_glass.cpp @@ -2,6 +2,8 @@ #include "viewer.h" #include "configuration.h" +#include "theme_manager.h" + #include MagnifyingGlass::MagnifyingGlass(int w, int h, float zoomLevel, QWidget *parent) @@ -77,7 +79,7 @@ void MagnifyingGlass::updateImage(int x, int y) if (outImage) { QImage img(zoomWidth, zoomHeight, QImage::Format_RGB32); img.setDevicePixelRatio(devicePixelRatioF()); - img.fill(Configuration::getConfiguration().getBackgroundColor()); + img.fill(Configuration::getConfiguration().getBackgroundColor(ThemeManager::instance().getCurrentTheme().viewer.defaultBackgroundColor)); if (zw > 0 && zh > 0) { QPainter painter(&img); painter.drawPixmap(xOffset, yOffset, image.copy(xp, yp, zw, zh)); @@ -118,7 +120,7 @@ void MagnifyingGlass::updateImage(int x, int y) if (outImage) { QImage img(zoomWidth, zoomHeight, QImage::Format_RGB32); img.setDevicePixelRatio(devicePixelRatioF()); - img.fill(Configuration::getConfiguration().getBackgroundColor()); + img.fill(Configuration::getConfiguration().getBackgroundColor(ThemeManager::instance().getCurrentTheme().viewer.defaultBackgroundColor)); if (zw > 0 && zh > 0) { QPainter painter(&img); painter.drawPixmap(xOffset, yOffset, image.copy(xp, yp, zw, zh)); diff --git a/YACReader/main_window_viewer.cpp b/YACReader/main_window_viewer.cpp index 2c833144..1c3e1981 100644 --- a/YACReader/main_window_viewer.cpp +++ b/YACReader/main_window_viewer.cpp @@ -18,6 +18,7 @@ #include "yacreader_global.h" #include "edit_shortcuts_dialog.h" #include "shortcuts_manager.h" +#include "theme_manager.h" #include "whats_new_controller.h" @@ -40,11 +41,12 @@ #endif MainWindowViewer::MainWindowViewer() - : QMainWindow(), fullscreen(false), toolbars(true), currentDirectory("."), currentDirectoryImgDest("."), isClient(false) + : QMainWindow(), fullscreen(false), toolbars(true), currentDirectory("."), currentDirectoryImgDest("."), openToolButton(nullptr), isClient(false) { loadConfiguration(); setupUI(); afterLaunchTasks(); + initTheme(this); } void MainWindowViewer::afterLaunchTasks() @@ -503,16 +505,16 @@ void MainWindowViewer::createToolBars() recentmenu->addAction(clearRecentFilesAction); refreshRecentFilesActionList(); - auto tb = new QToolButton(); + openToolButton = new QToolButton(); auto open = actionWithCustomIcon(QIcon(addExtensionToIconPathInToolbar(":/images/viewer_toolbar/open")), openAction); - tb->addAction(open); - tb->addAction(actionWithCustomIcon(QIcon(), openLatestComicAction)); - tb->addAction(actionWithCustomIcon(QIcon(addExtensionToIconPathInToolbar(":/images/viewer_toolbar/openFolder")), openFolderAction)); - tb->addAction(recentmenu->menuAction()); - tb->setPopupMode(QToolButton::MenuButtonPopup); - tb->setDefaultAction(open); + openToolButton->addAction(open); + openToolButton->addAction(actionWithCustomIcon(QIcon(), openLatestComicAction)); + openToolButton->addAction(actionWithCustomIcon(QIcon(addExtensionToIconPathInToolbar(":/images/viewer_toolbar/openFolder")), openFolderAction)); + openToolButton->addAction(recentmenu->menuAction()); + openToolButton->setPopupMode(QToolButton::MenuButtonPopup); + openToolButton->setDefaultAction(open); - comicToolBar->addWidget(tb); + comicToolBar->addWidget(openToolButton); #endif comicToolBar->addAction(actionWithCustomIcon(QIcon(addExtensionToIconPathInToolbar(":/images/viewer_toolbar/save")), saveImageAction)); @@ -1554,6 +1556,56 @@ void MainWindowViewer::setLoadedComicActionsEnabled(bool enabled) a->setEnabled(enabled); } +void MainWindowViewer::applyTheme() +{ + const auto toolbarTheme = ThemeManager::instance().getCurrentTheme().toolbar; + + if (comicToolBar) { + comicToolBar->setStyleSheet(toolbarTheme.toolbarQSS); + } + + auto setIcon = [](QAction *action, const QIcon &icon, const QIcon &icon18x18) { + if (action) { + action->setIcon(icon); + + auto action18x18 = action->property("customIconAction").value(); + if (action18x18) { + + action18x18->setIcon(icon18x18); + } + } + }; + + setIcon(openAction, toolbarTheme.openAction, toolbarTheme.openAction18x18); + setIcon(openFolderAction, toolbarTheme.openFolderAction, toolbarTheme.openFolderAction18x18); + setIcon(openLatestComicAction, toolbarTheme.openLatestComicAction, toolbarTheme.openLatestComicAction18x18); + setIcon(saveImageAction, toolbarTheme.saveImageAction, toolbarTheme.saveImageAction18x18); + setIcon(openComicOnTheLeftAction, toolbarTheme.openComicOnTheLeftAction, toolbarTheme.openComicOnTheLeftAction18x18); + setIcon(openComicOnTheRightAction, toolbarTheme.openComicOnTheRightAction, toolbarTheme.openComicOnTheRightAction18x18); + setIcon(goToPageOnTheLeftAction, toolbarTheme.goToPageOnTheLeftAction, toolbarTheme.goToPageOnTheLeftAction18x18); + setIcon(goToPageOnTheRightAction, toolbarTheme.goToPageOnTheRightAction, toolbarTheme.goToPageOnTheRightAction18x18); + setIcon(adjustHeightAction, toolbarTheme.adjustHeightAction, toolbarTheme.adjustHeightAction18x18); + setIcon(adjustWidthAction, toolbarTheme.adjustWidthAction, toolbarTheme.adjustWidthAction18x18); + setIcon(leftRotationAction, toolbarTheme.leftRotationAction, toolbarTheme.leftRotationAction18x18); + setIcon(rightRotationAction, toolbarTheme.rightRotationAction, toolbarTheme.rightRotationAction18x18); + setIcon(doublePageAction, toolbarTheme.doublePageAction, toolbarTheme.doublePageAction18x18); + setIcon(doubleMangaPageAction, toolbarTheme.doubleMangaPageAction, toolbarTheme.doubleMangaPageAction18x18); + setIcon(showZoomSliderlAction, toolbarTheme.showZoomSliderlAction, toolbarTheme.showZoomSliderlAction18x18); + setIcon(goToPageAction, toolbarTheme.goToPageAction, toolbarTheme.goToPageAction18x18); + setIcon(optionsAction, toolbarTheme.optionsAction, toolbarTheme.optionsAction18x18); + setIcon(helpAboutAction, toolbarTheme.helpAboutAction, toolbarTheme.helpAboutAction18x18); + setIcon(showMagnifyingGlassAction, toolbarTheme.showMagnifyingGlassAction, toolbarTheme.showMagnifyingGlassAction18x18); + setIcon(setBookmarkAction, toolbarTheme.setBookmarkAction, toolbarTheme.setBookmarkAction18x18); + setIcon(showBookmarksAction, toolbarTheme.showBookmarksAction, toolbarTheme.showBookmarksAction18x18); + setIcon(showShorcutsAction, toolbarTheme.showShorcutsAction, toolbarTheme.showShorcutsAction18x18); + setIcon(showInfoAction, toolbarTheme.showInfoAction, toolbarTheme.showInfoAction18x18); + setIcon(closeAction, toolbarTheme.closeAction, toolbarTheme.closeAction18x18); + setIcon(showDictionaryAction, toolbarTheme.showDictionaryAction, toolbarTheme.showDictionaryAction18x18); + setIcon(adjustToFullSizeAction, toolbarTheme.adjustToFullSizeAction, toolbarTheme.adjustToFullSizeAction18x18); + setIcon(fitToPageAction, toolbarTheme.fitToPageAction, toolbarTheme.fitToPageAction18x18); + setIcon(showFlowAction, toolbarTheme.showFlowAction, toolbarTheme.showFlowAction18x18); +} + void MainWindowViewer::dropEvent(QDropEvent *event) { QList urlList; diff --git a/YACReader/main_window_viewer.h b/YACReader/main_window_viewer.h index b2d08663..ec6033b8 100644 --- a/YACReader/main_window_viewer.h +++ b/YACReader/main_window_viewer.h @@ -3,12 +3,14 @@ #include #include #include +#include #include #include #include #include #include "yacreader_global.h" +#include "themable.h" #ifdef Y_MAC_UI #include "yacreader_macosx_toolbar.h" @@ -28,7 +30,7 @@ class EditShortcutsDialog; namespace YACReader { -class MainWindowViewer : public QMainWindow +class MainWindowViewer : public QMainWindow, protected Themable { Q_OBJECT @@ -153,6 +155,8 @@ private: QList mglassActions; QList loadedComicActions; + QToolButton *openToolButton; + YACReaderSlider *zoomSliderAction; HttpVersionChecker *versionChecker; @@ -170,6 +174,8 @@ private: void setMglassActionsEnabled(bool enabled); void setLoadedComicActionsEnabled(bool enabled); + void applyTheme() override; + //! Manejadores de evento: // void resizeEvent(QResizeEvent * event); void mouseDoubleClickEvent(QMouseEvent *event) override; diff --git a/YACReader/options_dialog.cpp b/YACReader/options_dialog.cpp index 10d73439..6a987c06 100644 --- a/YACReader/options_dialog.cpp +++ b/YACReader/options_dialog.cpp @@ -12,6 +12,7 @@ #include #include #include +#include "theme_manager.h" #include "yacreader_spin_slider_widget.h" #include "yacreader_3d_flow_config_widget.h" @@ -65,10 +66,12 @@ OptionsDialog::OptionsDialog(QWidget *parent) // backgroundColor->setMinimumWidth(100); colorSelection->addWidget(backgroundColor); colorSelection->addWidget(selectBackgroundColorButton = new QPushButton(tr("Choose"))); + colorSelection->addWidget(clearBackgroundColorButton = new QPushButton(tr("Clear"))); colorSelection->setStretchFactor(backgroundColor, 1); colorSelection->setStretchFactor(selectBackgroundColorButton, 0); // colorSelection->addStretch(); connect(selectBackgroundColorButton, &QAbstractButton::clicked, this, &OptionsDialog::showColorDialog); + connect(clearBackgroundColorButton, &QAbstractButton::clicked, this, &OptionsDialog::clearBackgroundColor); colorBox->setLayout(colorSelection); auto scrollBox = new QGroupBox(tr("Scroll behaviour")); @@ -278,7 +281,7 @@ void OptionsDialog::restoreOptions(QSettings *settings) showTimeInInformationLabel->setChecked(Configuration::getConfiguration().getShowTimeInInformation()); - updateColor(settings->value(BACKGROUND_COLOR).value()); + updateColor(settings->value(BACKGROUND_COLOR, ThemeManager::instance().getCurrentTheme().viewer.defaultBackgroundColor).value()); // fitToWidthRatioS->setSliderPosition(settings->value(FIT_TO_WIDTH_RATIO).toFloat()*100); quickNavi->setChecked(settings->value(QUICK_NAVI_MODE).toBool()); @@ -324,8 +327,6 @@ void OptionsDialog::updateColor(const QColor &color) backgroundColor->setAutoFillBackground(true); currentColor = color; - settings->setValue(BACKGROUND_COLOR, color); - emit changedOptions(); } @@ -392,3 +393,10 @@ void OptionsDialog::setFilters(int brightness, int contrast, int gamma) else gammaS->setValue(100); } + +void OptionsDialog::clearBackgroundColor() +{ + settings->remove(BACKGROUND_COLOR); + + updateColor(ThemeManager::instance().getCurrentTheme().viewer.defaultBackgroundColor); +} diff --git a/YACReader/options_dialog.h b/YACReader/options_dialog.h index 0f15e196..f1d96767 100644 --- a/YACReader/options_dialog.h +++ b/YACReader/options_dialog.h @@ -42,6 +42,7 @@ private: QLabel *backgroundColor; QPushButton *selectBackgroundColorButton; + QPushButton *clearBackgroundColorButton; QCheckBox *doNotTurnPageOnScroll; QCheckBox *useSingleScrollStepToTurnPage; @@ -72,6 +73,7 @@ public slots: void resetImageConfig(); void show(); void setFilters(int brightness, int contrast, int gamma); + void clearBackgroundColor(); signals: void changedOptions(); diff --git a/YACReader/page_label_widget.cpp b/YACReader/page_label_widget.cpp index 8fd6a4b9..afd60e9d 100644 --- a/YACReader/page_label_widget.cpp +++ b/YACReader/page_label_widget.cpp @@ -2,6 +2,8 @@ #include +#include "theme_manager.h" + PageLabelWidget::PageLabelWidget(QWidget *parent) : QWidget(parent) { @@ -25,13 +27,13 @@ PageLabelWidget::PageLabelWidget(QWidget *parent) int contentMargin = 0; if (verticalRes <= 1024) { - textLabel->setStyleSheet("QLabel { color : white; font-size:12px; }"); + fontSizePx = 12; contentMargin = 12; } else if (verticalRes <= 1200) { - textLabel->setStyleSheet("QLabel { color : white; font-size:16px; }"); + fontSizePx = 16; contentMargin = 16; } else { - textLabel->setStyleSheet("QLabel { color : white; font-size:20px; }"); + fontSizePx = 20; contentMargin = 20; } @@ -47,6 +49,8 @@ PageLabelWidget::PageLabelWidget(QWidget *parent) if (parent != nullptr) move(QPoint((parent->geometry().size().width() - this->width()), -this->height())); + + initTheme(this); } void PageLabelWidget::show() @@ -90,7 +94,7 @@ void PageLabelWidget::paintEvent(QPaintEvent *) { QPainter painter(this); - painter.fillRect(0, 0, width(), height(), QColor(0xBB000000)); + painter.fillRect(rect(), infoBackgroundColor); } void PageLabelWidget::updatePosition() @@ -106,3 +110,14 @@ void PageLabelWidget::updatePosition() else move(QPoint((parent->geometry().size().width() - this->width()), -this->height())); } + +void PageLabelWidget::applyTheme() +{ + const auto viewerTheme = ThemeManager::instance().getCurrentTheme().viewer; + + infoBackgroundColor = viewerTheme.infoBackgroundColor; + + textLabel->setStyleSheet(viewerTheme.infoLabelQSS.arg(fontSizePx)); + + update(); +} diff --git a/YACReader/page_label_widget.h b/YACReader/page_label_widget.h index 35b0c94e..f65cfd9c 100644 --- a/YACReader/page_label_widget.h +++ b/YACReader/page_label_widget.h @@ -3,18 +3,23 @@ #include +#include "themable.h" + class QLabel; class QPropertyAnimation; -class PageLabelWidget : public QWidget +class PageLabelWidget : public QWidget, protected Themable { Q_OBJECT private: QLabel *textLabel; QPropertyAnimation *animation; + QColor infoBackgroundColor; + int fontSizePx = 0; protected: void paintEvent(QPaintEvent *) override; + void applyTheme() override; public: PageLabelWidget(QWidget *parent); diff --git a/YACReader/themes/theme.h b/YACReader/themes/theme.h index c770f3e2..719ba61b 100644 --- a/YACReader/themes/theme.h +++ b/YACReader/themes/theme.h @@ -1,7 +1,100 @@ #ifndef THEME_H #define THEME_H +#include + +struct ToolbarThemeTemplates { + QString toolbarQSS = "QToolBar { border: none; background: %1; }\n" + "QToolBar::separator { background: %2; width: 1px; margin: 5px 4px; }\n" + "QToolButton:checked { background-color: %3; }\n" + "QToolButton::menu-button {border: none; width: 18px; }\n" + "QToolButton::menu-arrow { image: url(%4); width: 8px; height: 8px; }\n"; + QString menuArrowPath = ":/images/viewer_toolbar/menuArrow.svg"; +}; + +struct ViewerThemeTemplates { + QString infoLabelQSS = "QLabel { color : %1; font-size:%2px; }"; +}; + +struct ToolbarTheme { + QString toolbarQSS; + + QIcon openAction; + QIcon openAction18x18; + QIcon openFolderAction; + QIcon openFolderAction18x18; + QIcon openLatestComicAction; + QIcon openLatestComicAction18x18; + QIcon saveImageAction; + QIcon saveImageAction18x18; + QIcon openComicOnTheLeftAction; + QIcon openComicOnTheLeftAction18x18; + QIcon openComicOnTheRightAction; + QIcon openComicOnTheRightAction18x18; + QIcon goToPageOnTheLeftAction; + QIcon goToPageOnTheLeftAction18x18; + QIcon goToPageOnTheRightAction; + QIcon goToPageOnTheRightAction18x18; + QIcon adjustHeightAction; + QIcon adjustHeightAction18x18; + QIcon adjustWidthAction; + QIcon adjustWidthAction18x18; + QIcon leftRotationAction; + QIcon leftRotationAction18x18; + QIcon rightRotationAction; + QIcon rightRotationAction18x18; + QIcon doublePageAction; + QIcon doublePageAction18x18; + QIcon doubleMangaPageAction; + QIcon doubleMangaPageAction18x18; + QIcon increasePageZoomAction; + QIcon increasePageZoomAction18x18; + QIcon decreasePageZoomAction; + QIcon decreasePageZoomAction18x18; + QIcon resetZoomAction; + QIcon resetZoomAction18x18; + QIcon showZoomSliderlAction; + QIcon showZoomSliderlAction18x18; + QIcon goToPageAction; + QIcon goToPageAction18x18; + QIcon optionsAction; + QIcon optionsAction18x18; + QIcon helpAboutAction; + QIcon helpAboutAction18x18; + QIcon showMagnifyingGlassAction; + QIcon showMagnifyingGlassAction18x18; + QIcon setBookmarkAction; + QIcon setBookmarkAction18x18; + QIcon showBookmarksAction; + QIcon showBookmarksAction18x18; + QIcon showShorcutsAction; + QIcon showShorcutsAction18x18; + QIcon showInfoAction; + QIcon showInfoAction18x18; + QIcon closeAction; + QIcon closeAction18x18; + QIcon showDictionaryAction; + QIcon showDictionaryAction18x18; + QIcon adjustToFullSizeAction; + QIcon adjustToFullSizeAction18x18; + QIcon fitToPageAction; + QIcon fitToPageAction18x18; + QIcon showFlowAction; + QIcon showFlowAction18x18; +}; + +struct ViewerTheme { + QColor defaultBackgroundColor; + QColor defaultTextColor; + + QColor infoBackgroundColor; + + QString infoLabelQSS; +}; + struct Theme { + ToolbarTheme toolbar; + ViewerTheme viewer; }; #endif // THEME_H diff --git a/YACReader/themes/theme_factory.cpp b/YACReader/themes/theme_factory.cpp new file mode 100644 index 00000000..04002b47 --- /dev/null +++ b/YACReader/themes/theme_factory.cpp @@ -0,0 +1,223 @@ +#include "theme_factory.h" + +#include "icon_utils.h" + +struct ToolbarParams { + ToolbarThemeTemplates t; + + QColor iconColor; + QColor iconDisabledColor; + QColor iconCheckedColor; + QColor backgroundColor; + QColor separatorColor; + QColor checkedButtonColor; + QColor menuIndicatorColor; +}; + +struct ViewerParams { + ViewerThemeTemplates t; + + QColor defaultBackgroundColor; + QColor defaultTextColor; + QColor infoBackgroundColor; + QColor infoTextColor; +}; + +struct ThemeParams { + QString themeName; + + ToolbarParams toolbarParams; + ViewerParams viewerParams; +}; + +void setToolbarIconPair(QIcon &icon, + QIcon &icon18, + const QString &basePath, + const QColor &iconColor, + const QColor &disabledColor, + const QColor &checkedColor, + const QString &themeName) +{ + QString path18 = basePath; + if (path18.endsWith(".svg")) + path18.insert(path18.size() - 4, "_18x18"); + else + path18.append("_18x18"); + + // Normal + const QString normalPath = recoloredSvgToThemeFile(basePath, iconColor, themeName); + const QString normalPath18 = recoloredSvgToThemeFile(path18, iconColor, themeName); + // Disabled + const QString disabledPath = recoloredSvgToThemeFile(basePath, disabledColor, themeName, "_disabled"); + const QString disabledPath18 = recoloredSvgToThemeFile(path18, disabledColor, themeName, "_disabled"); + // Checked (On state) + const QString checkedPath = recoloredSvgToThemeFile(basePath, checkedColor, themeName, "_checked"); + const QString checkedPath18 = recoloredSvgToThemeFile(path18, checkedColor, themeName, "_checked"); + + icon.addFile(normalPath, QSize(), QIcon::Normal, QIcon::Off); + icon.addFile(disabledPath, QSize(), QIcon::Disabled, QIcon::Off); + icon.addFile(checkedPath, QSize(), QIcon::Normal, QIcon::On); + icon.addFile(disabledPath, QSize(), QIcon::Disabled, QIcon::On); + + icon18.addFile(normalPath18, QSize(), QIcon::Normal, QIcon::Off); + icon18.addFile(disabledPath18, QSize(), QIcon::Disabled, QIcon::Off); + icon18.addFile(checkedPath18, QSize(), QIcon::Normal, QIcon::On); + icon18.addFile(disabledPath18, QSize(), QIcon::Disabled, QIcon::On); +} + +Theme makeTheme(const ThemeParams ¶ms) +{ + Theme theme; + + // Toolbar & actions + theme.toolbar.toolbarQSS = params.toolbarParams.t.toolbarQSS.arg(params.toolbarParams.backgroundColor.name(), params.toolbarParams.separatorColor.name(), params.toolbarParams.checkedButtonColor.name(), recoloredSvgToThemeFile(params.toolbarParams.t.menuArrowPath, params.toolbarParams.menuIndicatorColor, params.themeName)); + + auto setToolbarIconPairT = [&](QIcon &icon, QIcon &icon18, const QString &basePath) { + setToolbarIconPair(icon, icon18, basePath, params.toolbarParams.iconColor, params.toolbarParams.iconDisabledColor, params.toolbarParams.iconCheckedColor, params.themeName); + }; + + setToolbarIconPairT(theme.toolbar.openAction, theme.toolbar.openAction18x18, ":/images/viewer_toolbar/open.svg"); + setToolbarIconPairT(theme.toolbar.openFolderAction, theme.toolbar.openFolderAction18x18, ":/images/viewer_toolbar/openFolder.svg"); + setToolbarIconPairT(theme.toolbar.openLatestComicAction, theme.toolbar.openLatestComicAction18x18, ":/images/viewer_toolbar/openNext.svg"); + setToolbarIconPairT(theme.toolbar.saveImageAction, theme.toolbar.saveImageAction18x18, ":/images/viewer_toolbar/save.svg"); + setToolbarIconPairT(theme.toolbar.openComicOnTheLeftAction, theme.toolbar.openComicOnTheLeftAction18x18, ":/images/viewer_toolbar/openPrevious.svg"); + setToolbarIconPairT(theme.toolbar.openComicOnTheRightAction, theme.toolbar.openComicOnTheRightAction18x18, ":/images/viewer_toolbar/openNext.svg"); + setToolbarIconPairT(theme.toolbar.goToPageOnTheLeftAction, theme.toolbar.goToPageOnTheLeftAction18x18, ":/images/viewer_toolbar/previous.svg"); + setToolbarIconPairT(theme.toolbar.goToPageOnTheRightAction, theme.toolbar.goToPageOnTheRightAction18x18, ":/images/viewer_toolbar/next.svg"); + setToolbarIconPairT(theme.toolbar.adjustHeightAction, theme.toolbar.adjustHeightAction18x18, ":/images/viewer_toolbar/toHeight.svg"); + setToolbarIconPairT(theme.toolbar.adjustWidthAction, theme.toolbar.adjustWidthAction18x18, ":/images/viewer_toolbar/toWidth.svg"); + setToolbarIconPairT(theme.toolbar.leftRotationAction, theme.toolbar.leftRotationAction18x18, ":/images/viewer_toolbar/rotateL.svg"); + setToolbarIconPairT(theme.toolbar.rightRotationAction, theme.toolbar.rightRotationAction18x18, ":/images/viewer_toolbar/rotateR.svg"); + setToolbarIconPairT(theme.toolbar.doublePageAction, theme.toolbar.doublePageAction18x18, ":/images/viewer_toolbar/doublePage.svg"); + setToolbarIconPairT(theme.toolbar.doubleMangaPageAction, theme.toolbar.doubleMangaPageAction18x18, ":/images/viewer_toolbar/doubleMangaPage.svg"); + setToolbarIconPairT(theme.toolbar.showZoomSliderlAction, theme.toolbar.showZoomSliderlAction18x18, ":/images/viewer_toolbar/zoom.svg"); + setToolbarIconPairT(theme.toolbar.goToPageAction, theme.toolbar.goToPageAction18x18, ":/images/viewer_toolbar/goto.svg"); + setToolbarIconPairT(theme.toolbar.optionsAction, theme.toolbar.optionsAction18x18, ":/images/viewer_toolbar/options.svg"); + setToolbarIconPairT(theme.toolbar.helpAboutAction, theme.toolbar.helpAboutAction18x18, ":/images/viewer_toolbar/help.svg"); + setToolbarIconPairT(theme.toolbar.showMagnifyingGlassAction, theme.toolbar.showMagnifyingGlassAction18x18, ":/images/viewer_toolbar/magnifyingGlass.svg"); + setToolbarIconPairT(theme.toolbar.setBookmarkAction, theme.toolbar.setBookmarkAction18x18, ":/images/viewer_toolbar/bookmark.svg"); + setToolbarIconPairT(theme.toolbar.showBookmarksAction, theme.toolbar.showBookmarksAction18x18, ":/images/viewer_toolbar/showBookmarks.svg"); + setToolbarIconPairT(theme.toolbar.showShorcutsAction, theme.toolbar.showShorcutsAction18x18, ":/images/viewer_toolbar/shortcuts.svg"); + setToolbarIconPairT(theme.toolbar.showInfoAction, theme.toolbar.showInfoAction18x18, ":/images/viewer_toolbar/info.svg"); + setToolbarIconPairT(theme.toolbar.closeAction, theme.toolbar.closeAction18x18, ":/images/viewer_toolbar/close.svg"); + setToolbarIconPairT(theme.toolbar.showDictionaryAction, theme.toolbar.showDictionaryAction18x18, ":/images/viewer_toolbar/translator.svg"); + setToolbarIconPairT(theme.toolbar.adjustToFullSizeAction, theme.toolbar.adjustToFullSizeAction18x18, ":/images/viewer_toolbar/full.svg"); + setToolbarIconPairT(theme.toolbar.fitToPageAction, theme.toolbar.fitToPageAction18x18, ":/images/viewer_toolbar/fitToPage.svg"); + setToolbarIconPairT(theme.toolbar.showFlowAction, theme.toolbar.showFlowAction18x18, ":/images/viewer_toolbar/flow.svg"); + // end Toolbar & actions + + // Viewer + theme.viewer.defaultBackgroundColor = params.viewerParams.defaultBackgroundColor; + theme.viewer.defaultTextColor = params.viewerParams.defaultTextColor; + theme.viewer.infoBackgroundColor = params.viewerParams.infoBackgroundColor; + theme.viewer.infoLabelQSS = params.viewerParams.t.infoLabelQSS.arg(params.viewerParams.infoTextColor.name()); + // end Viewer + + return theme; +} + +ThemeParams classicThemeParams(); +ThemeParams lightThemeParams(); +ThemeParams darkThemeParams(); + +Theme makeTheme(ThemeId themeId) +{ + switch (themeId) { + case ThemeId::Classic: + return makeTheme(classicThemeParams()); + case ThemeId::Light: + return makeTheme(lightThemeParams()); + case ThemeId::Dark: + return makeTheme(darkThemeParams()); + } +} + +ThemeParams classicThemeParams() +{ + ThemeParams params; + params.themeName = "classic"; + + ToolbarParams toolbarParams; + toolbarParams.iconColor = QColor(0x404040); + toolbarParams.iconDisabledColor = QColor(0x858585); + toolbarParams.iconCheckedColor = QColor(0x5A5A5A); + toolbarParams.backgroundColor = QColor(0xF3F3F3); + toolbarParams.separatorColor = QColor(0xCCCCCC); + toolbarParams.checkedButtonColor = QColor(0xCCCCCC); + toolbarParams.menuIndicatorColor = QColor(0x404040); + + params.toolbarParams = toolbarParams; + + ViewerParams viewerParams; + viewerParams.defaultBackgroundColor = QColor(0x282828); + viewerParams.defaultTextColor = Qt::white; + viewerParams.infoBackgroundColor = QColor::fromRgba(0xBB000000); + viewerParams.infoTextColor = Qt::white; + viewerParams.t = ViewerThemeTemplates(); + + params.viewerParams = viewerParams; + + return params; +} + +ThemeParams lightThemeParams() +{ + ThemeParams params; + params.themeName = "light"; + + ToolbarParams toolbarParams; + toolbarParams.iconColor = QColor(0x404040); + toolbarParams.iconDisabledColor = QColor(0xB0B0B0); + toolbarParams.iconCheckedColor = QColor(0x5A5A5A); + toolbarParams.backgroundColor = QColor(0xF3F3F3); + toolbarParams.separatorColor = QColor(0xCCCCCC); + toolbarParams.checkedButtonColor = QColor(0xCCCCCC); + toolbarParams.menuIndicatorColor = QColor(0x404040); + + params.toolbarParams = toolbarParams; + + ViewerParams viewerParams; + viewerParams.defaultBackgroundColor = QColor(0xF6F6F6); + viewerParams.defaultTextColor = QColor(0x202020); + viewerParams.infoBackgroundColor = QColor::fromRgba(0xBBFFFFFF); + viewerParams.infoTextColor = QColor(0x404040); + viewerParams.t = ViewerThemeTemplates(); + + params.viewerParams = viewerParams; + + return params; +} + +ThemeParams darkThemeParams() +{ + ThemeParams params; + params.themeName = "dark"; + + ToolbarParams toolbarParams; + toolbarParams.iconColor = QColor(0xCCCCCC); + toolbarParams.iconDisabledColor = QColor(0x444444); + toolbarParams.iconCheckedColor = QColor(0xDADADA); + toolbarParams.backgroundColor = QColor(0x202020); + toolbarParams.separatorColor = QColor(0x444444); + toolbarParams.checkedButtonColor = QColor(0x3A3A3A); + toolbarParams.menuIndicatorColor = QColor(0xCCCCCC); + + params.toolbarParams = toolbarParams; + + ViewerParams viewerParams; + viewerParams.defaultBackgroundColor = QColor(40, 40, 40); + viewerParams.defaultTextColor = Qt::white; + viewerParams.infoBackgroundColor = QColor::fromRgba(0xBB000000); + viewerParams.infoTextColor = QColor(0xB0B0B0); + viewerParams.t = ViewerThemeTemplates(); + + params.viewerParams = viewerParams; + + return params; +} + +// TODO +ThemeParams paramsFromFile(const QString &filePath) +{ + return {}; +} diff --git a/YACReader/themes/theme_factory.h b/YACReader/themes/theme_factory.h new file mode 100644 index 00000000..72cb4ca2 --- /dev/null +++ b/YACReader/themes/theme_factory.h @@ -0,0 +1,9 @@ +#ifndef THEME_FACTORY_H +#define THEME_FACTORY_H + +#include "theme.h" +#include "theme_id.h" + +Theme makeTheme(ThemeId themeId); + +#endif // THEME_FACTORY_H diff --git a/YACReader/themes/themes.pri b/YACReader/themes/themes.pri index 9e42ad15..eee35324 100644 --- a/YACReader/themes/themes.pri +++ b/YACReader/themes/themes.pri @@ -2,3 +2,6 @@ INCLUDEPATH += $$PWD HEADERS += \ $$PWD/theme.h \ + $$PWD/theme_factory.h +SOURCES += \ + $$PWD/theme_factory.cpp diff --git a/YACReader/viewer.cpp b/YACReader/viewer.cpp index d689e90b..c4245827 100644 --- a/YACReader/viewer.cpp +++ b/YACReader/viewer.cpp @@ -10,6 +10,7 @@ #include "notifications_label_widget.h" #include "comic_db.h" #include "shortcuts_manager.h" +#include "theme_manager.h" #include #include @@ -42,17 +43,12 @@ Viewer::Viewer(QWidget *parent) // current comic page content = new QLabel(this); configureContent(tr("Press 'O' to open comic.")); - // scroll area configuration - setBackgroundRole(QPalette::Dark); + setWidget(content); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setFrameStyle(QFrame::NoFrame); setAlignment(Qt::AlignCenter); - - QPalette palette; - palette.setColor(backgroundRole(), Configuration::getConfiguration().getBackgroundColor()); - setPalette(palette); //--------------------------------------- mglass = new MagnifyingGlass( Configuration::getConfiguration().getMagnifyingGlassSize(), @@ -116,6 +112,8 @@ Viewer::Viewer(QWidget *parent) informationLabel = new PageLabelWidget(this); setAcceptDrops(true); + + initTheme(this); } Viewer::~Viewer() @@ -1009,7 +1007,7 @@ void Viewer::showCursor() void Viewer::updateOptions() { goToFlow->setFlowType(Configuration::getConfiguration().getFlowType()); - updateBackgroundColor(Configuration::getConfiguration().getBackgroundColor()); + updateBackgroundColor(Configuration::getConfiguration().getBackgroundColor(ThemeManager::instance().getCurrentTheme().viewer.defaultBackgroundColor)); updateContentSize(); updateInformation(); } @@ -1021,6 +1019,16 @@ void Viewer::updateBackgroundColor(const QColor &color) setPalette(palette); } +void Viewer::applyTheme() +{ + const auto viewerTheme = ThemeManager::instance().getCurrentTheme().viewer; + + updateBackgroundColor(Configuration::getConfiguration().getBackgroundColor(ThemeManager::instance().getCurrentTheme().viewer.defaultBackgroundColor)); + + const QString textColor = viewerTheme.defaultTextColor.name(QColor::HexArgb); + content->setStyleSheet(QStringLiteral("QLabel { color : %1; background: transparent; }").arg(textColor)); +} + void Viewer::animateShowTranslator() { if (translator->isHidden() && translatorAnimation->state() != QPropertyAnimation::Running) { @@ -1084,7 +1092,7 @@ void Viewer::updateConfig(QSettings *settings) goToFlow->updateConfig(settings); QPalette palette; - palette.setColor(backgroundRole(), Configuration::getConfiguration().getBackgroundColor()); + palette.setColor(backgroundRole(), Configuration::getConfiguration().getBackgroundColor(ThemeManager::instance().getCurrentTheme().viewer.defaultBackgroundColor)); setPalette(palette); } diff --git a/YACReader/viewer.h b/YACReader/viewer.h index c2bb183b..e7dbaa5a 100644 --- a/YACReader/viewer.h +++ b/YACReader/viewer.h @@ -18,6 +18,7 @@ #include "scroll_management.h" #include "mouse_handler.h" +#include "themable.h" class ComicDB; class Comic; @@ -32,7 +33,7 @@ class Bookmarks; class PageLabelWidget; class NotificationsLabelWidget; -class Viewer : public QScrollArea, public ScrollManagement +class Viewer : public QScrollArea, public ScrollManagement, protected Themable { Q_OBJECT public: @@ -186,6 +187,9 @@ private: //! Mouse handler std::unique_ptr mouseHandler; +protected: + void applyTheme() override; + public: Viewer(QWidget *parent = nullptr); ~Viewer(); diff --git a/YACReader/yacreader_images.qrc b/YACReader/yacreader_images.qrc index 8d94645f..ef71304d 100644 --- a/YACReader/yacreader_images.qrc +++ b/YACReader/yacreader_images.qrc @@ -87,5 +87,6 @@ ../images/viewer_toolbar/toWidth_18x18.svg ../images/viewer_toolbar/translator_18x18.svg ../images/viewer_toolbar/zoom_18x18.svg + ../images/viewer_toolbar/menuArrow.svg diff --git a/common/themes/theme_manager.cpp b/common/themes/theme_manager.cpp index 70c4d075..4bfabb21 100644 --- a/common/themes/theme_manager.cpp +++ b/common/themes/theme_manager.cpp @@ -1,6 +1,7 @@ #include "theme_manager.h" #include "theme.h" +#include "theme_factory.h" #include #include @@ -46,5 +47,5 @@ void ThemeManager::setTheme(ThemeId themeId) void ThemeManager::updateCurrentTheme() { - // TODO + currentTheme = makeTheme(themeId); } diff --git a/common/yacreader_global_gui.cpp b/common/yacreader_global_gui.cpp index 7ad76dfa..abf4be55 100644 --- a/common/yacreader_global_gui.cpp +++ b/common/yacreader_global_gui.cpp @@ -32,7 +32,7 @@ QIcon YACReader::noHighlightedIcon(const QString &path) return icon; } -void YACReader::colorize(QImage &img, QColor &col) +void YACReader::colorize(QImage &img, const QColor &col) { QRgb *data = (QRgb *)img.bits(); QRgb *end = data + img.width() * img.height(); @@ -94,6 +94,9 @@ QAction *YACReader::actionWithCustomIcon(const QIcon &icon, QAction *action) QObject::connect(a, &QAction::toggled, action, &QAction::setChecked); QObject::connect(action, &QAction::toggled, a, &QAction::setChecked); + // asign a to action somehow so we can retrieve it later + action->setProperty("customIconAction", QVariant::fromValue(a)); + return a; } diff --git a/common/yacreader_global_gui.h b/common/yacreader_global_gui.h index a4e667e4..84f8e64c 100644 --- a/common/yacreader_global_gui.h +++ b/common/yacreader_global_gui.h @@ -24,7 +24,7 @@ #define DOUBLE_PAGE "DOUBLE_PAGE" #define DOUBLE_MANGA_PAGE "DOUBLE_MANGA_PAGE" #define COVER_IS_SP "COVER_IS_SP" -#define BACKGROUND_COLOR "BACKGROUND_COLOR" +#define BACKGROUND_COLOR "BACKGROUND_COLOR_10" #define SHOW_TOOLBARS "SHOW_TOOLBARS" #define BRIGHTNESS "BRIGHTNESS" #define CONTRAST "CONTRAST" @@ -108,7 +108,7 @@ enum LibraryUITheme { void addSperator(QWidget *w); QAction *createSeparator(); QIcon noHighlightedIcon(const QString &path); -void colorize(QImage &img, QColor &col); +void colorize(QImage &img, const QColor &col); QList mimeDataToComicsIds(const QMimeData *data); QString addExtensionToIconPath(const QString &path); QString addExtensionToIconPathInToolbar(const QString &path); diff --git a/images/viewer_toolbar/menuArrow.svg b/images/viewer_toolbar/menuArrow.svg new file mode 100644 index 00000000..077aad90 --- /dev/null +++ b/images/viewer_toolbar/menuArrow.svg @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file