mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 05:49:53 +08:00
add theme page
This commit is contained in:
parent
4636771081
commit
40a3df305b
@ -315,7 +315,9 @@ QString ConfigMgr::getAppThemeFolder() const
|
||||
|
||||
QString ConfigMgr::getUserThemeFolder() const
|
||||
{
|
||||
return PathUtils::concatenateFilePath(m_userConfigFolderPath, QStringLiteral("themes"));
|
||||
auto folderPath = PathUtils::concatenateFilePath(m_userConfigFolderPath, QStringLiteral("themes"));
|
||||
QDir().mkpath(folderPath);
|
||||
return folderPath;
|
||||
}
|
||||
|
||||
QString ConfigMgr::getAppDocsFolder() const
|
||||
@ -325,7 +327,9 @@ QString ConfigMgr::getAppDocsFolder() const
|
||||
|
||||
QString ConfigMgr::getUserDocsFolder() const
|
||||
{
|
||||
return PathUtils::concatenateFilePath(m_userConfigFolderPath, QStringLiteral("docs"));
|
||||
auto folderPath = PathUtils::concatenateFilePath(m_userConfigFolderPath, QStringLiteral("docs"));
|
||||
QDir().mkpath(folderPath);
|
||||
return folderPath;
|
||||
}
|
||||
|
||||
QString ConfigMgr::getAppSyntaxHighlightingFolder() const
|
||||
|
@ -41,12 +41,35 @@ bool Theme::isValidThemeFolder(const QString &p_folder)
|
||||
return true;
|
||||
}
|
||||
|
||||
QString Theme::getDisplayName(const QString &p_folder, const QString &p_locale)
|
||||
{
|
||||
auto obj = readPaletteFile(p_folder);
|
||||
const auto metaObj = obj[QStringLiteral("metadata")].toObject();
|
||||
QString prefix("display_name");
|
||||
|
||||
if (!p_locale.isEmpty()) {
|
||||
// Check full locale.
|
||||
auto fullLocale = QString("%1_%2").arg(prefix, p_locale);
|
||||
if (metaObj.contains(fullLocale)) {
|
||||
return metaObj.value(fullLocale).toString();
|
||||
}
|
||||
|
||||
auto shortLocale = QString("%1_%2").arg(prefix, p_locale.split('_')[0]);
|
||||
if (metaObj.contains(shortLocale)) {
|
||||
return metaObj.value(shortLocale).toString();
|
||||
}
|
||||
}
|
||||
|
||||
if (metaObj.contains(prefix)) {
|
||||
return metaObj.value(prefix).toString();
|
||||
}
|
||||
return PathUtils::dirName(p_folder);
|
||||
}
|
||||
|
||||
Theme *Theme::fromFolder(const QString &p_folder)
|
||||
{
|
||||
Q_ASSERT(!p_folder.isEmpty());
|
||||
QDir dir(p_folder);
|
||||
|
||||
auto obj = readJsonFile(QDir(p_folder).filePath(getFileName(File::Palette)));
|
||||
auto obj = readPaletteFile(p_folder);
|
||||
auto metadata = readMetadata(obj);
|
||||
auto paletteObj = translatePalette(obj);
|
||||
return new Theme(p_folder,
|
||||
@ -312,6 +335,12 @@ QJsonObject Theme::readJsonFile(const QString &p_filePath)
|
||||
return QJsonDocument::fromJson(bytes).object();
|
||||
}
|
||||
|
||||
QJsonObject Theme::readPaletteFile(const QString &p_folder)
|
||||
{
|
||||
auto obj = readJsonFile(QDir(p_folder).filePath(getFileName(File::Palette)));
|
||||
return obj;
|
||||
}
|
||||
|
||||
QJsonValue Theme::findValueByKeyPath(const Palette &p_palette, const QString &p_keyPath)
|
||||
{
|
||||
auto keys = p_keyPath.split('#');
|
||||
@ -366,6 +395,8 @@ QString Theme::getFileName(File p_fileType)
|
||||
return QStringLiteral("editor-highlight.theme");
|
||||
case File::MarkdownEditorHighlightStyle:
|
||||
return QStringLiteral("markdown-editor-highlight.theme");
|
||||
case File::Cover:
|
||||
return QStringLiteral("cover.png");
|
||||
default:
|
||||
Q_ASSERT(false);
|
||||
return "";
|
||||
@ -395,3 +426,18 @@ QString Theme::getMarkdownEditorHighlightTheme() const
|
||||
|
||||
return getEditorHighlightTheme();
|
||||
}
|
||||
|
||||
QString Theme::name() const
|
||||
{
|
||||
return PathUtils::dirName(m_themeFolderPath);
|
||||
}
|
||||
|
||||
QPixmap Theme::getCover(const QString &p_folder)
|
||||
{
|
||||
QDir dir(p_folder);
|
||||
if (dir.exists(getFileName(File::Cover))) {
|
||||
const auto coverFile = dir.filePath(getFileName(File::Cover));
|
||||
return QPixmap(coverFile);
|
||||
}
|
||||
return QPixmap();
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <QHash>
|
||||
#include <QJsonObject>
|
||||
#include <QPair>
|
||||
#include <QPixmap>
|
||||
|
||||
namespace tests
|
||||
{
|
||||
@ -26,6 +27,7 @@ namespace vnotex
|
||||
MarkdownEditorStyle,
|
||||
EditorHighlightStyle,
|
||||
MarkdownEditorHighlightStyle,
|
||||
Cover,
|
||||
Max
|
||||
};
|
||||
|
||||
@ -42,10 +44,16 @@ namespace vnotex
|
||||
// Return the file path of the theme or just the theme name.
|
||||
QString getMarkdownEditorHighlightTheme() const;
|
||||
|
||||
QString name() const;
|
||||
|
||||
static bool isValidThemeFolder(const QString &p_folder);
|
||||
|
||||
static Theme *fromFolder(const QString &p_folder);
|
||||
|
||||
static QString getDisplayName(const QString &p_folder, const QString &p_locale);
|
||||
|
||||
static QPixmap getCover(const QString &p_folder);
|
||||
|
||||
private:
|
||||
struct Metadata
|
||||
{
|
||||
@ -100,6 +108,8 @@ namespace vnotex
|
||||
|
||||
static QJsonObject readJsonFile(const QString &p_filePath);
|
||||
|
||||
static QJsonObject readPaletteFile(const QString &p_folder);
|
||||
|
||||
// Whether @p_str is a reference definition like "@xxxx".
|
||||
static bool isRef(const QString &p_str);
|
||||
|
||||
|
@ -8,6 +8,8 @@
|
||||
#include "exception.h"
|
||||
#include <utils/iconutils.h>
|
||||
#include <vtextedit/vtexteditor.h>
|
||||
#include "configmgr.h"
|
||||
#include "coreconfig.h"
|
||||
|
||||
using namespace vnotex;
|
||||
|
||||
@ -37,11 +39,13 @@ QString ThemeMgr::getIconFile(const QString &p_icon) const
|
||||
|
||||
void ThemeMgr::loadAvailableThemes()
|
||||
{
|
||||
m_themes.clear();
|
||||
|
||||
for (const auto &pa : s_searchPaths) {
|
||||
loadThemes(pa);
|
||||
}
|
||||
|
||||
if (m_availableThemes.isEmpty()) {
|
||||
if (m_themes.isEmpty()) {
|
||||
Exception::throwOne(Exception::Type::EssentialFileMissing,
|
||||
QString("no available themes found in paths: %1").arg(s_searchPaths.join(QLatin1Char(';'))));
|
||||
}
|
||||
@ -53,17 +57,21 @@ void ThemeMgr::loadThemes(const QString &p_path)
|
||||
QDir dir(p_path);
|
||||
dir.setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
|
||||
auto themeFolders = dir.entryList();
|
||||
const auto localeStr = ConfigMgr::getInst().getCoreConfig().getLocaleToUse();
|
||||
for (auto &folder : themeFolders) {
|
||||
checkAndAddThemeFolder(PathUtils::concatenateFilePath(p_path, folder));
|
||||
checkAndAddThemeFolder(PathUtils::concatenateFilePath(p_path, folder), localeStr);
|
||||
}
|
||||
}
|
||||
|
||||
void ThemeMgr::checkAndAddThemeFolder(const QString &p_folder)
|
||||
void ThemeMgr::checkAndAddThemeFolder(const QString &p_folder, const QString &p_locale)
|
||||
{
|
||||
if (Theme::isValidThemeFolder(p_folder)) {
|
||||
QString themeName = PathUtils::dirName(p_folder);
|
||||
m_availableThemes.insert(themeName, p_folder);
|
||||
qDebug() << "add theme" << themeName << p_folder;
|
||||
ThemeInfo info;
|
||||
info.m_name = PathUtils::dirName(p_folder);
|
||||
info.m_displayName = Theme::getDisplayName(p_folder, p_locale);
|
||||
info.m_folderPath = p_folder;
|
||||
m_themes.push_back(info);
|
||||
qDebug() << "add theme" << info.m_name << info.m_displayName << info.m_folderPath;
|
||||
}
|
||||
}
|
||||
|
||||
@ -76,14 +84,14 @@ void ThemeMgr::loadCurrentTheme(const QString &p_themeName)
|
||||
{
|
||||
auto themeFolder = findThemeFolder(p_themeName);
|
||||
if (themeFolder.isNull()) {
|
||||
qCritical() << "fail to locate theme" << p_themeName;
|
||||
qWarning() << "failed to locate theme" << p_themeName;
|
||||
} else {
|
||||
m_currentTheme.reset(loadTheme(themeFolder));
|
||||
}
|
||||
|
||||
if (!m_currentTheme) {
|
||||
const QString defaultTheme("native");
|
||||
qInfo() << "fall back to default theme" << defaultTheme;
|
||||
qWarning() << "fall back to default theme" << defaultTheme;
|
||||
m_currentTheme.reset(loadTheme(findThemeFolder(defaultTheme)));
|
||||
}
|
||||
}
|
||||
@ -91,28 +99,38 @@ void ThemeMgr::loadCurrentTheme(const QString &p_themeName)
|
||||
Theme *ThemeMgr::loadTheme(const QString &p_themeFolder)
|
||||
{
|
||||
if (p_themeFolder.isEmpty()) {
|
||||
qCritical("fail to load theme from empty folder");
|
||||
qWarning("failed to load theme from empty folder");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
try {
|
||||
return Theme::fromFolder(p_themeFolder);
|
||||
} catch (Exception &p_e) {
|
||||
qCritical("fail to load theme from folder %s (%s)",
|
||||
p_themeFolder.toStdString().c_str(),
|
||||
p_e.what());
|
||||
qWarning("failed to load theme from folder %s (%s)",
|
||||
p_themeFolder.toStdString().c_str(),
|
||||
p_e.what());
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
QString ThemeMgr::findThemeFolder(const QString &p_name) const
|
||||
{
|
||||
auto it = m_availableThemes.find(p_name);
|
||||
if (it != m_availableThemes.end()) {
|
||||
return it.value();
|
||||
auto theme = findTheme(p_name);
|
||||
if (theme) {
|
||||
return theme->m_folderPath;
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
const ThemeMgr::ThemeInfo *ThemeMgr::findTheme(const QString &p_name) const
|
||||
{
|
||||
for (const auto &info : m_themes) {
|
||||
if (info.m_name == p_name) {
|
||||
return &info;
|
||||
}
|
||||
}
|
||||
|
||||
return QString();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QString ThemeMgr::fetchQtStyleSheet() const
|
||||
@ -165,3 +183,22 @@ void ThemeMgr::setBaseBackground(const QColor &p_bg)
|
||||
{
|
||||
m_baseBackground = p_bg;
|
||||
}
|
||||
|
||||
const QVector<ThemeMgr::ThemeInfo> &ThemeMgr::getAllThemes() const
|
||||
{
|
||||
return m_themes;
|
||||
}
|
||||
|
||||
QPixmap ThemeMgr::getThemePreview(const QString &p_name) const
|
||||
{
|
||||
auto theme = findTheme(p_name);
|
||||
if (theme) {
|
||||
return Theme::getCover(theme->m_folderPath);
|
||||
}
|
||||
return QPixmap();
|
||||
}
|
||||
|
||||
void ThemeMgr::refresh()
|
||||
{
|
||||
loadAvailableThemes();
|
||||
}
|
||||
|
@ -4,10 +4,11 @@
|
||||
#include <QObject>
|
||||
|
||||
#include <QString>
|
||||
#include <QHash>
|
||||
#include <QScopedPointer>
|
||||
#include <QStringList>
|
||||
#include <QVector>
|
||||
#include <QColor>
|
||||
#include <QPixmap>
|
||||
|
||||
#include "theme.h"
|
||||
|
||||
@ -17,6 +18,17 @@ namespace vnotex
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
struct ThemeInfo
|
||||
{
|
||||
// Id.
|
||||
QString m_name;
|
||||
|
||||
// Locale supported.
|
||||
QString m_displayName;
|
||||
|
||||
QString m_folderPath;
|
||||
};
|
||||
|
||||
ThemeMgr(const QString &p_currentThemeName, QObject *p_parent = nullptr);
|
||||
|
||||
// @p_icon: file path or file name of the icon.
|
||||
@ -40,6 +52,18 @@ namespace vnotex
|
||||
const QColor &getBaseBackground() const;
|
||||
void setBaseBackground(const QColor &p_bg);
|
||||
|
||||
const QVector<ThemeInfo> &getAllThemes() const;
|
||||
|
||||
const Theme &getCurrentTheme() const;
|
||||
|
||||
QPixmap getThemePreview(const QString &p_name) const;
|
||||
|
||||
const ThemeInfo *findTheme(const QString &p_name) const;
|
||||
|
||||
// Refresh the themes list.
|
||||
// Won't affect current theme since we do not support changing theme real time for now.
|
||||
void refresh();
|
||||
|
||||
static void addSearchPath(const QString &p_path);
|
||||
|
||||
static void addSyntaxHighlightingSearchPaths(const QStringList &p_paths);
|
||||
@ -49,9 +73,7 @@ namespace vnotex
|
||||
|
||||
void loadThemes(const QString &p_path);
|
||||
|
||||
void checkAndAddThemeFolder(const QString &p_folder);
|
||||
|
||||
const Theme &getCurrentTheme() const;
|
||||
void checkAndAddThemeFolder(const QString &p_folder, const QString &p_locale);
|
||||
|
||||
void loadCurrentTheme(const QString &p_themeName);
|
||||
|
||||
@ -59,8 +81,7 @@ namespace vnotex
|
||||
|
||||
QString findThemeFolder(const QString &p_name) const;
|
||||
|
||||
// Theme name to folder path mapping.
|
||||
QHash<QString, QString> m_availableThemes;
|
||||
QVector<ThemeInfo> m_themes;
|
||||
|
||||
QScopedPointer<Theme> m_currentTheme;
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
<file>themes/native/interface.qss</file>
|
||||
<file>themes/native/web.css</file>
|
||||
<file>themes/native/palette.json</file>
|
||||
<file>themes/native/cover.png</file>
|
||||
<file>docs/en/get_started.txt</file>
|
||||
<file>docs/en/about_vnotex.txt</file>
|
||||
<file>docs/en/shortcuts.md</file>
|
||||
|
BIN
src/data/extra/themes/native/cover.png
Normal file
BIN
src/data/extra/themes/native/cover.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 237 KiB |
@ -7,7 +7,10 @@
|
||||
"//comment" : "If there is a file named 'markdown-editor-highlight.theme' under theme folder, this value will be ignored.",
|
||||
"//comment" : "Otherwise, this value specify the theme name to use.",
|
||||
"//comment" : "If empty, editor-highlight-theme will be used.",
|
||||
"markdown-editor-highlight-theme" : "Markdown Default"
|
||||
"markdown-editor-highlight-theme" : "Markdown Default",
|
||||
"display_name" : "Native",
|
||||
"//comment" : "Display name for different locales",
|
||||
"display_name_zh_CN" : "原素"
|
||||
},
|
||||
"base" : {
|
||||
"fg1" : "#31373c",
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <QModelIndex>
|
||||
#include <QFontDatabase>
|
||||
#include <QMenu>
|
||||
#include <QDebug>
|
||||
|
||||
using namespace vnotex;
|
||||
|
||||
@ -188,29 +189,62 @@ void WidgetUtils::resizeToHideScrollBarLater(QScrollArea *p_scroll, bool p_verti
|
||||
|
||||
void WidgetUtils::resizeToHideScrollBar(QScrollArea *p_scroll, bool p_vertical, bool p_horizontal)
|
||||
{
|
||||
p_scroll->adjustSize();
|
||||
bool changed = false;
|
||||
auto parentWidget = p_scroll->parentWidget();
|
||||
|
||||
if (p_horizontal && WidgetUtils::isScrollBarVisible(p_scroll, true)) {
|
||||
auto scrollBar = p_scroll->horizontalScrollBar();
|
||||
auto delta = scrollBar->maximum() - scrollBar->minimum();
|
||||
int newWidth = p_scroll->width() + delta;
|
||||
auto availableSize = WidgetUtils::availableScreenSize(p_scroll);
|
||||
if (newWidth <= availableSize.width()) {
|
||||
p_scroll->resize(newWidth, p_scroll->height());
|
||||
|
||||
if (parentWidget) {
|
||||
int newWidth = parentWidget->width() + delta;
|
||||
if (newWidth <= availableSize.width()) {
|
||||
changed = true;
|
||||
p_scroll->resize(p_scroll->width() + delta, p_scroll->height());
|
||||
auto geo = parentWidget->geometry();
|
||||
parentWidget->setGeometry(geo.x() - delta / 2,
|
||||
geo.y(),
|
||||
newWidth,
|
||||
geo.height());
|
||||
}
|
||||
} else {
|
||||
int newWidth = p_scroll->width() + delta;
|
||||
if (newWidth <= availableSize.width()) {
|
||||
changed = true;
|
||||
p_scroll->resize(newWidth, p_scroll->height());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (p_vertical && WidgetUtils::isScrollBarVisible(p_scroll, false)) {
|
||||
auto scrollBar = p_scroll->verticalScrollBar();
|
||||
auto delta = scrollBar->maximum() - scrollBar->minimum();
|
||||
int newHeight = p_scroll->height() + delta;
|
||||
auto availableSize = WidgetUtils::availableScreenSize(p_scroll);
|
||||
if (newHeight <= availableSize.height()) {
|
||||
p_scroll->resize(p_scroll->width(), newHeight);
|
||||
|
||||
if (parentWidget) {
|
||||
int newHeight = parentWidget->height() + delta;
|
||||
if (newHeight <= availableSize.height()) {
|
||||
changed = true;
|
||||
p_scroll->resize(p_scroll->width(), p_scroll->height() + delta);
|
||||
auto geo = parentWidget->geometry();
|
||||
parentWidget->setGeometry(geo.x(),
|
||||
geo.y() - delta / 2,
|
||||
geo.width(),
|
||||
newHeight);
|
||||
}
|
||||
} else {
|
||||
int newHeight = p_scroll->height() + delta;
|
||||
if (newHeight <= availableSize.height()) {
|
||||
changed = true;
|
||||
p_scroll->resize(p_scroll->width(), newHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p_scroll->updateGeometry();
|
||||
if (changed) {
|
||||
p_scroll->updateGeometry();
|
||||
}
|
||||
}
|
||||
|
||||
QShortcut *WidgetUtils::createShortcut(const QString &p_shortcut,
|
||||
|
@ -35,7 +35,7 @@ void SettingsDialog::setupUI()
|
||||
setupPageExplorer(mainLayout, widget);
|
||||
|
||||
m_pageLayout = new QStackedLayout();
|
||||
mainLayout->addLayout(m_pageLayout, 3);
|
||||
mainLayout->addLayout(m_pageLayout, 5);
|
||||
|
||||
setDialogButtonBox(QDialogButtonBox::Ok
|
||||
| QDialogButtonBox::Apply
|
||||
@ -56,6 +56,7 @@ void SettingsDialog::setupPageExplorer(QBoxLayout *p_layout, QWidget *p_parent)
|
||||
m_pageExplorer = new TreeWidget(TreeWidget::None, p_parent);
|
||||
TreeWidget::setupSingleColumnHeaderlessTree(m_pageExplorer, false, false);
|
||||
TreeWidget::showHorizontalScrollbar(m_pageExplorer);
|
||||
m_pageExplorer->setMinimumWidth(128);
|
||||
layout->addWidget(m_pageExplorer);
|
||||
|
||||
connect(m_pageExplorer, &QTreeWidget::currentItemChanged,
|
||||
@ -65,7 +66,7 @@ void SettingsDialog::setupPageExplorer(QBoxLayout *p_layout, QWidget *p_parent)
|
||||
m_pageLayout->setCurrentWidget(page);
|
||||
});
|
||||
|
||||
p_layout->addLayout(layout, 1);
|
||||
p_layout->addLayout(layout, 2);
|
||||
}
|
||||
|
||||
void SettingsDialog::setupPages()
|
||||
|
@ -2,8 +2,22 @@
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QGridLayout>
|
||||
#include <QLabel>
|
||||
#include <QGroupBox>
|
||||
#include <QDebug>
|
||||
#include <QUrl>
|
||||
#include <QScrollArea>
|
||||
|
||||
#include <widgets/listwidget.h>
|
||||
#include <QPushButton>
|
||||
#include <QListWidgetItem>
|
||||
#include <widgets/widgetsfactory.h>
|
||||
#include <core/thememgr.h>
|
||||
#include <core/vnotex.h>
|
||||
#include <core/configmgr.h>
|
||||
#include <utils/widgetutils.h>
|
||||
|
||||
using namespace vnotex;
|
||||
|
||||
@ -16,10 +30,71 @@ ThemePage::ThemePage(QWidget *p_parent)
|
||||
void ThemePage::setupUI()
|
||||
{
|
||||
auto mainLayout = new QVBoxLayout(this);
|
||||
|
||||
// Theme.
|
||||
{
|
||||
auto layout = new QGridLayout();
|
||||
mainLayout->addLayout(layout);
|
||||
|
||||
m_themeListWidget = new ListWidget(this);
|
||||
layout->addWidget(m_themeListWidget, 0, 0, 3, 2);
|
||||
connect(m_themeListWidget, &QListWidget::currentItemChanged,
|
||||
this, [this](QListWidgetItem *p_current, QListWidgetItem *p_previous) {
|
||||
Q_UNUSED(p_previous);
|
||||
loadThemePreview(p_current ? p_current->data(Qt::UserRole).toString() : QString());
|
||||
pageIsChanged();
|
||||
});
|
||||
|
||||
auto refreshBtn = new QPushButton(tr("Refresh"), this);
|
||||
layout->addWidget(refreshBtn, 3, 0, 1, 1);
|
||||
connect(refreshBtn, &QPushButton::clicked,
|
||||
this, [this]() {
|
||||
VNoteX::getInst().getThemeMgr().refresh();
|
||||
loadThemes();
|
||||
});
|
||||
|
||||
auto addBtn = new QPushButton(tr("Add/Delete"), this);
|
||||
layout->addWidget(addBtn, 3, 1, 1, 1);
|
||||
// TODO: open an editor to edit the theme list.
|
||||
connect(addBtn, &QPushButton::clicked,
|
||||
this, []() {
|
||||
WidgetUtils::openUrlByDesktop(QUrl::fromLocalFile(ConfigMgr::getInst().getUserThemeFolder()));
|
||||
});
|
||||
|
||||
auto updateBtn = new QPushButton(tr("Update"), this);
|
||||
layout->addWidget(updateBtn, 4, 0, 1, 1);
|
||||
|
||||
auto openLocationBtn = new QPushButton(tr("Open Location"), this);
|
||||
layout->addWidget(openLocationBtn, 4, 1, 1, 1);
|
||||
connect(openLocationBtn, &QPushButton::clicked,
|
||||
this, [this]() {
|
||||
auto theme = VNoteX::getInst().getThemeMgr().findTheme(currentTheme());
|
||||
if (theme) {
|
||||
WidgetUtils::openUrlByDesktop(QUrl::fromLocalFile(theme->m_folderPath));
|
||||
}
|
||||
});
|
||||
|
||||
m_noPreviewText = tr("No Preview Available");
|
||||
m_previewLabel = new QLabel(m_noPreviewText, this);
|
||||
m_previewLabel->setScaledContents(true);
|
||||
m_previewLabel->setAlignment(Qt::AlignCenter | Qt::AlignVCenter);
|
||||
auto scrollArea = new QScrollArea(this);
|
||||
scrollArea->setBackgroundRole(QPalette::Dark);
|
||||
scrollArea->setWidget(m_previewLabel);
|
||||
scrollArea->setMinimumSize(256, 256);
|
||||
layout->addWidget(scrollArea, 0, 2, 5, 1);
|
||||
}
|
||||
|
||||
// Override.
|
||||
{
|
||||
auto box = new QGroupBox(tr("Style Override"), this);
|
||||
mainLayout->addWidget(box);
|
||||
}
|
||||
}
|
||||
|
||||
void ThemePage::loadInternal()
|
||||
{
|
||||
loadThemes();
|
||||
}
|
||||
|
||||
void ThemePage::saveInternal()
|
||||
@ -30,3 +105,56 @@ QString ThemePage::title() const
|
||||
{
|
||||
return tr("Theme");
|
||||
}
|
||||
|
||||
void ThemePage::loadThemes()
|
||||
{
|
||||
const auto &themeMgr = VNoteX::getInst().getThemeMgr();
|
||||
const auto &themes = themeMgr.getAllThemes();
|
||||
|
||||
m_themeListWidget->clear();
|
||||
for (const auto &info : themes) {
|
||||
auto item = new QListWidgetItem(info.m_displayName, m_themeListWidget);
|
||||
item->setData(Qt::UserRole, info.m_name);
|
||||
item->setToolTip(info.m_folderPath);
|
||||
}
|
||||
|
||||
// Set current theme.
|
||||
bool found = false;
|
||||
const auto curThemeName = themeMgr.getCurrentTheme().name();
|
||||
for (int i = 0; i < m_themeListWidget->count(); ++i) {
|
||||
if (m_themeListWidget->item(i)->data(Qt::UserRole).toString() == curThemeName) {
|
||||
m_themeListWidget->setCurrentRow(i);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found && m_themeListWidget->count() > 0) {
|
||||
m_themeListWidget->setCurrentRow(0);
|
||||
}
|
||||
}
|
||||
|
||||
void ThemePage::loadThemePreview(const QString &p_name)
|
||||
{
|
||||
if (p_name.isEmpty()) {
|
||||
m_previewLabel->setText(m_noPreviewText);
|
||||
}
|
||||
|
||||
auto pixmap = VNoteX::getInst().getThemeMgr().getThemePreview(p_name);
|
||||
if (pixmap.isNull()) {
|
||||
m_previewLabel->setText(m_noPreviewText);
|
||||
} else {
|
||||
const int pwidth = 512;
|
||||
m_previewLabel->setPixmap(pixmap.scaledToWidth(pwidth, Qt::SmoothTransformation));
|
||||
}
|
||||
m_previewLabel->adjustSize();
|
||||
}
|
||||
|
||||
QString ThemePage::currentTheme() const
|
||||
{
|
||||
auto item = m_themeListWidget->currentItem();
|
||||
if (item) {
|
||||
return item->data(Qt::UserRole).toString();
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
@ -3,6 +3,9 @@
|
||||
|
||||
#include "settingspage.h"
|
||||
|
||||
class QListWidget;
|
||||
class QLabel;
|
||||
|
||||
namespace vnotex
|
||||
{
|
||||
class ThemePage : public SettingsPage
|
||||
@ -20,6 +23,18 @@ namespace vnotex
|
||||
|
||||
private:
|
||||
void setupUI();
|
||||
|
||||
void loadThemes();
|
||||
|
||||
void loadThemePreview(const QString &p_name);
|
||||
|
||||
QString currentTheme() const;
|
||||
|
||||
QListWidget *m_themeListWidget = nullptr;
|
||||
|
||||
QLabel *m_previewLabel = nullptr;
|
||||
|
||||
QString m_noPreviewText;
|
||||
};
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user