diff --git a/CMakeLists.txt b/CMakeLists.txt index 3b7eafc39dfc01f9e1b509c2d907480c0fc273e9..4b9521daace8a8d108f556c5f13bd582f085de6c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,20 +1,24 @@ cmake_minimum_required(VERSION 3.5) +project(kiran-integration VERSION 2.7.0) + set(CMAKE_CXX_STANDARD 11) -project(kiran-qt5-integration) +set(CMAKE_CXX_STANDARD_REQUIRED on) + +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") + +find_package(PkgConfig REQUIRED) +find_package(KQI REQUIRED) +find_package(Qt5 COMPONENTS Core Gui Widgets Svg DBus) -set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules ${ECM_MODULE_PATH} ) -list(APPEND ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake/modules/) +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTOUIC ON) +set(CMAKE_AUTORCC ON) -include(GNUInstallDirs) -include(Qt5PluginInstallDirs) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake-macros.h.in + ${CMAKE_CURRENT_BINARY_DIR}/cmake-macros.h) -#共用代码,生成静态库 -add_subdirectory(common) -#QPlatformTheme插件 -add_subdirectory(platformtheme) -#KiranStyle提供的相关接口,也提供给KiranStyle获取颜色表内容的接口 -add_subdirectory(style-helper) -#QStyle插件 -add_subdirectory(style) -#add_subdirectory(integration-test) +add_subdirectory(data) +add_subdirectory(lib) +add_subdirectory(plugins) +add_subdirectory(examples) diff --git a/README.md b/README.md index 484e8d6c2ba146ff26d90044a24e38cb82d77af5..e4723ad6c2966ecc7c13c222211e1493fc5f6c9d 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # kiran-qt5-integration -#### 介绍 +## 介绍 Kiran桌面qt5平台一体化插件,其中包含QPlatformTheme插件,QStyle插件以及提供给开发使用的kiran-style-helper的共享库 -#### 编译安装 +## 编译安装 ```shell # yum install cmake gcc-c++ qt5-linguist qt5-qtbase-devel qt5-qtbase-private-devel qt5-qtx11extras-devel kiran-qdbusxml2cpp kiran-log-qt5-devel qt5-qtsvg-devel gsettings-qt-devel # mkdir @@ -12,5 +12,45 @@ Kiran桌面qt5平台一体化插件,其中包含QPlatformTheme插件,QStyle插 # make install ``` -#### 运行 +## 运行 不需要运行,安装后,若是kiran桌面环境则会加载kiran QPlatformTheme插件,kiran QPlatformTheme插件会使Qt应用加载Kiran QStyle插件。也可通过启动参数-platformtheme和-style指定加载 + +插件会自动匹配指定的应用程序采用该主题样式,主要通过两种方式指定应用程序: +### 1. 代码内置 + +### 2. 配置文件 +配置文件地址: `/etc/kiran-integration/kiran-qt5-integration.ini` +内容如下: +```ini +[Style] +#启用kiran style的应用列表,已内置部分kiran桌面环境的组件,eg: kiran-*,kiran-panel +enabled-apps=ksl-os-gui,ksl-server-gui,ks-scmc-gui +``` + + +## 代码结构 + +- lib + - style: 实现自定义的QStyle,提供给QT插件和上层应用使用 +- plugins + - platformtheme: qt平台主题插件 + - style: qt style插件 + - decoration: kwin窗口标题栏样式插件 + + +## Other +```shell +cmake -S . -B build -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug +cmake --build build -j12 +sudo cmake --install build +./build/examples/kiran-integration-example + +# uninstall (just remove installed file) +sudo xargs rm -v < ./build/install_manifest.txt +``` + +### DEBUG +```shell +export QT_QPA_PLATFORMTHEME=kiran-next +export QT_DEBUG_PLUGINS=1 +``` \ No newline at end of file diff --git a/cmake-macros.h.in b/cmake-macros.h.in new file mode 100644 index 0000000000000000000000000000000000000000..4521a951256495eabb69d40a867ad86a3748ab23 --- /dev/null +++ b/cmake-macros.h.in @@ -0,0 +1,10 @@ + +#pragma once + +#define KQI_INSTALL_BINDIR "@CMAKE_INSTALL_FULL_BINDIR@" +#define KQI_INSTALL_DATADIR "@KQI_INSTALL_DATADIR@" +#define KQI_INSTALL_TRANSLATIONDIR "@KQI_INSTALL_TRANSLATIONDIR@" +#define PROJECT_NAME "@PROJECT_NAME@" +#define PROJECT_VERSION "@PROJECT_VERSION@" + +#define KQI_CONFIGURATION_PATH "@KQI_INSTALL_DATADIR@/@PROJECT_NAME@.ini" diff --git a/cmake/FindKQI.cmake b/cmake/FindKQI.cmake new file mode 100644 index 0000000000000000000000000000000000000000..b6b3574d29ff774a82acca3aa937f04dc63b00b2 --- /dev/null +++ b/cmake/FindKQI.cmake @@ -0,0 +1,2 @@ +include("kqi-macros") +include("kqi-variables") diff --git a/cmake/modules/FindQt5ThemeSupport.cmake b/cmake/FindQt5ThemeSupport.cmake similarity index 36% rename from cmake/modules/FindQt5ThemeSupport.cmake rename to cmake/FindQt5ThemeSupport.cmake index d5c1753f8631d25aa6c9e793117daa2ca2fad559..2c3ec51d4a71eef758cd5ae557c4228b3f595539 100644 --- a/cmake/modules/FindQt5ThemeSupport.cmake +++ b/cmake/FindQt5ThemeSupport.cmake @@ -1,44 +1,38 @@ find_package(PkgConfig) -# 提取Qt5Gui.pc中的信息 +# 提取Qt5Gui.pc中的信息 pkg_check_modules(PKG_Qt5ThemeSupport QUIET Qt5Gui) set(Qt5ThemeSupport_DEFINITIONS ${PKG_Qt5ThemeSupport_CFLAGS_OTHER}) set(Qt5ThemeSupport_VERSION ${PKG_Qt5ThemeSupport_VERSION}) # 拼出Qt5ThemeSupport头文件路径 -find_path(Qt5ThemeSupport_INCLUDE_DIR - NAMES - QtThemeSupport/private/qgenericunixthemes_p.h - HINTS - ${PKG_Qt5ThemeSupport_INCLUDEDIR}/QtThemeSupport/${PKG_Qt5ThemeSupport_VERSION}/ - ) - -# 拼出Qt5ThemeSupport静态库位置 -find_library(Qt5ThemeSupport_LIBRARY - NAMES - Qt5ThemeSupport - HINTS - ${PKG_Qt5ThemeSupport_LIBRARY_DIRS} - ) +find_path( + Qt5ThemeSupport_INCLUDE_DIR + NAMES QtThemeSupport/private/qgenericunixthemes_p.h + HINTS + ${PKG_Qt5ThemeSupport_INCLUDEDIR}/QtThemeSupport/${PKG_Qt5ThemeSupport_VERSION}/ +) + +# 拼出Qt5ThemeSupport静态库位置 +find_library( + Qt5ThemeSupport_LIBRARY + NAMES Qt5ThemeSupport + HINTS ${PKG_Qt5ThemeSupport_LIBRARY_DIRS}) include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(Qt5ThemeSupport - FOUND_VAR - Qt5ThemeSupport_FOUND - REQUIRED_VARS - Qt5ThemeSupport_LIBRARY - Qt5ThemeSupport_INCLUDE_DIR - VERSION_VAR - Qt5ThemeSupport_VERSION - ) +find_package_handle_standard_args( + Qt5ThemeSupport + FOUND_VAR Qt5ThemeSupport_FOUND + REQUIRED_VARS Qt5ThemeSupport_LIBRARY Qt5ThemeSupport_INCLUDE_DIR + VERSION_VAR Qt5ThemeSupport_VERSION) if(Qt5ThemeSupport_FOUND AND NOT TARGET Qt5ThemeSupport::Qt5ThemeSupport) - add_library(Qt5ThemeSupport::Qt5ThemeSupport UNKNOWN IMPORTED) - set_target_properties(Qt5ThemeSupport::Qt5ThemeSupport PROPERTIES - IMPORTED_LOCATION "${Qt5ThemeSupport_LIBRARY}" - INTERFACE_COMPILE_OPTIONS "${Qt5ThemeSupport_DEFINITIONS}" - INTERFACE_INCLUDE_DIRECTORIES "${Qt5ThemeSupport_INCLUDE_DIR}" - ) + add_library(Qt5ThemeSupport::Qt5ThemeSupport UNKNOWN IMPORTED) + set_target_properties( + Qt5ThemeSupport::Qt5ThemeSupport + PROPERTIES IMPORTED_LOCATION "${Qt5ThemeSupport_LIBRARY}" + INTERFACE_COMPILE_OPTIONS "${Qt5ThemeSupport_DEFINITIONS}" + INTERFACE_INCLUDE_DIRECTORIES "${Qt5ThemeSupport_INCLUDE_DIR}") endif() mark_as_advanced(Qt5ThemeSupport_LIBRARY Qt5ThemeSupport_INCLUDE_DIR) @@ -48,10 +42,8 @@ set(Qt5ThemeSupport_LIBRARIES ${Qt5ThemeSupport_LIBRARY}) set(Qt5ThemeSupport_INCLUDE_DIRS ${Qt5ThemeSupport_INCLUDE_DIR}) set(Qt5ThemeSupport_VERSION_STRING ${Qt5ThemeSupport_VERSION}) - include(FeatureSummary) -set_package_properties(Qt5ThemeSupport PROPERTIES - URL "https://www.qt.io" - DESCRIPTION "Qt ThemeSupport module." - ) - +set_package_properties( + Qt5ThemeSupport PROPERTIES + URL "https://www.qt.io" + DESCRIPTION "Qt ThemeSupport module.") diff --git a/integration-test/src/test.ui b/cmake/kqi-macros.cmake similarity index 100% rename from integration-test/src/test.ui rename to cmake/kqi-macros.cmake diff --git a/cmake/kqi-variables.cmake b/cmake/kqi-variables.cmake new file mode 100644 index 0000000000000000000000000000000000000000..a92497291235d2184c417008a579c12d1bcc7610 --- /dev/null +++ b/cmake/kqi-variables.cmake @@ -0,0 +1,16 @@ +include(GNUInstallDirs) + +find_package(PkgConfig REQUIRED) + +# 通过qt5的pkgconfig配置文件取出插件安装位置、插件共享库安装位置 +pkg_search_module(Qt5 REQUIRED Qt5) +pkg_get_variable(QT5_PLUGIN_DIR Qt5 plugindir) + +# 安装路径变量 +set(QT5_PLATFORM_THEME_INSTALL_DIR ${QT5_PLUGIN_DIR}/platformthemes/) +set(QT5_STYLE_INSTALL_DIR ${QT5_PLUGIN_DIR}/styles) + +set(KQI_INSTALL_INCLUDEDIR ${CMAKE_INSTALL_FULL_INCLUDEDIR}/${PROJECT_NAME}) +set(KQI_INSTALL_DATADIR ${CMAKE_INSTALL_FULL_DATADIR}/${PROJECT_NAME}) +set(KQI_INSTALL_TRANSLATIONDIR ${KQI_INSTALL_DATADIR}/translations) +set(KQI_INSTALL_SYSCONFDIR ${CMAKE_INSTALL_FULL_SYSCONFDIR}/${PROJECT_NAME}) diff --git a/cmake/modules/Qt5PluginInstallDirs.cmake b/cmake/modules/Qt5PluginInstallDirs.cmake deleted file mode 100644 index 5192444ea889ab3b723ee08ca3a7f49b9ea86594..0000000000000000000000000000000000000000 --- a/cmake/modules/Qt5PluginInstallDirs.cmake +++ /dev/null @@ -1,8 +0,0 @@ -find_package(PkgConfig REQUIRED) - -#通过qt5的pkgconfig配置文件取出插件安装位置、插件共享库安装位置 -pkg_search_module(Qt5 REQUIRED Qt5) -pkg_get_variable(QT5_PLUGIN_DIR Qt5 plugindir) - -set(QT5_PLATFORM_THEME_INSTALL_DIR ${QT5_PLUGIN_DIR}/platformthemes/) -set(QT5_STYLE_INSTALL_DIR ${QT5_PLUGIN_DIR}/styles) \ No newline at end of file diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt deleted file mode 100644 index db8b5ad2f2fa537eb4894af2d5dcea9a9b4a5120..0000000000000000000000000000000000000000 --- a/common/CMakeLists.txt +++ /dev/null @@ -1,55 +0,0 @@ -set(TARGET_NAME "common") - -find_package(Qt5 COMPONENTS Gui DBus) -find_package(PkgConfig REQUIRED) -find_package(KiranDBusGenerate REQUIRED) - -pkg_search_module(KIRAN_CC_DAEMON REQUIRED kiran-cc-daemon) -pkg_search_module(KLOG_QT5 REQUIRED klog-qt5) -pkg_search_module(GSETTINGS_QT REQUIRED gsettings-qt) - -set(CMAKE_AUTOMOC ON) -set(CMAKE_AUTOUIC ON) -set(CMAKE_AUTORCC ON) - -#生成使用的DBus接口源文件 -##kiran session appearance proxy -set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/data/com.kylinsec.Kiran.SessionDaemon.Appearance.xml - PROPERTIES - CLASSNAME KiranAppearanceProxy - NO_NAMESPACE true) -kiran_qt5_add_dbus_interface(KIRAN_INTERFACE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/data/com.kylinsec.Kiran.SessionDaemon.Appearance.xml kiran_appearance_proxy) -##kiran session display proxy -set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/data/com.kylinsec.Kiran.SessionDaemon.Display.xml - PROPERTIES - CLASSNAME KiranDisplayProxy - NO_NAMESPACE true) -kiran_qt5_add_dbus_interface(KIRAN_INTERFACE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/data/com.kylinsec.Kiran.SessionDaemon.Display.xml kiran_display_proxy) -#避免cmake错误 -foreach (interface_item ${KIRAN_INTERFACE_SRC}) - set_property(SOURCE ${interface_item} PROPERTY SKIP_AUTOGEN ON) -endforeach () - -file(GLOB_RECURSE COMMON_H_FILES src/*.h) -file(GLOB_RECURSE COMMON_CPP_FILES src/*.cpp) - -set (ALL_FILES ${COMMON_H_FILES} ${COMMON_CPP_FILES} ${KIRAN_INTERFACE_SRC}) -add_library(${TARGET_NAME} STATIC ${ALL_FILES}) - -target_link_libraries(${TARGET_NAME} - Qt5::Gui - Qt5::DBus - ${QGSETTINGS_LIBRARIES} - ${GSETTINGS_QT_LIBRARIES}) - -target_include_directories(${TARGET_NAME} PRIVATE - ${CMAKE_CURRENT_BINARY_DIR} - ${QGSETTINGS_INCLUDE_DIRS} - ${KIRAN_CC_DAEMON_INCLUDE_DIRS} - ${GSETTINGS_QT_INCLUDE_DIRS}) - -target_include_directories(${TARGET_NAME} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/src) - -install(FILES data/kiran-qt5-integration.ini - DESTINATION /${CMAKE_INSTALL_SYSCONFDIR}/kiran-qt5-integration/ ) \ No newline at end of file diff --git a/common/src/kiran-integration-settings.cpp b/common/src/kiran-integration-settings.cpp deleted file mode 100644 index a781fd3b40750b32a9d14a7f9b5724b54d47207f..0000000000000000000000000000000000000000 --- a/common/src/kiran-integration-settings.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#include "kiran-integration-settings.h" - -#include -#include -#include -#include -#include - -KiranIntegrationSettings::KiranIntegrationSettings() -{ - init(); -} - -KiranIntegrationSettings::~KiranIntegrationSettings() -{ - -} - -void KiranIntegrationSettings::init() -{ - QSettings settings("/etc/kiran-qt5-integration/kiran-qt5-integration.ini",QSettings::IniFormat); - QStringList kiranStyleApps = settings.value("Style/kiran-style-apps","").toStringList(); - m_kiranStyleApps.unite(kiranStyleApps.toSet()); -} - -KiranIntegrationSettings* KiranIntegrationSettings::instance() -{ - static QMutex mutex; - static QScopedPointer pInst; - - if (Q_UNLIKELY(!pInst)) - { - QMutexLocker locker(&mutex); - if (pInst.isNull()) - { - pInst.reset(new KiranIntegrationSettings); - } - } - - return pInst.data(); -} - -QSet KiranIntegrationSettings::getKiranStyleApps() -{ - return m_kiranStyleApps; -} - -bool KiranIntegrationSettings::appKiranStyleAvailable(const QString& app) -{ - bool matched = false; - QRegExp regExp("",Qt::CaseSensitive,QRegExp::Wildcard); - - auto set = KiranIntegrationSettings::instance()->getKiranStyleApps(); - foreach(auto pattern,set) - { - regExp.setPattern(pattern); - matched = regExp.exactMatch(app); - if( matched ) - break; - } - - return matched; -} \ No newline at end of file diff --git a/common/src/kiran-integration-settings.h b/common/src/kiran-integration-settings.h deleted file mode 100644 index 22d7be448d0aeaa1b7424bbc15f66f834f60c157..0000000000000000000000000000000000000000 --- a/common/src/kiran-integration-settings.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include -#include - -class KiranIntegrationSettings -{ -public: - static KiranIntegrationSettings* instance(); - ~KiranIntegrationSettings(); - - QSet getKiranStyleApps(); - static bool appKiranStyleAvailable(const QString& app); - -private: - KiranIntegrationSettings(); - void init(); - -private: - QSet m_kiranStyleApps = { - "kiran-control-panel", - "kiran-cpanel-*", - "kiran-polkit-agent", - "kiran-avatar-editor", - "kiran-calculator", - "kiran-power-status-icon", - "kiran-network-status-icon", - "kiran-audio-status-icon", - "kiran-flameshot" - }; -}; \ No newline at end of file diff --git a/common/src/logging-category.cpp b/common/src/logging-category.cpp deleted file mode 100644 index 6e65f6264810756451b1c0084f95dea8d3c9c5f5..0000000000000000000000000000000000000000 --- a/common/src/logging-category.cpp +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. - * kiran-qt5-integration is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - * - * Author: liuxinhao - */ - -#include "logging-category.h" - -Q_LOGGING_CATEGORY(kiranPlatformThemeCommon,"kiran.platformtheme.common",QtWarningMsg) diff --git a/data/CMakeLists.txt b/data/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..3b7edf48687377277278b3ffb960c1a3e3cbb554 --- /dev/null +++ b/data/CMakeLists.txt @@ -0,0 +1,7 @@ +configure_file(kiran-integration-theme.pc.in kiran-integration-theme.pc @ONLY) + +install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/kiran-qt5-integration.ini + DESTINATION ${KQI_INSTALL_SYSCONFDIR}) + +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/kiran-integration-theme.pc + DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig/) diff --git a/common/data/com.kylinsec.Kiran.SessionDaemon.Appearance.xml b/data/com.kylinsec.Kiran.SessionDaemon.Appearance.xml similarity index 100% rename from common/data/com.kylinsec.Kiran.SessionDaemon.Appearance.xml rename to data/com.kylinsec.Kiran.SessionDaemon.Appearance.xml diff --git a/common/data/com.kylinsec.Kiran.SessionDaemon.Display.xml b/data/com.kylinsec.Kiran.SessionDaemon.Display.xml similarity index 100% rename from common/data/com.kylinsec.Kiran.SessionDaemon.Display.xml rename to data/com.kylinsec.Kiran.SessionDaemon.Display.xml diff --git a/data/kiran-integration-theme.pc.in b/data/kiran-integration-theme.pc.in new file mode 100644 index 0000000000000000000000000000000000000000..3feadfdb8c457922f02a9850d8147300677b0fbf --- /dev/null +++ b/data/kiran-integration-theme.pc.in @@ -0,0 +1,9 @@ +LibDir=@CMAKE_INSTALL_FULL_LIBDIR@ +IncludeDir=@KQI_INSTALL_INCLUDEDIR@/theme + +Name: kiran integration theme library +Description: kiran integration theme library +Version: @PROJECT_VERSION@ +Requires: Qt5Core Qt5Gui Qt5Widgets +Libs: -L${LibDir} -lkiran-integration-theme +Cflags: -I${IncludeDir} diff --git a/common/data/kiran-qt5-integration.ini b/data/kiran-qt5-integration.ini similarity index 59% rename from common/data/kiran-qt5-integration.ini rename to data/kiran-qt5-integration.ini index 3bc4a53c1e461ab2801f8800a76cf252f1831440..8db983cac0a5e72f9ecd0f118d71da590ac9baef 100644 --- a/common/data/kiran-qt5-integration.ini +++ b/data/kiran-qt5-integration.ini @@ -1,3 +1,3 @@ [Style] #启用kiran style的应用列表,已内置部分kiran桌面环境的组件,eg: kiran-*,kiran-panel -kiran-style-apps=ksl-os-gui,ksl-server-gui,ks-scmc-gui \ No newline at end of file +enabled-apps=ksl-os-gui,ksl-server-gui,ks-scmc-gui,kiran-integration-example \ No newline at end of file diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..f874907bee0cad18f4f03b3bba8bf4fa7ab98634 --- /dev/null +++ b/examples/CMakeLists.txt @@ -0,0 +1,20 @@ +set(TARGET_NAME "kiran-integration-example") + +find_package(Qt5 COMPONENTS Widgets Svg) +pkg_search_module(KLOG_QT5 REQUIRED klog-qt5) + +file(GLOB_RECURSE EXAMPLE_H_FILES "./*.h") +file(GLOB_RECURSE EXAMPLE_CPP_FILES "./*.cpp") +qt5_wrap_ui(UI_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.ui) + +add_executable(${TARGET_NAME} ${EXAMPLE_H_FILES} ${EXAMPLE_CPP_FILES} + ${UI_FILES}) + +target_link_libraries(${TARGET_NAME} PRIVATE Qt5::Widgets Qt5::Gui Qt5::Svg + kiran-integration-theme) + +target_include_directories( + ${TARGET_NAME} + PRIVATE ${PROJECT_SOURCE_DIR} ${PROJECT_BINARY_DIR} + ${Qt5Gui_PRIVATE_INCLUDE_DIRS} ${Qt5Widgets_PRIVATE_INCLUDE_DIRS} + ${Qt5Svg_PRIVATE_INCLUDE_DIRS}) diff --git a/examples/colors-card.cpp b/examples/colors-card.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c73dcc69c87e7fd91f99111024e306954f6dbf24 --- /dev/null +++ b/examples/colors-card.cpp @@ -0,0 +1,161 @@ +#include "colors-card.h" +#include "ui_colors-card.h" + +#include +#include +#include +#include "examples/ui_widget-factory.h" +#include "lib/theme/style.h" +#include "lib/theme/palette.h" +#include + +ColorsCard::ColorsCard(QDialog *parent) : QDialog(parent), ui(new Ui::ColorsCard) +{ + ui->setupUi(this); + init(); +} + +void ColorsCard::init() +{ + this->setWindowTitle("ColorsCard"); +} + +ColorsCard::~ColorsCard() +{ + delete ui; +} + +void ColorsCard::renderColorsCard() +{ + // 在渲染之前先清空 ui->m_infoSpace1 ui->m_infoSpace2 + // 清空 ui->m_infoSpace1 + QLayoutItem* item1; + while ((item1 = ui->m_infoSpace1->takeAt(0)) != nullptr) { + delete item1->widget(); + delete item1; + } + // 清空 ui->m_infoSpace2 + QLayoutItem* item2; + while ((item2 = ui->m_infoSpace2->takeAt(0)) != nullptr) { + delete item2->widget(); + delete item2; + } + + // 清空 ui->m_baseColors + QLayoutItem* item3; + while ((item3 = ui->m_baseColors->takeAt(0)) != nullptr) { + delete item3->widget(); + delete item3; + } + + Kiran::Theme::Palette::BaseColors baseColors = Kiran::Theme::DEFAULT_PALETTE()->getBaseColors(); + auto baseColorsLayout = this->ui->m_baseColors; + auto baseGroupBox = new QGroupBox("baseColors", this); + auto baseGroupLayout = new QVBoxLayout; + auto spacer = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding); + + struct ColorData { + QString name; + QString tooltip; + QColor color; + }; + + // 定义颜色数据数组 + ColorData colors[] = { + {"baseBackground", "用于窗口背景、输入框背景和图标,即底色", baseColors.baseBackground}, + {"baseForeground", "用于文字和图标", baseColors.baseForeground}, + {"containerBackground", "用于容器背景,例如色块", baseColors.containerBackground}, + {"widgetBackground", "用于大部分控件的默认背景色", baseColors.widgetBackground}, + {"widgetBorder", "用于大部分控件的边框色、Switch关、滑块背景", baseColors.widgetBorder}, + {"widgetSelection", "用于控件选中背景、Switch开、滑块值、check/radio按钮选中", baseColors.widgetSelection}, + {"widgetMain", "用于文字和图标", baseColors.widgetMain}, + {"widgetWarning", "用于危险提示文字、图标和输入框错误描边", baseColors.widgetWarning} + }; + + // 遍历颜色数据数组并添加到布局中 + for (const auto& colorData : colors) { + auto hexColorStr = QString("%1: \t%2").arg(colorData.name, colorData.color.name()); + auto colorLabel = new QLabel(hexColorStr); + colorLabel->setFixedSize(350, 20); + colorLabel->setToolTip(colorData.tooltip); + + auto colorPanel = new QLabel(); + colorPanel->setFixedSize(100, 20); + colorPanel->setAutoFillBackground(true); + QPalette palette = colorLabel->palette(); + palette.setColor(QPalette::Window, colorData.color); + colorPanel->setPalette(palette); + + auto layout = new QHBoxLayout; + layout->addWidget(colorLabel); + layout->addWidget(colorPanel); + baseGroupLayout->addLayout(layout); + } + + baseGroupLayout->addSpacerItem(spacer); + baseGroupBox->setLayout(baseGroupLayout); + baseColorsLayout->addWidget(baseGroupBox); + + for (int i = 0; i < Kiran::Theme::Palette::N_COLOR_GROUPS; i++) { + auto groupBox = new QGroupBox(QMetaEnum::fromType().valueToKey(i), this); + auto groupLayout = new QVBoxLayout; + for (int j = 0; j < Kiran::Theme::Palette::N_COLOR_ROLES; j++) { + auto colorGroup = static_cast(i); + auto colorRole = static_cast(j); + QColor color = Kiran::Theme::DEFAULT_PALETTE()->getColor(colorGroup,colorRole); + QString colorValue = QString("0x%1%2%3") + .arg(color.red(), 2, 16, QLatin1Char('0')) + .arg(color.green(), 2, 16, QLatin1Char('0')) + .arg(color.blue(), 2, 16, QLatin1Char('0')); + + QString colorInfo = QString("%1+%2 \tis %3, Alpha is %4") + .arg(QMetaEnum::fromType().valueToKey(i)) + .arg(QMetaEnum::fromType().valueToKey(j)) + .arg(colorValue) + .arg(color.alphaF()); + + auto colorLabel = new QLabel(colorInfo); + colorLabel->setFixedSize(350, 20); + auto colorPanel = new QLabel(); + colorPanel->setFixedSize(100, 20); + colorPanel->setAutoFillBackground(true); + QPalette palette = colorLabel->palette(); + palette.setColor(QPalette::Window, color); + colorPanel->setPalette(palette); + + auto layout = new QHBoxLayout; + layout->addWidget(colorLabel); + layout->addWidget(colorPanel); + groupLayout->addLayout(layout); + } + groupBox->setLayout(groupLayout); + auto infoSpace = i < 3 ? ui->m_infoSpace1 : ui->m_infoSpace2; + infoSpace->addWidget(groupBox); + } +} + +void ColorsCard::start_view() +{ + this->show(); + renderColorsCard(); +} +// 遍历 ColorGroup 和 ColorRole 结构体,并输出颜色 +void ColorsCard::printAllColors() +{ + Kiran::Theme::Palette* kiranPalette = Kiran::Theme::DEFAULT_PALETTE(); + const Kiran::Theme::Palette::BaseColors& baseColors = kiranPalette->getBaseColors(); + + for (int group = 0; group < Kiran::Theme::Palette::N_COLOR_GROUPS; group++) + { + for (int role = 0; role < Kiran::Theme::Palette::N_COLOR_ROLES; role++) + { + auto colorGroup = static_cast(group); + auto colorRole = static_cast(role); + + QColor color = kiranPalette->getColor(colorGroup, colorRole); + + qDebug() << "Color for Group" << colorGroup << "Role" << colorRole << ":" + << "RGB(" << color.red() << "," << color.green() << "," << color.blue() << ")"; + } + } +} diff --git a/examples/colors-card.h b/examples/colors-card.h new file mode 100644 index 0000000000000000000000000000000000000000..b81adc96911e049e7f1c66445691c4c3dafb9824 --- /dev/null +++ b/examples/colors-card.h @@ -0,0 +1,29 @@ +#pragma once + +#include + +QT_BEGIN_NAMESPACE +namespace Ui +{ +class ColorsCard; +} +QT_END_NAMESPACE + +class ColorsCard : public QDialog +{ + Q_OBJECT + +public: + explicit ColorsCard(QDialog *parent = nullptr); + ~ColorsCard() override; + + void renderColorsCard(); + void printAllColors(); + +public slots: + void start_view(); + +private: + Ui::ColorsCard *ui; + void init(); +}; diff --git a/examples/colors-card.ui b/examples/colors-card.ui new file mode 100644 index 0000000000000000000000000000000000000000..73c0b069f75172816801c6a0224c525aa779a551 --- /dev/null +++ b/examples/colors-card.ui @@ -0,0 +1,30 @@ + + + ColorsCard + + + + 0 + 0 + 400 + 300 + + + + ColorsCard + + + + + + + + + + + + + + + + diff --git a/integration-test/src/main.cpp b/examples/main.cpp similarity index 68% rename from integration-test/src/main.cpp rename to examples/main.cpp index c1e9b071d3d5c13052d8e92ed2fe9917ab707b4a..e4ea44aae3a60dd49559478344ffab847dd4f72d 100644 --- a/integration-test/src/main.cpp +++ b/examples/main.cpp @@ -11,23 +11,25 @@ * * Author: liuxinhao */ -#include -#include -#include #include -#include -#include +#include +#include #include -#include "qt-widget-factor.h" +#include +#include +#include +#include +#include "examples/widget-factory.h" +#include "lib/theme/palette.h" bool test_load_plugin() { QPluginLoader loader; loader.setFileName("/usr/lib64/qt5/plugins/platformthemes/libqkiran.so"); - if(loader.load()) + if (loader.load()) { auto plugin = qobject_cast(loader.instance()); - if(!plugin) + if (!plugin) { qInfo() << "can't cast to QPlatformThemePlugin"; return false; @@ -44,10 +46,10 @@ bool test_load_plugin() } loader.setFileName("/usr/lib64/qt5/plugins/styles/libkiranstyle.so"); - if(loader.load()) + if (loader.load()) { auto plugin = qobject_cast(loader.instance()); - if(!plugin) + if (!plugin) { qInfo() << "can't cast to QStylePlugin"; return false; @@ -66,14 +68,24 @@ bool test_load_plugin() return true; } -int main(int argc,char* argv[]) +int main(int argc, char* argv[]) { - QApplication app(argc,argv); +// qputenv("QT_QPA_PLATFORMTHEME","kiran-next"); + QApplication app(argc, argv); + QLoggingCategory::defaultCategory()->setEnabled(QtDebugMsg, true); + + qDebug() << "==================================================="; + qDebug() << "supported style:" << QStyleFactory::keys(); + qDebug() << "current style:" << app.style()->objectName(); + qDebug() << "app palette:" << app.palette().brush(QPalette::Highlight); + qDebug() << "==================================================="; + QtWidgetFactor factor; factor.show(); QPalette palette = app.palette(); - palette.setColor(QPalette::Active,QPalette::Window,"red"); - app.setPalette(palette,""); + palette.setColor(QPalette::Active, QPalette::Window, "red"); + app.setPalette(palette, ""); + return app.exec(); } \ No newline at end of file diff --git a/integration-test/src/qt-widget-factor.cpp b/examples/widget-factory.cpp similarity index 58% rename from integration-test/src/qt-widget-factor.cpp rename to examples/widget-factory.cpp index 99ab9691f1daa43a2a740513d6dbfe962b6a63f5..7b4210c4c5fcbfccacd9fbc3e1c4d979305b0d17 100644 --- a/integration-test/src/qt-widget-factor.cpp +++ b/examples/widget-factory.cpp @@ -12,16 +12,21 @@ * Author: liuxinhao */ -#include "qt-widget-factor.h" +#include "examples/widget-factory.h" #include #include #include +#include #include #include #include -#include "style-property.h" -#include "ui_qt-widget-factor.h" +#include "colors-card.h" +#include "examples/ui_widget-factory.h" +#include "lib/theme/palette.h" +#include "lib/theme/style.h" + +#define KIRAN_STYLE_PROPERTY_BUTTON_TYPE "_kiran_button_type" using namespace Kiran; QtWidgetFactor::QtWidgetFactor(QWidget* parent) : QWidget(parent), ui(new Ui::QtWidgetFactor) @@ -33,8 +38,7 @@ QtWidgetFactor::QtWidgetFactor(QWidget* parent) : QWidget(parent), ui(new Ui::Qt initMenu(); initToolBar(); initTabBar(); - - StylePropertyHelper::setButtonType(ui->pushbutton_normal, BUTTON_Default); + initThemedIcon(); } QtWidgetFactor::~QtWidgetFactor() @@ -50,27 +54,30 @@ void QtWidgetFactor::initStyleSwitch() ui->comboBox_switchStyle->addItem(key); } - connect(ui->comboBox_switchStyle, &QComboBox::currentTextChanged, [this](const QString& text) { - qInfo() << "set style:" << text; - qApp->setStyle(QStyleFactory::create(text)); - }); + connect(ui->comboBox_switchStyle, &QComboBox::currentTextChanged, [this](const QString& text) + { + qInfo() << "set style:" << text; + qApp->setStyle(QStyleFactory::create(text)); + }); - int curIdx = ui->comboBox_switchStyle->findText("Kiran"); + QString curStyleName = qApp->style()->objectName(); + int curIdx = ui->comboBox_switchStyle->findText(curStyleName); ui->comboBox_switchStyle->setCurrentIndex(curIdx); } void QtWidgetFactor::initDisableSwitch() { - connect(ui->checkBox_disable, &QCheckBox::stateChanged, [this](int state) { - if (state == 2) - { - ui->tabWidget->setDisabled(true); - } - else - { - ui->tabWidget->setEnabled(true); - } - }); + connect(ui->checkBox_disable, &QCheckBox::stateChanged, [this](int state) + { + if (state == 2) + { + ui->tabWidget->setDisabled(true); + } + else + { + ui->tabWidget->setEnabled(true); + } + }); } void QtWidgetFactor::initMenu() @@ -96,6 +103,12 @@ void QtWidgetFactor::initToolBar() toolButton->setIcon(QIcon::fromTheme(app)); toolbar->addWidget(toolButton); } + // button + ui->pushButton_10->setProperty(KIRAN_STYLE_PROPERTY_BUTTON_TYPE, 1); + ui->pushButton_11->setProperty(KIRAN_STYLE_PROPERTY_BUTTON_TYPE, 2); + + auto colorManager = new ColorsCard; + connect(ui->m_start_colormanager, &QPushButton::clicked, colorManager, &ColorsCard::start_view); } void QtWidgetFactor::initTabBar() @@ -114,20 +127,21 @@ void QtWidgetFactor::initTabBar() iter.value()->setChecked(true); } - connect(ui->buttonGroup_2, QOverload::of(&QButtonGroup::buttonToggled), [&](QAbstractButton* button, bool toggled) { - if (toggled) - { - auto radio = qobject_cast(button); - if (!radio) - return; - - for (auto iter = shapeMap.begin(); iter != shapeMap.end(); iter++) + connect(ui->buttonGroup_2, QOverload::of(&QButtonGroup::buttonToggled), [&](QAbstractButton* button, bool toggled) { - if (iter.value() == radio) - ui->tabWidget->setTabShape(iter.key()); - } - } - }); + if (toggled) + { + auto radio = qobject_cast(button); + if (!radio) + return; + + for (auto iter = shapeMap.begin(); iter != shapeMap.end(); iter++) + { + if (iter.value() == radio) + ui->tabWidget->setTabShape(iter.key()); + } + } + }); //tab position static const QMap positionMap = { @@ -142,32 +156,51 @@ void QtWidgetFactor::initTabBar() positionIter.value()->setChecked(true); } - connect(ui->buttonGroup, QOverload::of(&QButtonGroup::buttonToggled), [&](QAbstractButton* button, bool toggled) { - if (toggled) - { - auto radio = qobject_cast(button); - if (!radio) - return; - - for (auto iter = positionMap.begin(); iter != positionMap.end(); iter++) + connect(ui->buttonGroup, QOverload::of(&QButtonGroup::buttonToggled), [&](QAbstractButton* button, bool toggled) { - if (iter.value() == radio) - ui->tabWidget->setTabPosition(iter.key()); - } - } - }); + if (toggled) + { + auto radio = qobject_cast(button); + if (!radio) + return; + + for (auto iter = positionMap.begin(); iter != positionMap.end(); iter++) + { + if (iter.value() == radio) + ui->tabWidget->setTabPosition(iter.key()); + } + } + }); //docment mode bool documentMode = ui->tabWidget->documentMode(); ui->check_docmode->setChecked(documentMode); - connect(ui->check_docmode, &QCheckBox::toggled, [&](bool checked) { - ui->tabWidget->setDocumentMode(checked); - }); + connect(ui->check_docmode, &QCheckBox::toggled, [&](bool checked) + { ui->tabWidget->setDocumentMode(checked); }); //auto hide bool autoHide = ui->tabWidget->tabBarAutoHide(); ui->check_tab_autohide->setChecked(autoHide); - connect(ui->check_tab_autohide, &QCheckBox::toggled, [&](bool checked) { - ui->tabWidget->setTabBarAutoHide(checked); - }); + connect(ui->check_tab_autohide, &QCheckBox::toggled, [&](bool checked) + { ui->tabWidget->setTabBarAutoHide(checked); }); +} + +void QtWidgetFactor::initThemedIcon() +{ + auto mainLayout = new QHBoxLayout(ui->themedIconContainerWidget); + + QList iconList = { + "firefox", + "kcp-authentication-driver", + "kcp-authentication-fingerprint" + }; + for(const auto& iconName:iconList) + { + auto btn = new QPushButton(ui->themedIconContainerWidget); + auto icon = QIcon::fromTheme(iconName); + btn->setIcon(icon); + btn->setText(iconName); + btn->setIconSize(QSize(48,48)); + mainLayout->addWidget(btn); + } } diff --git a/integration-test/src/qt-widget-factor.h b/examples/widget-factory.h similarity index 91% rename from integration-test/src/qt-widget-factor.h rename to examples/widget-factory.h index 3863c99a3abc8f76fc46e468f81c0636bceb48fd..9d0755dced88325e7d4433da46c92643839cd05c 100644 --- a/integration-test/src/qt-widget-factor.h +++ b/examples/widget-factory.h @@ -37,6 +37,10 @@ public: void initMenu(); void initToolBar(); void initTabBar(); + /* + * @description: 初始化主题ICON,测试图标引擎是否生效 + **/ + void initThemedIcon(); private: Ui::QtWidgetFactor *ui; diff --git a/integration-test/src/qt-widget-factor.ui b/examples/widget-factory.ui similarity index 96% rename from integration-test/src/qt-widget-factor.ui rename to examples/widget-factory.ui index e340d84c74a06258368b959ec430786cd5ea2ab7..319160fe1748cc522ba8ca78240e6f7023ddd0ad 100644 --- a/integration-test/src/qt-widget-factor.ui +++ b/examples/widget-factory.ui @@ -70,6 +70,19 @@ + + + + ColorsCard + + + + 16 + 8 + + + + @@ -85,7 +98,7 @@ QTabWidget::Rounded - 5 + 0 true @@ -187,6 +200,51 @@ + + + + 0 + + + 0 + + + + + normalButton + + + + + + + defaultButton + + + + + + + warningButton + + + + + + + PushButton + + + + + + + PushButton + + + + + @@ -1707,14 +1765,27 @@ p, li { white-space: pre-wrap; } ProgressBar - - + + + + 0 + + + -1 + + + + + 24 + + true + - + 24 @@ -1724,23 +1795,24 @@ p, li { white-space: pre-wrap; } - - + + 24 - - true - - - - - 0 + + + + Qt::Horizontal - - -1 + + + + + + Qt::Vertical @@ -1975,6 +2047,13 @@ p, li { white-space: pre-wrap; } + + + CheckBox + + + + @@ -2074,7 +2153,10 @@ p, li { white-space: pre-wrap; } - + + + + Qt::Vertical @@ -2087,6 +2169,16 @@ p, li { white-space: pre-wrap; } + + + + + 0 + 100 + + + + @@ -2116,7 +2208,7 @@ p, li { white-space: pre-wrap; } - + diff --git a/include/declarations.h b/include/declarations.h new file mode 100644 index 0000000000000000000000000000000000000000..dbc5b13d069aa973830e613738dc6e4758d26878 --- /dev/null +++ b/include/declarations.h @@ -0,0 +1,129 @@ +/** + * Copyright (c) 2023 ~ 2024 KylinSec Co., Ltd. + * kiran-qt5-integration is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * + * Author: tangjie02 + */ + +#pragma once + +#include +#include +#include + +#define CONNECTION(text1, text2) text1##text2 +#define CONNECT(text1, text2) CONNECTION(text1, text2) + +class KQIDefer +{ +public: + KQIDefer(std::function func, std::string fun_name) : func_(func), + fun_name_(fun_name) {} + ~KQIDefer() { func_(fun_name_); } + +private: + std::function func_; + std::string fun_name_; +}; + +// helper macro for KQIDefer class +#define SCOPE_EXIT(block) KQIDefer CONNECT(_defer_, __LINE__)([&](std::string _arg_function) block, __FUNCTION__) + +#define BREAK_IF_FALSE(cond) \ + { \ + if (!(cond)) break; \ + } + +#define BREAK_IF_TRUE(cond) \ + { \ + if (cond) break; \ + } + +#define RETURN_VAL_IF_FALSE(cond, val) \ + { \ + if (!(cond)) \ + { \ + return val; \ + } \ + } + +#define RETURN_VAL_IF_TRUE(cond, val) \ + { \ + if (cond) return val; \ + } + +#define RETURN_IF_FALSE(cond) \ + { \ + if (!(cond)) \ + { \ + return; \ + } \ + } + +#define RETURN_IF_TRUE(cond) \ + { \ + if (cond) return; \ + } + +#define CONTINUE_IF_FALSE(cond) \ + { \ + if (!(cond)) continue; \ + } + +#define CONTINUE_IF_TRUE(cond) \ + { \ + if (cond) continue; \ + } + +#define IGNORE_EXCEPTION(expr) \ + { \ + try \ + { \ + expr; \ + } \ + catch (const Glib::Error &e) \ + { \ + } \ + catch (const std::exception &e) \ + { \ + } \ + } + +#define POINTER_TO_STRING(p) ((p) ? QString(p) : QString()) + +using StringHash = uint32_t; + +constexpr StringHash prime = 9973; +constexpr StringHash basis = 0xCBF29CE4ul; +constexpr StringHash hash_compile_time(char const *str, StringHash last_value = basis) +{ + return *str ? hash_compile_time(str + 1, (StringHash)((*str ^ last_value) * (uint64_t)prime)) : last_value; +} + +inline StringHash shash(char const *str) +{ + StringHash ret{basis}; + + while (*str) + { + ret ^= *str; + ret *= prime; + str++; + } + + return ret; +} + +/// compile-time hash of string. +/// usage: "XXX"_hash +constexpr StringHash operator"" _hash(char const *p, size_t) +{ + return hash_compile_time(p); +} \ No newline at end of file diff --git a/integration-test/CMakeLists.txt b/integration-test/CMakeLists.txt deleted file mode 100644 index c757e4f0ded596bd0255106713576487a89e10d8..0000000000000000000000000000000000000000 --- a/integration-test/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -cmake_minimum_required(VERSION 3.5) - -project(integration-test) - -set(CMAKE_CXX_STANDARD 11) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -find_package(PkgConfig REQUIRED) -find_package(Qt5 COMPONENTS Widgets Svg) -pkg_search_module(KLOG_QT5 REQUIRED klog-qt5) -#pkg_search_module(KIRAN_STYLE_HELPER REQUIRED kiran-style-helper) - -set(CMAKE_AUTOMOC ON) -set(CMAKE_AUTOUIC ON) -set(CMAKE_AUTORCC ON) - -file(GLOB_RECURSE SRC "src/*.cpp" "src/*.h" "src/*.ui") - -add_executable(${PROJECT_NAME} ${SRC}) - -message("current source:${SRC}") - -target_link_libraries(${PROJECT_NAME} PRIVATE - Qt5::Widgets - Qt5::Gui - Qt5::Svg - kiran-style-helper - ${KLOG_QT5_LIBRARIES}) - -target_include_directories(${PROJECT_NAME} PRIVATE - ${KLOG_QT5_INCLUDE_DIRS} - ${CMAKE_CURRENT_BINARY_DIR} - ${Qt5Gui_PRIVATE_INCLUDE_DIRS} - ${Qt5Widgets_PRIVATE_INCLUDE_DIRS} - ${Qt5Svg_PRIVATE_INCLUDE_DIRS}) diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..e0b495f3ba9c4cc1d59994001972bca840eb2af8 --- /dev/null +++ b/lib/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(common) +add_subdirectory(theme) diff --git a/lib/common/CMakeLists.txt b/lib/common/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..e4cd6eaf6cef19827c10a15d854a126787c8f29d --- /dev/null +++ b/lib/common/CMakeLists.txt @@ -0,0 +1,18 @@ +set(TARGET_NAME "lib-common") + +find_package(KiranDBusGenerate REQUIRED) + +pkg_search_module(GSETTINGS_QT REQUIRED gsettings-qt) + +file(GLOB_RECURSE COMMON_H_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h) +file(GLOB_RECURSE COMMON_CPP_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) + +add_library(${TARGET_NAME} STATIC ${COMMON_H_FILES} ${COMMON_CPP_FILES}) + +target_link_libraries(${TARGET_NAME} Qt5::Core ${GSETTINGS_QT_LIBRARIES}) + +target_include_directories(${TARGET_NAME} + PRIVATE ${CMAKE_CURRENT_BINARY_DIR} + ${PROJECT_SOURCE_DIR} + ${PROJECT_SOURCE_DIR}/include + ${GSETTINGS_QT_INCLUDE_DIRS}) \ No newline at end of file diff --git a/lib/common/configuration.cpp b/lib/common/configuration.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b6f466cf576257956f2efa83a83150e17673abc9 --- /dev/null +++ b/lib/common/configuration.cpp @@ -0,0 +1,85 @@ +/** + * Copyright (c) 2023 ~ 2024 KylinSec Co., Ltd. + * kiran-qt5-integration is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * + * Author: tangjie02 + */ + +#include "configuration.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Kiran +{ +#define KQI_CONFIGURATION_PATH "/etc/kiran-integration/kiran-qt5-integration.ini" +#define KQI_INI_GROUP_NAME "Style" +#define KQI_INI_KEY_ENABLED_APPS "enabled-apps" + +Configuration::Configuration() : +m_settings(new QSettings(KQI_CONFIGURATION_PATH, QSettings::IniFormat)) +{ +} + +Configuration* Configuration::instance() +{ + static QMutex mutex; + static QScopedPointer pInst; + + if (Q_UNLIKELY(!pInst)) + { + QMutexLocker locker(&mutex); + if (pInst.isNull()) + { + pInst.reset(new Configuration); + } + } + + return pInst.data(); +} + +QSet Configuration::getEnabledApps() +{ + QSet enabledApps; + + m_settings->beginGroup(KQI_INI_GROUP_NAME); + QStringList enabledAppsList = m_settings->value(KQI_INI_KEY_ENABLED_APPS).toStringList(); + m_settings->endGroup(); + + enabledApps = QSet::fromList(enabledAppsList); + return enabledApps; +} + +bool Configuration::match(const QString& appName) +{ + QRegExp regExp("", Qt::CaseSensitive, QRegExp::Wildcard); + + for (const QString& appPattern : m_kiranStyleApps) + { + regExp.setPattern(appPattern); + RETURN_VAL_IF_TRUE(regExp.exactMatch(appName), true); + } + + QSet enabledApps = getEnabledApps(); + for (const QString& appPattern : enabledApps) + { + regExp.setPattern(appPattern); + RETURN_VAL_IF_TRUE(regExp.exactMatch(appName), true); + } + + return false; +} +} // namespace Kiran diff --git a/lib/common/configuration.h b/lib/common/configuration.h new file mode 100644 index 0000000000000000000000000000000000000000..a05b36d0fede12276442c041501636e4ffd01953 --- /dev/null +++ b/lib/common/configuration.h @@ -0,0 +1,63 @@ +/** + * Copyright (c) 2023 ~ 2024 KylinSec Co., Ltd. + * kiran-qt5-integration is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * + * Author: tangjie02 + */ + +#pragma once + +#include + +class QSettings; + +namespace Kiran +{ +// 此类判断是否当前应用名称是否打开主题, 通过调用 match 方法匹配 +// 1. 首先检测内置应用列表 m_kiranStyleApps +// 2. 从配置文件中读取应用列表 QSet +class Configuration +{ +public: + static Configuration* instance(); + + ~Configuration() = default;; + + // KQI_CONFIGURATION_PATH 示例 + // [Style] + // #启用kiran style的应用列表,已内置部分kiran桌面环境的组件,eg: kiran-*,kiran-panel + // enabled-apps=ksl-os-gui,ksl-server-gui,ks-scmc-gui + + // 在 getEnabledApps() 中通过获取到的 m_settings 转为 QSet 实现去重 + QSet getEnabledApps(); + // 通过应用名称判断是否是打开主题的应用(两种地方判断: m_kiranStyleApps 以及 getEnabledApps 中的) + bool match(const QString& appName); + +private: + Configuration(); + +private: + QStringList m_kiranStyleApps = { + "kiran-control-panel", + "kiran-cpanel-*", + "kiran-polkit-agent", + "kiran-avatar-editor", + "kiran-calculator", + "kiran-power-status-icon", + "kiran-network-status-icon", + "kiran-audio-status-icon", + "kiran-flameshot", + }; +// "kiran-integration-example" + + QSettings* m_settings{}; +}; + +} // namespace Kiran \ No newline at end of file diff --git a/lib/theme/CMakeLists.txt b/lib/theme/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..f029ab086d50dd002decfc413e42e156976f4d6a --- /dev/null +++ b/lib/theme/CMakeLists.txt @@ -0,0 +1,37 @@ +set(TARGET_NAME kiran-integration-theme) + +set(STYLE_QRC ${CMAKE_CURRENT_BINARY_DIR}/style.qrc) +configure_file(${PROJECT_SOURCE_DIR}/resources/style.qrc.in ${STYLE_QRC}) + +file(GLOB_RECURSE STYLE_CPP_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) +file(GLOB_RECURSE STYLE_H_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h) + +add_library(${TARGET_NAME} SHARED ${STYLE_CPP_FILES} ${STYLE_QRC} + ${STYLE_H_FILES}) + +set_target_properties(${TARGET_NAME} PROPERTIES VERSION ${PROJECT_VERSION} + SOVERSION 2) + +target_include_directories( + ${TARGET_NAME} + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} + ${PROJECT_SOURCE_DIR} + ${PROJECT_SOURCE_DIR}/include + ${Qt5Gui_PRIVATE_INCLUDE_DIRS} + ${Qt5Widgets_PRIVATE_INCLUDE_DIRS} + ${Qt5Svg_PRIVATE_INCLUDE_DIRS}) + +target_link_libraries(${TARGET_NAME} Qt5::Core Qt5::Gui Qt5::Widgets Qt5::Svg) + +install(TARGETS ${TARGET_NAME} DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}) + +# deprecated +install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/font-size-manager.h + DESTINATION ${KQI_INSTALL_INCLUDEDIR}/theme/) + +install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/palette.h + DESTINATION ${KQI_INSTALL_INCLUDEDIR}/theme/) + +install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/style-helper.h + DESTINATION ${KQI_INSTALL_INCLUDEDIR}/theme/) \ No newline at end of file diff --git a/style/src/define.h b/lib/theme/define.h similarity index 89% rename from style/src/define.h rename to lib/theme/define.h index f4c9230eeb4af55902c405992daf35144a25ccea..da7c73f8caa5108b8b843326bd17b44ba78e0a3a 100644 --- a/style/src/define.h +++ b/lib/theme/define.h @@ -12,8 +12,7 @@ * Author: liuxinhao */ -#ifndef __STYLE_DEFINE_H__ -#define __STYLE_DEFINE_H__ +#pragma once #include #include @@ -41,6 +40,14 @@ enum Corner AllCorners = CornerTopLeft | CornerTopRight | CornerBottomLeft | CornerBottomRight, }; Q_DECLARE_FLAGS(Corners, Corner) -} // namespace Kiran -#endif \ No newline at end of file +enum PaletteType +{ + PALETTE_LIGHT, + PALETTE_DARK, + PALETTE_LAST +}; + +#define KIRAN_STYLE_PROPERTY_BUTTON_TYPE "_kiran_button_type" + +} // namespace Kiran diff --git a/style-helper/src/font-size-manager-private.h b/lib/theme/font-size-manager-private.h similarity index 71% rename from style-helper/src/font-size-manager-private.h rename to lib/theme/font-size-manager-private.h index eccf04b40ddb1e3d2dcdc04a90f4332d6f055628..605f018629d0737b281182c1f739e0540aa5ade0 100644 --- a/style-helper/src/font-size-manager-private.h +++ b/lib/theme/font-size-manager-private.h @@ -1,6 +1,17 @@ -// -// Created by liuxinhao on 2022/6/20. -// +/** + * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. + * kiran-qt5-integration is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * + * Author: liuxinhao + */ + #pragma once #include @@ -29,7 +40,7 @@ public: #if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)) connect(&m_destorySignalMapper, &QSignalMapper::mappedWidget, this, &FontSizeManagerPrivate::handleBindWidgetDestroyed); #else - connect(&m_destorySignalMapper, QOverload::of(&QSignalMapper::mapped), this, &FontSizeManagerPrivate::handleBindWidgetDestroyed); + connect(&m_destorySignalMapper, QOverload::of(&QSignalMapper::mapped), this, &FontSizeManagerPrivate::handleBindWidgetDestroyed); #endif } diff --git a/style-helper/src/font-size-manager.cpp b/lib/theme/font-size-manager.cpp similarity index 83% rename from style-helper/src/font-size-manager.cpp rename to lib/theme/font-size-manager.cpp index 996e289dec88f1223cd9ff905ebe665f8cf6e7c3..2535934be9c2f26b04b31ba1257b847967f043aa 100644 --- a/style-helper/src/font-size-manager.cpp +++ b/lib/theme/font-size-manager.cpp @@ -1,6 +1,17 @@ -// -// Created by liuxinhao on 2022/6/20. -// +/** + * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. + * kiran-qt5-integration is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * + * Author: liuxinhao + */ + #define private public #include #undef private diff --git a/lib/theme/font-size-manager.h b/lib/theme/font-size-manager.h new file mode 100644 index 0000000000000000000000000000000000000000..488d552e50d441e9c7977791478be0b8dcecf96b --- /dev/null +++ b/lib/theme/font-size-manager.h @@ -0,0 +1,98 @@ +/** + * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. + * kiran-qt5-integration is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * + * Author: liuxinhao + */ + +#pragma once + +#include +#include + +/** + * 该类主要是解决系统字号设置为单一的应用程序设置,并不会做过多的区分设置项,导致系统描述字号级别不明显 + * 提供以下功能: + * 1. 字体分级 + * 支持将系统设置的应用程序字体分级,支持1~10个级别,需要相应分级的字体可从该接口统一获取 + * 2. QWidget绑定通用字体的指定字号级别 + * 支持将指定的QWidget以及派生类绑定到指定的字号级别,系统更改 <应用程序字体设置> 时,将会重新计算分级字体大小重新更新字号和字体 + * 3. QWidget绑定指定的字体(不跟随系统),但是字号绑定字号级别,跟随系统变化 + * 支持将指定的QWidget以及派生类绑定定指定的字体以及字号级别, + */ +namespace Kiran +{ +class FontSizeManagerPrivate; +class FontSizeManager : public QObject +{ + Q_OBJECT +public: + enum FontLevelEnum + { + FONT_LEVEL_1, + FONT_LEVEL_2, + FONT_LEVEL_3, + //控制中心设置项 "应用程序字体" 对应的字体级别,常规字体 + FONT_LEVEL_4, + FONT_LEVEL_5, + FONT_LEVEL_6, + FONT_LEVEL_7, + FONT_LEVEL_LAST + }; + +public: + static FontSizeManager* instance(); + + ~FontSizeManager(); + + /// 通过字体磅数计算字体像素尺寸 + /// \param font 需获取字体像素大小的字体 + /// \return 字体像素尺寸 + static int fontPixelSize(const QFont& font); + + /// 设置系统通用字号大小,且会同步影响所有字号级别的大小 + /// \param fontSize 系统通用字号大小(px) + void setUniversalFontSize(int fontSize); + + /// 控件绑定字号级别 + /// \param w 需绑定字号的控件 + /// \param fontLevel 字号级别 + void bind(QWidget* w, FontLevelEnum fontLevel); + + /// 控件绑定字号级别 + /// \param w 需绑定字号的控件 + /// \param weight 字体粗细,可直接使用QFont::Weight + /// \param fontLevel 字号级别 + void bind(QWidget* w, FontLevelEnum fontLevel, int weight); + + /// 控件解除绑定字号级别 + void unbind(QWidget* w); + + /// 获取指定的字体 + /// \param fontLevel 字号级别 + /// \param base 基础字体,可忽略该参数,使用系统字体构造字体对象 + /// \return 指定字体 + QFont getFont(FontLevelEnum fontLevel, const QFont& base = QFont()) const; + + /// 获取指定的字体 + /// \param fontLevel 级别 + /// \param weight 字体粗细,可直接使用QFont::Weight + /// \param base 基础字体,可忽略该参数 + /// \return 指定的字体 + QFont getFont(FontLevelEnum fontLevel, int weight, const QFont& base = QFont()) const; + +private: + explicit FontSizeManager(QObject* parent = nullptr); + +private: + FontSizeManagerPrivate* d_ptr; + Q_DECLARE_PRIVATE(FontSizeManager); +}; +} // namespace Kiran \ No newline at end of file diff --git a/style/src/metrics.h b/lib/theme/metrics.h similarity index 96% rename from style/src/metrics.h rename to lib/theme/metrics.h index 05169e4b7a305645069c014f8c5c3dc11e35ff69..b8e3b28d834b20ccd7e87dba16ed9e50ce144915 100644 --- a/style/src/metrics.h +++ b/lib/theme/metrics.h @@ -11,8 +11,8 @@ * * Author: liuxinhao */ -#ifndef KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_METRICS_H_ -#define KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_METRICS_H_ + +#pragma once namespace Kiran { @@ -141,5 +141,3 @@ struct Metrics static constexpr int Shadow_Overlap = 2; }; } // namespace Kiran - -#endif // KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_METRICS_H_ diff --git a/lib/theme/palette-private.h b/lib/theme/palette-private.h new file mode 100644 index 0000000000000000000000000000000000000000..d220480ff30ea930ebb96225b7ae133d1881d926 --- /dev/null +++ b/lib/theme/palette-private.h @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2023 ~ 2024 KylinSec Co., Ltd. + * kiranwidgets-qt5 is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * + * Author: tangjie02 + */ + +#pragma once + +#include +#include "lib/theme/palette.h" + +namespace Kiran +{ +namespace Theme +{ +class PalettePrivate : public QObject +{ + Q_OBJECT + +public: + explicit PalettePrivate(Palette* qptr); + ~PalettePrivate() override = default;; + + void setBaseColors(const Palette::BaseColors& baseColors); + void setColorFactor(const Palette::ColorFactor& colorFactor); + void setColorGroup(Palette::ColorGroup colorGroup, + const QColor& window, + const QColor& text, + const QColor& widget, + const QColor& icon, + const QColor& scroll, + const QColor& border); + + QColor getColor(Palette::ColorGroup colorGroup, Palette::ColorRole colorRole); + +private: + void calcWidgetColors(); + // 颜色混合 + QColor mixColor(const QColor& color1, const QColor& color2, double factor); + // 计算禁用颜色 + QColor disabledColor(const QColor& color); + // 打印颜色信息 + void dumpColors(); + +private: + Palette* q_ptr; + Q_DECLARE_PUBLIC(Palette) + +private: + Palette::BaseColors m_baseColors; + Palette::ColorFactor m_colorFactors{}; + // 其他控件状态都通过正常状态的颜色混合计算,这里保持计算系数 + // static double m_colorFactor[Palette::WIDGET_PSEUDO_LAST][Palette::WIDGET_AREA_LAST]; + + // 基于基础颜色组,生成每个控件类型在不同伪状态下的不同部位的颜色 + // QColor m_widgetColors[Palette::WIDGET_TYPE_LAST][Palette::WIDGET_PSEUDO_LAST][Palette::WIDGET_AREA_LAST]; + QColor m_colors[Palette::N_COLOR_GROUPS][Palette::N_COLOR_ROLES]; +}; + +} // namespace Theme + +} // namespace Kiran diff --git a/lib/theme/palette.cpp b/lib/theme/palette.cpp new file mode 100644 index 0000000000000000000000000000000000000000..176bb244e0643f9c8a151cf1a1134bfb622974e7 --- /dev/null +++ b/lib/theme/palette.cpp @@ -0,0 +1,337 @@ +/** + * Copyright (c) 2023 ~ 2024 KylinSec Co., Ltd. + * kiranwidgets-qt5 is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * + * Author: tangjie02 + */ + +#include "lib/theme/palette.h" +#include +#include +#include +#include +#include "lib/theme/palette-private.h" + +namespace Kiran +{ +namespace Theme +{ +// 定义内置的基础颜色,只包含浅色和深色 +Palette::BaseColors g_lightBaseColors = {.baseBackground = QColor(232, 232, 232), // #E8E8E8 + .baseForeground = QColor(34, 34, 34), // #222222 + .widgetBackground = QColor(239, 239, 239), // #EFEFEF + .widgetBorder = QColor(204, 204, 204), // #CCCCCC + .widgetSelection = QColor(0, 162, 255), // #00A2FF + .widgetMain = QColor(46, 179, 255), // #2EB3FF + .widgetWarning = QColor(250, 73, 73), // #FA4949 + .containerBackground = QColor(255, 255, 255)};// #FFFFFF + +Palette::BaseColors g_darkBaseColors = {.baseBackground = QColor(34, 34, 34), // #222222 + .baseForeground = QColor(255, 255, 255), // #FFFFFF + .widgetBackground = QColor(57, 57, 57), // #393939 + .widgetBorder = QColor(69, 69, 69), // #454545 + .widgetSelection = QColor(0, 162, 255), // #00A2FF + .widgetMain = QColor(46, 179, 255), // #2EB3FF + .widgetWarning = QColor(250, 73, 73), // #FA4949 + .containerBackground = QColor(45, 45, 45)};// #2d2d2d +// 颜色计算因子 +Palette::ColorFactor g_colorFactor = {.widgetHover = 0.9, + .widgetSunken = 0.8, + .iconHover = 0.3, + .iconSunken = 0.4, + .disabledAlpha = 0.65, + .disabledLightness = 0.1}; + +PalettePrivate::PalettePrivate(Palette* qptr) : q_ptr(qptr) +{ + // 默认为深色主题 + this->m_baseColors = g_darkBaseColors; + this->m_colorFactors = g_colorFactor; + this->calcWidgetColors(); +} + +void PalettePrivate::setBaseColors(const Palette::BaseColors& baseColors) +{ + this->m_baseColors = baseColors; + this->calcWidgetColors(); +} + +void PalettePrivate::setColorFactor(const Palette::ColorFactor& colorFactor) +{ + this->m_colorFactors = colorFactor; + this->calcWidgetColors(); +} + +void PalettePrivate::setColorGroup(Palette::ColorGroup colorGroup, + const QColor& window, + const QColor& text, + const QColor& widget, + const QColor& icon, + const QColor& scroll, + const QColor& border) +{ + this->m_colors[colorGroup][Palette::WINDOW] = window; + this->m_colors[colorGroup][Palette::TEXT] = text; + this->m_colors[colorGroup][Palette::WIDGET] = widget; + this->m_colors[colorGroup][Palette::ICON] = icon; + this->m_colors[colorGroup][Palette::SCROLL] = scroll; + this->m_colors[colorGroup][Palette::BORDER] = border; +} + +QColor PalettePrivate::getColor(Palette::ColorGroup colorGroup, Palette::ColorRole colorRole) +{ + if (colorGroup > Palette::N_COLOR_GROUPS || colorRole > Palette::N_COLOR_ROLES) + { + return QColor(); + } + + return this->m_colors[colorGroup][colorRole]; +} + +void PalettePrivate::calcWidgetColors() +{ + this->setColorGroup(Palette::ACTIVE, + this->m_baseColors.baseBackground, + this->m_baseColors.baseForeground, + this->m_baseColors.widgetBackground, + this->m_baseColors.baseForeground, + this->m_baseColors.widgetBorder, + this->m_baseColors.widgetBorder); + + this->setColorGroup(Palette::DISABLED, + this->m_baseColors.baseBackground, + this->disabledColor(this->m_baseColors.baseForeground), + this->disabledColor(this->m_baseColors.widgetBackground), + this->disabledColor(this->m_baseColors.baseForeground), + this->disabledColor(this->m_baseColors.widgetBorder), + this->disabledColor(this->m_baseColors.widgetBorder)); + + // 未激活状态暂时跟激活状态保持相同 + this->setColorGroup(Palette::INACTIVE, + this->m_baseColors.baseBackground, + this->m_baseColors.baseForeground, + this->m_baseColors.widgetBackground, + this->m_baseColors.baseForeground, + this->m_baseColors.widgetBorder, + this->m_baseColors.widgetBorder); + + this->setColorGroup(Palette::MOUSE_OVER, + this->m_baseColors.baseBackground, + this->m_baseColors.baseForeground, + this->mixColor(this->m_baseColors.widgetBackground, + this->m_baseColors.baseForeground, + this->m_colorFactors.widgetHover), + this->mixColor(this->m_baseColors.widgetBackground, + this->m_baseColors.baseForeground, + this->m_colorFactors.iconHover), + this->mixColor(this->m_baseColors.widgetBorder, + this->m_baseColors.baseForeground, + this->m_colorFactors.widgetHover), + this->m_baseColors.widgetBorder); + + this->setColorGroup(Palette::SUNKEN, + this->m_baseColors.baseBackground, + this->m_baseColors.baseForeground, + this->mixColor(this->m_baseColors.widgetBackground, + this->m_baseColors.baseForeground, + this->m_colorFactors.widgetSunken), + this->mixColor(this->m_baseColors.widgetBackground, + this->m_baseColors.baseForeground, + this->m_colorFactors.iconSunken), + this->m_baseColors.widgetSelection, + this->m_baseColors.widgetBorder); + + this->setColorGroup(Palette::SELECTED, + this->m_baseColors.baseBackground, + this->m_baseColors.baseForeground, + this->m_baseColors.widgetSelection, + this->m_baseColors.baseForeground, + this->m_baseColors.widgetBorder, + this->m_baseColors.widgetBorder); + + this->dumpColors(); +} + +QColor PalettePrivate::mixColor(const QColor& color1, const QColor& color2, double factor) +{ + return QColor(int(color1.red() * factor + color2.red() * (1 - factor)), + int(color1.green() * factor + color2.green() * (1 - factor)), + int(color1.blue() * factor + color2.blue() * (1 - factor))); +} + +QColor PalettePrivate::disabledColor(const QColor& color) +{ + // 沿用GTK主题的禁用色计算算法 + auto disabledColor = color; + + if ((this->m_baseColors.baseBackground.lightness() > this->m_baseColors.baseForeground.lightness() && + color.lightness() < this->m_baseColors.baseBackground.lightness()) || + (this->m_baseColors.baseBackground.lightness() <= this->m_baseColors.baseForeground.lightness() && + color.lightness() > this->m_baseColors.baseBackground.lightness())) + { + disabledColor.setAlphaF(this->m_colorFactors.disabledAlpha); + } + + disabledColor = disabledColor.lighter(100 * (1 - this->m_colorFactors.disabledLightness)); + return disabledColor; +} + +void PalettePrivate::dumpColors() +{ + for (uint32_t colorGroup = 0; colorGroup < Palette::N_COLOR_GROUPS; ++colorGroup) + { + for (uint32_t colorRole = 0; colorRole < Palette::N_COLOR_ROLES; ++colorRole) + { + qDebug().nospace() << "The color of " + << QMetaEnum::fromType().valueToKey(colorGroup) + << "+" + << QMetaEnum::fromType().valueToKey(colorRole) + << " is " + << qSetFieldWidth(2) + << qSetPadChar('0') + << "0x" + << hex + << this->m_colors[colorGroup][colorRole].red() + << this->m_colors[colorGroup][colorRole].green() + << this->m_colors[colorGroup][colorRole].blue() + << ", Alpha is " + << qSetFieldWidth(0) + << this->m_colors[colorGroup][colorRole].alphaF(); + } + } +} + +Palette::Palette(QObject* parent) : QObject(parent), + d_ptr(new PalettePrivate(this)) +{ +} + +Palette* Palette::m_instance = nullptr; +Palette* Palette::getDefault() +{ + if (!Palette::m_instance) + { + Palette::m_instance = new Palette(); + } + return Palette::m_instance; +} + +void Palette::setBaseColors(const BaseColors& baseColors) +{ + Q_D(Palette); + + d->setBaseColors(baseColors); +} + +const Palette::BaseColors& Palette::getBaseColors() +{ + Q_D(Palette); + + return d->m_baseColors; +} + +QColor Palette::getColor(QStyle::State styleState, Palette::ColorRole colorRole) +{ + Q_D(Palette); + + auto colorGroups = Kiran::Theme::Palette::styleState2ColorGroups(styleState); + + // 按照列表中的优先级顺序查找对应颜色 + QVector colorGroupsOrder = {Palette::DISABLED, + Palette::SELECTED, + Palette::SUNKEN, + Palette::MOUSE_OVER, + Palette::ACTIVE, + Palette::INACTIVE}; + + for (auto colorGroup : colorGroupsOrder) + { + if ((1 << colorGroup) & colorGroups) + { + return d->m_colors[colorGroup][colorRole]; + } + } + + return d->m_colors[Palette::ACTIVE][colorRole]; +} + +QColor Palette::getColor(Palette::ColorGroup colorGroup, Palette::ColorRole colorRole) +{ + Q_D(Palette); + + return d->getColor(colorGroup, colorRole); +} + +void Palette::polish(QPalette& qPalette) +{ + using ColorRoleInfo = QMap; + ColorRoleInfo colorRoleInfo = {{QPalette::ColorRole::Window, Palette::WINDOW}, + {QPalette::ColorRole::Background, Palette::WINDOW}, + {QPalette::ColorRole::WindowText, Palette::TEXT}, + {QPalette::ColorRole::Foreground, Palette::TEXT}, + {QPalette::ColorRole::Base, Palette::WINDOW}, + {QPalette::ColorRole::AlternateBase, Palette::WINDOW}, + {QPalette::ColorRole::ToolTipBase, Palette::WINDOW}, + {QPalette::ColorRole::ToolTipText, Palette::WINDOW}, + {QPalette::ColorRole::Text, Palette::TEXT}, + {QPalette::ColorRole::Button, Palette::WIDGET}, + {QPalette::ColorRole::ButtonText, Palette::TEXT}}; + + using ColorGroupInfo = QMap; + ColorGroupInfo colorGroupInfo = {{QPalette::ColorGroup::Active, Palette::ACTIVE}, + {QPalette::ColorGroup::Disabled, Palette::DISABLED}, + {QPalette::ColorGroup::Inactive, Palette::INACTIVE}, + {QPalette::ColorGroup::Normal, Palette::NORMAL}}; + + for (auto colorRoleInter = colorRoleInfo.begin(); colorRoleInter != colorRoleInfo.end(); ++colorRoleInter) + { + for (auto colorGroupInter = colorGroupInfo.begin(); colorGroupInter != colorGroupInfo.end(); ++colorGroupInter) + { + qPalette.setColor(colorGroupInter.key(), + colorRoleInter.key(), + this->getColor(colorGroupInter.value(), colorRoleInter.value())); + } + } +} + +uint32_t Palette::styleState2ColorGroups(QStyle::State styleState) +{ + uint32_t pseudos = 0; + + if (styleState & QStyle::State_Enabled) + { + pseudos |= (1 << Palette::ACTIVE); + } + else + { + pseudos |= (1 << Palette::DISABLED); + } + + if (styleState & QStyle::State_Sunken) + { + pseudos |= (1 << Palette::SUNKEN); + } + + if (styleState & QStyle::State_MouseOver) + { + pseudos |= (1 << Palette::MOUSE_OVER); + } + + if ((styleState & QStyle::State_On) || + (styleState & QStyle::State_Selected)) + { + pseudos |= (1 << Palette::SELECTED); + } + + return pseudos; +} + +} // namespace Theme +} // namespace Kiran diff --git a/lib/theme/palette.h b/lib/theme/palette.h new file mode 100644 index 0000000000000000000000000000000000000000..617c3507a51483ac6cea9be3e3bfeaf976fbf0aa --- /dev/null +++ b/lib/theme/palette.h @@ -0,0 +1,144 @@ +/** + * Copyright (c) 2023 ~ 2024 KylinSec Co., Ltd. + * kiranwidgets-qt5 is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * + * Author: tangjie02 + */ + +#pragma once + +#include +#include + +class QStyleOption; +class QWidget; +class QPalette; + +#define DEFAULT_PALETTE Palette::getDefault + +namespace Kiran +{ +namespace Theme +{ +class PalettePrivate; + +// 与QPalette类似,不同之处在于Palette是根据kiran的颜色规范来设计且调色更加细化 +class Palette : public QObject +{ + Q_OBJECT + +public: + struct BaseColors + { + // 用于窗口背景、输入框背景和图标,即底色 + QColor baseBackground; + // 用于文字和图标 + QColor baseForeground; + // 用于大部分控件的默认背景色 + QColor widgetBackground; + // 用于大部分控件的边框色、Switch关、滑块背景 + QColor widgetBorder; + // 用于控件选中背景、Switch开、滑块值、check/radio按钮选中 + QColor widgetSelection; + // 用于主要按钮 + QColor widgetMain; + // 用于危险提示文字、图标和输入框错误描边 + QColor widgetWarning; + // 用于大部分容器的默认背景色 + QColor containerBackground; + }; + + struct ColorFactor + { + // 一般控件悬浮 + double widgetHover; + // 一般控件按下 + double widgetSunken; + // 图标悬浮 + double iconHover; + // 图标按下 + double iconSunken; + // 被禁用后的透明度 + double disabledAlpha; + // 被禁用后的亮度调节 + double disabledLightness; + }; + + // 类似QPalette::ColorGroup + enum ColorGroup + { + // 激活状态 + ACTIVE, + // 禁用状态 + DISABLED, + // 未激活状态(即控件所在窗口未激活) + INACTIVE, + // 鼠标悬浮状态 + MOUSE_OVER, + // 按下状态 + SUNKEN, + // 选中、开启状态 + SELECTED, + // 总数 + N_COLOR_GROUPS, + NORMAL = ACTIVE, + BACKDROP = INACTIVE, + }; + Q_ENUM(ColorGroup) + + enum ColorRole + { + // 窗口背景色 + WINDOW, + // 文本颜色 + TEXT, + // 一般(非窗口)控件背景色,例如按钮 + WIDGET, + // 图标 + ICON, + // 滑动条 + SCROLL, + // 边框 + BORDER, + // 总数 + N_COLOR_ROLES, + }; + Q_ENUM(ColorRole) + +public: + explicit Palette(QObject* parent = nullptr); + ~Palette() override = default;; + + static Palette* getDefault(); + + // 设置基础颜色组,主题颜色都基于基础颜色组衍生 + void setBaseColors(const BaseColors& baseColors); + // 获取基础颜色组中的颜色 + const BaseColors& getBaseColors(); + + // 根据伪状态的优先级来确定实际颜色 + QColor getColor(QStyle::State styleState, Palette::ColorRole colorRole); + QColor getColor(Palette::ColorGroup colorGroup, Palette::ColorRole colorRole); + + void polish(QPalette& palette); + +private: + uint32_t styleState2ColorGroups(QStyle::State styleState); + +private: + static Palette* m_instance; + + PalettePrivate* d_ptr; + Q_DECLARE_PRIVATE(Palette) +}; + +} // namespace Theme + +} // namespace Kiran diff --git a/style/src/render-helper.cpp b/lib/theme/render-helper.cpp similarity index 97% rename from style/src/render-helper.cpp rename to lib/theme/render-helper.cpp index 9bf66d2e5d8f13b0bbba7c7afd362bb00badcadf..2cd3f5482b8ad0ee243c80c4833a34bffaf62ced 100644 --- a/style/src/render-helper.cpp +++ b/lib/theme/render-helper.cpp @@ -91,9 +91,9 @@ bool RenderHelper::isMenuTitle(const QWidget *widget) return false; } -QWindow* RenderHelper::getWindow(const QWidget* widget) +QWindow *RenderHelper::getWindow(const QWidget *widget) { - return widget? widget->window()->windowHandle(): nullptr; + return widget ? widget->window()->windowHandle() : nullptr; } QRectF RenderHelper::strokedRect(const QRectF &rect, const qreal penWidth) @@ -201,6 +201,7 @@ void RenderHelper::renderFrame(QPainter *painter, const QRect &rect, int penWidt if (outline.isValid()) { painter->setPen(outline); + // FIXME: 这里除以2是否存在问题,因为函数里面已经乘以0.5了,相当于除了两次 frameRect = strokedRect(frameRect, penWidth / 2.0); } else @@ -318,7 +319,7 @@ QPixmap RenderHelper::changeSVGFillColor(const QString &svgFile, const QColor &f void RenderHelper::renderArrow(QPainter *painter, const QRect &rect, ArrowOrientation orientation, const QColor &color, const QSize &arrowSize) { - QString svgFile = QString(":/style-helper/images/arrow-down.svg"); + QString svgFile = QString(":/style/images/arrow-down.svg"); PainterSaver painterSave(painter); painter->setRenderHint(QPainter::Antialiasing); diff --git a/style/src/render-helper.h b/lib/theme/render-helper.h similarity index 94% rename from style/src/render-helper.h rename to lib/theme/render-helper.h index 0363339ea7c6405508903ad95ec01bf9f865639c..d6295cf3f289283a2312ad0f074ac834a41df941 100644 --- a/style/src/render-helper.h +++ b/lib/theme/render-helper.h @@ -11,8 +11,8 @@ * * Author: liuxinhao */ -#ifndef KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_RENDER_HELPER_H_ -#define KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_RENDER_HELPER_H_ + +#pragma once #include #include "define.h" @@ -93,5 +93,3 @@ void renderArrow(QPainter* painter, const QRect& rect, ArrowOrientation orientat void renderTabBarTab(QPainter* painter, const QRect& rect, Corners corners, int radius, const QColor& background, const QColor& border = QColor()); }; // namespace RenderHelper } // namespace Kiran - -#endif // KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_RENDER_HELPER_H_ diff --git a/lib/theme/style-helper.cpp b/lib/theme/style-helper.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2a788b64c860193de21ff4702ed9a5e2c7507289 --- /dev/null +++ b/lib/theme/style-helper.cpp @@ -0,0 +1,45 @@ +// +// Created by skyzcyou on 2024/4/1. +// + +#include "style-helper.h" + +//extern Kiran::Theme::Palette::BaseColors g_lightBaseColors; +//extern Kiran::Theme::Palette::BaseColors g_darkBaseColors; + +Kiran::Theme::Palette::BaseColors g_lightBaseColors = {.baseBackground = QColor(232, 232, 232), // #E8E8E8 + .baseForeground = QColor(34, 34, 34), // #222222 + .widgetBackground = QColor(239, 239, 239), // #EFEFEF + .widgetBorder = QColor(204, 204, 204), // #CCCCCC + .widgetSelection = QColor(0, 162, 255), // #00A2FF + .widgetMain = QColor(46, 179, 255), // #2EB3FF + .widgetWarning = QColor(250, 73, 73)}; // #FA4949 + +Kiran::Theme::Palette::BaseColors g_darkBaseColors = {.baseBackground = QColor(34, 34, 34), // #222222 + .baseForeground = QColor(255, 255, 255), // #FFFFFF + .widgetBackground = QColor(57, 57, 57), // #393939 + .widgetBorder = QColor(69, 69, 69), // #454545 + .widgetSelection = QColor(0, 162, 255), // #00A2FF + .widgetMain = QColor(46, 179, 255), // #2EB3FF + .widgetWarning = QColor(250, 73, 73)}; // #FA4949 + +namespace Kiran +{ +namespace Theme +{ +StyleHelper::StyleHelper() += default; +StyleHelper::~StyleHelper()= default; + +void StyleHelper::doChangeTheme(Kiran::PaletteType paletteType) +{ + Palette::BaseColors baseColors; + if (paletteType == PaletteType::PALETTE_LIGHT) { + baseColors = g_lightBaseColors; + } else if (paletteType == PaletteType::PALETTE_DARK) { + baseColors = g_darkBaseColors; + } + DEFAULT_PALETTE()->setBaseColors(baseColors); +} +} // namespace Theme +} // namespace Kiran diff --git a/lib/theme/style-helper.h b/lib/theme/style-helper.h new file mode 100644 index 0000000000000000000000000000000000000000..67513545e45622218d8237fab1d9e7a868ebeaa2 --- /dev/null +++ b/lib/theme/style-helper.h @@ -0,0 +1,19 @@ +#pragma once + +#include "lib/theme/palette.h" +#include "lib/theme/define.h" + + +namespace Kiran +{ +namespace Theme +{ +class StyleHelper +{ +public: + explicit StyleHelper(); + ~StyleHelper(); + static void doChangeTheme(Kiran::PaletteType paletteType); +}; +} // namespace Theme +} // namespace Kiran \ No newline at end of file diff --git a/lib/theme/style-private.h b/lib/theme/style-private.h new file mode 100644 index 0000000000000000000000000000000000000000..3560f91a0c2e4094d41d61d29e1222ce0601fb0c --- /dev/null +++ b/lib/theme/style-private.h @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2023 ~ 2024 KylinSec Co., Ltd. + * kiranwidgets-qt5 is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * + * Author: tangjie02 + */ + +#pragma once + +#include +#include "lib/theme/define.h" +#include "lib/theme/style.h" + +class QStyleOptionTab; +class QStyleOptionSpinBox; + +namespace Kiran +{ +namespace Theme +{ +class Palette; + +class StylePrivate : QObject +{ + Q_OBJECT + + enum ButtonType + { + BUTTON_Normal, /** < 普通按钮 */ + BUTTON_Default, /** < 默认按钮,突出显示 */ + BUTTON_Warning /** < 警告按钮,突出警示显示 */ + }; + + enum ScrollBarButtonType + { + NoButton, + SingleButton, + DoubleButton + } _subLineButtons = NoButton, + _addLineButtons = NoButton; + +public: + explicit StylePrivate(Style* ptr); + + static ButtonType getButtonType(const QPushButton *btn); + void tabLayout(const QStyleOptionTab* opt, const QWidget* widget, QRect* textRect, QRect* iconRect) const; + void renderSpinBoxArrow(const QStyle::SubControl& subControl, const QStyleOptionSpinBox* option, QPainter* painter, const QWidget* widget) const; + int scrollBarButtonHeight(ScrollBarButtonType type) const; + QRect scrollBarInternalSubControlRect(const QStyleOptionComplex* option, QStyle::SubControl subControl) const; + void drawPEIndicatorArrow(ArrowOrientation orientation, const QStyleOption* option, QPainter* painter, const QWidget* widget) const; + +private: + Style* q_ptr; + Q_DECLARE_PUBLIC(Style); +}; +} // namespace Theme +} // namespace Kiran \ No newline at end of file diff --git a/lib/theme/style.cpp b/lib/theme/style.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ae045c768603eec648bcca0acd0c3d099844e255 --- /dev/null +++ b/lib/theme/style.cpp @@ -0,0 +1,3633 @@ +/** + * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. + * kiran-qt5-integration is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * + * Author: liuxinhao + */ + +#include "lib/theme/style.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "lib/theme/metrics.h" +#include "lib/theme/palette.h" +#include "lib/theme/style-private.h" +#include "render-helper.h" + +#if 0 +//调试用 +QDebug operator<<(QDebug dbg, const QColor &color) +{ + QString format = QString("[rgb(%1,%2,%3) #%4%5%6]") + .arg(color.red()).arg(color.green()).arg(color.blue()) + .arg(QString::number(color.red(),16)).arg(QString::number(color.green(),16)).arg(QString::number(color.blue(),16)); + dbg << format; + return dbg; +} +#endif + +namespace Kiran +{ +namespace Theme +{ +static const int groupBoxTopMargin = 3; + +StylePrivate::StylePrivate(Style *ptr) : q_ptr(ptr) +{ +} + +void StylePrivate::tabLayout(const QStyleOptionTab *opt, const QWidget *widget, QRect *textRect, QRect *iconRect) const +{ + auto q = q_func(); + + QRect tr = opt->rect; + bool verticalTabs = RenderHelper::isVerticalTab(opt->shape); + + if (verticalTabs) + tr.setRect(0, 0, tr.height(), tr.width()); // 0, 0 as we will have a translate transform + + /// 垂直和水平偏移量,以突出当前选中的Tab标签 + int verticalShift = q->pixelMetric(QStyle::PM_TabBarTabShiftVertical, opt, widget); + int horizontalShift = q->pixelMetric(QStyle::PM_TabBarTabShiftHorizontal, opt, widget); + + int hpadding = q->pixelMetric(QStyle::PM_TabBarTabHSpace, opt, widget) / 2; + int vpadding = q->pixelMetric(QStyle::PM_TabBarTabVSpace, opt, widget) / 2; + + if (opt->shape == QTabBar::RoundedSouth || opt->shape == QTabBar::TriangularSouth) + verticalShift = -verticalShift; + + tr.adjust(hpadding, verticalShift - vpadding, horizontalShift - hpadding, vpadding); + bool selected = opt->state & QStyle::State_Selected; + if (selected) + { + tr.setTop(tr.top() - verticalShift); + tr.setRight(tr.right() - horizontalShift); + } + + // left widget + if (!opt->leftButtonSize.isEmpty()) + { + tr.setLeft(tr.left() + 4 + + (verticalTabs ? opt->leftButtonSize.height() : opt->leftButtonSize.width())); + } + // right widget + if (!opt->rightButtonSize.isEmpty()) + { + tr.setRight(tr.right() - 4 - + (verticalTabs ? opt->rightButtonSize.height() : opt->rightButtonSize.width())); + } + + // icon + if (!opt->icon.isNull()) + { + QSize iconSize = opt->iconSize; + if (!iconSize.isValid()) + { + int iconExtent = q->pixelMetric(QStyle::PM_SmallIconSize); + iconSize = QSize(iconExtent, iconExtent); + } + QSize tabIconSize = opt->icon.actualSize(iconSize, + (opt->state & QStyle::State_Enabled) ? QIcon::Normal : QIcon::Disabled, + (opt->state & QStyle::State_Selected) ? QIcon::On : QIcon::Off); + // High-dpi icons do not need adjustment; make sure tabIconSize is not larger than iconSize + tabIconSize = QSize(qMin(tabIconSize.width(), iconSize.width()), qMin(tabIconSize.height(), iconSize.height())); + + *iconRect = QRect(tr.left(), tr.center().y() - tabIconSize.height() / 2, + tabIconSize.width(), tabIconSize.height()); + if (!verticalTabs) + *iconRect = q->visualRect(opt->direction, opt->rect, *iconRect); + tr.setLeft(tr.left() + tabIconSize.width() + 4); + } + + if (!verticalTabs) + tr = q->visualRect(opt->direction, opt->rect, tr); + + *textRect = tr; +} + +void StylePrivate::renderSpinBoxArrow(const QStyle::SubControl &subControl, const QStyleOptionSpinBox *option, QPainter *painter, const QWidget *widget) const +{ + auto q = q_func(); + + const QStyle::State &state(option->state); + + QRectF arrowRect(q->subControlRect(QStyle::CC_SpinBox, option, subControl, widget)); + + bool enabled(state & QStyle::State_Enabled); + const bool atLimit = (subControl == QStyle::SC_SpinBoxUp && !(option->stepEnabled & QAbstractSpinBox::StepUpEnabled)) || + (subControl == QStyle::SC_SpinBoxDown && !(option->stepEnabled & QAbstractSpinBox::StepDownEnabled)); + enabled &= !atLimit; + + const bool mouseOver(enabled && (state & QStyle::State_MouseOver)); + bool sunken(state & QStyle::State_Sunken && option->activeSubControls & subControl); + bool hasFocus(state & QStyle::State_HasFocus); + + const bool subControlHover(enabled && mouseOver && (option->activeSubControls & subControl)); + const bool subControlSunken(enabled && (sunken) && (option->activeSubControls & subControl)); + + const QMap subControlFlagMap = { + {QStyle::State_MouseOver, subControlHover}, + {QStyle::State_Sunken, subControlSunken}, + {QStyle::State_Enabled, enabled}}; + + // 复制一个子控件StyleOption,更新其中的状态 + QStyleOption tempOption(*option); + for (auto iter = subControlFlagMap.begin(); iter != subControlFlagMap.end(); iter++) + { + if (iter.value()) + { + tempOption.state |= iter.key(); + } + else + { + tempOption.state &= ~iter.key(); + } + } + + auto backgroundColor = Palette::getDefault()->getColor(Palette::SELECTED, Palette::WIDGET); + auto borderColor = Palette::getDefault()->getColor(tempOption.state, Palette::BORDER); + auto signColor = Palette::getDefault()->getColor(tempOption.state, Palette::ICON); + + // 绘制按钮与输入区域之间的分割线 + if (subControl == QStyle::SC_SpinBoxDown) + { + painter->setBrush(Qt::NoBrush); + painter->setPen(borderColor); + int highlight = hasFocus ? 1 : 0; + painter->drawLine(arrowRect.left(), arrowRect.top() + 2 + highlight, arrowRect.left(), arrowRect.bottom() - 1 - highlight); + } + + if (subControl == QStyle::SC_SpinBoxUp) + { + painter->setBrush(Qt::NoBrush); + painter->setPen(borderColor); + int highlight = hasFocus ? 1 : 0; + painter->drawLine(arrowRect.left(), arrowRect.top() + 2 + highlight, arrowRect.left(), arrowRect.bottom() - 1 - highlight); + } + + // 绘制按钮背景色 + painter->setPen(Qt::NoPen); + QColor background = backgroundColor; + painter->setBrush(background); + painter->drawRect(arrowRect.adjusted(0.5, 0.5, -0.5, -0.5)); + + // 绘制按钮之上的符号 “+”,“-” + QPen pen(signColor, 2); + pen.setCapStyle(Qt::FlatCap); + QRect r = arrowRect.adjusted(1, 2, 0, 0).toRect(); + painter->setPen(pen); + painter->drawLine(r.center() - QPointF(5, 0), r.center() + QPointF(5, 0)); + if (subControl == QStyle::SC_SpinBoxUp) + painter->drawLine(r.center() - QPointF(0, 5), r.center() + QPointF(0, 5)); +} + +//* returns height for scrollbar buttons depending of button types +int StylePrivate::scrollBarButtonHeight(ScrollBarButtonType type) const +{ + switch (type) + { + case NoButton: + return Metrics::ScrollBar_NoButtonHeight; + case SingleButton: + return Metrics::ScrollBar_SingleButtonHeight; + case DoubleButton: + return Metrics::ScrollBar_DoubleButtonHeight; + default: + return 0; + } +} + +QRect StylePrivate::scrollBarInternalSubControlRect(const QStyleOptionComplex *option, QStyle::SubControl subControl) const +{ + const QRect &rect = option->rect; + const QStyle::State &state(option->state); + bool horizontal(state & QStyle::State_Horizontal); + + switch (subControl) + { + case QStyle::SC_ScrollBarSubLine: + { + int majorSize(this->scrollBarButtonHeight(_subLineButtons)); + if (horizontal) + { + return QStyle::visualRect(option->direction, option->rect, QRect(rect.left(), rect.top(), majorSize, rect.height())); + } + else + { + return QStyle::visualRect(option->direction, option->rect, QRect(rect.left(), rect.top(), rect.width(), majorSize)); + } + } + case QStyle::SC_ScrollBarAddLine: + { + int majorSize(this->scrollBarButtonHeight(_addLineButtons)); + if (horizontal) + { + return QStyle::visualRect(option->direction, option->rect, QRect(rect.right() - majorSize + 1, rect.top(), majorSize, rect.height())); + } + else + { + return QStyle::visualRect(option->direction, option->rect, QRect(rect.left(), rect.bottom() - majorSize + 1, rect.width(), majorSize)); + } + } + + default: + return QRect(); + } +} + +void StylePrivate::drawPEIndicatorArrow(ArrowOrientation orientation, const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + auto palettes = Palette::getDefault(); + auto arrowColor = Palette::getDefault()->getColor(option->state, Palette::ICON); + + RenderHelper::renderArrow(painter, option->rect, orientation, arrowColor); +} + +StylePrivate::ButtonType StylePrivate::getButtonType(const QPushButton *btn) +{ + ButtonType buttonType = BUTTON_Normal; + + QVariant var = btn->property(KIRAN_STYLE_PROPERTY_BUTTON_TYPE); + if (var.isValid()) + { + bool toInt = false; + auto temp = static_cast(var.toInt(&toInt)); + if (toInt) + { + buttonType = temp; + } + } + + return buttonType; +} + +/* 这里应该需要给QProxyStyle指定一个非Kiran::Theme::Style类型的Style作为fallback,而不是使用QProxyStyle自动生成Style, + 因为自动生成的Style可能是Kiran::Theme::Style。最终导致死循环。整个顺序为Kiran::Theme::Style -> QProxyStyle -> QFusionStyle, + 如果QFusionStyle使用了proxy()函数,则又会回到Kiran::Theme::Style*/ +Style::Style() : QProxyStyle(QStyleFactory::create("fusion")), + d_ptr(new StylePrivate(this)) +{ +} + +Style::~Style() +{ + delete d_ptr; +} + +int Style::styleHint(QStyle::StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *returnData) const +{ + switch (hint) + { + // 下栏框的下栏列表鼠标追踪 + case SH_ComboBox_ListMouseTracking: + return true; + // 菜单栏鼠标追踪 + case SH_MenuBar_MouseTracking: + return true; + // 菜单鼠标追踪 + case SH_Menu_MouseTracking: + return true; + // 菜单之中子菜单弹出延时时间 + case SH_Menu_SubMenuPopupDelay: + return 150; + // 弹出菜单是否支持用户在跨越菜单的其他项时将鼠标光标移动到子菜单 + case SH_Menu_SloppySubMenus: + return true; +#if (QT_VERSION < QT_VERSION_CHECK(5, 10, 0)) + // 该值目前已废弃,改用SH_Widget_Animation_Duration + case SH_Widget_Animate: + return true; +#else + // 动画持续时间ms,0代表禁用 + case SH_Widget_Animation_Duration: + return 100; +#endif + // 确定样式是在菜单中显示节,还是将其视为普通分隔符。节是带有文本和图标提示的分隔符 + case SH_Menu_SupportsSections: + return true; + // 指示QDialogButtonBox中的标准按钮是否应具有图标 + case SH_DialogButtonBox_ButtonsHaveIcons: + return false; + // GroupBox文本标签垂直对齐选项 + case SH_GroupBox_TextLabelVerticalAlignment: + return Qt::AlignVCenter; + // TabBar的对齐方式 + case SH_TabBar_Alignment: + return Qt::AlignLeft | Qt::AlignVCenter; + // ToolBox中所选页面标题是否显示粗体 + case SH_ToolBox_SelectedPageTitleBold: + return false; + // 滚动条上单击鼠标中键滑块是否跳转到该绝对位置 + case SH_ScrollBar_MiddleClickAbsolutePosition: + return true; + // ScrollView是仅围绕内容(如Motif)还是围绕内容、滚动条和角部件(如窗口)绘制框架。 + case SH_ScrollView_FrameOnlyAroundContents: + return false; + // FormLayout对齐其内容的默认方式 + case SH_FormLayoutFormAlignment: + return Qt::AlignLeft | Qt::AlignVCenter; + // FormatLayout对齐标签的默认方式 + case SH_FormLayoutLabelAlignment: + return Qt::AlignRight; + // QFormLayout中字段增长方式的默认值。返回QFormLayout::FieldGrowthPolicy枚举 + case SH_FormLayoutFieldGrowthPolicy: + return QFormLayout::ExpandingFieldsGrow; + // QFormLayout中如何换行的默认方式。返回一个QFormLayout::RowWrapPolicy enum。 + case SH_FormLayoutWrapPolicy: + return QFormLayout::DontWrapRows; + // 消息框中的文本是否允许用户交互(如选择) + case SH_MessageBox_TextInteractionFlags: + return Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse; + // 进度对话框按钮取消按钮是否居中对齐,否则右对齐 + case SH_ProgressDialog_CenterCancelButton: + return false; + // 消息框是否按钮居中 + case SH_MessageBox_CenterButtons: + return false; + // 输入控件请求输入面板的时间点,返回类型为QStyle::RequestSoftwareInputPanel。 + case SH_RequestSoftwareInputPanel: + return RSIP_OnMouseClick; + // 标题栏无边框 + case SH_TitleBar_NoBorder: + return true; + // DockWidget的按钮是否有Frame + case SH_DockWidget_ButtonsHaveFrame: + return false; + // ToolTip透明文本标签的透明度 + case SH_ToolTipLabel_Opacity: + return 204; + // Table里网格线的颜色 + case SH_Table_GridLineColor: + return Palette::getDefault()->getBaseColors().widgetBorder.rgb(); + default: + return QProxyStyle::styleHint(hint, option, widget, returnData); + } +} + +int Style::pixelMetric(QStyle::PixelMetric metric, const QStyleOption *option, const QWidget *widget) const +{ + switch (metric) + { + case PM_DefaultFrameWidth: + return 6; + case PM_SpinBoxFrameWidth: + return 2; + case PM_ToolBarFrameWidth: + return 6; + case PM_ToolTipLabelFrameWidth: + return 3; + case PM_ComboBoxFrameWidth: + return 3; + case PM_FocusFrameVMargin: + case PM_FocusFrameHMargin: + return 2; + + // 布局默认边距 + case PM_LayoutLeftMargin: + case PM_LayoutTopMargin: + case PM_LayoutRightMargin: + case PM_LayoutBottomMargin: + { + // 使用子控件边距或顶层窗口边距,取决于部件类型 + if ((option && (option->state & QStyle::State_Window)) || (widget && widget->isWindow())) + { + return 10; + } + else + { + return 6; + } + } + + // 布局默认间距 + case PM_LayoutHorizontalSpacing: + case PM_LayoutVerticalSpacing: + return 6; + + // 按钮边距 + case PM_ButtonMargin: + return 12; + + // 按钮默认指示器边框宽度 + case PM_ButtonDefaultIndicator: + return 0; + // 当按钮按下时,按钮的内容水平移动偏移量。 + case PM_ButtonShiftHorizontal: + return 0; + // 当按钮按下时,按钮的内容垂直移动偏移量。 + case PM_ButtonShiftVertical: + return 0; + + // 菜单栏默认边框宽度 + case PM_MenuBarPanelWidth: + return 0; + // 菜单栏水平边距 + case PM_MenuBarHMargin: + return 0; + // 菜单栏垂直边距 + case PM_MenuBarVMargin: + return 3; + // 菜单项间距 + case PM_MenuBarItemSpacing: + return 10; + // 桌面菜单边框宽度 + case PM_MenuDesktopFrameWidth: + return 0; + + // 菜单按钮指示器宽度 + case PM_MenuButtonIndicator: + return 24; + + // toolbars + case PM_ToolBarHandleExtent: + return 10; + case PM_ToolBarSeparatorExtent: + return 8; + case PM_ToolBarExtensionExtent: + return pixelMetric(PM_SmallIconSize, option, widget) + 2 * 6; + + case PM_ToolBarItemMargin: + return 0; + case PM_ToolBarItemSpacing: + return 0; + + // tabbars + case PM_TabBarTabShiftVertical: + return 0; + case PM_TabBarTabShiftHorizontal: + return 0; + case PM_TabBarTabOverlap: + return 1; + case PM_TabBarBaseOverlap: + return 2; + case PM_TabBarTabHSpace: + return 2 * 8; + case PM_TabBarTabVSpace: + return 2 * 4; + case PM_TabCloseIndicatorWidth: + case PM_TabCloseIndicatorHeight: + return pixelMetric(PM_SmallIconSize, option, widget); + + // scrollbars + case PM_ScrollBarExtent: + return 5; + case PM_ScrollBarSliderMin: + return 20; + + // scrollview + case PM_ScrollView_ScrollBarOverlap: + return 1; + + // title bar + case PM_TitleBarHeight: + return 2 * 4 + pixelMetric(PM_SmallIconSize, option, widget); + + // sliders + case PM_SliderThickness: + return 16; + case PM_SliderControlThickness: + return 16; + case PM_SliderLength: + return 16; + + // checkboxes and radio buttons + case PM_IndicatorWidth: + case PM_IndicatorHeight: + case PM_ExclusiveIndicatorWidth: + case PM_ExclusiveIndicatorHeight: + return 15; + + // list headers + case PM_HeaderMarkSize: + return 10; + case PM_HeaderMargin: + return 6; + + // dock widget + // return 0 here, since frame is handled directly in polish + case PM_DockWidgetFrameWidth: + return 0; + case PM_DockWidgetTitleMargin: + return 4; + case PM_DockWidgetTitleBarButtonMargin: + return 6; + + case PM_SplitterWidth: + return 1; + case PM_DockWidgetSeparatorExtent: + return 1; + + default: // fallback + break; + } + return QProxyStyle::pixelMetric(metric, option, widget); +} + +void Style::drawPrimitive(QStyle::PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + PainterSaver painterSaver(painter); + + switch (element) + { + case PE_Frame: + this->drawPEFrame(option, painter, widget); + break; +// case PE_FrameFocusRect: +// this->drawPEFrameFocusRect(option, painter, widget); +// break; + case PE_FrameGroupBox: + this->drawPEFrameGroupBox(option, painter, widget); + break; + case PE_PanelButtonCommand: + this->drawPEPanelButtonCommand(option, painter, widget); + break; + case PE_PanelButtonTool: + this->drawPEPanelButtonTool(option, painter, widget); + break; + case PE_FrameLineEdit: + this->drawPEFrameLineEdit(option, painter, widget); + break; + case PE_PanelLineEdit: + { + /*作为QComoBox和QAbstractSpinBox的子控件时不进行绘制*/ + if (widget && widget->parentWidget()) + { + if (qobject_cast(widget->parentWidget()) || + qobject_cast(widget->parentWidget())) + { + return; + } + } + + if (const QStyleOptionFrame *panel = qstyleoption_cast(option)) + { + if (panel->lineWidth > 0) + { + return Style::drawPrimitive(PE_FrameLineEdit, panel, painter, widget); + } + return; + } + + break; + } + case PE_IndicatorButtonDropDown: + this->drawPEIndicatorButtonDropDown(option, painter, widget); + break; + case PE_IndicatorArrowUp: + this->drawPEIndicatorArrowUp(option, painter, widget); + break; + case PE_IndicatorArrowDown: + this->drawPEIndicatorArrowDown(option, painter, widget); + break; + case PE_IndicatorArrowLeft: + this->drawPEIndicatorArrowLeft(option, painter, widget); + break; + case PE_IndicatorArrowRight: + this->drawPEIndicatorArrowRight(option, painter, widget); + break; + case PE_IndicatorRadioButton: + this->drawPEIndicatorRadioButton(option, painter, widget); + break; + case PE_IndicatorCheckBox: + this->drawPEIndicatorCheckBox(option, painter, widget); + break; + case PE_IndicatorBranch: + this->drawPEIndicatorBranch(option, painter, widget); + break; + case PE_FrameTabWidget: + this->drawPEFrameTabWidget(option, painter, widget); + break; + case PE_IndicatorToolBarSeparator: + this->drawPEIndicatorToolBarSeparator(option, painter, widget); + break; + case PE_IndicatorToolBarHandle: + this->drawPEIndicatorToolBarHandle(option, painter, widget); + break; +// case PE_PanelItemViewRow: +// this->drawPanelItemViewRow(option, painter, widget); +// break; +// case PE_PanelItemViewItem: +// this->drawPanelItemViewItem(option, painter, widget); +// break; + default: + QProxyStyle::drawPrimitive(element, option, painter, widget); + break; + } +} + +void Style::drawComplexControl(QStyle::ComplexControl control, + const QStyleOptionComplex *option, + QPainter *painter, + const QWidget *widget) const +{ + PainterSaver painterSaver(painter); + + switch (control) + { + case QStyle::CC_ToolButton: + this->drawCCToolButton(option, painter, widget); + break; + case QStyle::CC_ComboBox: + this->drawCCComboBox(option, painter, widget); + break; + case QStyle::CC_ScrollBar: + this->drawCCScrollBar(option, painter, widget); + break; + case QStyle::CC_SpinBox: + this->drawCCSpinBox(option, painter, widget); + break; + case QStyle::CC_Slider: + this->drawCCSlider(option, painter, widget); + break; + default: + QProxyStyle::drawComplexControl(control, option, painter, widget); + break; + } +} + +QRect Style::subElementRect(QStyle::SubElement element, const QStyleOption *option, const QWidget *widget) const +{ + switch (element) + { + case QStyle::SE_TabBarTearIndicator: + case QStyle::SE_TabBarTabLeftButton: + case QStyle::SE_TabBarTabRightButton: + case QStyle::SE_TabBarTabText: + case QStyle::SE_TabBarScrollLeftButton: + case QStyle::SE_TabBarScrollRightButton: + case QStyle::SE_TabBarTearIndicatorRight: + return this->tabBarSubElementRect(element, option, widget); + case SE_ProgressBarGroove: + case SE_ProgressBarContents: + case SE_ProgressBarLabel: + return this->progressBarElementRect(element, option, widget); + case QStyle::SE_SliderFocusRect: + return this->sliderElementRect(element, option, widget); + default: + break; + } + + return QProxyStyle::subElementRect(element, option, widget); +} + +QRect Style::subControlRect(QStyle::ComplexControl complexControl, + const QStyleOptionComplex *option, + QStyle::SubControl subControl, + const QWidget *widget) const +{ + switch (complexControl) + { + case QStyle::CC_ToolButton: + return this->toolButtonSubControlRect(option, subControl, widget); + case QStyle::CC_ComboBox: + return this->comboBoxSubControlRect(option, subControl, widget); + case QStyle::CC_ScrollBar: + return this->scrollBarSubControlRect(option, subControl, widget); + case QStyle::CC_SpinBox: + return this->spinBoxSubControlRect(option, subControl, widget); + // TODO: 先注释 + // case QStyle::CC_GroupBox: + // return this->groupBoxSubControlRect(option, subControl, widget); + case QStyle::CC_Slider: + return this->sliderSubControlRect(option, subControl, widget); + default: + return QProxyStyle::subControlRect(complexControl, option, subControl, widget); + } +} + +QSize Style::sizeFromContents(QStyle::ContentsType type, const QStyleOption *option, const QSize &contentSize, const QWidget *widget) const +{ + switch (type) + { + case CT_PushButton: + return this->pushButtonSizeFromContents(option, contentSize, widget); + case CT_ToolButton: + return this->toolButtonSizeFromContents(option, contentSize, widget); + case CT_TabBarTab: + return this->tabBarTabSizeFromContents(option, contentSize, widget); + case CT_ComboBox: + return this->comboBoxSizeFromContents(option, contentSize, widget); + case CT_SpinBox: + return this->spinBoxSizeFromContents(option, contentSize, widget); + case CT_GroupBox: + return this->groupBoxSizeFromContents(option, contentSize, widget); + case CT_ProgressBar: + return this->progressBarSizeFromContents(option, contentSize, widget); + case CT_Slider: + return this->sliderSizeFromContents(option, contentSize, widget); + case CT_CheckBox: + break; + case CT_RadioButton: + break; + case CT_Splitter: + break; + case CT_MenuItem: + break; + case CT_MenuBarItem: + break; + case CT_MenuBar: + break; + case CT_Menu: + break; + case CT_LineEdit: + { + int buttuonMargin = pixelMetric(QStyle::PM_ButtonMargin, option, widget); + QSize size = contentSize + QSize(buttuonMargin, buttuonMargin); + return size; + } + case CT_SizeGrip: + break; + case CT_TabWidget: + break; + case CT_DialogButtons: + break; + case CT_HeaderSection: + break; + case CT_MdiControls: + break; + case CT_ItemViewItem: + break; + default: + break; + } + return QProxyStyle::sizeFromContents(type, option, contentSize, widget); +} + +void Style::drawControl(QStyle::ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + PainterSaver painterSaver(painter); + + switch (element) + { + case CE_PushButton: + this->drawPEPushButton(element, option, painter, widget); + break; + case CE_ShapedFrame: + this->drawControlShapedFrame(option, painter, widget); + break; + case CE_TabBarTabShape: + this->drawControlTabBarTabShape(option, painter, widget); + break; + case CE_ToolBoxTabLabel: + this->drawControlToolButtonLabel(option, painter, widget); + break; + case CE_ComboBoxLabel: + this->drawControlComboBoxLabel(option, painter, widget); + break; + case CE_HeaderLabel: + this->drawControlHeaderLabel(option, painter, widget); + break; + case CE_HeaderSection: + this->drawControlHeaderSection(option, painter, widget); + break; + case CE_HeaderEmptyArea: + this->drawControlHeaderEmptyArea(option, painter, widget); + break; + case CE_ScrollBarSlider: + this->drawControlScrollBarSlider(option, painter, widget); + break; + case CE_ProgressBar: + this->drawControlProgressBar(option, painter, widget); + break; + case CE_ProgressBarGroove: + this->drawControlProgressBarGroove(option, painter, widget); + break; + case CE_ProgressBarContents: + this->drawControlProgressBarContents(option, painter, widget); + break; + case CE_ProgressBarLabel: + this->drawControlProgressBarLabel(option, painter, widget); + break; + case CE_MenuBarItem: + this->drawControlMenuBarItem(option, painter, widget); + break; + case CE_MenuBarEmptyArea: + this->drawControlMenuBarEmptyArea(option, painter, widget); + break; + // 不绘制的控件元素集合 + case CE_ToolBar: + break; + case CE_ItemViewItem: + this->drawItemViewItem(element, option, painter, widget); + break; + default: + QProxyStyle::drawControl(element, option, painter, widget); + break; + } +} + +QPixmap Style::standardPixmap(QStyle::StandardPixmap standardPixmap, const QStyleOption *opt, const QWidget *widget) const +{ + switch (standardPixmap) + { + case SP_ArrowUp: + case SP_ArrowDown: + case SP_ArrowLeft: + case SP_ArrowRight: + { + QPalette palette = widget ? widget->palette() : qApp->palette(); + QPalette::ColorRole colorRole = widget ? widget->foregroundRole() : QPalette::ButtonText; + QPixmap arrowPixmap(16, 16); + arrowPixmap.fill(Qt::transparent); + QPainter painter(&arrowPixmap); + RenderHelper::renderArrow(&painter, arrowPixmap.rect(), (Kiran::ArrowOrientation)((int)standardPixmap - SP_ArrowUp), palette.color(colorRole)); + return arrowPixmap; + } + default: + break; + } + return QProxyStyle::standardPixmap(standardPixmap, opt, widget); +} + +QIcon Style::standardIcon(QStyle::StandardPixmap standardIcon, const QStyleOption *option, const QWidget *widget) const +{ + static const QMap titleBarIconMap = { + {SP_TitleBarMinButton, ":/style/images/window-minimum-symbolic.svg"}, + {SP_TitleBarMaxButton, ":/style/images/window-maximum-symbolic.svg"}, + {SP_TitleBarCloseButton, ":/style/images/window-close-symbolic.svg"}, + {SP_TitleBarNormalButton, ":/style/images/window-unmaximum-symbolic.svg"}, + + }; + switch (standardIcon) + { + case SP_TitleBarMinButton: + case SP_TitleBarMaxButton: + case SP_TitleBarCloseButton: + case SP_TitleBarNormalButton: + { + QSize defaultTitleBarIconSize(16, 16); + + QIcon res; + auto iter = titleBarIconMap.find(standardIcon); + QString iconPath = iter.value(); + QPalette palette = qApp->palette(); + + QPixmap normal = RenderHelper::changeSVGFillColor(iconPath, palette.color(QPalette::Normal, QPalette::Foreground), defaultTitleBarIconSize); + res.addPixmap(normal, QIcon::Normal); + + QPixmap disable = RenderHelper::changeSVGFillColor(iconPath, palette.color(QPalette::Disabled, QPalette::Foreground), defaultTitleBarIconSize); + res.addPixmap(normal, QIcon::Disabled); + return res; + } + default: + break; + } + return QProxyStyle::standardIcon(standardIcon, option, widget); +} + +void Style::polishScrollArea(QAbstractScrollArea *scrollArea) +{ + if (!scrollArea) + return; + + // enable mouse over effect in sunken scrollareas that support focus + if (scrollArea->frameShadow() == QFrame::Sunken && scrollArea->focusPolicy() & Qt::StrongFocus) + { + scrollArea->setAttribute(Qt::WA_Hover); + } + + // disable autofill background for flat (== NoFrame) scrollareas, with QPalette::Window as a background + // this fixes flat scrollareas placed in a tinted widget, such as groupboxes, tabwidgets or framed dock-widgets + if (!(scrollArea->frameShape() == QFrame::NoFrame || scrollArea->backgroundRole() == QPalette::Window)) + { + return; + } + + // get viewport and check background role + QWidget *viewport(scrollArea->viewport()); + if (!(viewport && viewport->backgroundRole() == QPalette::Window)) + return; + + // change viewport autoFill background. + // do the same for all children if the background role is QPalette::Window + viewport->setAutoFillBackground(false); + QList children(viewport->findChildren()); + foreach (QWidget *child, children) + { + if (child->parent() == viewport && child->backgroundRole() == QPalette::Window) + { + child->setAutoFillBackground(false); + } + } +} + +void Style::polish(QWidget *widget) +{ + RETURN_IF_FALSE(widget); + + // enable mouse over effects for all necessary widgets + if (qobject_cast(widget) || + qobject_cast(widget) || + qobject_cast(widget) || + qobject_cast(widget) || + qobject_cast(widget) || + qobject_cast(widget) || + qobject_cast(widget) || + qobject_cast(widget) || + qobject_cast(widget) || + qobject_cast(widget) || + qobject_cast(widget) || + qobject_cast(widget) || + qobject_cast(widget) || + qobject_cast(widget)) + { + widget->setAttribute(Qt::WA_Hover); + } + + polishScrollArea(qobject_cast(widget)); + + if (QAbstractItemView *itemView = qobject_cast(widget)) + { + // enable mouse over effects in itemviews' viewport + itemView->viewport()->setAttribute(Qt::WA_Hover); + } + + QProxyStyle::polish(widget); +} + +void Style::polish(QApplication *application) +{ + QProxyStyle::polish(application); + + QPalette palette; + this->polish(palette); + QApplication::setPalette(palette); +} + +void Style::polish(QPalette &palette) +{ + // 用于初始化部件的外观,会在部件创建完成之后,在第一次显示之前被调用,默认实现什么也不做。 + // 子类化 QStyle 时,可利用该函数的调用时机,对部件的一些属性进行初始化。 + // 通常在此函数内指定配色方案,也即配置调色板,改变调色板为样式指定的颜色调色板。 + DEFAULT_PALETTE()->polish(palette); +} + +void Style::drawPEFrame(const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + auto palettes = Palette::getDefault(); + auto background = Palette::getDefault()->getColor(option->state, Palette::WINDOW); + auto border = Palette::getDefault()->getColor(option->state, Palette::BORDER); + + if (qobject_cast(widget)) + { + RenderHelper::renderFrame(painter, option->rect, 1, 0, Qt::transparent, border); + } + else + { + RenderHelper::renderFrame(painter, option->rect, 1, 0, background, border); + } +} + +void Style::drawPEFrameFocusRect(const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + RETURN_IF_FALSE(qstyleoption_cast(option)); + + auto background = Palette::getDefault()->getColor(option->state, Palette::WIDGET); + const QStyle::State &state(option->state); + bool hasFocus(state & QStyle::State_HasFocus); + + if (hasFocus) + { + background = Qt::transparent; + QColor borderColor = DEFAULT_PALETTE()->getColor(Palette::SELECTED,Palette::WIDGET); + RenderHelper::renderFrame(painter, option->rect, 1, 4, background, borderColor); + } +} + +void Style::drawPEFrameGroupBox(const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + RETURN_IF_FALSE(qstyleoption_cast(option)); + + auto topMargin = qMax(pixelMetric(PM_ExclusiveIndicatorHeight), option->fontMetrics.height()) + groupBoxTopMargin; + auto frame = option->rect.adjusted(0, topMargin, 0, 0); + auto background = DEFAULT_PALETTE()->getBaseColors().baseBackground; + auto border = DEFAULT_PALETTE()->getBaseColors().widgetBorder; + RenderHelper::renderFrame(painter, frame, 1, 0, background, border); +} + +void Style::drawControlShapedFrame(const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + auto frameOption = qstyleoption_cast(option); + RETURN_IF_FALSE(frameOption); + + switch (frameOption->frameShape) + { + case QFrame::Box: + break; + case QFrame::HLine: + case QFrame::VLine: + { + const QRect &rect(option->rect); + bool isVertical(frameOption->frameShape == QFrame::VLine); + auto color = Palette::getDefault()->getColor(option->state, Palette::BORDER); + RenderHelper::renderSeparator(painter, option->rect, isVertical, color); + break; + } + case QFrame::StyledPanel: + { + if (RenderHelper::isQtQuickControl(option, widget)) + { + this->drawPrimitive(QStyle::PE_FrameMenu, option, painter, widget); + } + break; + } + default: + break; + } +} + +QSize Style::defaultSizeFromContents(const QStyleOption *option, const QSize &contentSize, const QWidget *widget) const +{ + return contentSize; +} + +// 根据按钮内容计算按钮尺寸 +QSize Style::pushButtonSizeFromContents(const QStyleOption *option, const QSize &contentSize, const QWidget *widget) const +{ + const auto buttonOption(qstyleoption_cast(option)); + if (!buttonOption) return contentSize; + + QSize size; + + const bool hasText(!buttonOption->text.isEmpty()); + const bool flat(buttonOption->features & QStyleOptionButton::Flat); + bool hasIcon(!buttonOption->icon.isNull()); + + if (!(hasText || hasIcon)) + { + // 没有文本以及图标,采用自定义按钮作为内容大小的起点 + size = contentSize; + } + else + { + // 不管Qt在内容大小如何计算,完全根据按钮选项重新计算按钮大小,保证渲染阶段的一致性 + hasIcon &= (RenderHelper::showIconsOnPushButtons() || flat || !hasText); + + // 文本大小 + if (hasText) + size = buttonOption->fontMetrics.size(Qt::TextShowMnemonic, buttonOption->text); + + // 图标大小 + if (hasIcon) + { + QSize iconSize = buttonOption->iconSize; + if (!iconSize.isValid()) + { + iconSize = QSize(this->pixelMetric(QStyle::PM_SmallIconSize, option, widget), + this->pixelMetric(QStyle::PM_SmallIconSize, option, widget)); + } + + size.setHeight(qMax(size.height(), iconSize.height())); + size.rwidth() += iconSize.width(); + + if (hasText) size.rwidth() += Metrics::Button_ItemSpacing; + } + } + + // 菜单 + const bool hasMenu(buttonOption->features & QStyleOptionButton::HasMenu); + if (hasMenu) + { + size.rwidth() += Metrics::MenuButton_IndicatorWidth; + if (hasText || hasIcon) size.rwidth() += Metrics::Button_ItemSpacing; + } + + // 扩展按钮内边距 + size = RenderHelper::expandSize(size, Metrics::Button_MarginWidth, Metrics::Button_MarginHeight); + // 扩张按钮边框宽度 + size = RenderHelper::expandSize(size, Metrics::Frame_FrameWidth); + + // 确保按钮有最小的宽度 + if (hasText) + { + size.setWidth(qMax(size.width(), int(Metrics::Button_MinWidth))); + } + + // 确保按钮有最小高度 + size.setHeight(qMax(size.height(), int(Metrics::Button_MinHeight))); + + return size; +} + +// 根据ToolButton内容大小获取尺寸 +QSize Style::toolButtonSizeFromContents(const QStyleOption *option, const QSize &contentSize, const QWidget *widget) const +{ + const auto toolButtonOption = qstyleoption_cast(option); + if (!toolButtonOption) return contentSize; + + QSize size = contentSize; + + const QStyle::State &state(option->state); + + // Auto Raise标志: true表示自动突出,false表示与父窗口齐平 + const bool autoRaise(state & QStyle::State_AutoRaise); + const bool hasPopupMenu(toolButtonOption->features & QStyleOptionToolButton::MenuButtonPopup); + const bool hasInlineIndicator(toolButtonOption->features & QStyleOptionToolButton::HasMenu && toolButtonOption->features & QStyleOptionToolButton::PopupDelay && !hasPopupMenu); + + // 若存在内部指示器,宽度加上一个内部指示器的宽度 + if (hasInlineIndicator) size.rwidth() += Metrics::ToolButton_InlineIndicatorWidth; + + // 总边距宽度=按钮边距宽度+Frame宽度 + int marginWidth = Metrics::Button_MarginWidth + Metrics::Frame_FrameWidth; + // 四周扩展边距宽度 + size = RenderHelper::expandSize(size, marginWidth); + + return size; +} + +QRect Style::toolButtonSubControlRect(const QStyleOptionComplex *option, QStyle::SubControl subControl, const QWidget *widget) const +{ + const auto toolButtonOption = qstyleoption_cast(option); + RETURN_VAL_IF_FALSE(toolButtonOption, QRect()); + + bool hasPopupMenu(toolButtonOption->features & QStyleOptionToolButton::MenuButtonPopup); + const bool hasInlineIndicator(toolButtonOption->features & QStyleOptionToolButton::HasMenu && + toolButtonOption->features & QStyleOptionToolButton::PopupDelay && + !hasPopupMenu); + + const QRect &rect(option->rect); + int menuButtonWidth(Metrics::MenuButton_IndicatorWidth); + + switch (subControl) + { + case QStyle::SC_ToolButtonMenu: + { + RETURN_VAL_IF_TRUE(!(hasPopupMenu || hasInlineIndicator), QRect()); + + QRect menuRect(rect); + // 定位菜单按钮为ToolButton右侧 + menuRect.setLeft(rect.right() - menuButtonWidth + 1); + if (hasInlineIndicator) + { + menuRect.setTop(menuRect.bottom() - menuButtonWidth); + } + return QStyle::visualRect(option->direction, option->rect, menuRect); + } + case QStyle::SC_ToolButton: + { + if (hasPopupMenu) + { + QRect contentsRect(rect); + contentsRect.setRight(rect.right() - menuButtonWidth); + return QStyle::visualRect(option->direction, option->rect, contentsRect); + } + else + { + return rect; + } + break; + } + default: + return QProxyStyle::subControlRect(QStyle::CC_ToolButton, option, subControl, widget); + } +} + +void Style::drawPEPushButton(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + auto buttonOption = qstyleoption_cast(option); + RETURN_IF_FALSE(buttonOption); + + const QRect &rect(buttonOption->rect); + const QStyle::State &state(option->state); + bool enabled(state & QStyle::State_Enabled); + bool windowActive(state & QStyle::State_Active); + bool mouseOver((state & QStyle::State_Active) && enabled && (state & QStyle::State_MouseOver)); + bool hasFocus((enabled && (state & QStyle::State_HasFocus)) && !(widget && widget->focusProxy())); + bool sunken = (state & (QStyle::State_On | QStyle::State_Sunken)); + bool flat(buttonOption->features & QStyleOptionButton::Flat); + + auto palette = Palette::getDefault(); + auto background = palette->getColor(option->state, Palette::WIDGET); + auto border = palette->getColor(option->state, Palette::BORDER); + + StylePrivate::ButtonType buttonType = StylePrivate::getButtonType(qobject_cast(widget)); + // 若为 Button_Default 按钮中的文字为白色 + if (enabled && buttonType == StylePrivate::BUTTON_Default) + { + QColor textColor = Qt::white; // 主按钮文字总为白色 + QStyleOptionButton modifiedOption(*buttonOption); + modifiedOption.palette.setColor(QPalette::ButtonText, textColor); + QProxyStyle::drawControl(element, &modifiedOption, painter, widget); + return; + } + if (enabled && qobject_cast(widget) && StylePrivate::getButtonType(qobject_cast(widget)) != StylePrivate::BUTTON_Normal) + { + if (buttonType == StylePrivate::BUTTON_Warning) + { + QColor textColor = DEFAULT_PALETTE()->getBaseColors().widgetWarning; + QStyleOptionButton modifiedOption(*buttonOption); + modifiedOption.palette.setColor(QPalette::ButtonText, textColor); + QProxyStyle::drawControl(element, &modifiedOption, painter, widget); + return; + } + } + QProxyStyle::drawControl(element, buttonOption, painter, widget); +} + +void Style::drawItemViewItem(QStyle::ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + const auto itemOption = qstyleoption_cast(option); + if (itemOption && itemOption->state & QStyle::State_Selected) + { + QStyleOptionViewItem newOption(*itemOption); +// newOption.palette.setColor(QPalette::HighlightedText, Qt::red); +// newOption.palette.setColor(QPalette::Highlight, Qt::transparent); + QProxyStyle::drawControl(element, &newOption, painter, widget); + return; + } + + QProxyStyle::drawControl(element, option, painter, widget); +} + +void Style::drawPEPanelButtonCommand(const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + auto buttonOption = qstyleoption_cast(option); + RETURN_IF_FALSE(buttonOption); + + const QRect &rect(option->rect); + const QStyle::State &state(option->state); + bool enabled(state & QStyle::State_Enabled); + bool windowActive(state & QStyle::State_Active); + bool mouseOver((state & QStyle::State_Active) && enabled && (state & QStyle::State_MouseOver)); + bool hasFocus((enabled && (state & QStyle::State_HasFocus)) && !(widget && widget->focusProxy())); + bool hasKeyboardFocusChange((option->state & State_KeyboardFocusChange) && hasFocus); // 加入 State_KeyboardFocusChange 的目的:确保是使用 TAB 键切换焦点才显示选中边框 + bool sunken(state & (QStyle::State_On | QStyle::State_Sunken)); + bool flat(buttonOption->features & QStyleOptionButton::Flat); + + auto palettes = Palette::getDefault(); + auto background = palettes->getColor(option->state, Palette::WIDGET); + auto border = palettes->getColor(option->state, Palette::BORDER); + + StylePrivate::ButtonType buttonType = StylePrivate::getButtonType(qobject_cast(widget)); + if (enabled && qobject_cast(widget) && buttonType != StylePrivate::BUTTON_Normal) + { + if (buttonType == StylePrivate::BUTTON_Default) + { + background = DEFAULT_PALETTE()->getBaseColors().widgetMain; + if (mouseOver) + { + background = DEFAULT_PALETTE()->getColor(Palette::MOUSE_OVER, Palette::WIDGET); + background = QColor(112, 203, 255); // FIXME: 颜色较特殊,暂时指定 + } + if (sunken) + { + background = DEFAULT_PALETTE()->getColor(Palette::SUNKEN, Palette::WIDGET); + background = QColor(0, 112, 176); // FIXME: 颜色较特殊,暂时指定 + } + } + if (buttonType == StylePrivate::BUTTON_Warning) + { + if (sunken) + { + background = DEFAULT_PALETTE()->getColor(Palette::SELECTED, Palette::WINDOW); + } + } + } + + if (flat && !sunken) + { + background = Qt::transparent; + } + + if (hasKeyboardFocusChange && !sunken) + { + border = DEFAULT_PALETTE()->getColor(Palette::SELECTED,Palette::WIDGET); + } + + RenderHelper::renderFrame(painter, option->rect, 1, 4, background, border); +} + +void Style::drawPEPanelButtonTool(const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + const QPalette &palette(option->palette); + QRect rect(option->rect); + + const QStyle::State &state(option->state); + bool autoRaise(state & QStyle::State_AutoRaise); + bool enabled(state & QStyle::State_Enabled); + bool windowActive(state & QStyle::State_Active); + bool sunken(state & (QStyle::State_On | QStyle::State_Sunken)); + bool mouseOver((state & QStyle::State_Active) && enabled && (option->state & QStyle::State_MouseOver)); + bool hasFocus(enabled && (option->state & (QStyle::State_HasFocus))); + + if (!autoRaise || mouseOver || sunken) + { + // need to check widget for popup mode, because option is not set properly + const auto *toolButton(qobject_cast(widget)); + bool hasPopupMenu(toolButton && toolButton->popupMode() == QToolButton::MenuButtonPopup); + + // adjust frame in case of menu + if (hasPopupMenu) + { + painter->setClipRect(rect); + rect.adjust(0, 0, Metrics::Frame_FrameRadius + 2, 0); + rect = QStyle::visualRect(option->direction, option->rect, rect); + } + + auto background = Palette::getDefault()->getColor(option->state, Palette::WIDGET); + auto border = Palette::getDefault()->getColor(option->state, Palette::BORDER); + RenderHelper::renderFrame(painter, rect, 1, 4, background, border); + } + else if (hasFocus) + { + auto background = Palette::getDefault()->getBaseColors().widgetWarning; +// auto border = DEFAULT_PALETTE()->getColor(Palette::SELECTED,Palette::WIDGET); + RenderHelper::renderFrame(painter, rect, 1, 4, background); + } + else + { + RenderHelper::renderFrame(painter, rect, 1, 4, Qt::transparent); + } +} + +void Style::drawControlToolButtonLabel(const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + const auto toolButtonOption(qstyleoption_cast(option)); + RETURN_IF_FALSE(toolButtonOption); + + const QRect &rect = option->rect; + const QPalette &palette = option->palette; + + const QStyle::State &state(option->state); + bool enabled(state & QStyle::State_Enabled); + bool sunken(state & (QStyle::State_On | QStyle::State_Sunken)); + bool mouseOver((state & QStyle::State_Active) && enabled && (option->state & QStyle::State_MouseOver)); + bool flat(state & QStyle::State_AutoRaise); + + bool hasFocus(false); + if (flat) + hasFocus = enabled && !mouseOver && (option->state & QStyle::State_HasFocus); + else + hasFocus = enabled && !mouseOver && (option->state & (QStyle::State_HasFocus | QStyle::State_Sunken)); + + bool hasArrow = toolButtonOption->features & QStyleOptionToolButton::Arrow; + bool hasIcon(!(hasArrow || toolButtonOption->icon.isNull())); + bool hasText(!toolButtonOption->text.isEmpty()); + + QRect contentsRect(rect); + QSize iconSize(toolButtonOption->iconSize); + int textFlags(RenderHelper::mnemonicsTextFlags()); + QSize textSize(option->fontMetrics.size(textFlags, toolButtonOption->text)); + + QRect iconRect; + QRect textRect; + + if (hasText && (!(hasArrow || hasIcon) || toolButtonOption->toolButtonStyle == Qt::ToolButtonTextOnly)) // 只显示文字 + { + textRect = contentsRect; + textFlags |= Qt::AlignCenter; + } + else if ((hasArrow || hasIcon) && (!hasText || toolButtonOption->toolButtonStyle == Qt::ToolButtonIconOnly)) // 只显示图标 + { + iconRect = contentsRect; + } + else if (toolButtonOption->toolButtonStyle == Qt::ToolButtonTextUnderIcon) // 文字位于图标之下 + { + int contentsHeight(iconSize.height() + textSize.height() + Metrics::ToolButton_ItemSpacing); + iconRect = QRect(QPoint(contentsRect.left() + (contentsRect.width() - iconSize.width()) / 2, contentsRect.top() + (contentsRect.height() - contentsHeight) / 2), iconSize); + textRect = QRect(QPoint(contentsRect.left() + (contentsRect.width() - textSize.width()) / 2, iconRect.bottom() + Metrics::ToolButton_ItemSpacing + 1), textSize); + textFlags |= Qt::AlignCenter; + } + else + { + // bool leftAlign(widget && widget->property(PropertyNames::toolButtonAlignment).toInt() == Qt::AlignLeft); + // if (leftAlign) + // iconRect = QRect(QPoint(contentsRect.left(), contentsRect.top() + (contentsRect.height() - iconSize.height()) / 2), iconSize); + // else + { + int contentsWidth(iconSize.width() + textSize.width() + Metrics::ToolButton_ItemSpacing); + iconRect = QRect(QPoint(contentsRect.left() + (contentsRect.width() - contentsWidth) / 2, contentsRect.top() + (contentsRect.height() - iconSize.height()) / 2), iconSize); + } + + textRect = QRect(QPoint(iconRect.right() + Metrics::ToolButton_ItemSpacing + 1, contentsRect.top() + (contentsRect.height() - textSize.height()) / 2), textSize); + + // handle right to left layouts + iconRect = QStyle::visualRect(option->direction, option->rect, iconRect); + textRect = QStyle::visualRect(option->direction, option->rect, textRect); + + textFlags |= Qt::AlignLeft | Qt::AlignVCenter; + } + + // make sure there is enough room for icon + if (iconRect.isValid()) iconRect = RenderHelper::centerRect(iconRect, iconSize); + + // render arrow or icon + if (hasArrow && iconRect.isValid()) + { + QStyleOptionToolButton copy(*toolButtonOption); + copy.rect = iconRect; + switch (toolButtonOption->arrowType) + { + case Qt::LeftArrow: + this->drawPrimitive(QStyle::PE_IndicatorArrowLeft, ©, painter, widget); + break; + case Qt::RightArrow: + this->drawPrimitive(QStyle::PE_IndicatorArrowRight, ©, painter, widget); + break; + case Qt::UpArrow: + this->drawPrimitive(QStyle::PE_IndicatorArrowUp, ©, painter, widget); + break; + case Qt::DownArrow: + this->drawPrimitive(QStyle::PE_IndicatorArrowDown, ©, painter, widget); + break; + default: + break; + } + } + else if (hasIcon && iconRect.isValid()) + { + // icon state and mode + const QIcon::State iconState(sunken ? QIcon::On : QIcon::Off); + QIcon::Mode iconMode; + if (!enabled) + iconMode = QIcon::Disabled; + else if (!flat && hasFocus) + iconMode = QIcon::Selected; + else if (mouseOver && flat) + iconMode = QIcon::Active; + else + iconMode = QIcon::Normal; + + QPixmap pixmap = toolButtonOption->icon.pixmap(iconSize, iconMode, iconState); + this->drawItemPixmap(painter, iconRect, Qt::AlignCenter, pixmap); + } + + // render text + if (hasText && textRect.isValid()) + { + QPalette::ColorRole textRole(QPalette::ButtonText); + if (flat) + textRole = (hasFocus && sunken && !mouseOver) ? QPalette::HighlightedText : QPalette::WindowText; + else if (hasFocus && !mouseOver) + textRole = QPalette::HighlightedText; + + painter->setFont(toolButtonOption->font); + this->drawItemText(painter, textRect, textFlags, palette, enabled, toolButtonOption->text, textRole); + } +} + +void Style::drawCCToolButton(const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const +{ + const auto *toolButtonOption(qstyleoption_cast(option)); + RETURN_IF_FALSE(toolButtonOption); + + const QStyle::State &state(option->state); + bool enabled(state & QStyle::State_Enabled); + bool mouseOver((state & QStyle::State_Active) && enabled && (option->state & QStyle::State_MouseOver)); + bool hasFocus(enabled && (option->state & QStyle::State_HasFocus)); + bool sunken(state & (QStyle::State_On | QStyle::State_Sunken)); + bool flat(state & QStyle::State_AutoRaise); + + bool isDockWidgetTitleButton(widget && widget->inherits("QDockWidgetTitleButton")); + bool inTabBar(widget && qobject_cast(widget->parentWidget())); + bool isMenuTitle(RenderHelper::isMenuTitle(widget)); + + if (isMenuTitle) + { + QStyleOptionToolButton copy(*toolButtonOption); + copy.font.setBold(false); + copy.state = QStyle::State_Enabled; + + return; + } + + // copy option and alter palette + QStyleOptionToolButton copy(*toolButtonOption); + + if (isDockWidgetTitleButton) + { + const QAbstractButton *button(qobject_cast(widget)); + if (button->isChecked() || button->isDown()) + { + copy.state |= QStyle::State_Enabled | QStyle::State_On | QStyle::State_Sunken; + } + if (button->underMouse()) + { + copy.state |= QStyle::State_Enabled | QStyle::State_MouseOver | QStyle::State_Active; + } + } + + bool hasPopupMenu(toolButtonOption->features & QStyleOptionToolButton::MenuButtonPopup); + const bool hasInlineIndicator( + toolButtonOption->features & QStyleOptionToolButton::HasMenu && toolButtonOption->features & QStyleOptionToolButton::PopupDelay && !hasPopupMenu); + + QRect buttonRect(this->subControlRect(QStyle::CC_ToolButton, option, QStyle::SC_ToolButton, widget)); + QRect menuRect(this->subControlRect(QStyle::CC_ToolButton, option, QStyle::SC_ToolButtonMenu, widget)); + + // frame + if (toolButtonOption->subControls & QStyle::SC_ToolButton || isDockWidgetTitleButton) + { + copy.rect = buttonRect; + if (inTabBar) + { + QRect rect(option->rect); + + auto background = Palette::getDefault()->getColor(option->state, Palette::WIDGET); + + painter->setPen(background); + painter->setBrush(background); + + switch (toolButtonOption->arrowType) + { + case Qt::UpArrow: + painter->drawRect(rect.adjusted(1, 1, -2, -1)); + break; + case Qt::DownArrow: + painter->drawRect(rect.adjusted(1, 0, -2, -2)); + break; + case Qt::LeftArrow: + painter->drawRect(rect.adjusted(1, 1, -1, -2)); + break; + case Qt::RightArrow: + painter->drawRect(rect.adjusted(0, 1, -2, -2)); + break; + } + +#if 0 + //位于QTabBar之上的QToolButton不绘制边框 + painter->setPen(border); + switch (toolButtonOption->arrowType) + { + case Qt::DownArrow: + painter->drawLine(rect.bottomLeft(), rect.bottomRight()); + break; + case Qt::RightArrow: + painter->drawLine(rect.topRight(), rect.bottomRight()); + break; + } + switch (toolButtonOption->arrowType) + { + case Qt::UpArrow: + case Qt::DownArrow: + painter->drawLine(rect.topLeft(), rect.bottomLeft()); + painter->drawLine(rect.topLeft(), rect.bottomLeft()); + break; + case Qt::LeftArrow: + case Qt::RightArrow: + painter->drawLine(rect.topLeft(), rect.topRight()); + painter->drawLine(rect.bottomLeft(), rect.bottomRight()); + break; + } +#endif + } + else if (sunken && hasPopupMenu && !(toolButtonOption->activeSubControls & QStyle::SC_ToolButton)) + { + // Only menu button is active. so draw left hand side od button raised + QStyleOptionToolButton btn(copy); + btn.state |= QStyle::State_Raised; + btn.state &= ~QStyle::State_Sunken; + btn.state &= ~QStyle::State_AutoRaise; + this->drawPrimitive(QStyle::PE_PanelButtonTool, &btn, painter, widget); + } + else + { + this->drawPrimitive(QStyle::PE_PanelButtonTool, ©, painter, widget); + } + } + + // arrow + if (hasPopupMenu) + { + copy.rect = menuRect; + + if (!flat || mouseOver || sunken) + this->drawPrimitive(QStyle::PE_IndicatorButtonDropDown, ©, painter, widget); + + this->drawPrimitive(QStyle::PE_IndicatorArrowDown, ©, painter, widget); + } + + else if (hasInlineIndicator) + { + copy.rect = menuRect; + + this->drawPrimitive(QStyle::PE_IndicatorArrowDown, ©, painter, widget); + } + + // contents + { + // restore state + copy.state = state; + + // define contents rect + QRect contentsRect(buttonRect); + + // detect dock widget title button + // for dockwidget title buttons, do not take out margins, so that icon do not get scaled down + if (isDockWidgetTitleButton) + { + // cast to abstract button + // adjust state to have correct icon rendered + const QAbstractButton *button(qobject_cast(widget)); + if (button->isChecked() || button->isDown()) + { + copy.state |= QStyle::State_Enabled | QStyle::State_On | QStyle::State_Sunken; + } + if (button->underMouse()) + { + copy.state |= QStyle::State_Enabled | QStyle::State_MouseOver | QStyle::State_Active; + } + } + else if (!inTabBar && hasInlineIndicator) + { + int marginWidth(flat ? Metrics::ToolButton_MarginWidth : Metrics::Button_MarginWidth + Metrics::Frame_FrameWidth); + contentsRect = RenderHelper::insideMargin(contentsRect, marginWidth, 0); + contentsRect.setRight(contentsRect.right() - Metrics::ToolButton_InlineIndicatorWidth); + contentsRect = QStyle::visualRect(option->direction, option->rect, contentsRect); + } + + copy.rect = contentsRect; + + // render + this->drawControl(QStyle::CE_ToolButtonLabel, ©, painter, widget); + } +} + +QSize Style::comboBoxSizeFromContents(const QStyleOption *option, const QSize &contentSize, const QWidget *widget) const +{ + const auto comboBoxOption(qstyleoption_cast(option)); + if (!comboBoxOption) return contentSize; + + QSize size(contentSize); + + // 若存在Frame绘制,大小扩展开 FrameWidth + const bool flat(!comboBoxOption->frame); + const int frameWidth(this->pixelMetric(QStyle::PM_ComboBoxFrameWidth, option, widget)); + if (!flat) + { + size = RenderHelper::expandSize(size, frameWidth); + } + + size.rwidth() += Metrics::MenuButton_IndicatorWidth; + size.rwidth() += Metrics::Button_ItemSpacing; + + size.rwidth() += size.height(); + + // 确保有足够的高度绘制下拉按钮指示器 + size.setHeight(qMax(size.height(), int(Metrics::MenuButton_IndicatorWidth))); + + // size = RenderHelper::expandSize(size, Metrics::ComboBox_MarginWidth, Metrics::ComboBox_MarginHeight); + + // 确保至少有最小大小 + size.setHeight(qMax(size.height(), int(Metrics::ComboBox_MinHeight))); + size.setWidth(qMax(size.width(), int(Metrics::ComboBox_MinWidth))); + + return size; +} + +QRect Style::comboBoxSubControlRect(const QStyleOptionComplex *option, QStyle::SubControl subControl, const QWidget *widget) const +{ + const auto comboBoxOption(qstyleoption_cast(option)); + if (!comboBoxOption) return QRect(); + + const bool editable(comboBoxOption->editable); + const bool flat(editable && !comboBoxOption->frame); + auto rect(option->rect); + const int frameWidth(this->pixelMetric(QStyle::PM_ComboBoxFrameWidth, option, widget)); + + switch (subControl) + { + case QStyle::SC_ComboBoxFrame: + return flat ? rect : QRect(); + case QStyle::SC_ComboBoxListBoxPopup: + return rect; + case QStyle::SC_ComboBoxArrow: + return QRect(rect.right() - rect.height() + 1, + rect.top(), + rect.height(), rect.height()); + break; + case QStyle::SC_ComboBoxEditField: + { + auto rect2 = QRect(rect.left(), rect.top(), rect.width() - rect.height() - 4, rect.height()); + rect2.adjust(frameWidth, frameWidth, 0, -frameWidth); + return QStyle::visualRect(option->direction, option->rect, rect2); + } + default: + return QProxyStyle::subControlRect(QStyle::CC_ComboBox, option, subControl, widget); + } +} + +void Style::drawCCComboBox(const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const +{ + const auto comboBoxOption(qstyleoption_cast(option)); + RETURN_IF_FALSE(comboBoxOption); + + const QStyle::State &state(option->state); + bool enabled(state & QStyle::State_Enabled); + bool windowActive(state & QStyle::State_Active); + bool editable(comboBoxOption->editable); + bool arrowActive(comboBoxOption->activeSubControls & QStyle::SC_ComboBoxArrow); + bool flat(!comboBoxOption->frame); + bool sunken; + + if (editable) + { + sunken = arrowActive && enabled && (state & (QStyle::State_On | QStyle::State_Sunken)); + } + else + { + sunken = enabled && (state & (QStyle::State_On | QStyle::State_Sunken)); + } + + const auto comboBox = qobject_cast(widget); + if (!comboBox) + return; + + const bool empty(comboBox && !comboBox->count()); + + // TODO: 当ComboBox为空时,应当特别绘制 + if (empty) + { + const auto &background = option->palette.color(QPalette::Base); + painter->fillRect(option->rect, background); + } + + // frame + if (option->subControls & QStyle::SC_ComboBoxFrame) + { + if (editable) + { + // FIXME:下拉框编辑状态悬浮判断没有区域 + flat |= (option->rect.height() <= 2 * Metrics::Frame_FrameWidth + Metrics::MenuButton_IndicatorWidth); + if (flat) + { + const auto &background = option->palette.color(QPalette::Base); + painter->setBrush(background); + painter->setPen(Qt::NoPen); + painter->drawRect(option->rect); + } + else + { + QRectF arrowRect = this->subControlRect(QStyle::CC_ComboBox, comboBoxOption, QStyle::SC_ComboBoxArrow, widget); + + // ComboBox 箭头按钮 + arrowRect.adjust(1.5, 1.5, -1.5, -1.5); + QPainterPath indicatorPainterPath = RenderHelper::roundedPath(arrowRect, CornersRight, 4); + + auto background = Palette::getDefault()->getColor(option->state, Palette::WIDGET); + auto border = Palette::getDefault()->getColor(option->state, Palette::BORDER); + + QPen pen = painter->pen(); + painter->setRenderHints(QPainter::Antialiasing); + painter->setPen(border); + painter->setBrush(background); + painter->drawPath(indicatorPainterPath); + + // 输入框 + QStyleOptionComplex tmpOpt(*option); + // 让输入框长度加上一个宽度进行绘制用来去掉输入框的圆角 + tmpOpt.rect.setWidth(tmpOpt.rect.width() - arrowRect.width() + 3); + this->drawPrimitive(QStyle::PE_FrameLineEdit, &tmpOpt, painter, widget); + } + } + else + { + if (flat) + { + auto background = Palette::getDefault()->getColor(option->state, Palette::WINDOW); + RenderHelper::renderFrame(painter, option->rect, 1, 0, background); + } + else + { + auto backgroundColor = Palette::getDefault()->getColor(option->state, Palette::WIDGET); + auto borderColor = Palette::getDefault()->getColor(option->state, Palette::BORDER); + RenderHelper::renderFrame(painter, option->rect, 1, 4, backgroundColor, borderColor); + } + } + } + + // arrow + if (option->subControls & QStyle::SC_ComboBoxArrow) + { + auto arrowRect(this->subControlRect(QStyle::CC_ComboBox, option, QStyle::SC_ComboBoxArrow, widget)); + auto arrowColor = Palette::getDefault()->getColor(option->state, Palette::ICON); + RenderHelper::renderArrow(painter, arrowRect, Arrow_Down, arrowColor); + } +} + +void Style::drawControlComboBoxLabel(const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + const auto comboBoxOption(qstyleoption_cast(option)); + if (!comboBoxOption) return; + // TODO: 是否给基类处理? + if (comboBoxOption->editable) return; + + const QStyle::State &state(option->state); + const bool enabled(state & QStyle::State_Enabled); + const bool sunken(state & (QStyle::State_On | QStyle::State_Sunken)); + const bool mouseOver(enabled && (option->state & QStyle::State_MouseOver)); + const bool hasFocus(enabled && !mouseOver && (option->state & QStyle::State_HasFocus)); + const bool flat(!comboBoxOption->frame); + + QPalette::ColorRole textRole; + if (flat) + { + textRole = QPalette::WindowText; + } + else if (hasFocus) + { + textRole = QPalette::ButtonText; + } + else + { + textRole = QPalette::ButtonText; + } + + painter->setPen(QPen(option->palette.color(textRole), 1)); + + // 获取文本框位置 + auto editRect = this->subControlRect(QStyle::CC_ComboBox, comboBoxOption, QStyle::SC_ComboBoxEditField, widget); + + painter->save(); + painter->setClipRect(editRect); + // 绘制图标 + if (!comboBoxOption->currentIcon.isNull() && qobject_cast(widget)) + { + QIcon::Mode mode; + + if ((comboBoxOption->state & QStyle::State_Selected) && (comboBoxOption->state & QStyle::State_Active)) + { + mode = QIcon::Selected; + } + else if (comboBoxOption->state & QStyle::State_Enabled) + { + mode = QIcon::Normal; + } + else + { + mode = QIcon::Disabled; + } + + QPixmap pixmap = comboBoxOption->currentIcon.pixmap(comboBoxOption->iconSize, mode); + QRect iconRect(editRect); + iconRect.setWidth(comboBoxOption->iconSize.width() + 4); + iconRect = QStyle::alignedRect(comboBoxOption->direction, + Qt::AlignLeft | Qt::AlignVCenter, + iconRect.size(), editRect); + + if (comboBoxOption->editable) + { + painter->fillRect(iconRect, option->palette.brush(QPalette::Base)); + } + + this->drawItemPixmap(painter, iconRect, Qt::AlignCenter, pixmap); + + if (comboBoxOption->direction == Qt::RightToLeft) + { + editRect.translate(-4 - comboBoxOption->iconSize.width(), 0); + } + else + { + editRect.translate(comboBoxOption->iconSize.width() + 4, 0); + } + } + + // 绘制文本 + if (!comboBoxOption->currentText.isEmpty() && !comboBoxOption->editable) + { + QRect itemTextRect = editRect.adjusted(Metrics::ComboBox_FrameWidth, 0, -1, 0); + int itemTextFlags = QStyle::visualAlignment(comboBoxOption->direction, Qt::AlignLeft | Qt::AlignVCenter); + bool itemTextEnable = comboBoxOption->state & QStyle::State_Enabled; + this->drawItemText(painter, itemTextRect, itemTextFlags, comboBoxOption->palette, itemTextEnable, comboBoxOption->currentText); + } + + painter->restore(); +} + +void Style::drawPEFrameLineEdit(const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + const auto &rect = option->rect; + + auto background = DEFAULT_PALETTE()->getColor(option->state, Palette::WINDOW); + auto border = DEFAULT_PALETTE()->getColor(option->state, Palette::BORDER); + + // 控件高度不足够绘制边框 + if (rect.height() < 2 + option->fontMetrics.height()) + { + painter->save(); + painter->setRenderHint(QPainter::Antialiasing, true); + painter->setPen(Qt::NoPen); + painter->setBrush(background); + painter->drawRect(rect); + painter->restore(); + } + else + { + if (qobject_cast(widget)) + { + RenderHelper::renderFlatFrame(painter, rect, 4, background, border); + } + else + { + RenderHelper::renderFrame(painter, rect, 1, 4, background, border); + } + } + + // 输入框聚焦时候高亮边框 + const QStyle::State &state(option->state); + bool hasFocus(state & QStyle::State_HasFocus); + + if (hasFocus) + { + const auto frameOption = qstyleoption_cast(option); + if (frameOption) + { + QColor borderColor = DEFAULT_PALETTE()->getColor(Palette::SELECTED, Palette::WIDGET); + RenderHelper::renderFrame(painter, frameOption->rect, 1, 4, background, borderColor); + } + } +} + +// copy from QCommonStyle +QSize Style::groupBoxSizeFromContents(const QStyleOption *option, const QSize &contentSize, const QWidget *widget) const +{ + if (!widget || !widget->inherits("QGroupBox")) + { + return {}; + } + + auto groupBox = qobject_cast(widget); + QSize size = contentSize + QSize(groupBox->isFlat() ? 16 : 0, 0); + + return size; +} + +// copy from QCommonStyle +QRect Style::groupBoxSubControlRect(const QStyleOptionComplex *option, QStyle::SubControl subControl, const QWidget *widget) const +{ + const auto groupBox = qstyleoption_cast(option); + RETURN_VAL_IF_FALSE(groupBox, QRect()); + + switch (subControl) + { + case QStyle::SC_GroupBoxFrame: + case QStyle::SC_GroupBoxContents: + { + int topMargin = 0; + int topHeight = 0; + int verticalAlignment = this->styleHint(QStyle::SH_GroupBox_TextLabelVerticalAlignment, groupBox, widget); + if (groupBox->text.size() || (groupBox->subControls & QStyle::SC_GroupBoxCheckBox)) + { + topHeight = groupBox->fontMetrics.height(); + if (verticalAlignment & Qt::AlignVCenter) + topMargin = topHeight / 2; + else if (verticalAlignment & Qt::AlignTop) + topMargin = topHeight; + } + + QRect frameRect = groupBox->rect; + frameRect.setTop(topMargin); + + if (subControl == QStyle::SC_GroupBoxFrame) + { + return frameRect; + } + + int frameWidth = 0; + if ((groupBox->features & QStyleOptionFrame::Flat) == 0) + frameWidth = this->pixelMetric(QStyle::PM_DefaultFrameWidth, groupBox, widget); + return frameRect.adjusted(frameWidth, frameWidth + topHeight - topMargin, -frameWidth, -frameWidth); + } + case QStyle::SC_GroupBoxCheckBox: + case QStyle::SC_GroupBoxLabel: + { + QRect controlRect; + QFontMetrics fontMetrics = groupBox->fontMetrics; + int h = fontMetrics.height(); + int tw = fontMetrics.size(Qt::TextShowMnemonic, groupBox->text + QLatin1Char(' ')).width(); + int marg = (groupBox->features & QStyleOptionFrame::Flat) ? 0 : 8; + controlRect = groupBox->rect.adjusted(marg, 0, -marg, 0); + controlRect.setHeight(h); + + int indicatorWidth = this->pixelMetric(QStyle::PM_IndicatorWidth, option, widget); + int indicatorSpace = this->pixelMetric(QStyle::PM_CheckBoxLabelSpacing, option, widget) - 1; + bool hasCheckBox = groupBox->subControls & QStyle::SC_GroupBoxCheckBox; + int checkBoxSize = hasCheckBox ? (indicatorWidth + indicatorSpace) : 0; + + // Adjusted rect for label + indicatorWidth + indicatorSpace + QRect totalRect = QStyle::alignedRect(groupBox->direction, groupBox->textAlignment, + QSize(tw + checkBoxSize, h), controlRect); + + // Adjust totalRect if checkbox is set + if (hasCheckBox) + { + bool ltr = groupBox->direction == Qt::LeftToRight; + int left = 0; + // Adjust for check box + if (subControl == QStyle::SC_GroupBoxCheckBox) + { + int indicatorHeight = this->pixelMetric(QStyle::PM_IndicatorHeight, option, widget); + left = ltr ? totalRect.left() : (totalRect.right() - indicatorWidth); + int top = totalRect.top() + qMax(0, fontMetrics.height() - indicatorHeight) / 2; + totalRect.setRect(left, top, indicatorWidth, indicatorHeight); + // Adjust for label + } + else + { + left = ltr ? (totalRect.left() + checkBoxSize - 2) : totalRect.left(); + totalRect.setRect(left, totalRect.top(), + totalRect.width() - checkBoxSize, totalRect.height()); + } + } + return totalRect; + } + default: + return QProxyStyle::subControlRect(QStyle::CC_GroupBox, option, subControl, widget); + } +} + +void Style::drawPEIndicatorButtonDropDown(const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + const auto toolButtonOption(qstyleoption_cast(option)); + RETURN_IF_FALSE(toolButtonOption); + + const QStyle::State &state(option->state); + bool autoRaise(state & QStyle::State_AutoRaise); + bool enabled(state & QStyle::State_Enabled); + bool mouseOver((state & QStyle::State_Active) && enabled && (state & QStyle::State_MouseOver)); + bool sunken(enabled && (state & QStyle::State_Sunken)); + + // do nothing for autoraise buttons + RETURN_IF_TRUE((autoRaise && !sunken && !mouseOver) || !(toolButtonOption->subControls & QStyle::SC_ToolButtonMenu)); + + const QPalette &palette(option->palette); + const QRect &rect(option->rect); + + auto backgroundColor = Palette::getDefault()->getColor(option->state, Palette::WIDGET); + auto borderColor = Palette::getDefault()->getColor(option->state, Palette::BORDER); + auto separatorColor = borderColor; + + QRect frameRect(rect); + painter->setClipRect(rect); + frameRect.adjust(-Metrics::Frame_FrameRadius - 1, 0, 0, 0); + frameRect = QStyle::visualRect(option->direction, option->rect, frameRect); + + // render + RenderHelper::renderFrame(painter, frameRect, 1, 4, backgroundColor, borderColor); + + // also render separator + QRect separatorRect(rect.adjusted(0, 2, -2, -2)); + separatorRect.setWidth(1); + separatorRect = QStyle::visualRect(option->direction, option->rect, separatorRect); + RenderHelper::renderSeparator(painter, separatorRect, true, separatorColor); +} + +void Style::drawPEIndicatorArrowUp(const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + auto d = d_func(); + + d->drawPEIndicatorArrow(Arrow_Up, option, painter, widget); +} + +void Style::drawPEIndicatorArrowDown(const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + auto d = d_func(); + + d->drawPEIndicatorArrow(Arrow_Down, option, painter, widget); +} + +void Style::drawPEIndicatorArrowLeft(const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + auto d = d_func(); + + d->drawPEIndicatorArrow(Arrow_Left, option, painter, widget); +} + +void Style::drawPEIndicatorArrowRight(const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + auto d = d_func(); + + d->drawPEIndicatorArrow(Arrow_Right, option, painter, widget); +} + +void Style::drawPEIndicatorRadioButton(const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + const auto &rect(option->rect); + + bool checked = option->state & QStyle::State_On; + QString state = "normal"; + if (!(option->state & QStyle::State_Enabled)) + { + state = "disabled"; + } + else if ((option->state & QStyle::State_Sunken)) + { + state = "active"; + } + else if ((option->state & QStyle::State_MouseOver)) + { + state = "hover"; + } + QString iconUrl = QString(":/style/images/radio-%1-%2.svg").arg(checked ? "checked" : "unchecked").arg(state); + // 参考 UI 设计文稿 6.1 单选框 & 复选框 设置 Hover 状态背景色 + if (option->state & State_MouseOver) { + painter->save(); + painter->setPen(Qt::NoPen); + painter->setBrush(DEFAULT_PALETTE()->getColor(Palette::MOUSE_OVER, Palette::WIDGET)); // # 454545 + painter->drawEllipse(rect); + painter->restore(); + } + + // 参考 UI 设计文稿 6.1 单选框 & 复选框 设置 Focus 状态背景色 + if (option->state & State_HasFocus) { + painter->save(); + painter->setPen(Qt::NoPen); + painter->setBrush(DEFAULT_PALETTE()->getColor(option->state, Palette::WINDOW)); // # 222222 + painter->drawEllipse(rect); + painter->restore(); + } + +// if (!(option->state & State_Enabled)) { +// painter->save(); +// painter->setPen(QPen(QColor(145, 145, 145))); // # 919191 //TODO: 取消手动指定颜色 +// painter->setPen(Qt::NoPen); +// painter->setBrush(QColor(145, 145, 145)); +// painter->drawEllipse(option->rect); +// painter->restore(); +// } + + painter->save(); + painter->setRenderHints(QPainter::SmoothPixmapTransform | QPainter::HighQualityAntialiasing); + QSvgRenderer renderer(iconUrl); + renderer.render(painter, rect); + painter->restore(); +} + +void Style::drawPEIndicatorCheckBox(const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + const auto &rect(option->rect); + + bool checked = option->state & QStyle::State_On; + QString state = "normal"; + if (!(option->state & QStyle::State_Enabled)) + { + state = "disabled"; + } + else if ((option->state & QStyle::State_Sunken)) + { + state = "active"; + } + else if ((option->state & QStyle::State_MouseOver)) + { + state = "hover"; + } + QString iconUrl = QString(":/style/images/check-%1-%2.svg").arg(checked ? "checked" : "unchecked").arg(state); + + // 参考 UI 设计文稿 6.1 单选框 & 复选框 设置 Hover 状态背景色 + if (option->state & State_MouseOver) { + auto lineColor = Palette::getDefault()->getColor(option->state, Palette::BORDER); + + painter->save(); + painter->setPen(QPen(lineColor, 1)); + painter->setBrush(DEFAULT_PALETTE()->getColor(Palette::MOUSE_OVER, Palette::WIDGET)); // # 454545 + painter->drawRect(rect); + painter->restore(); + } + + // 参考 UI 设计文稿 6.1 单选框 & 复选框 设置 Focus 状态背景色 + if (option->state & State_HasFocus) { + // 自定义获取焦点时的背景色 + painter->save(); + painter->setPen(QPen()); + painter->setBrush(DEFAULT_PALETTE()->getColor(option->state, Palette::WINDOW)); // # 222222 + painter->drawRect(rect); + painter->restore(); + } + +// if (!(option->state & State_Enabled)) { +// painter->save(); +// painter->setPen(QPen(QColor(145, 145, 145))); // # 919191 //TODO: 取消手动指定颜色 +// painter->setPen(Qt::NoPen); +// painter->setBrush(QColor(145, 145, 145)); +// painter->drawRect(option->rect); +// painter->restore(); +// } + + painter->save(); + painter->setRenderHints(QPainter::SmoothPixmapTransform | QPainter::HighQualityAntialiasing); + QSvgRenderer renderer(iconUrl); + renderer.render(painter, rect); + painter->restore(); +} + +void Style::drawPEIndicatorBranch(const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + const QRect &rect(option->rect); + const QPalette &palette(option->palette); + + const QStyle::State &state(option->state); + bool reverseLayout(option->direction == Qt::RightToLeft); + + // 绘制扩展的箭头 + int expanderAdjust = 0; + if (state & QStyle::State_Children) + { + // state + bool expanderOpen(state & QStyle::State_Open); + bool enabled(state & QStyle::State_Enabled); + bool mouseOver((state & QStyle::State_Active) && enabled && (state & QStyle::State_MouseOver)); + + // expander rect + int expanderSize = qMin(rect.width(), rect.height()); + expanderSize = qMin(expanderSize, int(Metrics::ItemView_ArrowSize)); + expanderAdjust = expanderSize / 2 + 1; + QRect arrowRect = RenderHelper::centerRect(rect, expanderSize, expanderSize); + + // get orientation from option + ArrowOrientation orientation; + if (expanderOpen) + { + orientation = Arrow_Down; + } + else if (reverseLayout) + { + orientation = Arrow_Left; + } + else + { + orientation = Arrow_Right; + } + auto arrowColor = Palette::getDefault()->getColor(option->state, Palette::ICON); + RenderHelper::renderArrow(painter, arrowRect, orientation, arrowColor, QSize(12, 12)); + } + + RETURN_IF_FALSE(RenderHelper::drawTreeBranches()); + + QPoint center(rect.center()); + auto lineColor = Palette::getDefault()->getColor(option->state, Palette::BORDER); + painter->save(); + painter->setRenderHint(QPainter::Antialiasing, true); + painter->translate(0.5, 0.5); + painter->setPen(QPen(lineColor, 1)); + if (state & (QStyle::State_Item | QStyle::State_Children | QStyle::State_Sibling)) + { + QLineF line(QPointF(center.x(), rect.top()), QPointF(center.x(), center.y() - expanderAdjust - 1)); + painter->drawLine(line); + } + + // 如果存在Item则绘制左/右取决与方向的线 + if (state & QStyle::State_Item) + { + const QLineF line = reverseLayout ? QLineF(QPointF(rect.left(), center.y()), QPointF(center.x() - expanderAdjust, center.y())) : QLineF(QPointF(center.x() + expanderAdjust, center.y()), QPointF(rect.right(), center.y())); + painter->drawLine(line); + } + + // 如果存在同级节点的话,则绘制上下的线 + if (state & QStyle::State_Sibling) + { + QLineF line(QPointF(center.x(), center.y() + expanderAdjust), QPointF(center.x(), rect.bottom())); + painter->drawLine(line); + } + painter->restore(); +} + +void Style::drawPEIndicatorToolBarSeparator(const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + const QStyle::State &state = option->state; + bool enable = (state & QStyle::State_Enabled); + bool separatorIsVertical(state & QStyle::State_Horizontal); + + auto separatorColor = Palette::getDefault()->getColor(option->state, Palette::BORDER); + + RenderHelper::renderSeparator(painter, option->rect, separatorIsVertical, separatorColor); +} + +void Style::drawPEIndicatorToolBarHandle(const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + const QStyle::State &state = option->state; + QRect rect(option->rect); + bool separatorIsVertical(state & QStyle::State_Horizontal); + bool enabled(state & QStyle::State_Enabled); + + auto separatorColor = Palette::getDefault()->getColor(option->state, Palette::BORDER); + + if (separatorIsVertical) + { + rect.setWidth(Metrics::ToolBar_HandleWidth); + rect = RenderHelper::centerRect(option->rect, rect.size()); + rect.setWidth(3); + RenderHelper::renderSeparator(painter, rect, separatorIsVertical, separatorColor); + + rect.translate(2, 0); + RenderHelper::renderSeparator(painter, rect, separatorIsVertical, separatorColor); + } + else + { + rect.setHeight(Metrics::ToolBar_HandleWidth); + rect = RenderHelper::centerRect(option->rect, rect.size()); + rect.setHeight(3); + RenderHelper::renderSeparator(painter, rect, separatorIsVertical, separatorColor); + + rect.translate(0, 2); + RenderHelper::renderSeparator(painter, rect, separatorIsVertical, separatorColor); + } +} + +void Style::drawControlHeaderSection(const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + const QRect &rect(option->rect); + const QPalette &palette(option->palette); + const QStyle::State &state(option->state); + bool enabled(state & QStyle::State_Enabled); + bool mouseOver((state & QStyle::State_Active) && enabled && (state & QStyle::State_MouseOver)); + + const auto *headerOption(qstyleoption_cast(option)); + RETURN_IF_FALSE(headerOption); + + bool horizontal(headerOption->orientation == Qt::Horizontal); + bool isFirst(horizontal && (headerOption->position == QStyleOptionHeader::Beginning)); + bool isCorner(widget && widget->inherits("QTableCornerButton")); + bool reverseLayout(option->direction == Qt::RightToLeft); + + // outline + painter->setBrush(Qt::NoBrush); + // TODO: 需要确认该颜色是否合适 + // 该元素主要为表头框线条,颜色为边框颜色合适 + auto outlineColor = Palette::getDefault()->getColor(option->state, Palette::BORDER); + painter->setPen(outlineColor); + + if (isCorner) + { + if (reverseLayout) + { + painter->drawPoint(rect.bottomLeft()); + } + else + { + painter->drawPoint(rect.bottomRight()); + } + } + else if (horizontal) + { + painter->drawLine(rect.bottomLeft(), rect.bottomRight()); + } + else + { + if (reverseLayout) + { + painter->drawLine(rect.topLeft(), rect.bottomLeft()); + } + else + { + painter->drawLine(rect.topRight(), rect.bottomRight()); + } + } + + // separators + if (horizontal) + { + if (headerOption->section != 0 || isFirst) + { + if (reverseLayout) + { + painter->drawLine(rect.topLeft(), rect.bottomLeft() - QPoint(0, 1)); + } + else + { + painter->drawLine(rect.topRight(), rect.bottomRight() - QPoint(0, 1)); + } + } + } + else + { + if (reverseLayout) + { + painter->drawLine(rect.bottomLeft() + QPoint(1, 0), rect.bottomRight()); + } + else + { + painter->drawLine(rect.bottomLeft(), rect.bottomRight() - QPoint(1, 0)); + } + } +} + +void Style::drawControlHeaderLabel(const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + if (const QStyleOptionHeader *header = qstyleoption_cast(option)) + { + QRect rect = header->rect; + if (!header->icon.isNull()) + { + QPixmap pixmap = header->icon.pixmap(this->pixelMetric(QStyle::PM_SmallIconSize), (header->state & QStyle::State_Enabled) ? QIcon::Normal : QIcon::Disabled); + int pixw = pixmap.width(); + + QRect aligned = QStyle::alignedRect(header->direction, QFlag(header->iconAlignment), pixmap.size(), rect); + QRect inter = aligned.intersected(rect); + painter->drawPixmap(inter.x(), inter.y(), pixmap, inter.x() - aligned.x(), inter.y() - aligned.y(), inter.width(), inter.height()); + + if (header->direction == Qt::LeftToRight) + rect.setLeft(rect.left() + pixw + 2); + else + rect.setRight(rect.right() - pixw - 2); + } + + QFont fnt = painter->font(); + painter->setFont(fnt); + QPalette palette(header->palette); + this->drawItemText(painter, rect, header->textAlignment, palette, (header->state & QStyle::State_Active), header->text, QPalette::Text); + } +} + +void Style::drawControlHeaderEmptyArea(const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + // use the same background as in drawHeaderPrimitive + const QRect &rect(option->rect); + QPalette palette(option->palette); + + bool horizontal(option->state & QStyle::State_Horizontal); + bool reverseLayout(option->direction == Qt::RightToLeft); + + // fill + painter->setRenderHint(QPainter::Antialiasing, false); + painter->setBrush(palette.color(QPalette::Base)); + painter->setPen(Qt::NoPen); + painter->drawRect(rect); + + // outline + // TODO: 需要确认该颜色是否合适 + // 该元素用于表格空内容区域分割线, 颜色合适 + auto outlineColor = Palette::getDefault()->getColor(option->state, Palette::BORDER); + painter->setBrush(Qt::NoBrush); + painter->setPen(outlineColor); + + if (horizontal) + { + painter->drawLine(rect.bottomLeft(), rect.bottomRight()); + } + else + { + if (reverseLayout) + { + painter->drawLine(rect.topLeft(), rect.bottomLeft()); + } + else + { + painter->drawLine(rect.topRight(), rect.bottomRight()); + } + } +} + +void Style::drawControlMenuBarItem(const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + auto menuItemOption = qstyleoption_cast(option); + const QStyle::State &state = option->state; + const bool enabled(option->state & QStyle::State_Enabled); + const bool mouseOver((option->state & QStyle::State_MouseOver) && enabled); + const bool sunken((option->state & QStyle::State_Sunken) && enabled); + + PainterSaver painterSaver(painter); + +#if 0 + if(mouseOver && sunken) + { + auto background = schemeLoader->getColor(widget,option,SchemeLoader::MenuBar_ItemBackground); + painter->setRenderHints(QPainter::Antialiasing); + painter->setPen(Qt::NoPen); + painter->setBrush(background); + painter->drawRoundedRect(option->rect,4,4); + } +#endif + //TODO: menubaritem 和 menubar背景存在差异 + if (menuItemOption) + { + int alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine; + + if (!this->styleHint(QStyle::SH_UnderlineShortcut, option, widget)) + { + alignment |= Qt::TextHideMnemonic; + } + + int iconExtent = this->pixelMetric(QStyle::PM_SmallIconSize); + + QPixmap pix = menuItemOption->icon.pixmap(widget ? widget->window()->windowHandle() : nullptr, QSize(iconExtent, iconExtent), enabled ? (mouseOver ? QIcon::Active : QIcon::Normal) : QIcon::Disabled); + + if (!pix.isNull()) + { + this->drawItemPixmap(painter, option->rect, alignment, pix); + } + else + { + QStyleOptionMenuItem itemOption = *menuItemOption; + QColor bgColor; + if (mouseOver || sunken) + { + // TODO: 需要确认 + bgColor = Palette::getDefault()->getColor(option->state, Palette::WINDOW); + painter->fillRect(option->rect, bgColor); + } + this->drawItemText(painter, itemOption.rect, alignment, itemOption.palette, enabled, itemOption.text, QPalette::ButtonText); + } + } +} + +void Style::drawControlMenuBarEmptyArea(const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + // TODO: 需要确认 + auto background = Palette::getDefault()->getColor(option->state, Palette::WINDOW); + painter->fillRect(option->rect, background); +} + +QSize Style::progressBarSizeFromContents(const QStyleOption *option, const QSize &contentSize, const QWidget *widget) const +{ + const auto progressBarOption(qstyleoption_cast(option)); + if (!progressBarOption) return contentSize; + + bool horizontal(progressBarOption->orientation == Qt::Horizontal); + + QSize size(contentSize); + + if (horizontal) + { + bool textVisible(progressBarOption->textVisible); + + size.setWidth(qMax(size.width(), int(Metrics::ProgressBar_Thickness))); + size.setHeight(qMax(size.height(), int(Metrics::ProgressBar_Thickness))); + if (textVisible) size.setHeight(qMax(size.height(), option->fontMetrics.height())); + } + else + { + size.setHeight(qMax(size.height(), int(Metrics::ProgressBar_Thickness))); + size.setWidth(qMax(size.width(), int(Metrics::ProgressBar_Thickness))); + } + + return size; +} + +QRect Style::progressBarElementRect(QStyle::SubElement subElement, const QStyleOption *option, const QWidget *widget) const +{ + const auto progressBarOption(qstyleoption_cast(option)); + if (!progressBarOption) return option->rect; + + bool textVisible(progressBarOption->textVisible); + bool horizontal(progressBarOption->orientation == Qt::Horizontal); + bool inverted(progressBarOption->invertedAppearance); + + QRect rect(option->rect); + int frameWidth(this->pixelMetric(QStyle::PM_DefaultFrameWidth, option, widget)); + + if (horizontal) + rect = RenderHelper::insideMargin(rect, frameWidth, 0); + else + rect = RenderHelper::insideMargin(rect, 0, frameWidth); + + switch (subElement) + { + case QStyle::SE_ProgressBarContents: + { + rect = this->subElementRect(QStyle::SE_ProgressBarGroove, option, widget); + + qreal progress(progressBarOption->progress - progressBarOption->minimum); + int steps(qMax(progressBarOption->maximum - progressBarOption->minimum, 1)); + qreal widthFrac = qMin(qreal(1), progress / steps); + int indicatorSize(widthFrac * (horizontal ? rect.width() : rect.height())); + + if (horizontal) + { + rect = QRect(inverted ? (rect.right() - indicatorSize + 1) : rect.left(), rect.y(), indicatorSize, rect.height()); + rect = QStyle::visualRect(option->direction, rect, rect); + } + else + { + rect = QRect(rect.x(), inverted ? rect.top() : (rect.bottom() - indicatorSize + 1), rect.width(), indicatorSize); + } + break; + } + case QStyle::SE_ProgressBarGroove: + { + if (textVisible && horizontal) + { + QRect textRect(this->subElementRect(QStyle::SE_ProgressBarLabel, option, widget)); + textRect = QStyle::visualRect(option->direction, option->rect, textRect); + rect.setRight(textRect.left() - Metrics::ProgressBar_ItemSpacing - 1); + rect = QStyle::visualRect(option->direction, option->rect, rect); + rect = RenderHelper::centerRect(rect, rect.width(), Metrics::ProgressBar_Thickness); + } + else if (horizontal) + { + rect = RenderHelper::centerRect(rect, rect.width(), Metrics::ProgressBar_Thickness); + } + else + { + rect = RenderHelper::centerRect(rect, Metrics::ProgressBar_Thickness, rect.height()); + } + break; + } + case QStyle::SE_ProgressBarLabel: + { + if (!textVisible) + return QRect(); + + int textWidth = qMax( + option->fontMetrics.size(RenderHelper::mnemonicsTextFlags(), progressBarOption->text).width(), + option->fontMetrics.size(RenderHelper::mnemonicsTextFlags(), QStringLiteral("100%")).width()); + + rect = RenderHelper::insideMargin(option->rect, Metrics::Frame_FrameWidth, 0); + rect.setLeft(rect.right() - textWidth + 1); + rect = QStyle::visualRect(option->direction, option->rect, rect); + break; + } + default: + break; + } + + return rect; +} + +void Style::drawControlProgressBar(const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + const auto progressBarOption(qstyleoption_cast(option)); + RETURN_IF_FALSE(progressBarOption); + + QStyleOptionProgressBar tempOption(*progressBarOption); + + QRect grooveRect = this->subElementRect(QStyle::SE_ProgressBarGroove, option, widget); + QRect contentsRect = this->subElementRect(QStyle::SE_ProgressBarContents, option, widget); + QRect labelRect = this->subElementRect(QStyle::SE_ProgressBarLabel, option, widget); + + tempOption.rect = grooveRect; + this->drawControl(QStyle::CE_ProgressBarGroove, &tempOption, painter, widget); + + tempOption.rect = contentsRect; + this->drawControl(QStyle::CE_ProgressBarContents, &tempOption, painter, widget); + + bool textVisible(progressBarOption->textVisible); + bool busy(progressBarOption->minimum == 0 && progressBarOption->maximum == 0); + if (textVisible && !busy) + { + tempOption.rect = labelRect; + this->drawControl(QStyle::CE_ProgressBarLabel, &tempOption, painter, widget); + } + + // TODO: BUSY动画 +// if (busy) { + +// } +} + +void Style::drawControlProgressBarGroove(const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + const auto progressBarOption(qstyleoption_cast(option)); + RETURN_IF_FALSE(progressBarOption); + + auto grooveColor = Palette::getDefault()->getColor(option->state & (QStyle::State_Enabled), Palette::SCROLL); + + RenderHelper::renderFrame(painter, option->rect, 1, 4, grooveColor); +} + +void Style::drawControlProgressBarContents(const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + const auto progressBarOption(qstyleoption_cast(option)); + RETURN_IF_FALSE(progressBarOption); + + // TODO: 进度条滑动区域左侧颜色,需要确认是否合理 + // 为主要基本色,合理 + auto palettes = Palette::getDefault(); + auto contentsColor = palettes->getBaseColors().widgetMain; + + RenderHelper::renderFrame(painter, option->rect, 1, 4, contentsColor); +} + +void Style::drawControlProgressBarLabel(const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + const auto progressBarOption(qstyleoption_cast(option)); + RETURN_IF_FALSE(progressBarOption); + + bool horizontal = progressBarOption->orientation == Qt::Horizontal; + RETURN_IF_FALSE(horizontal); + + const QRect &rect(option->rect); + const QPalette &palette(option->palette); + + // store state and direction + const QStyle::State &state(option->state); + bool enabled(state & QStyle::State_Enabled); + + // define text rect + Qt::Alignment hAlign((progressBarOption->textAlignment == Qt::AlignLeft) ? Qt::AlignHCenter : progressBarOption->textAlignment); + this->drawItemText(painter, rect, Qt::AlignVCenter | hAlign, palette, enabled, progressBarOption->text, QPalette::WindowText); +} + +QRect Style::scrollBarSubControlRect(const QStyleOptionComplex *option, QStyle::SubControl subControl, const QWidget *widget) const +{ + auto d = d_func(); + + const auto sliderOption(qstyleoption_cast(option)); + RETURN_VAL_IF_FALSE(sliderOption, QRect()); + + const QStyle::State &state(option->state); + bool horizontal(state & QStyle::State_Horizontal); + + switch (subControl) + { + case QStyle::SC_ScrollBarAddLine: + case QStyle::SC_ScrollBarSubLine: + case QStyle::SC_ScrollBarAddPage: + case QStyle::SC_ScrollBarSubPage: + return QRect(); + case QStyle::SC_ScrollBarSlider: + { + // handle RTL here to unreflect things if need be + QRect groove = QStyle::visualRect(option->direction, option->rect, this->subControlRect(QStyle::CC_ScrollBar, option, QStyle::SC_ScrollBarGroove, widget)); + groove.adjust(0, 0, 1, 1); + + if (sliderOption->minimum == sliderOption->maximum) + { + return groove; + } + + // Figure out how much room there is + int space(horizontal ? groove.width() : groove.height()); + + // Calculate the portion of this space that the slider should occupy + int sliderSize = space * qreal(sliderOption->pageStep) / (sliderOption->maximum - sliderOption->minimum + sliderOption->pageStep); + sliderSize = qMax(sliderSize, static_cast(Metrics::ScrollBar_MinSliderHeight)); + sliderSize = qMin(sliderSize, space); + + space -= sliderSize; + if (space <= 0) + { + return groove; + } + + int pos = qRound(qreal(sliderOption->sliderPosition - sliderOption->minimum) / (sliderOption->maximum - sliderOption->minimum) * space); + if (sliderOption->upsideDown) + { + pos = space - pos; + } + + if (horizontal) + { + return QStyle::visualRect(option->direction, option->rect, QRect(groove.left() + pos, groove.top(), sliderSize, groove.height())); + } + else + { + return QStyle::visualRect(option->direction, option->rect, QRect(groove.left(), groove.top() + pos, groove.width(), sliderSize)); + } + break; + } + case QStyle::SC_ScrollBarGroove: + { + QRect topRect = QStyle::visualRect(option->direction, option->rect, d->scrollBarInternalSubControlRect(option, QStyle::SC_ScrollBarSubLine)); + QRect bottomRect = QStyle::visualRect(option->direction, option->rect, d->scrollBarInternalSubControlRect(option, QStyle::SC_ScrollBarAddLine)); + + QPoint topLeftCorner; + QPoint botRightCorner; + + if (horizontal) + { + topLeftCorner = QPoint(topRect.right() + 1, topRect.top()); + botRightCorner = QPoint(bottomRect.left() - 1, topRect.bottom()); + } + else + { + topLeftCorner = QPoint(topRect.left(), topRect.bottom() + 1); + botRightCorner = QPoint(topRect.right(), bottomRect.top() - 1); + } + + // define rect + return QStyle::visualRect(option->direction, option->rect, QRect(topLeftCorner, botRightCorner)); + } + default: + return QProxyStyle::subControlRect(QStyle::CC_ScrollBar, option, subControl, widget); + } +} + +void Style::drawCCScrollBar(const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const +{ + const auto scrollbarOption = qstyleoption_cast(option); + RETURN_IF_FALSE(scrollbarOption); + + bool enabled(option->state & QStyle::State_Enabled); + bool mouseOver((option->state & QStyle::State_Active) && option->state & QStyle::State_MouseOver); + + if (option->subControls & QStyle::SC_ScrollBarGroove) + { + auto grooveRect = this->subControlRect(QStyle::CC_ScrollBar, option, QStyle::SC_ScrollBarGroove, widget); +// 不绘制滑动槽 +#if 0 + if( mouseOver ) + { + QColor grooveColor = KiranPalette::instance()->color(widget,option,KiranPalette::Window,KiranPalette::Background); + painter->save(); + painter->setPen(Qt::NoPen); + painter->setBrush(grooveColor); + painter->drawRect(grooveRect); + painter->restore(); + } +#endif + } + + if (scrollbarOption->subControls & QStyle::SC_ScrollBarSlider) + { + QStyleOptionSlider sliderOption = *scrollbarOption; + sliderOption.state = scrollbarOption->state; + sliderOption.rect = this->subControlRect(QStyle::CC_ScrollBar, &sliderOption, QStyle::SC_ScrollBarSlider, widget); + if (sliderOption.rect.isValid()) + { + this->drawControl(QStyle::CE_ScrollBarSlider, &sliderOption, painter, widget); + } + } +} + +void Style::drawControlScrollBarSlider(const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + auto sliderOption = qstyleoption_cast(option); + RETURN_IF_FALSE(sliderOption); + + const QStyle::State &state(option->state); + bool horizontal(state & QStyle::State_Horizontal); + const QRect &rect(option->rect); + QRect handleRect; + + bool enabled(state & QStyle::State_Enabled); + bool mouseOver((state & QStyle::State_Active) && enabled && (state & QStyle::State_MouseOver)); + + const QWidget *parent = nullptr; + if ((widget && widget->parentWidget())) + { + auto scrollBar = qobject_cast(widget); + + QAbstractScrollArea *scrollArea = nullptr; + if (!(scrollArea = qobject_cast(widget->parentWidget()))) + { + scrollArea = qobject_cast(widget->parentWidget()->parentWidget()); + } + + if (scrollArea && (scrollBar == scrollArea->verticalScrollBar() || scrollBar == scrollArea->horizontalScrollBar())) + { + parent = scrollArea; + } + } + + handleRect = rect; + if (!mouseOver && horizontal) + { + handleRect = rect.adjusted(0, 1, 0, -1); + } + else if (!mouseOver && !horizontal) + { + handleRect = rect.adjusted(1, 0, -1, 0); + } + + auto sliderColor = Palette::getDefault()->getColor(option->state, Palette::SCROLL); + painter->setRenderHint(QPainter::Antialiasing, true); + QPainterPath painterPath = RenderHelper::roundedPath(handleRect, AllCorners, 2); + painter->fillPath(painterPath, sliderColor); +} + +// TODO: 之后整合所有的绘制过程中的是否启用的开关 +static const bool sliderDrawTickMarks = true; +enum Side +{ + SideNone = 0x0, + SideLeft = 0x1, + SideTop = 0x2, + SideRight = 0x4, + SideBottom = 0x8, + AllSides = SideLeft | SideTop | SideRight | SideBottom +}; + +QSize Style::sliderSizeFromContents(const QStyleOption *option, const QSize &contentSize, const QWidget *widget) const +{ + // cast option and check + const auto sliderOption(qstyleoption_cast(option)); + if (!sliderOption) return contentSize; + + // store tick position and orientation + const QSlider::TickPosition &tickPosition(sliderOption->tickPosition); + bool horizontal(sliderOption->orientation == Qt::Horizontal); + bool disableTicks = !sliderDrawTickMarks; + + // do nothing if no ticks are requested + if (tickPosition == QSlider::NoTicks) return contentSize; + + /* + * Qt adds its own tick length directly inside QSlider. + * Take it out and replace by ours, if needed + */ + const int tickLength(disableTicks ? 0 : (Metrics::Slider_TickLength + Metrics::Slider_TickMarginWidth + (Metrics::Slider_GrooveThickness - Metrics::Slider_ControlThickness) / 2)); + + int builtInTickLength(2); + + QSize size(contentSize); + if (horizontal) + { + if (tickPosition & QSlider::TicksAbove) size.rheight() += tickLength - builtInTickLength; + if (tickPosition & QSlider::TicksBelow) size.rheight() += tickLength - builtInTickLength; + } + else + { + if (tickPosition & QSlider::TicksAbove) size.rwidth() += tickLength - builtInTickLength; + if (tickPosition & QSlider::TicksBelow) size.rwidth() += tickLength - builtInTickLength; + } + + return size; +} + +void Style::drawCCSlider(const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const +{ + // cast option and check + const auto sliderOption(qstyleoption_cast(option)); + RETURN_IF_FALSE(sliderOption); + + // copy rect and palette + const QRect &rect(option->rect); + const QPalette &palette(option->palette); + + // copy state + const QStyle::State &state(option->state); + bool enabled(state & QStyle::State_Enabled); + bool windowActive(state & QStyle::State_Active); + bool mouseOver((state & QStyle::State_Active) && enabled && (state & QStyle::State_MouseOver)); + bool hasFocus(enabled && (state & QStyle::State_HasFocus)); + bool horizontal(sliderOption->orientation == Qt::Horizontal); + Side tickSide{SideNone}; + if (horizontal && sliderOption->tickPosition == QSlider::TicksAbove) tickSide = (Side)((int)tickSide | (int)SideTop); + if (horizontal && sliderOption->tickPosition == QSlider::TicksBelow) tickSide = (Side)((int)tickSide | (int)SideBottom); + if (!horizontal && sliderOption->tickPosition == QSlider::TicksLeft) tickSide = (Side)((int)tickSide | (int)SideLeft); + if (!horizontal && sliderOption->tickPosition == QSlider::TicksRight) tickSide = (Side)((int)tickSide | (int)SideRight); + + auto palettes = Palette::getDefault(); + // 背景只考虑启用和禁用状态,悬浮和点击不用变颜色 + auto grooveColor = Palette::getDefault()->getColor(option->state & (QStyle::State_Enabled), Palette::SCROLL); + auto contentColor = Palette::getDefault()->getBaseColors().widgetSelection; + + // tickmarks + if (sliderDrawTickMarks && (sliderOption->subControls & QStyle::SC_SliderTickmarks)) + { + bool upsideDown(sliderOption->upsideDown); + int tickPosition(sliderOption->tickPosition); + int available(this->pixelMetric(QStyle::PM_SliderSpaceAvailable, option, widget)); + int interval = sliderOption->tickInterval; + if (interval < 1) interval = sliderOption->pageStep; + if (interval >= 1) + { + int fudge(this->pixelMetric(QStyle::PM_SliderLength, option, widget) / 2); + int current(sliderOption->minimum); + + // store tick lines + QRect grooveRect(this->subControlRect(QStyle::CC_Slider, sliderOption, QStyle::SC_SliderGroove, widget)); + QList tickLines; + if (horizontal) + { + if (tickPosition & QSlider::TicksAbove) tickLines.append(QLine(rect.left(), grooveRect.top() - Metrics::Slider_TickMarginWidth, rect.left(), grooveRect.top() - Metrics::Slider_TickMarginWidth - Metrics::Slider_TickLength)); + if (tickPosition & QSlider::TicksBelow) tickLines.append(QLine(rect.left(), grooveRect.bottom() + Metrics::Slider_TickMarginWidth, rect.left(), grooveRect.bottom() + Metrics::Slider_TickMarginWidth + Metrics::Slider_TickLength)); + } + else + { + if (tickPosition & QSlider::TicksAbove) tickLines.append(QLine(grooveRect.left() - Metrics::Slider_TickMarginWidth, rect.top(), grooveRect.left() - Metrics::Slider_TickMarginWidth - Metrics::Slider_TickLength, rect.top())); + if (tickPosition & QSlider::TicksBelow) tickLines.append(QLine(grooveRect.right() + Metrics::Slider_TickMarginWidth, rect.top(), grooveRect.right() + Metrics::Slider_TickMarginWidth + Metrics::Slider_TickLength, rect.top())); + } + + while (current <= sliderOption->maximum) + { + // adjust color + QColor color((enabled && current <= sliderOption->sliderPosition) ? contentColor : grooveColor); + painter->setPen(color); + + // calculate positions and draw lines + int position(QStyle::sliderPositionFromValue(sliderOption->minimum, sliderOption->maximum, current, available) + fudge); + foreach (const QLine &tickLine, tickLines) + { + if (horizontal) + painter->drawLine(tickLine.translated(upsideDown ? (rect.width() - position) : position, 0)); + else + painter->drawLine(tickLine.translated(0, upsideDown ? (rect.height() - position) : position)); + } + + // go to next position + current += interval; + } + } + } + + // groove + if (sliderOption->subControls & QStyle::SC_SliderGroove) + { + if (hasFocus) + { + QRect focusRect = this->subElementRect(QStyle::SE_SliderFocusRect, option, widget); + + QStyleOptionFocusRect fropt; + fropt.QStyleOption::operator=(*option); + fropt.rect = focusRect; + this->drawPrimitive(QStyle::PE_FrameFocusRect, &fropt, painter, widget); + } + + // retrieve groove rect + QRect grooveRect(this->subControlRect(QStyle::CC_Slider, sliderOption, QStyle::SC_SliderGroove, widget)); + + if (!enabled) + { + RenderHelper::renderFrame(painter, grooveRect, 1, 0, grooveColor); + } + else + { + bool upsideDown(sliderOption->upsideDown); + + // handle rect + QRect handleRect(this->subControlRect(QStyle::CC_Slider, sliderOption, QStyle::SC_SliderHandle, widget)); + + if (sliderOption->orientation == Qt::Horizontal) + { + QRect leftRect(grooveRect); + QRect rightRect(grooveRect); + leftRect.setRight(handleRect.right() - Metrics::Slider_ControlThickness / 2); + rightRect.setLeft(handleRect.left() + Metrics::Slider_ControlThickness / 2); + + if (upsideDown) + { + RenderHelper::renderFrame(painter, leftRect, 1, 0, grooveColor); + RenderHelper::renderFrame(painter, rightRect, 1, 0, contentColor); + } + else + { + RenderHelper::renderFrame(painter, leftRect, 1, 0, contentColor); + RenderHelper::renderFrame(painter, rightRect, 1, 0, grooveColor); + } + } + else + { + QRect topRect(grooveRect); + topRect.setBottom(handleRect.bottom() - Metrics::Slider_ControlThickness / 2); + QRect bottomRect(grooveRect); + bottomRect.setTop(handleRect.top() + Metrics::Slider_ControlThickness / 2); + + if (upsideDown) + { + RenderHelper::renderFrame(painter, topRect, 1, 0, grooveColor); + RenderHelper::renderFrame(painter, bottomRect, 1, 0, contentColor); + } + else + { + RenderHelper::renderFrame(painter, topRect, 1, 0, contentColor); + RenderHelper::renderFrame(painter, bottomRect, 1, 0, grooveColor); + } + } + } + } + + // handle + if (sliderOption->subControls & QStyle::SC_SliderHandle) + { + // get rect and center + QRectF handleRect(this->subControlRect(QStyle::CC_Slider, sliderOption, QStyle::SC_SliderHandle, widget)); + + // handle state + bool handleActive(sliderOption->activeSubControls & QStyle::SC_SliderHandle); + bool sunken(state & (QStyle::State_On | QStyle::State_Sunken)); + + auto handleBorder = QColor(255, 255, 255); + auto handleBackground = palettes->getColor(option->state, Palette::SCROLL); + + // draw handle + painter->setRenderHint(QPainter::Antialiasing); + handleRect.adjust(1, 1, -1, -1); + + if (handleBorder.isValid()) + { + QPen pen; + pen.setCapStyle(Qt::RoundCap); + pen.setColor(handleBorder); + pen.setWidth(2); + painter->setPen(pen); + handleRect = RenderHelper::strokedRect(handleRect, 2); + } + else + { + painter->setPen(Qt::NoPen); + } + painter->setBrush(handleBackground); + painter->drawRoundedRect(handleRect, handleRect.width() / 2, handleRect.width()); + } +} + +QRect Style::sliderElementRect(QStyle::SubElement subElement, const QStyleOption *option, const QWidget *widget) const +{ + QRect rect(option->rect); + + switch (subElement) + { + case QStyle::SE_SliderFocusRect: + { + const auto sliderOption(qstyleoption_cast(option)); + QRect r(option->rect); + if (sliderOption->orientation == Qt::Vertical) + { + int thickness = Metrics::Slider_GrooveThickness + 8; + return QRect(r.center().x() - thickness / 2, r.top() + 1, thickness + 1, r.height() - 1); + } + else + { + int thickness = Metrics::Slider_GrooveThickness + 6; + return QRect(r.left() + 1, r.center().y() - thickness / 2, r.width() - 1, thickness + 1); + } + } + default: + break; + } + + return rect; +} + +QRect Style::sliderSubControlRect(const QStyleOptionComplex *option, QStyle::SubControl subControl, const QWidget *widget) const +{ + // cast option and check + auto sliderOption = qstyleoption_cast(option); + RETURN_VAL_IF_FALSE(sliderOption, QRect()); + + switch (subControl) + { + case QStyle::SC_SliderGroove: + { + // direction + bool horizontal(sliderOption->orientation == Qt::Horizontal); + + // get base class rect + // NOTE:该处直接调用父类的方法 + QRect grooveRect = qobject_cast(this)->QProxyStyle::subControlRect(QStyle::CC_Slider, option, subControl, widget); + grooveRect = RenderHelper::insideMargin(grooveRect, this->pixelMetric(QStyle::PM_DefaultFrameWidth, option, widget)); + + // centering + if (horizontal) + grooveRect = RenderHelper::centerRect(grooveRect, grooveRect.width(), Metrics::Slider_GrooveThickness); + else + grooveRect = RenderHelper::centerRect(grooveRect, Metrics::Slider_GrooveThickness, grooveRect.height()); + + return grooveRect; + } + default: + return QProxyStyle::subControlRect(QStyle::CC_Slider, option, subControl, widget); + } +} + +QSize Style::spinBoxSizeFromContents(const QStyleOption *option, const QSize &contentSize, const QWidget *widget) const +{ + const auto spinBoxOption(qstyleoption_cast(option)); + if (!spinBoxOption) return contentSize; + + bool flat(!spinBoxOption->frame); + + // copy size + QSize size(contentSize); + + // add editor margins + int frameWidth(this->pixelMetric(QStyle::PM_SpinBoxFrameWidth, option, widget)); + if (!flat) size = RenderHelper::expandSize(size, frameWidth); + + // add button width and spacing + size.rwidth() += 2 * size.height() - 1; + + return size; +} + +QRect Style::spinBoxSubControlRect(const QStyleOptionComplex *option, QStyle::SubControl subControl, const QWidget *widget) const +{ + const auto spinBoxOption(qstyleoption_cast(option)); + RETURN_VAL_IF_FALSE(spinBoxOption, QRect()); + + bool flat(!spinBoxOption->frame); + + QRect rect(option->rect); + switch (subControl) + { + case QStyle::SC_SpinBoxFrame: + return flat ? QRect() : rect; + break; + case QStyle::SC_SpinBoxUp: + if (rect.width() > 2 * rect.height() + 24) + { + return QRect(rect.right() - rect.height(), rect.top(), rect.height(), rect.height() - 1); + } + else + { + return QRect(rect.right() - 0.6 * rect.height() + 1, rect.top(), rect.height() * 0.6, rect.height() / 2 + 3); + } + break; + case QStyle::SC_SpinBoxDown: + if (rect.width() > 2 * rect.height() + 24) + { + return QRect(rect.right() - 2 * rect.height() + 1, rect.top(), rect.height(), rect.height() - 1); + } + else + { + return QRect(rect.right() - 0.6 * rect.height() + 1, rect.top() + rect.height() / 2 - 2, rect.height() * 0.6, rect.height() / 2 + 2); + } + break; + case QStyle::SC_SpinBoxEditField: + { + QRect rect2; + int frameWidth(this->pixelMetric(QStyle::PM_SpinBoxFrameWidth, option, widget)); + if (rect.width() > 2 * rect.height() + 24) + { + rect2 = QRect(rect.left(), rect.top(), + rect.width() - 2 * rect.height() - frameWidth, + rect.height()); + } + else + { + rect2 = QRect( + rect.left(), rect.top(), + rect.width() - 0.6 * rect.height() - frameWidth, + rect.height()); + } + // remove right side line editor margins + if (!flat && rect2.height() >= option->fontMetrics.height() + 2 * frameWidth) + { + rect2.adjust(frameWidth, frameWidth, 0, -frameWidth); + } + + return QStyle::visualRect(option->direction, option->rect, rect2); + } + default: + return QProxyStyle::subControlRect(QStyle::CC_SpinBox, option, subControl, widget); + } +} + +void Style::drawCCSpinBox(const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const +{ + auto d = d_func(); + + const auto spinBoxOption(qstyleoption_cast(option)); + RETURN_IF_FALSE(spinBoxOption); + + const QPalette &palette(option->palette); + const QRect &rect(option->rect); + + if (option->subControls & QStyle::SC_SpinBoxFrame) + { + // detect flat spinboxes + bool flat(!spinBoxOption->frame); + flat |= (rect.height() < 2 * Metrics::Frame_FrameWidth + Metrics::SpinBox_ArrowButtonWidth); + if (flat) + { + const auto &background = palette.color(QPalette::Base); + + painter->setBrush(background); + painter->setPen(Qt::NoPen); + painter->drawRect(rect); + } + else + { + this->drawPrimitive(QStyle::PE_FrameLineEdit, option, painter, widget); + } + } + + // 裁剪掉按钮露出圆角边框的区域 + QPainterPath catPath = RenderHelper::roundedPath(RenderHelper::insideMargin(option->rect, 1), AllCorners, 4); + PainterSaver painterSaver(painter); + painter->setClipPath(catPath); + if (option->subControls & QStyle::SC_SpinBoxUp) + { + d->renderSpinBoxArrow(QStyle::SC_SpinBoxUp, spinBoxOption, painter, widget); + } + + if (option->subControls & QStyle::SC_SpinBoxDown) + { + d->renderSpinBoxArrow(QStyle::SC_SpinBoxDown, spinBoxOption, painter, widget); + } +} + +QSize Style::tabBarTabSizeFromContents(const QStyleOption *option, const QSize &contentSize, const QWidget *widget) const +{ + const auto tabOption(qstyleoption_cast(option)); + const bool hasText(tabOption && !tabOption->text.isEmpty()); + const bool hasIcon(tabOption && !tabOption->icon.isNull()); + const bool hasLeftButton(tabOption && !tabOption->leftButtonSize.isEmpty()); + const bool hasRightButton(tabOption && !tabOption->leftButtonSize.isEmpty()); + + // calculate width increment for horizontal tabs + int widthIncrement = 10; + if (hasIcon && !(hasText || hasLeftButton || hasRightButton)) widthIncrement -= 4; + if (hasText && hasIcon) widthIncrement += Metrics::TabBar_TabItemSpacing; + if (hasLeftButton && (hasText || hasIcon)) widthIncrement += Metrics::TabBar_TabItemSpacing; + if (hasRightButton && (hasText || hasIcon || hasLeftButton)) widthIncrement += Metrics::TabBar_TabItemSpacing; + + // add margins + QSize size(contentSize); + + // compare to minimum size + const bool verticalTabs(tabOption && RenderHelper::isVerticalTab(tabOption->shape)); + if (verticalTabs) + { + size.rheight() += widthIncrement; + if (hasIcon && !hasText) + size = size.expandedTo(QSize(Metrics::TabBar_TabMinHeight, 0)); + else + size = size.expandedTo(QSize(Metrics::TabBar_TabMinHeight, Metrics::TabBar_TabMinWidth)); + } + else + { + size.rwidth() += widthIncrement; + if (hasIcon && !hasText) + size = size.expandedTo(QSize(0, Metrics::TabBar_TabMinHeight)); + else + size = size.expandedTo(QSize(Metrics::TabBar_TabMinWidth, Metrics::TabBar_TabMinHeight)); + } + + return size; +} + +void Style::drawPEFrameTabWidget(const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + auto palettes = Palette::getDefault(); + auto background = Palette::getDefault()->getColor(option->state, Palette::WINDOW); + auto border = Palette::getDefault()->getColor(option->state, Palette::BORDER); + RenderHelper::renderFrame(painter, option->rect, 1, 0, background, border); +} + +void Style::drawControlTabBarTabShape(const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + const auto tabOption(qstyleoption_cast(option)); + RETURN_IF_FALSE(tabOption); + + const QPalette &palette(option->palette); + const QStyle::State &state(option->state); + bool enabled(state & QStyle::State_Enabled); + bool selected(state & QStyle::State_Selected); + bool mouseOver((state & QStyle::State_Active) && !selected && (state & QStyle::State_MouseOver) && enabled); + + // check if tab is being dragged + bool isDragged(widget && selected && painter->device() != widget); + // bool isLocked(widget && _tabBarData->isLocked(widget)); + + const QStyleOptionTab::TabPosition &position = tabOption->position; + const bool isSingle(position == QStyleOptionTab::OnlyOneTab); + const bool isQtQuickControl(RenderHelper::isQtQuickControl(option, widget)); + bool isFirst(isSingle || position == QStyleOptionTab::Beginning); + bool isLast(isSingle || position == QStyleOptionTab::End); + bool isLeftOfSelected(/*!isLocked &&*/ tabOption->selectedPosition == QStyleOptionTab::NextIsSelected); + bool isRightOfSelected(/*!isLocked &&*/ tabOption->selectedPosition == QStyleOptionTab::PreviousIsSelected); + + // true if widget is aligned to the frame + // need to check for 'isRightOfSelected' because for some reason the isFirst flag is set when active tab is being moved + isFirst &= !isRightOfSelected; + isLast &= !isLeftOfSelected; + + // 若是反向布局交换状态,改变与方向相关属性 + const bool reverseLayout(option->direction == Qt::RightToLeft); + const bool verticalTabs(RenderHelper::isVerticalTab(tabOption->shape)); + if (reverseLayout && !verticalTabs) + { + qSwap(isFirst, isLast); + qSwap(isLeftOfSelected, isRightOfSelected); + } + + // 根据TabBar方向调整选项卡圆角的位置 + Corners corners; + switch (tabOption->shape) + { + case QTabBar::RoundedNorth: + case QTabBar::TriangularNorth: + corners = CornersTop; + break; + case QTabBar::RoundedSouth: + case QTabBar::TriangularSouth: + corners = CornersBottom; + break; + case QTabBar::RoundedWest: + case QTabBar::TriangularWest: + corners = CornersLeft; + break; + case QTabBar::RoundedEast: + case QTabBar::TriangularEast: + corners = CornersRight; + break; + default: + break; + } + + auto background = Palette::getDefault()->getColor(option->state, Palette::WIDGET); + RenderHelper::renderTabBarTab(painter, option->rect, corners, 4, background); +} + +QRect Style::tabBarSubElementRect(QStyle::SubElement subElement, const QStyleOption *option, const QWidget *widget) const +{ + const auto *tabOption(qstyleoption_cast(option)); + + if (!widget || !widget->inherits("QTabBar")) + { + return QRect(); + } + + const auto tabBar = qobject_cast(widget); + const QRect &rect = option->rect; + + switch (subElement) + { + case QStyle::SE_TabBarTearIndicator: + case QStyle::SE_TabBarTearIndicatorRight: + return QRect(); + + // QTabBar::setTabButton所设置位于单个Tab左右的控件 + case QStyle::SE_TabBarTabLeftButton: + case QStyle::SE_TabBarTabRightButton: + { + if (!tabOption) + { + return QRect(); + } + + bool isLeft = (subElement == QStyle::SE_TabBarTabLeftButton); + + QSize size(isLeft ? tabOption->leftButtonSize : tabOption->rightButtonSize); + if (size.isEmpty()) + { + return QRect(); + } + + QRect buttonRect(QPoint(0, 0), size); + + switch (tabOption->shape) + { + case QTabBar::RoundedNorth: + case QTabBar::TriangularNorth: + + case QTabBar::RoundedSouth: + case QTabBar::TriangularSouth: + if (isLeft) + { + buttonRect.moveLeft(rect.left() + Metrics::TabBar_TabMarginWidth); + } + else + { + buttonRect.moveRight(rect.right() - Metrics::TabBar_TabMarginWidth); + } + buttonRect.moveTop((rect.height() - buttonRect.height()) / 2); + buttonRect = QStyle::visualRect(option->direction, option->rect, buttonRect); + break; + + case QTabBar::RoundedWest: + case QTabBar::TriangularWest: + if (isLeft) + { + buttonRect.moveBottom(rect.bottom() - Metrics::TabBar_TabMarginWidth); + } + else + { + buttonRect.moveTop(rect.top() + Metrics::TabBar_TabMarginWidth); + } + buttonRect.moveLeft((rect.width() - buttonRect.width()) / 2); + break; + + case QTabBar::RoundedEast: + case QTabBar::TriangularEast: + if (isLeft) + { + buttonRect.moveTop(rect.top() + Metrics::TabBar_TabMarginWidth); + } + else + { + buttonRect.moveBottom(rect.bottom() - Metrics::TabBar_TabMarginWidth); + } + buttonRect.moveLeft((rect.width() - buttonRect.width()) / 2); + break; + + default: + break; + } + + return buttonRect; + } + + case QStyle::SE_TabBarTabText: + { + auto d = d_func(); + QRect textRect; + QRect iconRect; + d->tabLayout(tabOption, widget, &textRect, &iconRect); + return textRect; + } + + // 当QTabBar过多时,QTabBar左右滑动的按钮 + case QStyle::SE_TabBarScrollLeftButton: + case QStyle::SE_TabBarScrollRightButton: + { + bool isLeft = (subElement == QStyle::SE_TabBarScrollLeftButton); + const int buttonWidth = this->pixelMetric(QStyle::PM_TabBarScrollButtonWidth, nullptr, widget); + QRect scrollButtonRect; + + if (RenderHelper::isVerticalTab(tabBar->shape())) + { + scrollButtonRect = QRect(0, isLeft ? 0 : (rect.height() - buttonWidth), rect.width(), buttonWidth); + } + else + { + scrollButtonRect = QRect(isLeft ? 0 : (rect.width() - buttonWidth), 0, buttonWidth, rect.height()); + QStyle::visualRect(option->direction, option->rect, scrollButtonRect); + } + return scrollButtonRect; + } + default: + break; + } + + return QRect(); +} + +QPainterPath roundedItemPath(const QStyleOptionViewItem *o, const QWidget *w) +{ + int radius = 4; + int backgroundMarginLeft = 0; + int backgroundMarginRight = 0; + + QPainterPath path; + path.setFillRule(Qt::WindingFill); + path.addRoundedRect(o->rect.adjusted(backgroundMarginLeft, 0, -backgroundMarginRight, 0), radius, radius); + return path; +} + +void Style::drawPanelItemViewRow(const QStyleOption *pOption, QPainter *pPainter, const QWidget *pWidget) const +{ + if (const auto vopt = qstyleoption_cast(pOption)) { + + pPainter->setRenderHint(QPainter::Antialiasing); + QPainterPath path = roundedItemPath(vopt, pWidget); + QPalette::ColorGroup colorGroup = (pWidget ? pWidget->isEnabled() : (vopt->state & QStyle::State_Enabled)) + ? QPalette::Normal : QPalette::Disabled; + if (colorGroup == QPalette::Normal && !(vopt->state & QStyle::State_Active)) + colorGroup = QPalette::Inactive; + + if ((vopt->state & QStyle::State_Selected) && proxy()->styleHint(QStyle::SH_ItemView_ShowDecorationSelected, pOption, pWidget)) + { + pPainter->fillRect(vopt->rect, vopt->palette.brush(colorGroup, QPalette::Text)); // 选中高亮 + } + else if (vopt->features & QStyleOptionViewItem::Alternate) + { + pPainter->fillPath(path, vopt->palette.brush(colorGroup, QPalette::AlternateBase)); + } + } +} + +void Style::drawPanelItemViewItem(const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + if (const auto vopt = qstyleoption_cast(option)) { + + painter->setRenderHint(QPainter::Antialiasing); + QPainterPath path = roundedItemPath(vopt, widget); + QPalette::ColorGroup cg = (widget ? widget->isEnabled() : (vopt->state & QStyle::State_Enabled)) + ? QPalette::Normal : QPalette::Disabled; + if (cg == QPalette::Normal && !(vopt->state & QStyle::State_Active)) + cg = QPalette::Inactive; + if (vopt->showDecorationSelected && (vopt->state & QStyle::State_Selected)) + { + painter->fillPath(path, vopt->palette.brush(cg, QPalette::Highlight)); + } + else + { + if (vopt->backgroundBrush.style() != Qt::NoBrush) { + QPointF brushOriginOld = painter->brushOrigin(); + painter->setBrushOrigin(vopt->rect.topLeft()); + painter->fillPath(path, vopt->backgroundBrush); + painter->setBrushOrigin(brushOriginOld); + } + + if (vopt->state & QStyle::State_Selected) { + QRect textRect = subElementRect(QStyle::SE_ItemViewItemText, option, widget); + painter->fillRect(textRect, vopt->palette.brush(cg, QPalette::Text)); + } + } + } +} +void Style::drawTextEditor(QStyle::ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + const auto itemOption = qstyleoption_cast(option); + if (itemOption && itemOption->state & QStyle::State_Selected) + { + QStyleOptionViewItem newOption(*itemOption); +// newOption.palette.setColor(QPalette::Highlight, Qt::transparent); + QProxyStyle::drawControl(element, &newOption, painter, widget); + return; + } + + QProxyStyle::drawControl(element, option, painter, widget); +} + +} // namespace Theme +} // namespace Kiran \ No newline at end of file diff --git a/lib/theme/style.h b/lib/theme/style.h new file mode 100644 index 0000000000000000000000000000000000000000..987f3f3573414803bebc4d419652f720fe6bf87d --- /dev/null +++ b/lib/theme/style.h @@ -0,0 +1,160 @@ +/** + * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. + * kiran-qt5-integration is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * + * Author: liuxinhao + */ + +#pragma once + +#include +#include + +class QAbstractScrollArea; + +namespace Kiran +{ +namespace Theme +{ +class StylePrivate; +class Palette; + +class Style : public QProxyStyle +{ +public: + explicit Style(); + ~Style() override; + + int styleHint(StyleHint hint, const QStyleOption* option = nullptr, const QWidget* widget = nullptr, QStyleHintReturn* returnData = nullptr) const override; + int pixelMetric(PixelMetric metric, const QStyleOption* option = nullptr, const QWidget* widget = nullptr) const override; + + void drawPrimitive(PrimitiveElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const override; + void drawComplexControl(ComplexControl control, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget) const override; + void drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget = nullptr) const override; + + QRect subElementRect(SubElement element, const QStyleOption* option, const QWidget* widget) const override; + QRect subControlRect(ComplexControl complexControl, + const QStyleOptionComplex* option, + SubControl subControl, + const QWidget* widget) const override; + QSize sizeFromContents(ContentsType type, const QStyleOption* option, const QSize& contentSize, const QWidget* widget) const override; + + QPixmap standardPixmap(StandardPixmap standardPixmap, const QStyleOption* option, const QWidget* widget) const override; + QIcon standardIcon(StandardPixmap standardIcon, const QStyleOption* option, const QWidget* widget) const override; + + void polishScrollArea(QAbstractScrollArea* scrollArea); + void polish(QWidget* widget) override; + void polish(QApplication* application) override; + void polish(QPalette& palette) override; + +private: + // 绘制Frame背景和边框 + void drawPEFrame(const QStyleOption* option, QPainter* painter, const QWidget* widget) const; + // 绘制聚焦时候的边框 + void drawPEFrameFocusRect(const QStyleOption* option, QPainter* painter, const QWidget* widget) const; + // 绘制QGroupBox控件的边框和背景 + void drawPEFrameGroupBox(const QStyleOption* option, QPainter* painter, const QWidget* widget) const; + void drawControlShapedFrame(const QStyleOption* option, QPainter* painter, const QWidget* widget) const; + QSize defaultSizeFromContents(const QStyleOption* option, const QSize& contentSize, const QWidget* widget) const; + + // button + QSize pushButtonSizeFromContents(const QStyleOption* option, const QSize& contentSize, const QWidget* widget) const; + QSize toolButtonSizeFromContents(const QStyleOption* option, const QSize& contentSize, const QWidget* widget) const; + QRect toolButtonSubControlRect(const QStyleOptionComplex* option, QStyle::SubControl subControl, const QWidget* widget) const; + void drawPEPushButton(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const; + // 绘制列表条目 + void drawItemViewItem(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const; + // 文本选中颜色 + void drawTextEditor(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const; + void drawPEPanelButtonCommand(const QStyleOption* option, QPainter* painter, const QWidget* widget) const; + void drawPEPanelButtonTool(const QStyleOption* option, QPainter* painter, const QWidget* widget) const; + void drawControlToolButtonLabel(const QStyleOption* option, QPainter* painter, const QWidget* widget) const; + void drawCCToolButton(const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget) const; + + // combobox + QSize comboBoxSizeFromContents(const QStyleOption* option, const QSize& contentSize, const QWidget* widget) const; + QRect comboBoxSubControlRect(const QStyleOptionComplex* option, QStyle::SubControl subControl, const QWidget* widget) const; + void drawCCComboBox(const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget) const; + void drawControlComboBoxLabel(const QStyleOption* option, QPainter* painter, const QWidget* widget) const; + + // edit + void drawPEFrameLineEdit(const QStyleOption* option, QPainter* painter, const QWidget* widget) const; + + // groupbox + QSize groupBoxSizeFromContents(const QStyleOption* option, const QSize& contentSize, const QWidget* widget) const; + QRect groupBoxSubControlRect(const QStyleOptionComplex* option, QStyle::SubControl subControl, const QWidget* widget) const; + + // indicator + void drawPEIndicatorButtonDropDown(const QStyleOption* option, QPainter* painter, const QWidget* widget) const; + void drawPEIndicatorArrowUp(const QStyleOption* option, QPainter* painter, const QWidget* widget) const; + void drawPEIndicatorArrowDown(const QStyleOption* option, QPainter* painter, const QWidget* widget) const; + void drawPEIndicatorArrowLeft(const QStyleOption* option, QPainter* painter, const QWidget* widget) const; + void drawPEIndicatorArrowRight(const QStyleOption* option, QPainter* painter, const QWidget* widget) const; + // 绘制单选框按钮 + void drawPEIndicatorRadioButton(const QStyleOption* option, QPainter* painter, const QWidget* widget) const; + // 绘制复选框按钮 + void drawPEIndicatorCheckBox(const QStyleOption* option, QPainter* painter, const QWidget* widget) const; + void drawPEIndicatorBranch(const QStyleOption* option, QPainter* painter, const QWidget* widget) const; + void drawPEIndicatorToolBarSeparator(const QStyleOption* option, QPainter* painter, const QWidget* widget) const; + void drawPEIndicatorToolBarHandle(const QStyleOption* option, QPainter* painter, const QWidget* widget) const; + + //item view + void drawControlHeaderSection(const QStyleOption* option, QPainter* painter, const QWidget* widget) const; + void drawControlHeaderLabel(const QStyleOption* option, QPainter* painter, const QWidget* widget) const; + void drawControlHeaderEmptyArea(const QStyleOption* option, QPainter* painter, const QWidget* widget) const; + + // menu + void drawControlMenuBarItem(const QStyleOption* option, QPainter* painter, const QWidget* widget) const; + void drawControlMenuBarEmptyArea(const QStyleOption* option, QPainter* painter, const QWidget* widget) const; + + // progressbar + QSize progressBarSizeFromContents(const QStyleOption* option, const QSize& contentSize, const QWidget* widget) const; + QRect progressBarElementRect(QStyle::SubElement subElement, const QStyleOption* option, const QWidget* widget) const; + void drawControlProgressBar(const QStyleOption* option, QPainter* painter, const QWidget* widget) const; + void drawControlProgressBarGroove(const QStyleOption* option, QPainter* painter, const QWidget* widget) const; + void drawControlProgressBarContents(const QStyleOption* option, QPainter* painter, const QWidget* widget) const; + void drawControlProgressBarLabel(const QStyleOption* option, QPainter* painter, const QWidget* widget) const; + + // scrollbar + QRect scrollBarSubControlRect(const QStyleOptionComplex* option, QStyle::SubControl subControl, const QWidget* widget) const; + void drawCCScrollBar(const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget) const; + // 绘制滑动条可滑动区域 + void drawControlScrollBarSlider(const QStyleOption* option, QPainter* painter, const QWidget* widget) const; + + // slider + QSize sliderSizeFromContents(const QStyleOption* option, const QSize& contentSize, const QWidget* widget) const; + void drawCCSlider(const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget) const; + QRect sliderElementRect(QStyle::SubElement subElement, const QStyleOption* option, const QWidget* widget) const; + QRect sliderSubControlRect(const QStyleOptionComplex* option, QStyle::SubControl subControl, const QWidget* widget) const; + + // spinbox + QSize spinBoxSizeFromContents(const QStyleOption* option, const QSize& contentSize, const QWidget* widget) const; + QRect spinBoxSubControlRect(const QStyleOptionComplex* option, QStyle::SubControl subControl, const QWidget* widget) const; + void drawCCSpinBox(const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget) const; + + // tabbar FIXME:需要和sizeFromContents获取的大小对应 + QSize tabBarTabSizeFromContents(const QStyleOption* option, const QSize& contentSize, const QWidget* widget) const; + QRect tabBarSubElementRect(QStyle::SubElement subElement, const QStyleOption* option, const QWidget* widget) const; + // tab选项卡下边内容控件的背景绘制 + void drawPEFrameTabWidget(const QStyleOption* option, QPainter* painter, const QWidget* widget) const; + // tab选项卡形状和背景绘制 + void drawControlTabBarTabShape(const QStyleOption* option, QPainter* painter, const QWidget* widget) const; + + // ListItem 行样式 TODO: 弃用 + void drawPanelItemViewRow(const QStyleOption* pOption, QPainter* pPainter, const QWidget* pWidget) const; + void drawPanelItemViewItem(const QStyleOption* option, QPainter* painter, const QWidget* widget) const; + +private: + StylePrivate* d_ptr; + Q_DECLARE_PRIVATE(Style); +}; + +} // namespace Theme +} // namespace Kiran \ No newline at end of file diff --git a/platformtheme/CMakeLists.txt b/platformtheme/CMakeLists.txt deleted file mode 100644 index a8462d5f7d534c874d1655aff38e624da244dbc8..0000000000000000000000000000000000000000 --- a/platformtheme/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -set(TARGET_NAME "qkiran") - -find_package(PkgConfig REQUIRED) -find_package(Qt5 COMPONENTS Widgets Gui Svg DBus) -find_package(Qt5ThemeSupport REQUIRED) - -pkg_search_module(KLOG_QT5 REQUIRED klog-qt5) -pkg_search_module(QGSETTINGS REQUIRED gsettings-qt) - -set(CMAKE_AUTOMOC ON) -set(CMAKE_AUTOUIC ON) -set(CMAKE_AUTORCC ON) - -file(GLOB_RECURSE SRC "*.cpp" "*.h" "*.ui") - -add_library(${TARGET_NAME} SHARED - ${SRC}) - -target_include_directories(${TARGET_NAME} PUBLIC - ${CMAKE_CURRENT_BINARY_DIR} - ${Qt5Gui_PRIVATE_INCLUDE_DIRS} - ${Qt5Widgets_PRIVATE_INCLUDE_DIRS} - ${Qt5ThemeSupport_INCLUDE_DIRS} - ${QGSETTINGS_INCLUDE_DIRS} - ${KIRAN_CC_DAEMON_INCLUDE_DIRS}) - -target_link_libraries(${TARGET_NAME} - common - kiran-style-helper - Qt5::Widgets - Qt5::Gui - Qt5::DBus - Qt5::Svg - ${Qt5ThemeSupport_LIBRARIES} - ${QGSETTINGS_LIBRARIES}) - -install(TARGETS ${TARGET_NAME} DESTINATION ${QT5_PLATFORM_THEME_INSTALL_DIR}) \ No newline at end of file diff --git a/platformtheme/logging-category.cpp b/platformtheme/logging-category.cpp deleted file mode 100644 index ae072a8e77fc279dd67e56fb0a7d93e821e5d840..0000000000000000000000000000000000000000 --- a/platformtheme/logging-category.cpp +++ /dev/null @@ -1,7 +0,0 @@ -// -// Created by lxh on 2022/3/18. -// - -#include "logging-category.h" - -Q_LOGGING_CATEGORY(kiranPlatformTheme,"kiran.platformtheme",QtWarningMsg) diff --git a/platformtheme/logging-category.h b/platformtheme/logging-category.h deleted file mode 100644 index 33ac457261fa9d9c8c487350dbd49f4cc2355b79..0000000000000000000000000000000000000000 --- a/platformtheme/logging-category.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef KIRAN_QT5_INTEGRATION_PLATFORMTHEME_LOGGIN_CATEGORY_H_ -#define KIRAN_QT5_INTEGRATION_PLATFORMTHEME_LOGGIN_CATEGORY_H_ - -#include - -Q_DECLARE_LOGGING_CATEGORY(kiranPlatformTheme) - -#endif //KIRAN_QT5_INTEGRATION_PLATFORMTHEME_LOGGIN_CATEGORY_H_ diff --git a/platformtheme/qkiran.json b/platformtheme/qkiran.json deleted file mode 100644 index 794d5ad449996fd08edc6c39a17e3b8e429dee71..0000000000000000000000000000000000000000 --- a/platformtheme/qkiran.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "Keys": [ "kiran"] -} diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..6738ace51dd5d49119ff4e0c62151bf345fd4fdb --- /dev/null +++ b/plugins/CMakeLists.txt @@ -0,0 +1,3 @@ + +add_subdirectory(platformtheme) +add_subdirectory(style) diff --git a/plugins/platformtheme/CMakeLists.txt b/plugins/platformtheme/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..c137af7b62ff1e01ca17c6d119408a4e659106bd --- /dev/null +++ b/plugins/platformtheme/CMakeLists.txt @@ -0,0 +1,60 @@ +set(TARGET_NAME "qkiran-next") + +find_package(KiranDBusGenerate REQUIRED) +find_package(PkgConfig REQUIRED) +find_package(Qt5ThemeSupport REQUIRED) +pkg_search_module(KIRAN_CC_DAEMON REQUIRED kiran-cc-daemon) +pkg_search_module(QGSETTINGS REQUIRED gsettings-qt) + +# 生成使用的DBus接口源文件 kiran session appearance proxy +set_source_files_properties( + ${PROJECT_SOURCE_DIR}/data/com.kylinsec.Kiran.SessionDaemon.Appearance.xml + PROPERTIES CLASSNAME AppearanceProxy NO_NAMESPACE true) + +kiran_qt5_add_dbus_interface( + KIRAN_INTERFACE_SRC + ${PROJECT_SOURCE_DIR}/data/com.kylinsec.Kiran.SessionDaemon.Appearance.xml + appearance_proxy) + +# kiran session display proxy +set_source_files_properties( + ${PROJECT_SOURCE_DIR}/data/com.kylinsec.Kiran.SessionDaemon.Display.xml + PROPERTIES CLASSNAME DisplayProxy NO_NAMESPACE true) + +kiran_qt5_add_dbus_interface( + KIRAN_INTERFACE_SRC + ${PROJECT_SOURCE_DIR}/data/com.kylinsec.Kiran.SessionDaemon.Display.xml + display_proxy) + +# 避免cmake错误 +foreach(interface_item ${KIRAN_INTERFACE_SRC}) + set_property(SOURCE ${interface_item} PROPERTY SKIP_AUTOGEN ON) +endforeach() + +file(GLOB_RECURSE SRC "*.cpp" "*.h" "*.ui") + +add_library(${TARGET_NAME} SHARED ${SRC} ${KIRAN_INTERFACE_SRC}) + +target_include_directories( + ${TARGET_NAME} + PUBLIC ${PROJECT_SOURCE_DIR} + ${PROJECT_BINARY_DIR} + ${Qt5Gui_PRIVATE_INCLUDE_DIRS} + ${Qt5Widgets_PRIVATE_INCLUDE_DIRS} + ${Qt5ThemeSupport_INCLUDE_DIRS} + ${QGSETTINGS_INCLUDE_DIRS} + ${KIRAN_CC_DAEMON_INCLUDE_DIRS}) + +target_link_libraries( + ${TARGET_NAME} + lib-common + kiran-integration-theme + Qt5::Core + Qt5::Widgets + Qt5::Gui + Qt5::DBus + Qt5::Svg + ${Qt5ThemeSupport_LIBRARIES} + ${QGSETTINGS_LIBRARIES}) + +install(TARGETS ${TARGET_NAME} DESTINATION ${QT5_PLATFORM_THEME_INSTALL_DIR}) diff --git a/common/src/kiran-appearance-monitor.cpp b/plugins/platformtheme/appearance-monitor.cpp similarity index 54% rename from common/src/kiran-appearance-monitor.cpp rename to plugins/platformtheme/appearance-monitor.cpp index f48ea416663f4161b84462017b190f271d0749e8..48739318d927185d843e35c2e39f54afe5d38764 100644 --- a/common/src/kiran-appearance-monitor.cpp +++ b/plugins/platformtheme/appearance-monitor.cpp @@ -12,23 +12,27 @@ * Author: liuxinhao */ -#include "kiran-appearance-monitor.h" -#include "kiran_appearance_proxy.h" -#include "kiran_display_proxy.h" -#include "logging-category.h" - +#include "plugins/platformtheme/appearance-monitor.h" #include - +#include #include #include +#include +#include +#include "plugins/platformtheme/appearance_proxy.h" +#include "plugins/platformtheme/display_proxy.h" -KiranAppearanceMonitor::KiranAppearanceMonitor(QObject *parent) +namespace Kiran +{ +namespace Platformtheme +{ +AppearanceMonitor::AppearanceMonitor(QObject *parent) : QObject(parent) { - m_appearanceIface = new KiranAppearanceProxy("com.kylinsec.Kiran.SessionDaemon.Appearance", - "/com/kylinsec/Kiran/SessionDaemon/Appearance", - QDBusConnection::sessionBus(), - this); + m_appearanceIface = new AppearanceProxy("com.kylinsec.Kiran.SessionDaemon.Appearance", + "/com/kylinsec/Kiran/SessionDaemon/Appearance", + QDBusConnection::sessionBus(), + this); if (QDBusConnection::sessionBus().interface()->isServiceRegistered("com.kylinsec.Kiran.SessionDaemon.Appearance")) { @@ -40,113 +44,111 @@ KiranAppearanceMonitor::KiranAppearanceMonitor(QObject *parent) { m_appFontName = tempFontName; m_appFontSize = tempFontSize; - qDebug(kiranPlatformThemeCommon,"application font: %s %d",m_appFontName.toStdString().c_str(),m_appFontSize); + qDebug("application font: %s %d", m_appFontName.toStdString().c_str(), m_appFontSize); } else { - qWarning(kiranPlatformThemeCommon) << "appearance monitor: parse application font failed!"; + qWarning() << "appearance monitor: parse application font failed!"; } //window titlebar font fontValue = m_appearanceIface->GetFont(APPEARANCE_FONT_TYPE_WINDOW_TITLE); - if(parseFontValue(fontValue,tempFontName,tempFontSize)) + if (parseFontValue(fontValue, tempFontName, tempFontSize)) { m_titleBarFontName = tempFontName; m_titleBarFontSize = tempFontSize; - qDebug(kiranPlatformThemeCommon,"title bar font: %s %d",m_titleBarFontName.toStdString().c_str(),m_titleBarFontSize); + qDebug("title bar font: %s %d", m_titleBarFontName.toStdString().c_str(), m_titleBarFontSize); } else { - qDebug(kiranPlatformThemeCommon) << "parse titlebar font failed!"; + qDebug() << "parse titlebar font failed!"; } //icon theme auto themeReply = m_appearanceIface->GetTheme(APPEARANCE_THEME_TYPE_ICON); themeReply.waitForFinished(); - if( !themeReply.isError() ) + if (!themeReply.isError()) { m_iconTheme = themeReply.value(); - qDebug(kiranPlatformThemeCommon,"icon theme: %s",m_iconTheme.toStdString().c_str()); + qDebug("icon theme: %s", m_iconTheme.toStdString().c_str()); } else { - qDebug(kiranPlatformThemeCommon) << "get icon theme failed," << themeReply.error(); + qDebug() << "get icon theme failed," << themeReply.error(); } //gtk theme themeReply = m_appearanceIface->GetTheme(APPEARANCE_THEME_TYPE_GTK); themeReply.waitForFinished(); - if( !themeReply.isError() ) + if (!themeReply.isError()) { QString gtkThemeName = themeReply.value(); - if( gtkThemeName.contains("dark",Qt::CaseInsensitive) ) + if (gtkThemeName.contains("dark", Qt::CaseInsensitive)) m_gtkThemeName = "kiran-dark"; else m_gtkThemeName = "kiran"; - qDebug(kiranPlatformThemeCommon,"gtk theme: %s",m_gtkThemeName.toStdString().c_str()); + qDebug("gtk theme: %s", m_gtkThemeName.toStdString().c_str()); } else { - qDebug(kiranPlatformThemeCommon) << "get gtk theme failed," << themeReply.error(); + qDebug() << "get gtk theme failed," << themeReply.error(); } } else { - qDebug(kiranPlatformThemeCommon) << "kiran session daemon appearance service isn't registered!"; + qDebug() << "kiran session daemon appearance service isn't registered!"; } - connect(m_appearanceIface, &KiranAppearanceProxy::FontChanged, - this, &KiranAppearanceMonitor::handleFontSettingChanged); - connect(m_appearanceIface,&KiranAppearanceProxy::ThemeChanged, - this,&KiranAppearanceMonitor::handleThemeSettingChanged); - + connect(m_appearanceIface, &AppearanceProxy::FontChanged, + this, &AppearanceMonitor::handleFontSettingChanged); + connect(m_appearanceIface, &AppearanceProxy::ThemeChanged, + this, &AppearanceMonitor::handleThemeSettingChanged); - m_displayIface = new KiranDisplayProxy("com.kylinsec.Kiran.SessionDaemon.Display", - "/com/kylinsec/Kiran/SessionDaemon/Display", - QDBusConnection::sessionBus(), - this); + m_displayIface = new DisplayProxy("com.kylinsec.Kiran.SessionDaemon.Display", + "/com/kylinsec/Kiran/SessionDaemon/Display", + QDBusConnection::sessionBus(), + this); if (QDBusConnection::sessionBus().interface()->isServiceRegistered("com.kylinsec.Kiran.SessionDaemon.Display")) { m_scaleFactor = m_displayIface->window_scaling_factor(); } else { - qDebug(kiranPlatformThemeCommon) << "kiran session daemon display service isn't registered!"; + qDebug() << "kiran session daemon display service isn't registered!"; } - connect(m_displayIface, &KiranDisplayProxy::window_scaling_factorChanged, - this, &KiranAppearanceMonitor::handleWindowScaleFactorChanged); + connect(m_displayIface, &DisplayProxy::window_scaling_factorChanged, + this, &AppearanceMonitor::handleWindowScaleFactorChanged); m_polishCursorTimer.setInterval(500); m_polishCursorTimer.setSingleShot(true); - connect(&m_polishCursorTimer,&QTimer::timeout,this,&KiranAppearanceMonitor::handleCursorThemeChanged); + connect(&m_polishCursorTimer, &QTimer::timeout, this, &AppearanceMonitor::handleCursorThemeChanged); } -KiranAppearanceMonitor *KiranAppearanceMonitor::instance() +AppearanceMonitor *AppearanceMonitor::instance() { static QMutex mutex; - static QScopedPointer pInst; + static QScopedPointer pInst; if (Q_UNLIKELY(!pInst)) { QMutexLocker locker(&mutex); if (pInst.isNull()) { - pInst.reset(new KiranAppearanceMonitor); + pInst.reset(new AppearanceMonitor); } } return pInst.data(); } -KiranAppearanceMonitor::~KiranAppearanceMonitor() +AppearanceMonitor::~AppearanceMonitor() { - } -void KiranAppearanceMonitor::handleFontSettingChanged(int type, const QString &fontValue) +void AppearanceMonitor::handleFontSettingChanged(int type, const QString &fontValue) { QString fontName; int fontSize; @@ -175,18 +177,18 @@ void KiranAppearanceMonitor::handleFontSettingChanged(int type, const QString &f } } -void KiranAppearanceMonitor::handleWindowScaleFactorChanged(int scaleFactor) +void AppearanceMonitor::handleWindowScaleFactorChanged(int scaleFactor) { m_scaleFactor = scaleFactor; emit scaleFactorChanged(m_scaleFactor); } -bool KiranAppearanceMonitor::parseFontValue(const QString &font, QString &fontName, int &fontSize) +bool AppearanceMonitor::parseFontValue(const QString &font, QString &fontName, int &fontSize) { int fontSizeIdx = font.lastIndexOf(' '); if (fontSizeIdx <= 0) { - qDebug(kiranPlatformThemeCommon) << "Invalid font value format:" << font; + qDebug() << "Invalid font value format:" << font; return false; } @@ -197,7 +199,7 @@ bool KiranAppearanceMonitor::parseFontValue(const QString &font, QString &fontNa fontSize = fontSizeStr.toInt(&toIntOk); if (!toIntOk || fontSize <= 0) { - qDebug(kiranPlatformThemeCommon) << "Invalid font size:" << fontSizeStr; + qDebug() << "Invalid font size:" << fontSizeStr; return false; } @@ -205,21 +207,21 @@ bool KiranAppearanceMonitor::parseFontValue(const QString &font, QString &fontNa fontName = font.left(fontSizeIdx); if (fontName.isEmpty()) { - qDebug(kiranPlatformThemeCommon) << "Invalid font name:" << fontName; + qDebug() << "Invalid font name:" << fontName; return false; } QFontDatabase fontDatabase; if (!fontDatabase.hasFamily(fontName)) { - qDebug(kiranPlatformThemeCommon) << "Font not available in database:" << fontName; + qDebug() << "Font not available in database:" << fontName; return false; } return true; } -QFont KiranAppearanceMonitor::appFont() const +QFont AppearanceMonitor::appFont() const { QFont font = QFont(QString()); font.setFamily(m_appFontName); @@ -227,12 +229,12 @@ QFont KiranAppearanceMonitor::appFont() const return font; } -int KiranAppearanceMonitor::scaleFactor() const +int AppearanceMonitor::scaleFactor() const { return m_scaleFactor; } -QFont KiranAppearanceMonitor::titleBarFont() const +QFont AppearanceMonitor::titleBarFont() const { QFont font = QFont(QString()); font.setFamily(m_titleBarFontName); @@ -240,23 +242,23 @@ QFont KiranAppearanceMonitor::titleBarFont() const return font; } -QString KiranAppearanceMonitor::iconTheme() const +QString AppearanceMonitor::iconTheme() const { return m_iconTheme; } -void KiranAppearanceMonitor::handleThemeSettingChanged(int type, const QString &themeName) +void AppearanceMonitor::handleThemeSettingChanged(int type, const QString &themeName) { - if(type == APPEARANCE_THEME_TYPE_ICON) + if (type == APPEARANCE_THEME_TYPE_ICON) { m_iconTheme = themeName; emit iconThemeChanged(m_iconTheme); } - else if(type == APPEARANCE_THEME_TYPE_GTK) + else if (type == APPEARANCE_THEME_TYPE_GTK) { QString gtkTheme; - if( themeName.contains("dark",Qt::CaseInsensitive) ) + if (themeName.contains("dark", Qt::CaseInsensitive)) { gtkTheme = "kiran-dark"; } @@ -265,14 +267,14 @@ void KiranAppearanceMonitor::handleThemeSettingChanged(int type, const QString & gtkTheme = "kiran"; } - if(gtkTheme!=m_gtkThemeName) + if (gtkTheme != m_gtkThemeName) { - qDebug(kiranPlatformThemeCommon) << "gtk theme changed:" << themeName; + qDebug() << "gtk theme changed:" << themeName; m_gtkThemeName = gtkTheme; emit gtkThemeChanged(m_gtkThemeName); } } - else if(type==APPEARANCE_THEME_TYPE_CURSOR) + else if (type == APPEARANCE_THEME_TYPE_CURSOR) { // 延迟通知,让QXcbCursor更新主题 // 若未变化光标,qt5.15之前都需要合入修复补丁 @@ -280,12 +282,14 @@ void KiranAppearanceMonitor::handleThemeSettingChanged(int type, const QString & } } -void KiranAppearanceMonitor::handleCursorThemeChanged() +void AppearanceMonitor::handleCursorThemeChanged() { emit cursorThemeChanged(); } -QString KiranAppearanceMonitor::gtkTheme() const +QString AppearanceMonitor::gtkTheme() const { return m_gtkThemeName; } +} // namespace Platformtheme +} // namespace Kiran \ No newline at end of file diff --git a/common/src/kiran-appearance-monitor.h b/plugins/platformtheme/appearance-monitor.h similarity index 71% rename from common/src/kiran-appearance-monitor.h rename to plugins/platformtheme/appearance-monitor.h index 8d7033f2e7c4d81b7a8ecef3d01f60f9202007d1..f00fb6d71ecdcbdfe05d05a5e81ebb97c23d6392 100644 --- a/common/src/kiran-appearance-monitor.h +++ b/plugins/platformtheme/appearance-monitor.h @@ -11,22 +11,29 @@ * * Author: liuxinhao */ + #pragma once -#include #include +#include #include -class KiranDisplayProxy; -class KiranAppearanceProxy; -class KiranAppearanceMonitor : public QObject +class DisplayProxy; +class AppearanceProxy; + +namespace Kiran +{ +namespace Platformtheme +{ +class AppearanceMonitor : public QObject { Q_OBJECT private: - explicit KiranAppearanceMonitor(QObject* parent= nullptr); + explicit AppearanceMonitor(QObject* parent = nullptr); + public: - static KiranAppearanceMonitor* instance(); - ~KiranAppearanceMonitor() override; + static AppearanceMonitor* instance(); + ~AppearanceMonitor() override; QFont appFont() const; QFont titleBarFont() const; @@ -43,12 +50,12 @@ signals: void cursorThemeChanged(); private: - static bool parseFontValue(const QString& font,QString& fontName,int& fontSize); + static bool parseFontValue(const QString& font, QString& fontName, int& fontSize); private slots: - void handleFontSettingChanged(int type,const QString& fontValue); + void handleFontSettingChanged(int type, const QString& fontValue); void handleWindowScaleFactorChanged(int scaleFactor); - void handleThemeSettingChanged(int type,const QString& themeName); + void handleThemeSettingChanged(int type, const QString& themeName); void handleCursorThemeChanged(); private: @@ -64,6 +71,8 @@ private: QString m_gtkThemeName = "kiran"; QTimer m_polishCursorTimer; - KiranDisplayProxy* m_displayIface; - KiranAppearanceProxy* m_appearanceIface; -}; \ No newline at end of file + DisplayProxy* m_displayIface; + AppearanceProxy* m_appearanceIface; +}; +} // namespace Platformtheme +} // namespace Kiran \ No newline at end of file diff --git a/platformtheme/kiran-theme-plugin.cpp b/plugins/platformtheme/plugin.cpp similarity index 43% rename from platformtheme/kiran-theme-plugin.cpp rename to plugins/platformtheme/plugin.cpp index 961b7b3cc64fb237b35ffd351e9cbb37f609b895..7bae7d20bd1544ce4745d9ef9aaedf5102cf35da 100644 --- a/platformtheme/kiran-theme-plugin.cpp +++ b/plugins/platformtheme/plugin.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. + * Copyright (c) 2023 ~ 2024 KylinSec Co., Ltd. * kiran-qt5-integration is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. * You may obtain a copy of Mulan PSL v2 at: @@ -9,23 +9,34 @@ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. * See the Mulan PSL v2 for more details. * - * Author: liuxinhao + * Author: tangjie02 */ -#include "kiran-theme-plugin.h" -#include "kiran-theme.h" -#include "logging-category.h" +#include "plugins/platformtheme/plugin.h" +#include "plugins/platformtheme/theme.h" + #include +#include +#include -QPlatformTheme* KiranThemePlugin::create(const QString& key, const QStringList& paramList) +namespace Kiran +{ +namespace Platformtheme { - static QSet keySet = {"kiran","gnome","gtk3","qgnomeplatform"}; +QPlatformTheme* Plugin::create(const QString& key, const QStringList& paramList) +{ + static QSet keySet = {"kiran-next", "kiran", "gnome", "gtk3", "qgnomeplatform"}; - if(keySet.contains(key)) + if (keySet.contains(key)) { - qDebug(kiranPlatformTheme) << "create kiran platformtheme for" << QCoreApplication::applicationName(); - return new KiranTheme(paramList); + qDebug() << "create kiran platformtheme for" << QCoreApplication::applicationName() + << " with key=" << key + << " and paramList=" << paramList; + return new Theme(paramList); } return nullptr; } + +} // namespace Platformtheme +} // namespace Kiran \ No newline at end of file diff --git a/platformtheme/kiran-theme-plugin.h b/plugins/platformtheme/plugin.h similarity index 58% rename from platformtheme/kiran-theme-plugin.h rename to plugins/platformtheme/plugin.h index 6dbfe0cd0a4f3842e5cf5a5fa1f610d39d61c460..cf7c9fb8af39bbd725669d0ab5e24ee23da465f4 100644 --- a/platformtheme/kiran-theme-plugin.h +++ b/plugins/platformtheme/plugin.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. + * Copyright (c) 2023 ~ 2024 KylinSec Co., Ltd. * kiran-qt5-integration is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. * You may obtain a copy of Mulan PSL v2 at: @@ -9,24 +9,28 @@ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. * See the Mulan PSL v2 for more details. * - * Author: liuxinhao + * Author: tangjie02 */ -#ifndef KIRAN_QT5_PLATFORMTHEME_PLATFORMTHEME_KIRAN_THEME_PLUGIN_H_ -#define KIRAN_QT5_PLATFORMTHEME_PLATFORMTHEME_KIRAN_THEME_PLUGIN_H_ + +#pragma once #include -class KiranThemePlugin : public QPlatformThemePlugin +namespace Kiran +{ +namespace Platformtheme +{ +class Plugin : public QPlatformThemePlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID QPlatformThemeFactoryInterface_iid FILE "qkiran.json") + Q_PLUGIN_METADATA(IID QPlatformThemeFactoryInterface_iid FILE "plugin.json") + public: - explicit KiranThemePlugin(QObject *parent=nullptr) :QPlatformThemePlugin(parent){}; - ~KiranThemePlugin() override = default; + explicit Plugin(QObject *parent = nullptr) : QPlatformThemePlugin(parent){}; + virtual ~Plugin() override = default; QPlatformTheme *create(const QString &key, const QStringList ¶mList) override; - -private: }; -#endif //KIRAN_QT5_PLATFORMTHEME_PLATFORMTHEME_KIRAN_THEME_PLUGIN_H_ +} // namespace Platformtheme +} // namespace Kiran diff --git a/plugins/platformtheme/plugin.json b/plugins/platformtheme/plugin.json new file mode 100644 index 0000000000000000000000000000000000000000..c3edb6b473cdcb4b7d0b07725a36377ed33b8482 --- /dev/null +++ b/plugins/platformtheme/plugin.json @@ -0,0 +1,3 @@ +{ + "Keys": [ "kiran-next"] +} diff --git a/platformtheme/kiran-theme.cpp b/plugins/platformtheme/theme.cpp similarity index 52% rename from platformtheme/kiran-theme.cpp rename to plugins/platformtheme/theme.cpp index 86eb2e1cc0e629aa56876cfc751d1d292f8dc2ab..fceea892999f6c4c108f6276eca7efabbd9f7545 100644 --- a/platformtheme/kiran-theme.cpp +++ b/plugins/platformtheme/theme.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. + * Copyright (c) 2023 ~ 2024 KylinSec Co., Ltd. * kiran-qt5-integration is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. * You may obtain a copy of Mulan PSL v2 at: @@ -9,14 +9,10 @@ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. * See the Mulan PSL v2 for more details. * - * Author: liuxinhao + * Author: tangjie02 */ -#include "kiran-theme.h" -#include "kiran-appearance-monitor.h" -#include "logging-category.h" -#include "kiran-integration-settings.h" - +#include "plugins/platformtheme/theme.h" #include #include #include @@ -25,55 +21,69 @@ #define private public #include #undef private - #include #include #include #include +#include #include #include #include #include -#include "style-palette.h" +#include "lib/common/configuration.h" +#include "lib/theme/palette.h" +#include "lib/theme/style.h" +#include "plugins/platformtheme/appearance-monitor.h" +#include "plugins/platformtheme/themed-icon-engine.h" + +extern Kiran::Theme::Palette::BaseColors g_lightBaseColors; +extern Kiran::Theme::Palette::BaseColors g_darkBaseColors; -using namespace Kiran; +// TODO: 修改为统一图标名称前缀,目前暂定 kcp- +#define THEMED_SVG_ICON_PREFIX "kcp-" -KiranTheme::KiranTheme(const QStringList& paramList) +namespace Kiran +{ +namespace Platformtheme +{ +Theme::Theme(const QStringList& paramList) : QGenericUnixTheme() { init(); } -KiranTheme::~KiranTheme() -{ -} +Theme::~Theme() = default; -bool KiranTheme::usePlatformNativeDialog(QPlatformTheme::DialogType type) const +bool Theme::usePlatformNativeDialog(QPlatformTheme::DialogType type) const { return QGenericUnixTheme::usePlatformNativeDialog(type); } -QPlatformDialogHelper* KiranTheme::createPlatformDialogHelper(QPlatformTheme::DialogType type) const +QPlatformDialogHelper* Theme::createPlatformDialogHelper(QPlatformTheme::DialogType type) const { return QGenericUnixTheme::createPlatformDialogHelper(type); } -QIconEngine* KiranTheme::createIconEngine(const QString& iconName) const +QIconEngine* Theme::createIconEngine(const QString& iconName) const { + if ( iconName.startsWith(THEMED_SVG_ICON_PREFIX) && ThemedIconEngine::isValid(iconName)) + { + return new ThemedIconEngine(iconName); + } return QGenericUnixTheme::createIconEngine(iconName); } -QPixmap KiranTheme::standardPixmap(QPlatformTheme::StandardPixmap sp, const QSizeF& size) const +QPixmap Theme::standardPixmap(QPlatformTheme::StandardPixmap sp, const QSizeF& size) const { return QGenericUnixTheme::standardPixmap(sp, size); } -QIcon KiranTheme::fileIcon(const QFileInfo& fileInfo, QPlatformTheme::IconOptions iconOptions) const +QIcon Theme::fileIcon(const QFileInfo& fileInfo, QPlatformTheme::IconOptions iconOptions) const { return QGenericUnixTheme::fileIcon(fileInfo, iconOptions); } -QVariant KiranTheme::themeHint(QPlatformTheme::ThemeHint hint) const +QVariant Theme::themeHint(QPlatformTheme::ThemeHint hint) const { switch (hint) { @@ -86,64 +96,72 @@ QVariant KiranTheme::themeHint(QPlatformTheme::ThemeHint hint) const << "/usr/share/icons" << "/usr/local/share/icons"; case StyleNames: - return QStringList{"kiran","fusion"}; + return QStringList{"kiran-next", "kiran", "fusion"}; default: break; } return QGenericUnixTheme::themeHint(hint); } -const QPalette* KiranTheme::palette(QPlatformTheme::Palette type) const +const QPalette* Theme::palette(QPlatformTheme::Palette type) const { if (type != SystemPalette) { return QGenericUnixTheme::palette(type); } - bool enable = KiranIntegrationSettings::appKiranStyleAvailable(qAppName()); - if( !enable ) + bool enable = Configuration::instance()->match(qAppName()); + if (!enable) { return QGenericUnixTheme::palette(type); } - static QPalette kiranThemePalette; - StylePalette::instance()->polishPalette(&kiranThemePalette); - return &kiranThemePalette; + static QPalette themePalette; + Kiran::Theme::Palette::getDefault()->polish(themePalette); + return &themePalette; } -void KiranTheme::init() +void Theme::init() { - qDebug(kiranPlatformTheme) << "init kiran theme..."; - m_settingsMonitor = KiranAppearanceMonitor::instance(); + qDebug() << "init kiran theme..."; + m_settingsMonitor = AppearanceMonitor::instance(); + + // 根据当前初始明暗主题设定调色板, + if (!m_settingsMonitor->gtkTheme().contains("dark")) + { + Kiran::Theme::Palette::getDefault()->setBaseColors(g_lightBaseColors); + } m_scaleFactor = m_settingsMonitor->scaleFactor(); - qDebug(kiranPlatformTheme) << "\tscale factor:" << m_scaleFactor; + qDebug() << "\tscale factor:" << m_scaleFactor; m_systemFont.setFamily(m_settingsMonitor->appFont().family()); m_systemFont.setPointSize(m_settingsMonitor->appFont().pointSize()); QApplication::setFont(m_systemFont); - qDebug(kiranPlatformTheme) << "\tapplication font:" << m_settingsMonitor->appFont().family() << m_settingsMonitor->appFont().pointSize(); + qDebug() << "\tapplication font:" << m_settingsMonitor->appFont().family() << m_settingsMonitor->appFont().pointSize(); m_titleBarFont.setFamily(m_settingsMonitor->titleBarFont().family()); m_titleBarFont.setPointSize(m_settingsMonitor->titleBarFont().pointSize()); - qDebug(kiranPlatformTheme) << "\ttitle bar font:" << m_settingsMonitor->titleBarFont().family() << m_settingsMonitor->titleBarFont().pointSize(); + qDebug() << "\ttitle bar font:" << m_settingsMonitor->titleBarFont().family() << m_settingsMonitor->titleBarFont().pointSize(); - QObject::connect(m_settingsMonitor, &KiranAppearanceMonitor::appFontChanged, this, &KiranTheme::handleAppFontChanged); - QObject::connect(m_settingsMonitor, &KiranAppearanceMonitor::titleBarFontChanged, this, &KiranTheme::handleTitleBarFontChanged); - QObject::connect(m_settingsMonitor, &KiranAppearanceMonitor::iconThemeChanged, this, &KiranTheme::handleIconThemeChanged); - QObject::connect(m_settingsMonitor, &KiranAppearanceMonitor::scaleFactorChanged, this, &KiranTheme::handleScaleFactorChanged); - QObject::connect(m_settingsMonitor, &KiranAppearanceMonitor::cursorThemeChanged, this, &KiranTheme::handleCursorThemeChanged); + QObject::connect(m_settingsMonitor, &AppearanceMonitor::appFontChanged, this, &Theme::handleAppFontChanged); + QObject::connect(m_settingsMonitor, &AppearanceMonitor::titleBarFontChanged, this, &Theme::handleTitleBarFontChanged); + QObject::connect(m_settingsMonitor, &AppearanceMonitor::iconThemeChanged, this, &Theme::handleIconThemeChanged); + QObject::connect(m_settingsMonitor, &AppearanceMonitor::scaleFactorChanged, this, &Theme::handleScaleFactorChanged); + QObject::connect(m_settingsMonitor, &AppearanceMonitor::cursorThemeChanged, this, &Theme::handleCursorThemeChanged); + QObject::connect(m_settingsMonitor, &AppearanceMonitor::gtkThemeChanged, this, &Theme::handleThemeChanged); - // 不从KiranAppearanceMonitor接受主题变更事件,修改为接受KiranPalette的主题变更信号,能监听到系统主题变更以及应用程序手动指定主题 - //QObject::connect(m_settingsMonitor, &KiranAppearanceMonitor::gtkThemeChanged, this, &KiranTheme::handleThemeChanged); - QObject::connect(StylePalette::instance(),&StylePalette::themeChanged,this,&KiranTheme::handleThemeChanged); + // TODO: 确定从AppearanceMonitor监听是否可行 + // 不从AppearanceMonitor接受主题变更事件,修改为接受KiranPalette的主题变更信号,能监听到系统主题变更以及应用程序手动指定主题 + //QObject::connect(m_settingsMonitor, &AppearanceMonitor::gtkThemeChanged, this, &KiranTheme::handleThemeChanged); + // QObject::connect(StylePalette::instance(), &StylePalette::cursorThemeChanged, this, &Theme::handleThemeChanged); - QObject::connect(qApp, &QApplication::screenAdded, this, &KiranTheme::handleScreenAdded); + QObject::connect(qApp, &QApplication::screenAdded, this, &Theme::handleScreenAdded); handleScaleFactorChanged(m_scaleFactor); } -const QFont* KiranTheme::font(QPlatformTheme::Font type) const +const QFont* Theme::font(QPlatformTheme::Font type) const { switch (type) { @@ -171,22 +189,22 @@ const QFont* KiranTheme::font(QPlatformTheme::Font type) const // NOTE:也可通过删除QGuiApplication::app_font,对qapp下的所有window发送ApplicationFontChanged事件 // 但是若是设置了样式表(setStyleSheet)会抑制字体的传递。该方法可能耗资源更少 -void KiranTheme::handleAppFontChanged() +void Theme::handleAppFontChanged() { - qDebug(kiranPlatformTheme) << "application font changed:" - << m_settingsMonitor->appFont().family() - << m_settingsMonitor->appFont().pointSize(); + qDebug() << "application font changed:" + << m_settingsMonitor->appFont().family() + << m_settingsMonitor->appFont().pointSize(); m_systemFont.setFamily(m_settingsMonitor->appFont().family()); m_systemFont.setPointSize(m_settingsMonitor->appFont().pointSize()); QApplication::setFont(m_systemFont); } -void KiranTheme::handleTitleBarFontChanged() +void Theme::handleTitleBarFontChanged() { - qDebug(kiranPlatformTheme) << "title bar font changed:" - << m_settingsMonitor->titleBarFont().family() - << m_settingsMonitor->titleBarFont().pointSize(); + qDebug() << "title bar font changed:" + << m_settingsMonitor->titleBarFont().family() + << m_settingsMonitor->titleBarFont().pointSize(); m_titleBarFont.setFamily(m_settingsMonitor->titleBarFont().family()); m_titleBarFont.setPointSize(m_settingsMonitor->titleBarFont().pointSize()); @@ -207,10 +225,10 @@ void KiranTheme::handleTitleBarFontChanged() } } -void KiranTheme::handleScaleFactorChanged(int factor) +void Theme::handleScaleFactorChanged(int factor) { - qDebug(kiranPlatformTheme) << "scale factor changed:" - << m_settingsMonitor->scaleFactor(); + qDebug() << "scale factor changed:" + << m_settingsMonitor->scaleFactor(); // 缩放的话,同时也应该调整设置到窗口管理器的边缘阴影属性 if (enableRealTimeScaling()) @@ -225,7 +243,7 @@ void KiranTheme::handleScaleFactorChanged(int factor) } else if (factor == 1 || factor == 2) // 手动固定分辨率 { - qDebug(kiranPlatformTheme) << "update scale factor:" << factor; + qDebug() << "update scale factor:" << factor; if (qFuzzyCompare(QHighDpiScaling::m_factor, factor)) { return; @@ -282,24 +300,24 @@ void KiranTheme::handleScaleFactorChanged(int factor) } else { - qDebug(kiranPlatformTheme) << "not support this factor:" << factor; + qDebug() << "not support this factor:" << factor; return; } } else { - qDebug(kiranPlatformTheme) << "disable real time scaling,ignore scale factor changed!"; + qDebug() << "disable real time scaling,ignore scale factor changed!"; } } -void KiranTheme::handleCursorThemeChanged() +void Theme::handleCursorThemeChanged() { // 强制让窗口更新光标 QApplication::setOverrideCursor(QCursor()); QApplication::restoreOverrideCursor(); } -bool KiranTheme::enableRealTimeScaling() +bool Theme::enableRealTimeScaling() { static bool enable = !qEnvironmentVariableIsSet("QT_DEVICE_PIXEL_RATIO") && !qEnvironmentVariableIsSet("QT_SCALE_FACTOR") && @@ -311,7 +329,7 @@ bool KiranTheme::enableRealTimeScaling() return enable; } -void KiranTheme::handleScreenAdded(QScreen* screen) +void Theme::handleScreenAdded(QScreen* screen) { if (m_scaleFactor == 0) // 计算并自动调整该屏幕的缩放 { @@ -323,7 +341,7 @@ void KiranTheme::handleScreenAdded(QScreen* screen) } } -void KiranTheme::handleIconThemeChanged() +void Theme::handleIconThemeChanged() { qInfo() << "update icon theme:" << m_settingsMonitor->iconTheme(); QIconLoader::instance()->updateSystemTheme(); @@ -339,44 +357,53 @@ void KiranTheme::handleIconThemeChanged() } } -void KiranTheme::handleThemeChanged() +void Theme::handleThemeChanged() { - // NOTE: SchemeLoader会接收KiranAppearanceMonitor的GTK主题改变信号,重新加载配色方案 - // 此处只需等到下一个事件循环,通知QGuiApplication重新更新palette - - // clang-format off - QTimer::singleShot(0, [this] { - // 此事件会促使QGuiApplication重新从QPlatformTheme中获取系统级别的QPalette - QWindowSystemInterfacePrivate::ThemeChangeEvent event(nullptr); - - ///NOTE: - ///QGuiApplicationPrivate::processThemeChanged -> QGuiApplicationPrivate::notifyThemeChanged - ///5.11.1 - /// QGuiApplicationPrivate::notifyThemeChanged若非特殊设置过Palette,是直接清空QGuiApplicajtionPrivate::app_pal, - /// 然后重新从QPlatformTheme之中取出system palette,重新构建QGuiApplicajtionPrivate::app_pal - ///5.15.2 - /// QGuiApplicationPrivate::app_pal初始化 - /// 默认初始化一个QPalette,若QAGuiApplicationPrivate::app_pal不存在,则调用qpalette.cpp之中qt_palette_from_color构造一个 - /// QGuiApplicationPrivate::app_pal会采用上述的QPalette作为默认值 - /// - /// 后续调用processThemeChanged->updatePalette,都只是QGuiApplicationPrivate::app_pal从QPlatformTheme::palette(system)之中取出缺失的 - /// 所以QGuiApplicationPrivate::app_pal第一次初始化后,第一次主题应用能更新系统级别QPalette,但是之后主题变更应用不了 - - ///FIXME: - ///1.后续看是否有更好的方式能应用更新系统级别QPalette - ///2.加入判断是否外部自定义设置Application palette,若外部自定义设置了,则应不做处理 - - QPalette* oldPalette = nullptr; - oldPalette = QGuiApplicationPrivate::app_pal; - - QGuiApplicationPrivate::app_pal = new QPalette(*palette(SystemPalette)); - - if( oldPalette ) - delete oldPalette; - - // 该接口原本用于windows通知窗口主题变化时使用,现用来通知调用QGuiApplicationPrivate::notifyThemeChanged - QGuiApplicationPrivate::processThemeChanged(&event); - emit qApp->paletteChanged(*palette(SystemPalette)); - }); - // clang-format on + auto themeName = m_settingsMonitor->gtkTheme(); + + if (themeName.compare("kiran") == 0) + { + Kiran::Theme::Palette::getDefault()->setBaseColors(g_lightBaseColors); + } + else + { + Kiran::Theme::Palette::getDefault()->setBaseColors(g_darkBaseColors); + } + + QTimer::singleShot(0, [this] + { + // 此事件会促使QGuiApplication重新从QPlatformTheme中获取系统级别的QPalette + QWindowSystemInterfacePrivate::ThemeChangeEvent event(nullptr); + + ///NOTE: + ///QGuiApplicationPrivate::processThemeChanged -> QGuiApplicationPrivate::notifyThemeChanged + ///5.11.1 + /// QGuiApplicationPrivate::notifyThemeChanged若非特殊设置过Palette,是直接清空QGuiApplicajtionPrivate::app_pal, + /// 然后重新从QPlatformTheme之中取出system palette,重新构建QGuiApplicajtionPrivate::app_pal + ///5.15.2 + /// QGuiApplicationPrivate::app_pal初始化 + /// 默认初始化一个QPalette,若QAGuiApplicationPrivate::app_pal不存在,则调用qpalette.cpp之中qt_palette_from_color构造一个 + /// QGuiApplicationPrivate::app_pal会采用上述的QPalette作为默认值 + /// + /// 后续调用processThemeChanged->updatePalette,都只是QGuiApplicationPrivate::app_pal从QPlatformTheme::palette(system)之中取出缺失的 + /// 所以QGuiApplicationPrivate::app_pal第一次初始化后,第一次主题应用能更新系统级别QPalette,但是之后主题变更应用不了 + + ///FIXME: + ///1.后续看是否有更好的方式能应用更新系统级别QPalette + ///2.加入判断是否外部自定义设置Application palette,若外部自定义设置了,则应不做处理 + + QPalette* oldPalette = nullptr; + oldPalette = QGuiApplicationPrivate::app_pal; + + QGuiApplicationPrivate::app_pal = new QPalette(*palette(SystemPalette)); + + delete oldPalette; + + // 该接口原本用于windows通知窗口主题变化时使用,现用来通知调用QGuiApplicationPrivate::notifyThemeChanged + QGuiApplicationPrivate::processThemeChanged(&event); + emit qApp->paletteChanged(*palette(SystemPalette)); + }); } + +} // namespace Platformtheme +} // namespace Kiran \ No newline at end of file diff --git a/platformtheme/kiran-theme.h b/plugins/platformtheme/theme.h similarity index 75% rename from platformtheme/kiran-theme.h rename to plugins/platformtheme/theme.h index 243789c7ac52f70537e2bae1a13325e256366d9f..57981317488d8e88026c9f29f596063df1f84c25 100644 --- a/platformtheme/kiran-theme.h +++ b/plugins/platformtheme/theme.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. + * Copyright (c) 2023 ~ 2024 KylinSec Co., Ltd. * kiran-qt5-integration is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. * You may obtain a copy of Mulan PSL v2 at: @@ -9,21 +9,27 @@ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. * See the Mulan PSL v2 for more details. * - * Author: liuxinhao + * Author: tangjie02 */ -#ifndef KIRAN_QT5_PLATFORMTHEME_PLATFORMTHEME_KIRAN_THEME_H_ -#define KIRAN_QT5_PLATFORMTHEME_PLATFORMTHEME_KIRAN_THEME_H_ -#include -#include + +#pragma once + #include -class KiranAppearanceMonitor; -class KiranTheme : public QObject,public QGenericUnixTheme +class QScreen; + +namespace Kiran +{ +namespace Platformtheme +{ +class AppearanceMonitor; + +class Theme : public QObject, public QGenericUnixTheme { Q_OBJECT public: - explicit KiranTheme(const QStringList& paramList); - ~KiranTheme() override; + explicit Theme(const QStringList& paramList); + virtual ~Theme() override; //是否使用系统本地提示框 bool usePlatformNativeDialog(DialogType type) const override; @@ -53,10 +59,10 @@ private slots: void handleCursorThemeChanged(); private: - KiranAppearanceMonitor* m_settingsMonitor; + AppearanceMonitor* m_settingsMonitor; int m_scaleFactor; QFont m_systemFont; QFont m_titleBarFont; }; - -#endif //KIRAN_QT5_PLATFORMTHEME_PLATFORMTHEME_KIRAN_THEME_H_ +} // namespace Platformtheme +} // namespace Kiran diff --git a/plugins/platformtheme/themed-icon-engine.cpp b/plugins/platformtheme/themed-icon-engine.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a58429e6c609ebe1c046b165a9650a238293a13b --- /dev/null +++ b/plugins/platformtheme/themed-icon-engine.cpp @@ -0,0 +1,184 @@ +/** + * Copyright (c) 2020 ~ 2024 KylinSec Co., Ltd. + * svg-icon-switcher is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * + * Author: youzhengcai + */ + +#include "plugins/platformtheme/themed-icon-engine.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Kiran +{ +namespace Platformtheme +{ +ThemedIconEngine::ThemedIconEngine(const QString &themeSvgIconName) + : QIconEngine(), + m_iconName(themeSvgIconName) +{ + m_settingsMonitor = Kiran::Platformtheme::AppearanceMonitor::instance(); + QObject::connect(m_settingsMonitor, &Kiran::Platformtheme::AppearanceMonitor::gtkThemeChanged, [this](){ + changeSvgIconColor(); + }); +} + +ThemedIconEngine::~ThemedIconEngine() = default; + +bool ThemedIconEngine::isValid(const QString &themeSvgIconName) +{ + auto themeIconInfo = QIconLoader::instance()->loadIcon(themeSvgIconName); + + auto scalableSvgIcons = getScalableSvgIconFromTheme(themeSvgIconName); + return !scalableSvgIcons.isEmpty(); +} + +QSize ThemedIconEngine::actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state) +{ + auto pmckey = pixmapCacheKey(size, mode, state); + if (m_pixmapCache.contains(pmckey)) + { + QPixmap temp = m_pixmapCache.value(pmckey); + return temp.size(); + } + + auto pm = pixmap(size, mode, state); + if (pm.isNull()) + return {}; + + return pm.size(); +} + +QPixmap ThemedIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) +{ + ensureLoaded(); + auto pmckey = pixmapCacheKey(size, mode, state); + + QPixmap pm; + if (m_pixmapCache.contains(pmckey)) + { + QPixmap temp = m_pixmapCache.value(pmckey); + return temp; + } + + QSvgRenderer renderer(m_svgIconPath); + auto actualSize = renderer.defaultSize(); + QImage img(actualSize, QImage::Format_ARGB32_Premultiplied); + img.fill(0x00000000); + + QPainter p(&img); + renderer.render(&p); + + // Selected 状态下保持本色 + if (mode != QIcon::Selected) + { + m_svgColor = Kiran::Theme::Palette::getDefault()->getBaseColors().baseForeground; + p.setCompositionMode(QPainter::CompositionMode_SourceIn); + p.fillRect(QRect(0, 0, actualSize.width(), actualSize.height()), m_svgColor); + } + + p.end(); + pm = QPixmap::fromImage(img); + if (!pm.isNull()) + { + m_pixmapCache.insert(pmckey, pm); + } + return pm; +} + +void ThemedIconEngine::paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) +{ + ensureLoaded(); + + QSize pixmapSize = rect.size(); + if (painter->device()) + { + pixmapSize *= painter->device()->devicePixelRatioF(); + } + + painter->drawPixmap(rect, pixmap(pixmapSize,mode,state)); +} + +QIconEngine *ThemedIconEngine::clone() const +{ + return new ThemedIconEngine(*this); +} + +QByteArray ThemedIconEngine::pixmapCacheKey(const QSize &size, QIcon::Mode mode, QIcon::State state) +{ + QByteArray data; + QDataStream stream(&data, QIODevice::WriteOnly); + stream << m_iconName << size.width() << size.height() << mode << state; + return QCryptographicHash::hash(data, QCryptographicHash::Sha1); +} + +QStringList ThemedIconEngine::getScalableSvgIconFromTheme(const QString &iconName) +{ + QStringList res; + auto themeIconInfo = QIconLoader::instance()->loadIcon(iconName); + if (themeIconInfo.entries.isEmpty()) + { + return res; + } + + for (auto themeIconEntry : themeIconInfo.entries) + { + if ((themeIconEntry->dir.type == QIconDirInfo::Scalable) && + (themeIconEntry->filename.endsWith(".svg")) && (QFileInfo::exists(themeIconEntry->filename))) + { + res << themeIconEntry->filename; + } + } + + return res; +} + +void ThemedIconEngine::ensureLoaded() +{ + if (!(QIconLoader::instance()->themeKey() == m_iconLoaderThemeKey)) + { + qInfo() << "cache need update" << QIconLoader::instance()->themeKey() << "," << m_iconLoaderThemeKey; + m_svgIconPath.clear(); + m_pixmapCache.clear(); + + m_iconLoaderThemeKey = QIconLoader::instance()->themeKey(); + auto resList = getScalableSvgIconFromTheme(m_iconName); + + qInfo() << "update cache" << resList << "choose" << (resList.isEmpty() ? "null" : resList[0]); + if (!resList.isEmpty()) + { + m_svgIconPath = resList[0]; + } + } +} + +void ThemedIconEngine::changeSvgIconColor() +{ + // 清理图片缓存 + m_pixmapCache.clear(); + + // 通知所有窗口重绘制 + QEvent update(QEvent::UpdateRequest); + for (QWindow* window : qGuiApp->allWindows()) + { + if (window->type() == Qt::Desktop) + continue; + qApp->sendEvent(window, &update); + } +} +} // namespace Platformtheme +} // namespace Kiran diff --git a/plugins/platformtheme/themed-icon-engine.h b/plugins/platformtheme/themed-icon-engine.h new file mode 100644 index 0000000000000000000000000000000000000000..47038b12cb0374a65eead3f4426ae29f300bb668 --- /dev/null +++ b/plugins/platformtheme/themed-icon-engine.h @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2020 ~ 2024 KylinSec Co., Ltd. + * svg-icon-swithcer is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * + * Author: youzhengcai + */ +#pragma once + +#include +#include +#include +#include +#include +#include "lib/theme/palette.h" +#include "plugins/platformtheme/appearance-monitor.h" + +namespace Kiran +{ +namespace Platformtheme +{ +class ThemedIconEngine:public QIconEngine +{ +public: + explicit ThemedIconEngine(const QString& themeSvgIconName); + ~ThemedIconEngine() override; + + static bool isValid(const QString& themeSvgIconName); + QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state) override; + QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) override; + void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) override; + QIconEngine *clone() const override; + +private: + QByteArray pixmapCacheKey(const QSize &size, QIcon::Mode mode, QIcon::State state); + static QStringList getScalableSvgIconFromTheme(const QString& iconName); + void ensureLoaded(); + +private slots: + void changeSvgIconColor(); + +private: + QColor m_svgColor = Kiran::Theme::Palette::getDefault()->getBaseColors().baseForeground; + QString m_iconName; + QString m_svgIconPath; + + QMap m_pixmapCache; + + uint m_iconLoaderThemeKey = 0; + Platformtheme::AppearanceMonitor* m_settingsMonitor; +}; +} // namespace Platformtheme +} // namespace Kiran diff --git a/plugins/style/CMakeLists.txt b/plugins/style/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..ec007b89691a3258bb076233307268cda56febe1 --- /dev/null +++ b/plugins/style/CMakeLists.txt @@ -0,0 +1,15 @@ +set(TARGET_NAME "kiranstyle-next") + +file(GLOB_RECURSE SRC "*.cpp" "*.h" "*.ui") + +add_library(${TARGET_NAME} SHARED ${SRC}) + +target_include_directories( + ${TARGET_NAME} PRIVATE ${PROJECT_SOURCE_DIR} ${Qt5Svg_PRIVATE_INCLUDE_DIRS} + ${Qt5Widgets_PRIVATE_INCLUDE_DIRS}) + +target_link_libraries(${TARGET_NAME} kiran-integration-theme Qt5::Widgets lib-common + Qt5::DBus Qt5::Svg) + +# kiran style 插件 +install(TARGETS ${TARGET_NAME} DESTINATION ${QT5_STYLE_INSTALL_DIR}) diff --git a/style/src/kiran-style-plugin.cpp b/plugins/style/plugin.cpp similarity index 46% rename from style/src/kiran-style-plugin.cpp rename to plugins/style/plugin.cpp index 08eaae21d280d52daa4c35c196e4e915b9d65db6..846c39e2825b63396dd3f5a399ece95b426f852b 100644 --- a/style/src/kiran-style-plugin.cpp +++ b/plugins/style/plugin.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. + * Copyright (c) 2023 ~ 2024 KylinSec Co., Ltd. * kiran-qt5-integration is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. * You may obtain a copy of Mulan PSL v2 at: @@ -9,37 +9,42 @@ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. * See the Mulan PSL v2 for more details. * - * Author: liuxinhao + * Author: tangjie02 */ -#include "kiran-style-plugin.h" -#include "style.h" -#include "kiran-integration-settings.h" +#include "plugins/style/plugin.h" #include #include #include +#include "lib/common/configuration.h" +#include "lib/theme/style.h" -KiranStylePlugin::KiranStylePlugin(QObject *parent) : QStylePlugin(parent) +namespace Kiran +{ +namespace Style +{ +Plugin::Plugin(QObject *parent) : QStylePlugin(parent) { - } -QStyle *KiranStylePlugin::create(const QString & key) +QStyle *Plugin::create(const QString &key) { - if( key.compare("kiran",Qt::CaseInsensitive) == 0 ) + // 对比平台主题名称,若为匹配则应用 Kiran 主题 + if (key.compare("kiran-next", Qt::CaseInsensitive) == 0) { - auto processName = qAppName(); - bool enable = KiranIntegrationSettings::appKiranStyleAvailable(processName); - if( !enable ) + auto appName = qAppName(); + if (!Kiran::Configuration::instance()->match(appName)) { - qDebug("%s not enable kiran style,create fusion style for it.",processName.toStdString().c_str()); + qDebug("%s not enable kiran style, create fusion style for it.", appName.toStdString().c_str()); return QStyleFactory::create("fusion"); } else { - qDebug("create style:%s",key.toStdString().c_str()); - return new Style(); + qDebug("create style: %s", key.toStdString().c_str()); + return new Kiran::Theme::Style(); } } return nullptr; } +} // namespace Style +} // namespace Kiran \ No newline at end of file diff --git a/common/src/logging-category.h b/plugins/style/plugin.h similarity index 54% rename from common/src/logging-category.h rename to plugins/style/plugin.h index 676783e6b96154ce6728e841d2c689476149bcaa..4a4ca01b1e75236246a8b3a6f034a5f5a0b41065 100644 --- a/common/src/logging-category.h +++ b/plugins/style/plugin.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. + * Copyright (c) 2023 ~ 2024 KylinSec Co., Ltd. * kiran-qt5-integration is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. * You may obtain a copy of Mulan PSL v2 at: @@ -9,10 +9,25 @@ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. * See the Mulan PSL v2 for more details. * - * Author: liuxinhao + * Author: tangjie02 */ + #pragma once -#include +#include + +namespace Kiran +{ +namespace Style +{ +class Plugin : public QStylePlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QStyleFactoryInterface_iid FILE "plugin.json") -Q_DECLARE_LOGGING_CATEGORY(kiranPlatformThemeCommon) \ No newline at end of file +public: + explicit Plugin(QObject* parent = nullptr); + QStyle* create(const QString& key) override; +}; +} // namespace Style +} // namespace Kiran \ No newline at end of file diff --git a/plugins/style/plugin.json b/plugins/style/plugin.json new file mode 100644 index 0000000000000000000000000000000000000000..8b45d0cb368bacae9c9046125f5680be2896f507 --- /dev/null +++ b/plugins/style/plugin.json @@ -0,0 +1 @@ +{ "Keys": [ "kiran-next" ] } diff --git a/style-helper/data/images/arrow-down-disabled.svg b/resources/images/arrow-down-disabled.svg similarity index 100% rename from style-helper/data/images/arrow-down-disabled.svg rename to resources/images/arrow-down-disabled.svg diff --git a/style-helper/data/images/arrow-down.svg b/resources/images/arrow-down.svg similarity index 100% rename from style-helper/data/images/arrow-down.svg rename to resources/images/arrow-down.svg diff --git a/style-helper/data/images/arrow-left.png b/resources/images/arrow-left.png similarity index 100% rename from style-helper/data/images/arrow-left.png rename to resources/images/arrow-left.png diff --git a/style-helper/data/images/arrow-right-disabled.png b/resources/images/arrow-right-disabled.png similarity index 100% rename from style-helper/data/images/arrow-right-disabled.png rename to resources/images/arrow-right-disabled.png diff --git a/style-helper/data/images/arrow-right.png b/resources/images/arrow-right.png similarity index 100% rename from style-helper/data/images/arrow-right.png rename to resources/images/arrow-right.png diff --git a/style-helper/data/images/arrow-up.svg b/resources/images/arrow-up.svg similarity index 100% rename from style-helper/data/images/arrow-up.svg rename to resources/images/arrow-up.svg diff --git a/style-helper/data/images/arrow.svg b/resources/images/arrow.svg similarity index 100% rename from style-helper/data/images/arrow.svg rename to resources/images/arrow.svg diff --git a/style-helper/data/images/check-checked-active.svg b/resources/images/check-checked-active.svg similarity index 100% rename from style-helper/data/images/check-checked-active.svg rename to resources/images/check-checked-active.svg diff --git a/style-helper/data/images/check-checked-disabled.svg b/resources/images/check-checked-disabled.svg similarity index 100% rename from style-helper/data/images/check-checked-disabled.svg rename to resources/images/check-checked-disabled.svg diff --git a/style-helper/data/images/check-checked-hover.svg b/resources/images/check-checked-hover.svg similarity index 100% rename from style-helper/data/images/check-checked-hover.svg rename to resources/images/check-checked-hover.svg diff --git a/style-helper/data/images/check-checked-normal.svg b/resources/images/check-checked-normal.svg similarity index 100% rename from style-helper/data/images/check-checked-normal.svg rename to resources/images/check-checked-normal.svg diff --git a/style-helper/data/images/check-indeterminate-active.svg b/resources/images/check-indeterminate-active.svg similarity index 100% rename from style-helper/data/images/check-indeterminate-active.svg rename to resources/images/check-indeterminate-active.svg diff --git a/style-helper/data/images/check-indeterminate-disabled.svg b/resources/images/check-indeterminate-disabled.svg similarity index 100% rename from style-helper/data/images/check-indeterminate-disabled.svg rename to resources/images/check-indeterminate-disabled.svg diff --git a/style-helper/data/images/check-indeterminate-hover.svg b/resources/images/check-indeterminate-hover.svg similarity index 100% rename from style-helper/data/images/check-indeterminate-hover.svg rename to resources/images/check-indeterminate-hover.svg diff --git a/style-helper/data/images/check-indeterminate-normal.svg b/resources/images/check-indeterminate-normal.svg similarity index 100% rename from style-helper/data/images/check-indeterminate-normal.svg rename to resources/images/check-indeterminate-normal.svg diff --git a/style-helper/data/images/check-unchecked-active.svg b/resources/images/check-unchecked-active.svg similarity index 100% rename from style-helper/data/images/check-unchecked-active.svg rename to resources/images/check-unchecked-active.svg diff --git a/style-helper/data/images/check-unchecked-disabled.svg b/resources/images/check-unchecked-disabled.svg similarity index 100% rename from style-helper/data/images/check-unchecked-disabled.svg rename to resources/images/check-unchecked-disabled.svg diff --git a/style-helper/data/images/check-unchecked-hover.svg b/resources/images/check-unchecked-hover.svg similarity index 100% rename from style-helper/data/images/check-unchecked-hover.svg rename to resources/images/check-unchecked-hover.svg diff --git a/style-helper/data/images/check-unchecked-normal.svg b/resources/images/check-unchecked-normal.svg similarity index 100% rename from style-helper/data/images/check-unchecked-normal.svg rename to resources/images/check-unchecked-normal.svg diff --git a/style-helper/data/images/checkbox-checked.svg b/resources/images/checkbox-checked.svg similarity index 100% rename from style-helper/data/images/checkbox-checked.svg rename to resources/images/checkbox-checked.svg diff --git a/style-helper/data/images/checkbox-unchecked.svg b/resources/images/checkbox-unchecked.svg similarity index 100% rename from style-helper/data/images/checkbox-unchecked.svg rename to resources/images/checkbox-unchecked.svg diff --git a/style-helper/data/images/expander-collapsed.png b/resources/images/expander-collapsed.png similarity index 100% rename from style-helper/data/images/expander-collapsed.png rename to resources/images/expander-collapsed.png diff --git a/style-helper/data/images/expander-expanded.png b/resources/images/expander-expanded.png similarity index 100% rename from style-helper/data/images/expander-expanded.png rename to resources/images/expander-expanded.png diff --git a/style-helper/data/images/panel-grid-horizontal-symbolic.svg b/resources/images/panel-grid-horizontal-symbolic.svg similarity index 100% rename from style-helper/data/images/panel-grid-horizontal-symbolic.svg rename to resources/images/panel-grid-horizontal-symbolic.svg diff --git a/style-helper/data/images/panel-grid-vertical-symbolic.svg b/resources/images/panel-grid-vertical-symbolic.svg similarity index 100% rename from style-helper/data/images/panel-grid-vertical-symbolic.svg rename to resources/images/panel-grid-vertical-symbolic.svg diff --git a/style-helper/data/images/radio-checked-active.svg b/resources/images/radio-checked-active.svg similarity index 100% rename from style-helper/data/images/radio-checked-active.svg rename to resources/images/radio-checked-active.svg diff --git a/style-helper/data/images/radio-checked-disabled.svg b/resources/images/radio-checked-disabled.svg similarity index 100% rename from style-helper/data/images/radio-checked-disabled.svg rename to resources/images/radio-checked-disabled.svg diff --git a/style-helper/data/images/radio-checked-hover.svg b/resources/images/radio-checked-hover.svg similarity index 100% rename from style-helper/data/images/radio-checked-hover.svg rename to resources/images/radio-checked-hover.svg diff --git a/style-helper/data/images/radio-checked-normal.svg b/resources/images/radio-checked-normal.svg similarity index 100% rename from style-helper/data/images/radio-checked-normal.svg rename to resources/images/radio-checked-normal.svg diff --git a/style-helper/data/images/radio-selected.svg b/resources/images/radio-selected.svg similarity index 100% rename from style-helper/data/images/radio-selected.svg rename to resources/images/radio-selected.svg diff --git a/style-helper/data/images/radio-unchecked-active.svg b/resources/images/radio-unchecked-active.svg similarity index 100% rename from style-helper/data/images/radio-unchecked-active.svg rename to resources/images/radio-unchecked-active.svg diff --git a/style-helper/data/images/radio-unchecked-disabled.svg b/resources/images/radio-unchecked-disabled.svg similarity index 100% rename from style-helper/data/images/radio-unchecked-disabled.svg rename to resources/images/radio-unchecked-disabled.svg diff --git a/style-helper/data/images/radio-unchecked-hover.svg b/resources/images/radio-unchecked-hover.svg similarity index 100% rename from style-helper/data/images/radio-unchecked-hover.svg rename to resources/images/radio-unchecked-hover.svg diff --git a/style-helper/data/images/radio-unchecked-normal.svg b/resources/images/radio-unchecked-normal.svg similarity index 100% rename from style-helper/data/images/radio-unchecked-normal.svg rename to resources/images/radio-unchecked-normal.svg diff --git a/style-helper/data/images/scale-disabled.png b/resources/images/scale-disabled.png similarity index 100% rename from style-helper/data/images/scale-disabled.png rename to resources/images/scale-disabled.png diff --git a/style-helper/data/images/scale-normal.png b/resources/images/scale-normal.png similarity index 100% rename from style-helper/data/images/scale-normal.png rename to resources/images/scale-normal.png diff --git a/style-helper/data/images/scale-pressed.png b/resources/images/scale-pressed.png similarity index 100% rename from style-helper/data/images/scale-pressed.png rename to resources/images/scale-pressed.png diff --git a/style-helper/data/images/search-light.svg b/resources/images/search-light.svg similarity index 100% rename from style-helper/data/images/search-light.svg rename to resources/images/search-light.svg diff --git a/style-helper/data/images/search.svg b/resources/images/search.svg similarity index 100% rename from style-helper/data/images/search.svg rename to resources/images/search.svg diff --git a/style-helper/data/images/thumbnail.png b/resources/images/thumbnail.png similarity index 100% rename from style-helper/data/images/thumbnail.png rename to resources/images/thumbnail.png diff --git a/style-helper/data/images/window-close-symbolic.svg b/resources/images/window-close-symbolic.svg similarity index 100% rename from style-helper/data/images/window-close-symbolic.svg rename to resources/images/window-close-symbolic.svg diff --git a/style-helper/data/images/window-maximum-symbolic.svg b/resources/images/window-maximum-symbolic.svg similarity index 100% rename from style-helper/data/images/window-maximum-symbolic.svg rename to resources/images/window-maximum-symbolic.svg diff --git a/style-helper/data/images/window-minimum-symbolic.svg b/resources/images/window-minimum-symbolic.svg similarity index 100% rename from style-helper/data/images/window-minimum-symbolic.svg rename to resources/images/window-minimum-symbolic.svg diff --git a/style-helper/data/images/window-unmaximum-symbolic.svg b/resources/images/window-unmaximum-symbolic.svg similarity index 100% rename from style-helper/data/images/window-unmaximum-symbolic.svg rename to resources/images/window-unmaximum-symbolic.svg diff --git a/resources/style.qrc.in b/resources/style.qrc.in new file mode 100644 index 0000000000000000000000000000000000000000..70399bc94d7b42d98cd27a74b48a0219f596f3c6 --- /dev/null +++ b/resources/style.qrc.in @@ -0,0 +1,53 @@ + + + @KIRAN_DARK_COLORS@ + @KIRAN_LIGHT_COLORS@ + + + + @PROJECT_SOURCE_DIR@/resources/images/arrow.svg + @PROJECT_SOURCE_DIR@/resources/images/arrow-down.svg + @PROJECT_SOURCE_DIR@/resources/images/arrow-down-disabled.svg + @PROJECT_SOURCE_DIR@/resources/images/arrow-left.png + @PROJECT_SOURCE_DIR@/resources/images/arrow-right.png + @PROJECT_SOURCE_DIR@/resources/images/arrow-right-disabled.png + @PROJECT_SOURCE_DIR@/resources/images/arrow-up.svg + @PROJECT_SOURCE_DIR@/resources/images/checkbox-checked.svg + @PROJECT_SOURCE_DIR@/resources/images/checkbox-unchecked.svg + @PROJECT_SOURCE_DIR@/resources/images/check-checked-active.svg + @PROJECT_SOURCE_DIR@/resources/images/check-checked-disabled.svg + @PROJECT_SOURCE_DIR@/resources/images/check-checked-hover.svg + @PROJECT_SOURCE_DIR@/resources/images/check-checked-normal.svg + @PROJECT_SOURCE_DIR@/resources/images/check-indeterminate-active.svg + @PROJECT_SOURCE_DIR@/resources/images/check-indeterminate-disabled.svg + @PROJECT_SOURCE_DIR@/resources/images/check-indeterminate-hover.svg + @PROJECT_SOURCE_DIR@/resources/images/check-indeterminate-normal.svg + @PROJECT_SOURCE_DIR@/resources/images/check-unchecked-active.svg + @PROJECT_SOURCE_DIR@/resources/images/check-unchecked-disabled.svg + @PROJECT_SOURCE_DIR@/resources/images/check-unchecked-hover.svg + @PROJECT_SOURCE_DIR@/resources/images/check-unchecked-normal.svg + @PROJECT_SOURCE_DIR@/resources/images/expander-collapsed.png + @PROJECT_SOURCE_DIR@/resources/images/expander-expanded.png + @PROJECT_SOURCE_DIR@/resources/images/panel-grid-horizontal-symbolic.svg + @PROJECT_SOURCE_DIR@/resources/images/panel-grid-vertical-symbolic.svg + @PROJECT_SOURCE_DIR@/resources/images/radio-checked-active.svg + @PROJECT_SOURCE_DIR@/resources/images/radio-checked-disabled.svg + @PROJECT_SOURCE_DIR@/resources/images/radio-checked-hover.svg + @PROJECT_SOURCE_DIR@/resources/images/radio-checked-normal.svg + @PROJECT_SOURCE_DIR@/resources/images/radio-selected.svg + @PROJECT_SOURCE_DIR@/resources/images/radio-unchecked-active.svg + @PROJECT_SOURCE_DIR@/resources/images/radio-unchecked-disabled.svg + @PROJECT_SOURCE_DIR@/resources/images/radio-unchecked-hover.svg + @PROJECT_SOURCE_DIR@/resources/images/radio-unchecked-normal.svg + @PROJECT_SOURCE_DIR@/resources/images/scale-disabled.png + @PROJECT_SOURCE_DIR@/resources/images/scale-normal.png + @PROJECT_SOURCE_DIR@/resources/images/scale-pressed.png + @PROJECT_SOURCE_DIR@/resources/images/search.svg + @PROJECT_SOURCE_DIR@/resources/images/search-light.svg + @PROJECT_SOURCE_DIR@/resources/images/thumbnail.png + @PROJECT_SOURCE_DIR@/resources/images/window-close-symbolic.svg + @PROJECT_SOURCE_DIR@/resources/images/window-maximum-symbolic.svg + @PROJECT_SOURCE_DIR@/resources/images/window-minimum-symbolic.svg + @PROJECT_SOURCE_DIR@/resources/images/window-unmaximum-symbolic.svg + + diff --git a/style-helper/CMakeLists.txt b/style-helper/CMakeLists.txt deleted file mode 100644 index 004222a5ec761a7da6619ac16b5b9544bc581ac8..0000000000000000000000000000000000000000 --- a/style-helper/CMakeLists.txt +++ /dev/null @@ -1,75 +0,0 @@ -set(TARGET_NAME "kiran-style-helper") - -set(KIRAN_STYLE_HELPER_VERSION 2.3.0) -set(KIRAN_STYLE_HELPER_SO_VERSION 2) - -# light theme -set(KIRAN_LIGHT_COLORS ${CMAKE_CURRENT_BINARY_DIR}/kiran-light/kiran-light-colors.css) -add_custom_command( - OUTPUT ${KIRAN_LIGHT_COLORS} - COMMAND ./build-qt-theme.sh - -c data/color-scheme/light.colors - -b data/color-scheme/base.colors - -t kiran-light - -d ${CMAKE_CURRENT_BINARY_DIR}/kiran-light - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} -) - -# dark theme -set(KIRAN_DARK_COLORS ${CMAKE_CURRENT_BINARY_DIR}/kiran-dark/kiran-dark-colors.css) -add_custom_command( - OUTPUT ${KIRAN_DARK_COLORS} - COMMAND ./build-qt-theme.sh - -c data/color-scheme/dark.colors - -b data/color-scheme/base.colors - -t kiran-dark - -d ${CMAKE_CURRENT_BINARY_DIR}/kiran-dark - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} -) - -set(KIRANSTYLE_HELPER_QRC ${CMAKE_CURRENT_BINARY_DIR}/kiranstyle-helper.qrc) -configure_file(kiranstyle-helper.qrc.in ${KIRANSTYLE_HELPER_QRC}) - -message("${CMAKE_CURRENT_SOURCE_DIR}") -find_package(Qt5 COMPONENTS Core Gui Widgets) -file(GLOB_RECURSE SRC "src/*.cpp" "src/*.h" "src/*.ui") -file(GLOB_RECURSE INCLUDE "include/*.h") - -set(CMAKE_AUTOMOC ON) -set(CMAKE_AUTOUIC ON) -set(CMAKE_AUTORCC ON) - -add_library(${TARGET_NAME} SHARED - ${SRC} - ${KIRANSTYLE_HELPER_QRC} - ${INCLUDE} - ${KIRAN_DARK_COLORS} - ${KIRAN_LIGHT_COLORS}) - -set_target_properties(${TARGET_NAME} PROPERTIES - VERSION ${KIRAN_STYLE_HELPER_VERSION} - SOVERSION ${KIRAN_STYLE_HELPER_SO_VERSION}) - -target_include_directories(${TARGET_NAME} PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/src - ${CMAKE_CURRENT_BINARY_DIR} - ${Qt5Gui_PRIVATE_INCLUDE_DIRS}) - -target_include_directories(${TARGET_NAME} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/include) - -target_link_libraries(${TARGET_NAME} - common - Qt5::Core - Qt5::Gui - Qt5::Widgets) - -set(KIRAN_STYLE_HELPER_LIB_DIR ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/) -install(TARGETS ${TARGET_NAME} DESTINATION ${KIRAN_STYLE_HELPER_LIB_DIR}) - -set(KIRAN_STYLE_HELPER_INCLUDE_DIR ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/kiran-style) -install(FILES ${INCLUDE} DESTINATION ${KIRAN_STYLE_HELPER_INCLUDE_DIR}) - -configure_file(kiran-style-helper.pc.in kiran-style-helper.pc @ONLY) -install(FILES ${CMAKE_CURRENT_BINARY_DIR}/kiran-style-helper.pc - DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/pkgconfig/) \ No newline at end of file diff --git a/style-helper/build-qt-theme.sh b/style-helper/build-qt-theme.sh deleted file mode 100755 index 3d4b43526cec973ff114498a017e49e6f219f006..0000000000000000000000000000000000000000 --- a/style-helper/build-qt-theme.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/bin/bash -#该脚本主要负责: -# 1. 调用python脚本根据colors描述文件提取相应的颜色信息并进行相应的颜色转换(ColorEffect)到_global.scss -# 2. 通过sassc将该项目中内置的scss与_global.scss,_functions.scss生成对应的颜色表一起转换至css之中 - -set -e - -# Usage: render_theme -# example: render_theme dark.colors base.colors /tmp/dark/ dark -render_theme () { - # step-1: 提取colorscheme与base-colorscheme颜色表中所定义的数据提取到generate-dir下的_global.scss之中 - python3 extract_color_from_scheme.py -c "$1" -b "$2" -d "$3" - # step-2: 通过sassc将项目内置的scss与_global.scss,functions.scss转换为一个新的css文件 - sassc -I "$3" ./data/qt5.scss "$3/$4-colors.css" -} - -COLOR_SCHEME_FILE="" -BASE_SCHEME_FILE="" -THEME_NAME="" -THEME_BUILD_DIR="" - -while [ "$#" -gt 0 ]; do - case "$1" in - -h|--help) - echo "help" - echo "$0: build kiran qt theme" - echo "Usage: $0 .." - exit 0 - ;; - -c|--color-scheme-file) - shift - COLOR_SCHEME_FILE="$1" - ;; - -b|--base-scheme-file) - shift - BASE_SCHEME_FILE="$1" - ;; - -t|--theme-name) - shift - THEME_NAME="$1" - ;; - -d|--dest-dir) - shift - THEME_BUILD_DIR="$1" - ;; - esac - shift -done - -render_theme "${COLOR_SCHEME_FILE}" "${BASE_SCHEME_FILE}" "${THEME_BUILD_DIR}" "${THEME_NAME}" - diff --git a/style-helper/data/_colors-public.scss b/style-helper/data/_colors-public.scss deleted file mode 100644 index 83323e6d7b610ba6d43dbbf56157695c412e9b75..0000000000000000000000000000000000000000 --- a/style-helper/data/_colors-public.scss +++ /dev/null @@ -1,131 +0,0 @@ -@charset "UTF-8"; - -//apps rely on some named colors to be exported -/* GTK NAMED COLORS - ---------------- - use responsibly! */ - - -//changed!!! -@define-color theme_selected_background_normal #{"" + internal_selection(background)}; -@define-color theme_selected_foreground_normal #{"" + internal_selection(foreground)}; -@define-color theme_selected_background_insensitive #{"" + internal_insensitive(internal_selection(background))}; -@define-color theme_selected_foreground_insensitive #{"" + internal_insensitive(internal_selection(foreground))}; -@define-color theme_selected_background_backdrop #{"" + internal_backdrop(internal_selection(background))}; -@define-color theme_selected_foreground_backdrop #{"" + internal_backdrop(internal_selection(foreground))}; - -// Sass thinks we're using the colors in the variables as strings and may shoot -// warning, it's innocuous and can be defeated by using "" + $var -/* --------------------------------------------------------------- Default Colors --------------------------------------------------------------- */ -@define-color theme_default_background_normal #{"" + internal_default(background)}; -@define-color theme_default_background_insensitive #{"" + internal_insensitive(internal_default(background))}; -@define-color theme_default_background_backdrop #{"" + internal_backdrop(internal_default(background))}; -@define-color theme_default_background_backdrop_insensitive #{"" + internal_insensitive(internal_backdrop(internal_default(background)))}; -@define-color theme_default_foreground_normal #{"" + internal_default(foreground)}; -@define-color theme_default_foreground_insensitive #{"" + internal_insensitive(internal_default(foreground))}; -@define-color theme_default_foreground_backdrop #{"" + internal_backdrop(internal_default(foreground))}; -@define-color theme_default_foreground_backdrop_insensitive #{"" + internal_insensitive(internal_backdrop(internal_default(foreground)))}; -@define-color theme_default_border_normal #{"" + internal_default(border)}; -@define-color theme_default_border_insensitive #{"" + internal_insensitive(internal_default(border))}; -@define-color theme_default_border_backdrop #{"" + internal_backdrop(internal_default(border))}; -@define-color theme_default_border_backdrop_insensitive #{"" + internal_insensitive(internal_backdrop(internal_default(border)))}; -@define-color theme_default_warning #{"" + internal_default(warning)}; -@define-color theme_default_warning_backdrop #{"" + internal_backdrop(internal_default(warning))}; -@define-color theme_default_error #{"" + internal_default(error)}; -@define-color theme_default_error_backdrop #{"" + internal_backdrop(internal_default(error))}; -@define-color theme_default_success #{"" + internal_default(success)}; -@define-color theme_default_success_backdrop #{"" + internal_backdrop(internal_default(success))}; -@define-color theme_default_bulk #{"" + internal_default(bulk)}; - -/* these are pretty self explicative */ -@define-color warning_color #{"" +internal_default(warning)}; -@define-color error_color #{"" +internal_default(error)}; -@define-color success_color #{"" +internal_default(success)}; - - -/* --------------------------------------------------------------- Widget Colors --------------------------------------------------------------- */ -@define-color theme_widget_background_normal #{"" + internal_widget(background)}; -@define-color theme_widget_background_hover #{"" + internal_widget(background-hover)}; -@define-color theme_widget_background_active #{"" + internal_widget(background-active)}; -@define-color theme_widget_background_checked #{"" + internal_widget(background-checked)}; -@define-color theme_widget_background_insensitive #{"" + internal_insensitive(internal_widget(background))}; -@define-color theme_widget_background_backdrop #{"" + internal_backdrop(internal_widget(background))}; -@define-color theme_widget_background_backdrop_checked #{"" + internal_backdrop(internal_widget(background-checked))}; -@define-color theme_widget_background_backdrop_insensitive #{"" + internal_insensitive(internal_backdrop(internal_widget(background)))}; -@define-color theme_widget_foreground_normal #{"" + internal_widget(foreground)}; -@define-color theme_widget_foreground_hover #{"" + internal_widget(foreground-hover)}; -@define-color theme_widget_foreground_active #{"" + internal_widget(foreground-active)}; -@define-color theme_widget_foreground_checked #{"" + internal_widget(foreground-checked)}; -@define-color theme_widget_foreground_insensitive #{"" + internal_insensitive(internal_widget(foreground))}; -@define-color theme_widget_foreground_backdrop #{"" + internal_backdrop(internal_widget(foreground))}; -@define-color theme_widget_foreground_backdrop_checked #{"" + internal_backdrop(internal_widget(foreground-checked))}; -@define-color theme_widget_foreground_backdrop_insensitive #{"" + internal_insensitive(internal_backdrop(internal_widget(foreground)))}; -@define-color theme_widget_border_normal #{"" + internal_widget(border)}; -@define-color theme_widget_border_hover #{"" + internal_widget(border-hover)}; -@define-color theme_widget_border_focus #{"" + internal_widget(border-focus)}; -@define-color theme_widget_border_insensitive #{"" + internal_insensitive(internal_widget(border))}; -@define-color theme_widget_border_backdrop #{"" + internal_backdrop(internal_widget(border))}; -@define-color theme_widget_border_backdrop_insensitive #{"" + internal_insensitive(internal_backdrop(internal_widget(border)))}; - - -/* --------------------------------------------------------------- Bare Colors --------------------------------------------------------------- */ -@define-color theme_bare_background_normal #{"" + internal_bare(background)}; -@define-color theme_bare_background_hover #{"" + internal_bare(background-hover)}; -@define-color theme_bare_background_active #{"" + internal_bare(background-active)}; -@define-color theme_bare_background_checked #{"" + internal_bare(background-checked)}; -@define-color theme_bare_background_insensitive #{"" + internal_insensitive(internal_bare(background))}; -@define-color theme_bare_background_backdrop #{"" + internal_backdrop(internal_bare(background))}; -@define-color theme_bare_background_backdrop_checked #{"" + internal_backdrop(internal_bare(background-checked))}; -@define-color theme_bare_background_backdrop_insensitive #{"" + internal_insensitive(internal_backdrop(internal_bare(background)))}; -@define-color theme_bare_foreground_normal #{"" + internal_bare(foreground)}; -@define-color theme_bare_foreground_hover #{"" + internal_bare(foreground-hover)}; -@define-color theme_bare_foreground_active #{"" + internal_bare(foreground-active)}; -@define-color theme_bare_foreground_checked #{"" + internal_bare(foreground-checked)}; -@define-color theme_bare_foreground_insensitive #{"" + internal_insensitive(internal_bare(foreground))}; -@define-color theme_bare_foreground_backdrop #{"" + internal_backdrop(internal_bare(foreground))}; -@define-color theme_bare_foreground_backdrop_checked #{"" + internal_backdrop(internal_bare(foreground-checked))}; -@define-color theme_bare_foreground_backdrop_insensitive #{"" + internal_insensitive(internal_backdrop(internal_bare(foreground)))}; - -/* --------------------------------------------------------------- Window Colors --------------------------------------------------------------- */ -@define-color theme_window_background_normal #{"" + internal_window(background)}; -@define-color theme_window_background_insensitive #{"" + internal_insensitive(internal_window(background))}; -@define-color theme_window_background_backdrop #{"" + internal_backdrop(internal_window(background))}; -@define-color theme_window_background_backdrop_insensitive #{"" + internal_insensitive(internal_backdrop(internal_window(background)))}; -@define-color theme_window_foreground_normal #{"" + internal_window(foreground)}; -@define-color theme_window_foreground_insensitive #{"" + internal_insensitive(internal_window(foreground))}; -@define-color theme_window_foreground_backdrop #{"" + internal_backdrop(internal_window(foreground))}; -@define-color theme_window_foreground_backdrop_insensitive #{"" + internal_insensitive(internal_backdrop(internal_window(foreground)))}; -@define-color theme_window_border_normal #{"" + internal_window(border)}; -@define-color theme_window_border_insensitive #{"" + internal_insensitive(internal_window(border))}; -@define-color theme_window_border_backdrop #{"" + internal_backdrop(internal_window(border))}; -@define-color theme_window_border_backdrop_insensitive #{"" + internal_insensitive(internal_backdrop(internal_window(border)))}; - -/* --------------------------------------------------------------- View Colors --------------------------------------------------------------- */ -@define-color theme_view_background_normal #{"" + internal_view(background)}; -@define-color theme_view_background_insensitive #{"" + internal_insensitive(internal_view(background))}; -@define-color theme_view_background_backdrop #{"" + internal_backdrop(internal_view(background))}; -@define-color theme_view_background_backdrop_insensitive #{"" + internal_insensitive(internal_backdrop(internal_view(background)))}; -@define-color theme_view_foreground_normal #{"" + internal_view(foreground)}; -@define-color theme_view_foreground_insensitive #{"" + internal_insensitive(internal_view(foreground))}; -@define-color theme_view_foreground_backdrop #{"" + internal_backdrop(internal_view(foreground))}; -@define-color theme_view_foreground_backdrop_insensitive #{"" + internal_insensitive(internal_backdrop(internal_view(foreground)))}; -@define-color theme_view_border_normal #{"" + internal_view(border)}; -@define-color theme_view_border_focus #{"" + internal_view(border-focus)}; -@define-color theme_view_border_insensitive #{"" + internal_insensitive(internal_view(border))}; -@define-color theme_view_border_backdrop #{"" + internal_backdrop(internal_view(border))}; -@define-color theme_view_border_backdrop_insensitive #{"" + internal_insensitive(internal_backdrop(internal_view(border)))}; - - -/* -------------------------------------------------------------- Titlebar Colors -------------------------------------------------------------- */ -@define-color theme_titlebar_background_normal #{"" + internal_titlebar(background)}; -@define-color theme_titlebar_background_insensitive #{"" + internal_insensitive(internal_titlebar(background))}; -@define-color theme_titlebar_background_backdrop #{"" + internal_backdrop(internal_titlebar(background))}; -@define-color theme_titlebar_background_backdrop_insensitive #{"" + internal_insensitive(internal_backdrop(internal_titlebar(background)))}; -@define-color theme_titlebar_foreground_normal #{"" + internal_titlebar(foreground)}; -@define-color theme_titlebar_foreground_insensitive #{"" + internal_insensitive(internal_titlebar(foreground))}; -@define-color theme_titlebar_foreground_backdrop #{"" + internal_backdrop(internal_titlebar(foreground))}; -@define-color theme_titlebar_foreground_backdrop_insensitive #{"" + internal_insensitive(internal_backdrop(internal_titlebar(foreground)))}; -@define-color theme_titlebar_border_normal #{"" + internal_titlebar(border)}; -@define-color theme_titlebar_border_insensitive #{"" + internal_insensitive(internal_titlebar(border))}; -@define-color theme_titlebar_border_backdrop #{"" + internal_backdrop(internal_titlebar(border))}; -@define-color theme_titlebar_border_backdrop_insensitive #{"" + internal_insensitive(internal_backdrop(internal_titlebar(border)))}; diff --git a/style-helper/data/_functions.scss b/style-helper/data/_functions.scss deleted file mode 100644 index ffaa78bd421c51b66404e5d0a40f57361bdf72cf..0000000000000000000000000000000000000000 --- a/style-helper/data/_functions.scss +++ /dev/null @@ -1,414 +0,0 @@ -@charset "UTF-8"; - -// GTK functions - -// escape string entirely -@function gtk($str) { - @return unquote("#{$str}"); -} - -// alpha function -@function gtkalpha($c, $a) { - @return unquote("alpha(#{$c},#{$a})"); -} - -// shade function -@function gtkshade($c, $a) { - @return unquote("shade(#{$c},#{$a})"); -} - -// mix function -@function gtkmix($c1, $c2, $m) { - @return unquote("mix(#{$c1},#{$c2},#{$m})"); -} - -// -// Theme color functions -// - -// Default Color -@function internal_default($c: background) { - @if $c == background { - @return $DefaultBackgroundNormal; - } - @if $c == foreground { - @return $DefaultForegroundNormal; - } - @if $c == border { - @return $DefaultBorder; - } - @if $c == warning { - @return $DefaultWarning; - } - @if $c == error { - @return $DefaultError; - } - @if $c == success { - @return $DefaultSuccess; - } - @if $c ==bulk { - @return $DefaultBulk; - } - @if $c == link { - @return $DefaultLink; - } - @if $c == link-visited { - @return $DefaultLinkVisited; - } -} - -// Widget Color -@function internal_widget($c: background) { - @if $c == background { - @return $WidgetBackgroundNormal; - } - @if $c == foreground { - @return $WidgetForegroundNormal; - } - @if $c == background-hover { - @return $WidgetBackgroundHover; - } - @if $c == background-active { - @return $WidgetBackgroundActive; - } - @if $c == background-checked { - @return $WidgetBackgroundChecked; - } - @if $c == foreground-hover { - @return $WidgetForegroundHover; - } - @if $c == foreground-active { - @return $WidgetForegroundActive; - } - @if $c == foreground-checked { - @return $WidgetForegroundChecked; - } - @if $c == border { - @return $WidgetBorderNormal; - } - @if $c == border-hover { - @return $WidgetBorderHover; - } - @if $c == border-focus { - @return $WidgetBorderFocus; - } -} - -// Bare(No border) Widget Color -@function internal_bare($c: background) { - @if $c == background { - @return $BareBackgroundNormal; - } - @if $c == foreground { - @return $BareForegroundNormal; - } - @if $c == background-hover { - @return $BareBackgroundHover; - } - @if $c == background-active { - @return $BareBackgroundActive; - } - @if $c == background-checked { - @return $BareBackgroundChecked; - } - @if $c == foreground-hover { - @return $BareForegroundHover; - } - @if $c == foreground-active { - @return $BareForegroundActive; - } - @if $c == foreground-checked { - @return $BareForegroundChecked; - } -} - -// Selection Color -@function internal_selection($c: background) { - @if $c == background { - @return $SelectionBackgroundNormal; - } - @if $c == foreground { - @return $SelectionForegroundNormal; - } - @if $c == hover { - @return $SelectionDecorationHover; - } - @if $c == backdrop { - @return transparentize($SelectionBackgroundNormal, 0.5); - } -} - -// View Color -@function internal_view($c: background) { - @if $c == background { - @return $ViewBackgroundNormal; - } - @if $c == foreground { - @return $ViewForegroundNormal; - } - @if $c == border { - @return $ViewBorderNormal; - } - @if $c == border-focus { - @return $ViewBorderFocus; - } - -} - -// Window Color -@function internal_window($c: background) { - @if $c == background { - @return $WindowBackgroundNormal; - } - @if $c == background-hover { - @return $WindowBackgroundHover; - } - @if $c == foreground { - @return $WindowForegroundNormal; - } - @if $c == border { - @return $WindowBorderNormal; - } -} - -// Titlebar color -@function internal_titlebar($c: foreground) { - @if $c == foreground { - @return $WMForegroundNormal; - } - @if $c == background { - @return $WMBackgroundNormal; - } - @if $c == border { - @return $WMBorderNormal; - } -} - -@function internal_tooltip($c: foreground) { - @if $c == foreground { - @return $TooltipForegroundNormal; - } - @if $c == background { - @return $TooltipBackgroundNormal; - } - @if $c == border { - @return mix($TooltipForegroundNormal, $TooltipBackgroundNormal, 25%); - } -} - -@function internal_button_gradient($c, $state: background) { - @if $state == background { - @return linear-gradient( - to bottom, - change-color($c, $lightness: min(lightness($c) * 1.01, 100%)), - change-color($c, $lightness: min(lightness($c) / 1.03, 100%)) - ); - } @else { - @return linear-gradient( - to bottom, - change-color($c, $lightness: min(lightness($c) * 1.03, 100%)), - change-color($c, $lightness: min(lightness($c) / 1.1, 100%)) - ); - } -} - -@function internal_special_button($c: color) { - @if $c == default { - @return $SpecialButtonDefaultNormal; - } - @if $c == default-hover { - @return $SpecialButtonDefaultHover; - } - @if $c == default-active { - @return $SpecialButtonDefaultActive; - } - @if $c == warnning { - @return $SpecialButtonWarnningNormal; - } - @if $c == warnning-hover { - @return $SpecialButtonWarnningHover; - } - @if $c == warnning-active { - @return $SpecialButtonWarnningActive; - } -} - -$border_color: mix($WindowBackgroundNormal, $WindowForegroundNormal, 75%); -$menu_color: internal_window(background); - -$arrow_down: 'go-down-symbolic'; -$arrow_left: 'go-previous-symbolic'; -$arrow_right: 'go-next-symbolic'; -$arrow_up: 'go-up-symbolic'; - -$trough_color: gtkmix(gtk("@theme_bg_color"), gtk("@theme_fg_color"), 0.7); -$trough_color_backdrop: gtkmix( - gtk("@theme_unfocused_bg_color"), - gtk("@theme_unfocused_fg_color"), - 0.7 -); -$trough_color_insensitive: gtkmix( - gtk("@insensitive_bg_color"), - gtk("@insensitive_fg_color"), - 0.7 -); -$trough_color_backdrop_insensitive: gtkmix( - gtk("@insensitive_unfocused_bg_color"), - gtk("@insensitive_unfocused_fg_color"), - 0.7 -); - -$scrollbar_color: gtkmix($trough_color, gtk("@theme_text_color"), 0.5); -$scrollbar_color_backdrop: gtkmix( - $trough_color_backdrop, - gtk("@theme_unfocused_text_color"), - 0.5 -); - -// -// Color effects -// -// -// Color maps for color effect functions -// -$Color: ( - Disabled: $DisabledColor, - Inactive: $InactiveColor, -); -$ColorAmount: ( - Disabled: $DisabledColorAmount, - Inactive: $InactiveColorAmount, -); -$ColorEffect: ( - Disabled: $DisabledColorEffect, - Inactive: $InactiveColorEffect, -); -$ContrastAmount: ( - Disabled: $DisabledContrastAmount, - Inactive: $InactiveContrastAmount, -); -$ContrastEffect: ( - Disabled: $DisabledContrastEffect, - Inactive: $InactiveContrastEffect, -); -$IntensityAmount: ( - Disabled: $DisabledIntensityAmount, - Inactive: $InactiveIntensityAmount, -); -$IntensityEffect: ( - Disabled: $DisabledIntensityEffect, - Inactive: $InactiveIntensityEffect, -); - -$r: 3px; // standard radius - -@function internal_insensitive($c) { - @return internal_Color( - internal_Intensity(internal_Contrast($c, Disabled), Disabled), - Disabled - ); -} - -@function internal_backdrop($c) { - @if $InactiveEnable == True { - @return internal_Color( - internal_Intensity(internal_Contrast($c, Inactive), Inactive), - Inactive - ); - } @else { - @return $c; - } -} - -@function internal_Contrast($c, $state) { - @if map-get($ContrastEffect, $state) == 0 { - @return $c; - } - - @if map-get($ContrastEffect, $state) == 1 or map-get($ContrastEffect, $state) ==2 { - @if lightness(internal_window()) > lightness(internal_window(foreground)) { - @if lightness($c) < lightness(internal_window()) or - ($c == internal_titlebar(foreground) and lightness(internal_titlebar(background)) <= lightness(internal_titlebar(foreground))) - { - @return transparentize($c, map-get($ContrastAmount, $state)); - } @else { - @return $c; - } - } - @if lightness(internal_window()) <= lightness(internal_window(foreground)) { - @if lightness($c) > lightness(internal_window()) or - ($c == internal_titlebar(foreground) and lightness(internal_titlebar(background)) > lightness(internal_titlebar(foreground))) - { - @return transparentize($c, map-get($ContrastAmount, $state)); - } @else { - @return $c; - } - } - } -} - -@function internal_Color($c, $state) { - @if map-get($ColorEffect, $state) ==0 { - @return $c; - } - - @if map-get($ColorEffect, $state) ==1 { - @if map-get($ColorAmount, $state) >=0 { - @return desaturate($c, percentage(map-get($ColorAmount, $state))); - } @else { - @return saturate($c, percentage(abs(map-get($ColorAmount, $state)))); - } - } - - @if map-get($ColorEffect, $state) ==2 or map-get($ColorEffect, $state) ==3 { - // 2 and 3 seem to do the same - @return mix( - map-get($Color, $state), - $c, - percentage(map-get($ColorAmount, $state)) - ); - } -} - -@function internal_Intensity($c, $state) { - @if map-get($IntensityEffect, $state) == 0 { - @return $c; - } - @if map-get($IntensityEffect, $state) == 1 { - @if map-get($IntensityAmount, $state) >= 0 { - @return mix(white, $c, percentage(map-get($IntensityAmount, $state))); - } @else { - @return mix( - black, - $c, - percentage(abs(map-get($IntensityAmount, $state))) - ); - } - } - - @if map-get($IntensityEffect, $state) == 2 { - @if map-get($IntensityAmount, $state) == -1 { - @return change-color($c, $lightness: 100%); - } @else { - @return change-color( - $c, - $lightness: - min(lightness($c) / (1 + map-get($IntensityAmount, $state)), 100%) - ); - } - } - - @if map-get($IntensityEffect, $state) == 3 { - @return change-color( - $c, - $lightness: - min(lightness($c) * (1 + map-get($IntensityAmount, $state)), 100%) - ); - } -} - -@function internal_alpha2solid($c, $background) { - $amount: alpha($c); - $c: rgb(red($c), green($c), blue($c)); - @return mix($c, $background, $amount); -} \ No newline at end of file diff --git a/style-helper/data/color-scheme/base.colors b/style-helper/data/color-scheme/base.colors deleted file mode 100644 index 3b616342810e1c1a286d8c190abe4b402b2359c6..0000000000000000000000000000000000000000 --- a/style-helper/data/color-scheme/base.colors +++ /dev/null @@ -1,8 +0,0 @@ -[Global:Radius] -SLittle=2px -Little=4px -Middle=6px -Big=8px -SBig=10px -SSBig=12px -Menu=8px \ No newline at end of file diff --git a/style-helper/data/color-scheme/dark.colors b/style-helper/data/color-scheme/dark.colors deleted file mode 100644 index 5054755a727247fcc3490e30f7e93d1f03fb2958..0000000000000000000000000000000000000000 --- a/style-helper/data/color-scheme/dark.colors +++ /dev/null @@ -1,86 +0,0 @@ -[ColorEffects:Disabled] -Color=56,56,56 -ColorAmount=0 -ColorEffect=0 -ContrastAmount=0.65 -ContrastEffect=1 -IntensityAmount=0.1 -IntensityEffect=2 - -[ColorEffects:Inactive] -ChangeSelectionColor=true -Color=112,111,110 -ColorAmount=0.1 -ColorEffect=2 -ContrastAmount=0.05 -ContrastEffect=2 -Enable=true -IntensityAmount=0 -IntensityEffect=0 - -[Colors:Default] -BackgroundNormal=0x222222 -ForegroundNormal=0xFFFFFF -BareNormal=0x595959 -Border=0x454545 -Bulk=0x2d2d2d -Selection=0x2EB3FF -Warning=0xFA4949 -Error=0xCC0000 -Success=darken(0x73D216, 0.1) -Link=lighten(Default::Selection, 0.1) -LinkVisited=lighten(Default::Selection, 0.2) - -[Colors:Widget] -BackgroundNormal=0x393939 -ForegroundNormal=Default::ForegroundNormal -BackgroundHover=mix(Widget::BackgroundNormal, Widget::ForegroundNormal, 0.9) -BackgroundActive=mix(Widget::BackgroundNormal, Widget::ForegroundNormal, 0.8) -BackgroundChecked=Default::Selection -ForegroundHover=mix(Widget::BackgroundNormal, Widget::ForegroundNormal, 0.3) -ForegroundActive=mix(Widget::BackgroundNormal, Widget::ForegroundNormal, 0.4) -ForegroundChecked=Default::Selection -BorderNormal=Default::Border -BorderHover=mix(Widget::BorderNormal, Widget::ForegroundNormal, 0.3) -BorderFocus=Default::Selection - -[Colors:Bare] -BackgroundNormal=Default::BareNormal -ForegroundNormal=Default::ForegroundNormal -BackgroundHover=mix(Bare::BackgroundNormal, Bare::ForegroundNormal, 0.9) -BackgroundActive=mix(Bare::BackgroundNormal, Bare::ForegroundNormal, 0.8) -BackgroundChecked=Default::Selection -ForegroundHover=mix(Bare::BackgroundNormal, Bare::ForegroundNormal, 0.3) -ForegroundActive=mix(Bare::BackgroundNormal, Bare::ForegroundNormal, 0.4) -ForegroundChecked=Default::Selection - -[Colors:Window] -BackgroundNormal=Default::BackgroundNormal -ForegroundNormal=Default::ForegroundNormal -BorderNormal=Default::Border -BackgroundHover=mix(Window::BackgroundNormal, Window::ForegroundNormal, 0.9) - -[Colors:Selection] -BackgroundNormal=Default::Selection -ForegroundNormal=Default::ForegroundNormal - -[Colors:View] -BackgroundNormal=Default::BackgroundNormal -ForegroundNormal=Default::ForegroundNormal -BorderNormal=Default::Border -BorderFocus=Default::Selection - - -[WM] -BackgroundNormal=Default::BackgroundNormal -BackgroundBackdrop=0x2a2a2a -ForegroundNormal=Default::ForegroundNormal -BorderNormal=Default::Border - -[Colors:SpecialButton] -DefaultNormal=Default::Selection -DefaultHover=mix(Default::Selection, Default::ForegroundNormal, 0.9) -DefaultActive=mix(Default::Selection, Default::ForegroundNormal,0.8) -WarnningNormal=Default::Error -WarnningHover=mix(Default::Error, Default::ForegroundNormal,0.9) -WarnningActive=mix(Default::Error, Default::ForegroundNormal,0.8) \ No newline at end of file diff --git a/style-helper/data/color-scheme/light.colors b/style-helper/data/color-scheme/light.colors deleted file mode 100644 index a9ac842ae191fe661dbfd3283e4cc662da2340ea..0000000000000000000000000000000000000000 --- a/style-helper/data/color-scheme/light.colors +++ /dev/null @@ -1,87 +0,0 @@ -[ColorEffects:Disabled] -Color=56,56,56 -ColorAmount=0 -ColorEffect=0 -ContrastAmount=0.65 -ContrastEffect=1 -IntensityAmount=0.1 -IntensityEffect=2 - -[ColorEffects:Inactive] -ChangeSelectionColor=true -Color=112,111,110 -ColorAmount=0.1 -ColorEffect=2 -ContrastAmount=0.05 -ContrastEffect=2 -Enable=true -IntensityAmount=0 -IntensityEffect=0 - -[Colors:Default] -BackgroundNormal=0xe8e8e8 -ForegroundNormal=0x222222 -BareNormal=0xCCCCCC -Border=0xCCCCCC -Bulk=0xffffff -Selection=0x2EB3FF -Warning=0xFA4949 -Error=0xCC0000 -Success=0x73D216 -Link=darken(Default::Selection, 0.1) -LinkVisited=darken(Default::Selection, 0.2) - -[Colors:Widget] -BackgroundNormal=0xefefef -ForegroundNormal=Default::ForegroundNormal -BackgroundHover=mix(Widget::BackgroundNormal, Widget::ForegroundNormal, 0.9) -BackgroundActive=mix(Widget::BackgroundNormal, Widget::ForegroundNormal, 0.8) -BackgroundChecked=Default::Selection -ForegroundHover=mix(Widget::BackgroundNormal, Widget::ForegroundNormal, 0.3) -ForegroundActive=mix(Widget::BackgroundNormal, Widget::ForegroundNormal, 0.4) -ForegroundChecked=Default::Selection -BorderNormal=Default::Border -BorderHover=mix(Widget::BorderNormal, Widget::ForegroundNormal, 0.3) -BorderFocus=Default::Selection - -[Colors:Bare] -BackgroundNormal=Default::BareNormal -ForegroundNormal=Default::ForegroundNormal -BackgroundHover=mix(Bare::BackgroundNormal, Bare::ForegroundNormal, 0.9) -BackgroundActive=mix(Bare::BackgroundNormal, Bare::ForegroundNormal, 0.8) -BackgroundChecked=Default::Selection -ForegroundHover=mix(Bare::BackgroundNormal, Bare::ForegroundNormal, 0.3) -ForegroundActive=mix(Bare::BackgroundNormal, Bare::ForegroundNormal, 0.4) -ForegroundChecked=Default::Selection - -[Colors:Window] -BackgroundNormal=Default::BackgroundNormal -ForegroundNormal=Default::ForegroundNormal -BorderNormal=Default::Border -BackgroundHover=mix(Window::BackgroundNormal, Window::ForegroundNormal, 0.9) -BackgroundAlternate=227,229,231 - -[Colors:Selection] -BackgroundNormal=Default::Selection -ForegroundNormal=Default::ForegroundNormal - - -[Colors:View] -BackgroundNormal=Default::BackgroundNormal -ForegroundNormal=Default::ForegroundNormal -BorderNormal=Default::Border -BorderFocus=Default::Selection - -[WM] -BackgroundNormal=Default::BackgroundNormal -BackgroundBackdrop=0xf1f1f1 -ForegroundNormal=Default::ForegroundNormal -BorderNormal=Default::Border - -[Colors:SpecialButton] -DefaultNormal=Default::Selection -DefaultHover=mix(Default::Selection, Default::ForegroundNormal, 0.9) -DefaultActive=mix(Default::Selection, Default::ForegroundNormal,0.8) -WarnningNormal=Default::Error -WarnningHover=mix(Default::Error, Default::ForegroundNormal,0.9) -WarnningActive=mix(Default::Error, Default::ForegroundNormal,0.8) \ No newline at end of file diff --git a/style-helper/data/qt5.scss b/style-helper/data/qt5.scss deleted file mode 100644 index 35e2be1e51ffb925dcda54c8f724a7d1c35a0b3a..0000000000000000000000000000000000000000 --- a/style-helper/data/qt5.scss +++ /dev/null @@ -1,493 +0,0 @@ -@import "global"; -@import "functions"; - -// default -$default_background_normal: #{"" + internal_default(background)}; -$default_background_insensitive: #{"" + internal_insensitive(internal_default(background))}; -$default_background_backdrop: #{"" + internal_backdrop(internal_default(background))}; -$default_background_backdrop_insensitive: #{"" + internal_insensitive(internal_backdrop(internal_default(background)))}; -$default_foreground_normal: #{"" + internal_default(foreground)}; -$default_foreground_insensitive: #{"" + internal_insensitive(internal_default(foreground))}; -$default_foreground_backdrop: #{"" + internal_backdrop(internal_default(foreground))}; -$default_foreground_backdrop_insensitive: #{"" + internal_insensitive(internal_backdrop(internal_default(foreground)))}; -$default_border_normal: #{"" + internal_default(border)}; -$default_border_insensitive: #{"" + internal_insensitive(internal_default(border))}; -$default_border_backdrop: #{"" + internal_backdrop(internal_default(border))}; -$default_border_backdrop_insensitive: #{"" + internal_insensitive(internal_backdrop(internal_default(border)))}; -$default_warning: #{"" + internal_default(warning)}; -$default_warning_backdrop: #{"" + internal_backdrop(internal_default(warning))}; -$default_error: #{"" + internal_default(error)}; -$default_error_backdrop: #{"" + internal_backdrop(internal_default(error))}; -$default_success: #{"" + internal_default(success)}; -$default_success_backdrop: #{"" + internal_backdrop(internal_default(success))}; -$default_bulk: #{"" + internal_default(bulk)}; - -// selection -$selection_background_normal: #{"" + internal_selection(background)}; -$selection_foreground_normal: #{"" + internal_selection(foreground)}; -$selection_background_insensitive: #{"" + internal_insensitive(internal_selection(background))}; -$selection_foreground_insensitive: #{"" + internal_insensitive(internal_selection(foreground))}; -$selection_background_backdrop: #{"" + internal_backdrop(internal_selection(background))}; -$selection_foreground_backdrop: #{"" + internal_backdrop(internal_selection(foreground))}; - -// widget -$widget_background_normal: #{"" + internal_widget(background)}; -$widget_background_hover: #{"" + internal_widget(background-hover)}; -$widget_background_active: #{"" + internal_widget(background-active)}; -$widget_background_checked: #{"" + internal_widget(background-checked)}; -$widget_background_insensitive: #{"" + internal_insensitive(internal_widget(background))}; -$widget_background_backdrop: #{"" + internal_backdrop(internal_widget(background))}; -$widget_background_backdrop_checked: #{"" + internal_backdrop(internal_widget(background-checked))}; -$widget_background_backdrop_insensitive: #{"" + internal_insensitive(internal_backdrop(internal_widget(background)))}; -$widget_foreground_normal: #{"" + internal_widget(foreground)}; -$widget_foreground_hover: #{"" + internal_widget(foreground-hover)}; -$widget_foreground_active: #{"" + internal_widget(foreground-active)}; -$widget_foreground_checked: #{"" + internal_widget(foreground-checked)}; -$widget_foreground_insensitive: #{"" + internal_insensitive(internal_widget(foreground))}; -$widget_foreground_backdrop: #{"" + internal_backdrop(internal_widget(foreground))}; -$widget_foreground_backdrop_checked: #{"" + internal_backdrop(internal_widget(foreground-checked))}; -$widget_foreground_backdrop_insensitive: #{"" + internal_insensitive(internal_backdrop(internal_widget(foreground)))}; -$widget_border_normal: #{"" + internal_widget(border)}; -$widget_border_hover: #{"" + internal_widget(border-hover)}; -$widget_border_focus: #{"" + internal_widget(border-focus)}; -$widget_border_insensitive: #{"" + internal_insensitive(internal_widget(border))}; -$widget_border_backdrop: #{"" + internal_backdrop(internal_widget(border))}; -$widget_border_backdrop_insensitive: #{"" + internal_insensitive(internal_backdrop(internal_widget(border)))}; - -// bare -$bare_background_normal: #{"" + internal_bare(background)}; -$bare_background_hover: #{"" + internal_bare(background-hover)}; -$bare_background_active: #{"" + internal_bare(background-active)}; -$bare_background_checked: #{"" + internal_bare(background-checked)}; -$bare_background_insensitive: #{"" + internal_insensitive(internal_bare(background))}; -$bare_background_backdrop: #{"" + internal_backdrop(internal_bare(background))}; -$bare_background_backdrop_checked: #{"" + internal_backdrop(internal_bare(background-checked))}; -$bare_background_backdrop_insensitive: #{"" + internal_insensitive(internal_backdrop(internal_bare(background)))}; -$bare_foreground_normal: #{"" + internal_bare(foreground)}; -$bare_foreground_hover: #{"" + internal_bare(foreground-hover)}; -$bare_foreground_active: #{"" + internal_bare(foreground-active)}; -$bare_foreground_checked: #{"" + internal_bare(foreground-checked)}; -$bare_foreground_insensitive: #{"" + internal_insensitive(internal_bare(foreground))}; -$bare_foreground_backdrop: #{"" + internal_backdrop(internal_bare(foreground))}; -$bare_foreground_backdrop_checked: #{"" + internal_backdrop(internal_bare(foreground-checked))}; -$bare_foreground_backdrop_insensitive: #{"" + internal_insensitive(internal_backdrop(internal_bare(foreground)))}; - -// window -$window_background_normal: #{"" + internal_window(background)}; -$window_background_hover: #{"" + internal_window(background-hover)}; -$window_background_insensitive: #{"" + internal_insensitive(internal_window(background))}; -$window_background_backdrop: #{"" + internal_backdrop(internal_window(background))}; -$window_background_backdrop_insensitive: #{"" + internal_insensitive(internal_backdrop(internal_window(background)))}; -$window_foreground_normal: #{"" + internal_window(foreground)}; -$window_foreground_insensitive: #{"" + internal_insensitive(internal_window(foreground))}; -$window_foreground_backdrop: #{"" + internal_backdrop(internal_window(foreground))}; -$window_foreground_backdrop_insensitive: #{"" + internal_insensitive(internal_backdrop(internal_window(foreground)))}; -$window_border_normal: #{"" + internal_window(border)}; -$window_border_insensitive: #{"" + internal_insensitive(internal_window(border))}; -$window_border_backdrop: #{"" + internal_backdrop(internal_window(border))}; -$window_border_backdrop_insensitive: #{"" + internal_insensitive(internal_backdrop(internal_window(border)))}; - -// view -$view_background_normal: #{"" + internal_view(background)}; -$view_background_insensitive: #{"" + internal_insensitive(internal_view(background))}; -$view_background_backdrop: #{"" + internal_backdrop(internal_view(background))}; -$view_background_backdrop_insensitive: #{"" + internal_insensitive(internal_backdrop(internal_view(background)))}; -$view_foreground_normal: #{"" + internal_view(foreground)}; -$view_foreground_insensitive: #{"" + internal_insensitive(internal_view(foreground))}; -$view_foreground_backdrop: #{"" + internal_backdrop(internal_view(foreground))}; -$view_foreground_backdrop_insensitive: #{"" + internal_insensitive(internal_backdrop(internal_view(foreground)))}; -$view_border_normal: #{"" + internal_view(border)}; -$view_border_focus: #{"" + internal_view(border-focus)}; -$view_border_insensitive: #{"" + internal_insensitive(internal_view(border))}; -$view_border_backdrop: #{"" + internal_backdrop(internal_view(border))}; -$view_border_backdrop_insensitive: #{"" + internal_insensitive(internal_backdrop(internal_view(border)))}; - -// title bar -$titlebar_background_normal: #{"" + internal_titlebar(background)}; -$titlebar_background_insensitive: #{"" + internal_insensitive(internal_titlebar(background))}; -$titlebar_background_backdrop: #{"" + internal_backdrop(internal_titlebar(background))}; -$titlebar_background_backdrop_insensitive: #{"" + internal_insensitive(internal_backdrop(internal_titlebar(background)))}; -$titlebar_foreground_normal: #{"" + internal_titlebar(foreground)}; -$titlebar_foreground_insensitive: #{"" + internal_insensitive(internal_titlebar(foreground))}; -$titlebar_foreground_backdrop: #{"" + internal_backdrop(internal_titlebar(foreground))}; -$titlebar_foreground_backdrop_insensitive: #{"" + internal_insensitive(internal_backdrop(internal_titlebar(foreground)))}; -$titlebar_border_normal: #{"" + internal_titlebar(border)}; -$titlebar_border_insensitive: #{"" + internal_insensitive(internal_titlebar(border))}; -$titlebar_border_backdrop: #{"" + internal_backdrop(internal_titlebar(border))}; -$titlebar_border_backdrop_insensitive: #{"" + internal_insensitive(internal_backdrop(internal_titlebar(border)))}; - -// flags -$special_button_default_normal: #{"" + internal_special_button(default)}; -$special_button_default_hover: #{"" + internal_special_button(default-hover)}; -$special_button_default_active: #{"" + internal_special_button(default-active)}; -$special_button_default_insensitive: #{"" + internal_insensitive(internal_widget(background))}; - -$special_button_warnning_normal: #{"" + internal_special_button(warnning)}; -$special_button_warnning_hover: #{"" + internal_special_button(warnning-hover)}; -$special_button_warnning_active: #{"" + internal_special_button(warnning-active)}; -$special_button_warnning_insensitive: #{"" + internal_insensitive(internal_widget(background))}; - -// === Flag === -//NOTE:此处需要修改,.colors之中定义的Success为绿色,应该是错误的,而且其他类型也并未有其他状态的值 -Flag { - Warning: $default_warning; - Error: $default_error; - Success: $default_success; -} - -// === QPalette-兼容QPalette === -Palette:active { - Window: $window_background_normal; - WindowText: $window_foreground_normal; - - Base: $view_background_normal; - Text: $view_foreground_normal; - - Button: $widget_background_normal; - ButtonText: $widget_foreground_normal; - - Highlight: $selection_background_normal; - //HighlightedText: $selection_foreground_normal; - HighlightedText: #ffffff; - - ToolTipBase: $window_background_normal; - ToolTipText: $window_foreground_normal; -} - -//QPalette inacitve窗口的调色盘,暂时未使用 -Palette { - Window: $window_background_backdrop; - WindowText: $window_foreground_backdrop; - - Base: $view_background_backdrop; - Text: $view_foreground_backdrop; - - Button: $widget_background_backdrop; - ButtonText: $widget_foreground_backdrop; - - Highlight: $selection_background_backdrop; - HighlightedText: $selection_foreground_backdrop; - - ToolTipBase: $window_background_backdrop; - ToolTipText: $window_foreground_backdrop; -} - -Palette:disabled { - Window: $window_background_insensitive; - WindowText: $window_foreground_insensitive; - - Base: $view_background_insensitive; - Text: $view_foreground_insensitive; - - Button: $widget_background_insensitive; - ButtonText: $widget_foreground_insensitive; - - Highlight: $selection_background_insensitive; - HighlightedText: $selection_foreground_insensitive; - - ToolTipBase: $window_background_insensitive; - ToolTipText: $window_foreground_insensitive; -} - -// === Window === -Window { - Background: $window_background_normal; - Foreground: $window_foreground_normal; - Border: $window_border_normal; -} - -Window:hover { - Background: $window_background_hover; -} - -Window:disabled { - Background: $window_background_insensitive; - Foreground: $window_foreground_insensitive; - Border: $window_border_insensitive; -} - -// === Bare === -Bare { - Background: $bare_background_normal; - Foreground: $bare_foreground_normal; -} - -Bare:pressed { - Background: $bare_background_active; - Foreground: $bare_foreground_active; -} - -Bare:hover { - Background: $bare_background_hover; - Foreground: $bare_foreground_hover; -} - -Bare:checked { - Background: $bare_background_checked; - Foreground: $bare_foreground_checked; -} - -Bare:disabled { - Background: $bare_background_insensitive; - Foreground: $bare_foreground_insensitive; -} - -// === widget === -Widget { - Background: $widget_background_normal; - Foreground: $widget_foreground_normal; - Border: $widget_border_normal; -} - -Widget:hover { - Background: $widget_background_hover; - Foreground: $widget_foreground_hover; - //Border: $widget_border_hover; -} - -Widget:pressed { - Background: $widget_background_active; - Foreground: $widget_foreground_active; - Border: $widget_border_focus; -} - -Widget:checked, -Widget:selected { - Background: $widget_background_checked; - Foreground: $widget_foreground_checked; - Border: $widget_border_focus; -} - -Widget:disabled { - Background: $widget_background_insensitive; - Foreground: $widget_foreground_insensitive; - Border: $widget_border_insensitive; -} - -// === view === -View { - Background: $view_background_normal; - Foreground: $view_foreground_normal; - Border: $view_border_normal; -} - -View:focus { - Border: $view_border_focus; -} - -View:disabled { - Background: $view_background_insensitive; - Foreground: $view_foreground_insensitive; - Border: $view_border_insensitive; -} - -// === selection === -Selection { - Background: $selection_background_normal; - Foreground: $selection_foreground_normal; -} - -Selection:disabled { - Background: $selection_background_insensitive; - Foreground: $selection_foreground_insensitive; -} - -// === title bar === -TitleBar { - Background: $titlebar_background_normal; - Foreground: $titlebar_foreground_normal; - Border: $titlebar_border_normal; -} - -TitleBar:disabled { - Background: $titlebar_background_insensitive; - Foreground: $titlebar_foreground_insensitive; - Border: $titlebar_border_insensitive; -} - - -/** --- 提供给KiranStyle直接使用的相关属性 --- **/ -Frame { - Background: $window_background_normal; - Border: $window_border_normal; -} - -Frame:disabled { - Background: $window_background_insensitive; - Border: $window_border_insensitive; -} - -Button { - Background: $widget_background_normal; - Border: $widget_border_normal; -} - -Button:hover { - Background: $widget_background_hover; -} - -Button:pressed { - Background: $widget_background_active; -} - -Button:disabled { - Background: $widget_background_insensitive; - Border: $widget_border_insensitive; -} - -SpecialButton { - DefaultBackground: $special_button_default_normal; - WarnningBackground: $special_button_warnning_normal; -} - -SpecialButton:hover { - DefaultBackground: $special_button_default_hover; - WarnningBackground: $special_button_warnning_hover; -} - -SpecialButton:pressed { - DefaultBackground: $special_button_default_active; - WarnningBackground: $special_button_warnning_active; -} - -SpecialButton:disabled { - DefaultBackground: $special_button_default_insensitive; - WarnningBackground: $special_button_warnning_insensitive; -} - -Edit { - Background: $widget_background_normal; - Foreground: $view_foreground_normal; - Border: $view_border_normal; -} - -Edit:focus { - Border: $view_border_focus; -} - -Edit:disabled { - Background: $widget_background_insensitive; - Border: transparent; -} - -Indicator { - Arrow: $widget_foreground_normal; -} - -Indicator:disabled { - Arrow: $widget_foreground_insensitive; -} - -Combo { - Background: $widget_background_normal; - Border: $widget_border_normal; -} - -Combo:hover { - Background: $widget_background_hover; -} - -Combo:pressed { - Background: $widget_background_active; -} - -Combo:disabled { - Background: $widget_background_insensitive; - Border: transparent; -} - -ItemView { - Branch: $widget_border_normal; -} - -ItemView:disabled { - Branch: $widget_border_insensitive; -} - -MenuBar { - ItemBackground: $window_background_normal; - EmptyAreaBackground: $window_background_normal; -} - -MenuBar:hover { - ItemBackground: $widget_background_hover; -} - -MenuBar:pressed { - ItemBackground: $widget_background_active; -} - -MenuBar:disabled { - ItemBackground: $window_background_insensitive; - EmptyAreaBackground: $window_background_insensitive; -} - -Progress { - Groove: $bare_background_normal; - Content: $bare_foreground_checked; -} - -Progress:disabled { - Groove: $bare_background_insensitive; - Content: $bare_foreground_insensitive; -} - -Scroll { - Slider: $bare_background_normal; -} - -Scroll:hover { - Slider: $bare_background_hover; -} - -Scroll:pressed { - Slider: $bare_background_checked; -} - -Scroll:disabled { - Slider: $bare_background_insensitive; -} - -Slider { - Groove: $bare_background_normal; - Content: $bare_foreground_checked; - HandleBorder: white; - HandleBackground: $bare_foreground_checked; -} - -Slider:pressed { - HandleBorder: white; - HandleBackground: white; -} - -Slider:disabled { - Groove: $bare_background_insensitive; - Content: $bare_foreground_insensitive; - HandleBorder: $bare_foreground_insensitive; - HandleBackground: $bare_foreground_insensitive; -} - -SpinBox { - Background: $widget_background_normal; - Border: $widget_border_normal; - SignColor: $widget_foreground_normal; -} - -SpinBox:hover { - Background: $widget_background_hover; - Border: $widget_border_hover; -} - -SpinBox:pressed { - Background: $widget_background_active; -} - -SpinBox:disabled { - Background: $widget_background_insensitive; - Border: transparent; - SignColor: $widget_foreground_insensitive; -} - -Bulk { - Background: $default_bulk -} \ No newline at end of file diff --git a/style-helper/extract_color_from_scheme.py b/style-helper/extract_color_from_scheme.py deleted file mode 100644 index f52ff4b4e43d3404fcda8675e9eecfbe6fca9b8d..0000000000000000000000000000000000000000 --- a/style-helper/extract_color_from_scheme.py +++ /dev/null @@ -1,253 +0,0 @@ -import os -import argparse -import sys -import cairo -import re -import colorsys - -def make_sure_path_exists(path): - try: - os.makedirs(path) - except FileExistsError as exception: - pass - pass - -class ReadGlobals(): - def __init__(self,base_file_name): - self._colors = {} - self._colors = self.read_globals(base_file_name) - - def read_globals(self,filename): - with open(filename,'r',encoding="utf-8") as lines: - while True: - prefix_name = str() - for line in lines: - match_groups = re.search('([a-zA-Z]+)\]$', line) - prefixs = ['Radius', 'Disabled', 'Inactive', 'Default', 'Widget', 'Bare', 'Window', 'Selection', 'View', 'WM','SpecialButton'] - if match_groups != None and len(match_groups.groups()) == 1 and match_groups.groups()[0] in prefixs: - prefix_name = match_groups.groups()[0] - break - if len(prefix_name) == 0: - break - - for line in lines: - if line == '\n': - break - key = '{0}{1}'.format(prefix_name, line.strip().split('=')[0]) - value = line.strip().split('=')[1] - if value == '': - continue - self._colors[key] = self.trans_value(value) - return self._colors - - def _get_function_args(self, func_expr): - args = list() - cur_index = func_expr.find('(') - while cur_index != -1: - last_index = func_expr.find(',', cur_index + 1) - if last_index == -1: - last_index = func_expr.find(')', cur_index + 1) - - if last_index != -1 and last_index > cur_index + 1: - arg = func_expr[cur_index + 1:last_index].strip() - if len(arg) > 0: - args.append(arg) - - cur_index = last_index - return args - - def trans_value(self, value): - # function - if str.startswith(value, 'lighten'): - color, amount = self._get_function_args(value) - color = Color.int_to_rgb(self.trans_value(color)) - return Color.rgb_to_int(Color.lighter(color, float(amount))) - elif str.startswith(value, 'darken'): - color, amount = self._get_function_args(value) - color = Color.int_to_rgb(self.trans_value(color)) - return Color.rgb_to_int(Color.darker(color, float(amount))) - elif str.startswith(value, 'mix'): - color1, color2, weight = self._get_function_args(value) - color1 = Color.int_to_rgb(self.trans_value(color1)) - color2 = Color.int_to_rgb(self.trans_value(color2)) - return Color.rgb_to_int(Color.mix(color1, color2, float(weight))) - elif str.endswith(value, 'px'): - return value - # bool value - elif value.lower() == 'true' or value.lower() == 'false': - return bool(value) - # variable - elif not re.match('^\d', value): - return self._colors[value.replace(':', '')] - # float value - elif value.find('.') != -1: - return float(value) - # color value - elif value.find(',') != -1: - r = int(value.split(',')[0], 0) - g = int(value.split(',')[1], 0) - b = int(value.split(',')[2], 0) - return Color.rgb255_to_int((r, g, b)) - # integer value - else: - return int(value, 0) -class Color(object): - def __init__(self, colordict, name, name2=None, amount=0): - color = colordict[name] - self.colordict = colordict - - r, g, b = Color.int_to_rgb255(color) - if name2 is not None: - color2 = colordict[name2] - r2, g2, b2 = Color.int_to_rgb255(color2) - r = r * amount + float(r2) * (1 - amount) - g = g * amount + float(g2) * (1 - amount) - b = b * amount + float(b2) * (1 - amount) - - self.rgb255 = (int(r), int(g), int(b)) - self.rgb = (r / 255, g / 255, b / 255) - self.html = '#%02x%02x%02x' % self.rgb255 - self.insensitive = self._color_effect(self._intensity_effect(self.rgb, 'Disabled'), 'Disabled') - self.insensitive_alpha = self._contrast_effect(self.rgb, 'Disabled') - - if not self.colordict['InactiveEnable']: - self.inactive = self.rgb - self.inactive_alpha = 1.0 - else: - self.inactive = self._color_effect(self._intensity_effect(self.rgb, 'Inactive'), 'Inactive') - self.inactive_alpha = self._contrast_effect(self.rgb, 'Inactive') - self.inactive_insensitive = self._color_effect(self._intensity_effect(self.inactive, 'Disabled'), 'Disabled') - self.inactive_insensitive_alpha = max(self.inactive_alpha - (1 - self.insensitive_alpha), 0) - - @staticmethod - def int_to_rgb255(num): - r = ((num >> 16) & 0xff) - g = ((num >> 8) & 0xff) - b = (num & 0xff) - return (r, g, b) - - @staticmethod - def int_to_rgb(num): - r = float((num >> 16) & 0xff) / 255 - g = float((num >> 8) & 0xff) / 255 - b = float(num & 0xff) / 255 - return (r, g, b) - - @staticmethod - def rgb_to_int(rgb): - return (int(rgb[0] * 255) << 16) + (int(rgb[1] * 255) << 8) + int(rgb[2] * 255) - - @staticmethod - def rgb255_to_int(rgb): - return (rgb[0] << 16) + (rgb[1] << 8) + rgb[2] - - @staticmethod - def mix(color, mix_color, amount): - r = color[0] * amount + mix_color[0] * (1 - amount) - g = color[1] * amount + mix_color[1] * (1 - amount) - b = color[2] * amount + mix_color[2] * (1 - amount) - return (r, g, b) - - @staticmethod - def lighter(color, amount): - h, s, v = colorsys.rgb_to_hsv(color[0], color[1], color[2]) - v = min((1 + amount) * v, 1) - r, g, b = colorsys.hsv_to_rgb(h, s, v) - return (r, g, b) - - @staticmethod - def darker(color, amount): - h, s, v = colorsys.rgb_to_hsv(color[0], color[1], color[2]) - if amount == -1: - v = 1 - else: - v = min(v / (1 + amount), 1) - r, g, b = colorsys.hsv_to_rgb(h, s, v) - return (r, g, b) - - @staticmethod - def desaturate(color, amount): - h, s, v = colorsys.rgb_to_hsv(color[0], color[1], color[2]) - s = min(s * (1 - amount), 1) - r, g, b = colorsys.hsv_to_rgb(h, s, v) - return (r, g, b) - - def _intensity_effect(self, color, state): - effect = int(self.colordict[state + 'IntensityEffect']) - amount = float(self.colordict[state + 'IntensityAmount']) - if effect == 0: - (r, g, b) = color - elif effect == 1: - if amount >= 0: - (r, g, b) = self.mix((1.0, 1.0, 1.0), color, amount) - else: - (r, g, b) = self.mix((0.0, 0.0, 0.0), color, amount) - elif effect == 2: - (r, g, b) = self.darker(color, amount) - elif effect == 3: - (r, g, b) = self.lighter(color, amount) - return (r, g, b) - - def _color_effect(self, color, state): - effect = int(self.colordict[state + 'ColorEffect']) - amount = float(self.colordict[state + 'ColorAmount']) - effect_color = self.int_to_rgb(self.colordict[state + 'Color']) - if effect == 0: - (r, g, b) = color - elif effect == 1: - (r, g, b) = self.desaturate(color, amount) - else: - (r, g, b) = self.mix(effect_color, color, amount) - return (r, g, b) - - def _contrast_effect(self, color, state): - effect = int(self.colordict[state + 'ContrastEffect']) - amount = float(self.colordict[state + 'ContrastAmount']) - if effect == 0: - return 1.0 - else: - return 1.0 - amount - - def lighten_color(self, amount): - h, s, v = colorsys.rgb_to_hsv(self.rgb[0], self.rgb[1], self.rgb[2]) - v = (1 + amount) * v - r, g, b = colorsys.hsv_to_rgb(h, s, v) - self.rgb = (r, g, b) - self.rgb255 = (int(r * 255), int(g * 255), int(b * 255)) - - def gradient(self, state='', alpha=1.0): - if state == 'active': - stop1 = self.lighter(self.rgb, 0.03) - stop2 = self.darker(self.rgb, 0.10) - linear = cairo.LinearGradient(1, 1, 1, 19) - linear.add_color_stop_rgba(0.0, stop1[0], stop1[1], stop1[2], alpha) - linear.add_color_stop_rgba(1.0, stop2[0], stop2[1], stop2[2], alpha) - else: - stop1 = self.lighter(self.rgb, 0.01) - stop2 = self.darker(self.rgb, 0.03) - linear = cairo.LinearGradient(1, 1, 1, 19) - linear.add_color_stop_rgba(0.0, stop1[0], stop1[1], stop1[2], alpha) - linear.add_color_stop_rgba(1.0, stop2[0], stop2[1], stop2[2], alpha) - return linear -# ___________________________________________________________________________________ -parser = argparse.ArgumentParser(description='Generates Kiran assets according to the specified color ' 'scheme.') -parser.add_argument('--colorscheme', '-c', action='store', help='color scheme to use') -parser.add_argument('--basecolorscheme', '-b', action='store', help='base color scheme') -parser.add_argument('--generate-dir', '-d', action='store', help='generate color directory') - -args = parser.parse_args() - -generate_path = args.generate_dir -make_sure_path_exists(generate_path) - -_colors = ReadGlobals(args.basecolorscheme).read_globals(args.colorscheme) - -globalScss = open(os.path.join(generate_path, '_global.scss'), 'w') -for key in sorted(_colors): - if key == 'DisabledColor' or key == 'InactiveColor': - globalScss.write('${0}: #{1:x};\n'.format(key, _colors[key])) - elif type(_colors[key]) == type(str()) or ('Disabled' in key or 'Inactive' in key): - globalScss.write('${0}: {1};\n'.format(key, _colors[key])) - else: - globalScss.write('${0}: #{1:x};\n'.format(key, _colors[key])) -globalScss.close() \ No newline at end of file diff --git a/style-helper/include/font-size-manager.h b/style-helper/include/font-size-manager.h deleted file mode 100644 index 2ccd949d1b8b6d0982395185826b6476342db830..0000000000000000000000000000000000000000 --- a/style-helper/include/font-size-manager.h +++ /dev/null @@ -1,87 +0,0 @@ -// -// Created by liuxinhao on 2022/6/20. -// -#pragma once - -#include -#include - -/** - * 该类主要是解决系统字号设置为单一的应用程序设置,并不会做过多的区分设置项,导致系统描述字号级别不明显 - * 提供以下功能: - * 1. 字体分级 - * 支持将系统设置的应用程序字体分级,支持1~10个级别,需要相应分级的字体可从该接口统一获取 - * 2. QWidget绑定通用字体的指定字号级别 - * 支持将指定的QWidget以及派生类绑定到指定的字号级别,系统更改 <应用程序字体设置> 时,将会重新计算分级字体大小重新更新字号和字体 - * 3. QWidget绑定指定的字体(不跟随系统),但是字号绑定字号级别,跟随系统变化 - * 支持将指定的QWidget以及派生类绑定定指定的字体以及字号级别, - */ - namespace Kiran - { - class FontSizeManagerPrivate; - class FontSizeManager : public QObject - { - Q_OBJECT - public: - enum FontLevelEnum - { - FONT_LEVEL_1, - FONT_LEVEL_2, - FONT_LEVEL_3, - - FONT_LEVEL_4, //控制中心设置项 "应用程序字体" 对应的字体级别,常规字体 - - FONT_LEVEL_5, - FONT_LEVEL_6, - FONT_LEVEL_7, - FONT_LEVEL_LAST - }; - public: - static FontSizeManager* instance(); - - ~FontSizeManager(); - - /// 通过字体磅数计算字体像素尺寸 - /// \param font 需获取字体像素大小的字体 - /// \return 字体像素尺寸 - static int fontPixelSize(const QFont& font); - - /// 设置系统通用字号大小,且会同步影响所有字号级别的大小 - /// \param fontSize 系统通用字号大小(px) - void setUniversalFontSize(int fontSize); - - /// 控件绑定字号级别 - /// \param w 需绑定字号的控件 - /// \param fontLevel 字号级别 - void bind(QWidget* w,FontLevelEnum fontLevel); - - /// 控件绑定字号级别 - /// \param w 需绑定字号的控件 - /// \param weight 字体粗细,可直接使用QFont::Weight - /// \param fontLevel 字号级别 - void bind(QWidget* w,FontLevelEnum fontLevel,int weight); - - /// 控件解除绑定字号级别 - void unbind(QWidget* w); - - /// 获取指定的字体 - /// \param fontLevel 字号级别 - /// \param base 基础字体,可忽略该参数,使用系统字体构造字体对象 - /// \return 指定字体 - QFont getFont(FontLevelEnum fontLevel,const QFont& base=QFont()) const; - - /// 获取指定的字体 - /// \param fontLevel 级别 - /// \param weight 字体粗细,可直接使用QFont::Weight - /// \param base 基础字体,可忽略该参数 - /// \return 指定的字体 - QFont getFont(FontLevelEnum fontLevel,int weight,const QFont& base=QFont()) const; - - private: - explicit FontSizeManager(QObject* parent = nullptr); - - private: - FontSizeManagerPrivate* d_ptr; - Q_DECLARE_PRIVATE(FontSizeManager); - }; - } \ No newline at end of file diff --git a/style-helper/include/style-global-define.h b/style-helper/include/style-global-define.h deleted file mode 100644 index 69f39d5e837c8845793292bb612c54704fe26838..0000000000000000000000000000000000000000 --- a/style-helper/include/style-global-define.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -namespace Kiran -{ -enum PaletteType -{ - PALETTE_LIGHT, - PALETTE_DARK, - PALETTE_LAST -}; -} \ No newline at end of file diff --git a/style-helper/include/style-palette.h b/style-helper/include/style-palette.h deleted file mode 100644 index 7ca6543154390350dfd553a7ea8028c1fb1dc0ec..0000000000000000000000000000000000000000 --- a/style-helper/include/style-palette.h +++ /dev/null @@ -1,147 +0,0 @@ -#pragma once - -#include -#include - -class QPalette; -class QWidget; -class QStyleOption; - -namespace Kiran -{ -class SchemeLoader; -class StylePalettePrivate; -// KiranStyle提供的更便捷的方法取出KiranStyle里相关颜色的类 -class StylePalette : public QObject -{ - Q_OBJECT - friend class SchemeLoaderFetcher; - -private: - explicit StylePalette(QObject* parent = nullptr); - -public: - // 扩展状态类型,尽量避免使用传入QStyleOption进行匹配 - enum ColorState - { - Normal = 0x00000001, // 普通状态 - Active = 0x00000002, // 激活 - Checked = 0x00000004, // 选中状态 - Hover = 0x00000008, // 悬浮状态 - Disabled = 0x00000010 // 禁用状态 - }; - Q_ENUM(ColorState); - Q_DECLARE_FLAGS(ColorStateFlags, ColorState) - Q_FLAG(ColorStateFlags) - - // WARNING:WidgetType,WidgetColorRule,FlagColorRule枚举值切勿随意更改 - // 该枚举与SchemeLoader::SchemePropertyName相关联 - enum WidgetType - { - // 窗口类型或提示框类型 - Window = 0x00000020, - // 无边框控件 - Bare = 0x00000030, - // 默认控件类型 - Widget = 0x00000040, - // 视图类型,含有可选中的文本 - View = 0x00000050, - // 选中高亮的类型 - Selection = 0x00000060, - // 标题栏 - TitleBar = 0x00000070 - }; - Q_ENUM(WidgetType) - - enum WidgetColorRule - { - // 背景色 - Background = 0x00000000, - // 前景色 - Foreground = 0x00000001, - // 边框 - Border = 0x00000002 - }; - Q_ENUM(WidgetColorRule) - - enum FlagColorRule - { - // 告警-标志色 - Warning = 0x00000010, - // 错误-标志色 - Error = 0x00000011, - // 成功-标志色 - Success = 0x00000012 - }; - Q_ENUM(FlagColorRule) - - static StylePalette* instance(); - ~StylePalette(); - - /** - * 将Kiran调色盘转换至Qt调色盘 - * \param palette - */ - void polishPalette(QPalette* palette); - - /** - * 获取当前主题调色盘类型 - * \return 调色盘类型 - */ - Kiran::PaletteType paletteType(); - - /** - * 应用程序指定主题调色盘类型 - * Warning: 指定主题调色盘后,不会根据系统主题变更更改主题调色盘 - * \param type 调色盘类型 - */ - void setDesignatedPaletteType(Kiran::PaletteType type); - - bool isDesignatedPaletteType(); - - /** - * 根据控件类型,控件状态,颜色类型取出颜色表之中预定的颜色 - * \param state 颜色状态,例如:悬浮,禁用,正常等 - * \param type 控件类型,详情见WidgetType枚举值定义 - * \param rule 控件颜色类型,例如:背景,前景,边框 - * \return 颜色表之中预定义的颜色 - */ - QColor color(ColorStateFlags state, WidgetType type, WidgetColorRule rule); - - /** - * 根据控件状态,标志颜色类型取出颜色表之中预定的颜色 - * \param rule 标志颜色类型,例如:成功,失败,警告等 - * \return 颜色表之中预定义的颜色 - */ - QColor color(FlagColorRule rule); - - /** - * 根据传入QWidget指针以及StyleOption进行伪状态猜测并进行匹配 - * 匹配顺序(找到一项即返回): - * 1. 全匹配: QStyleOption之中存在高优先状态(eg:禁用,按下,悬浮,聚焦) 和 传入的specialState 和 从派生关系与QStyleOption检测出的状态 - * 2. 匹配: 高优先级状态: QStyleOption之中存在高优先状态(eg:禁用,按下,悬浮,聚焦) - * 3. 匹配: 传入的specialState 和 从派生关系与QStyleOption检测出的扩展状态 - * 4. 匹配: 传入的specialState - * 5. 匹配: 不带伪状态选择器匹配 - * \param widget 控件 - * \param option QStyle绘制的选项 - * \param type 控件类型 - * \param rule 控件颜色类型 - * \param specialState 指定加入匹配的状态 - * \return 颜色表之中预定义的颜色 - */ - QColor color(const QWidget* widget, const QStyleOption* option, WidgetType type, WidgetColorRule rule, ColorState specialState = Normal); - - QColor getBulkColor(); - - void dump(); -signals: - void themeChanged(Kiran::PaletteType paletteType); - -private: - Kiran::SchemeLoader* getSchemeLoader(); - -private: - StylePalettePrivate* d_ptr; -}; -} diff --git a/style-helper/include/style-property.h b/style-helper/include/style-property.h deleted file mode 100644 index 80358bbf96485f7a9e826bf912e2fb485200ba56..0000000000000000000000000000000000000000 --- a/style-helper/include/style-property.h +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once - -class QPushButton; -class QProgressBar; -namespace Kiran -{ -enum ButtonType -{ - BUTTON_Normal, /** < 普通按钮 */ - BUTTON_Default, /** < 默认按钮,突出显示 */ - BUTTON_Warning /** < 警告按钮,突出警示显示 */ -}; -enum ProgressBarTextPosition -{ - PROGRESS_TEXT_LEFT, /** < 水平-左侧 垂直-上侧 */ - PROGRESS_TEXT_CENTER, /** < 中间 */ - PROGRESS_TEXT_RIGHT /** < 水平-右侧 垂直-下侧 */ -}; -/** - * @brief - * KiranStyle自定义属性读写接口,可定制部分KiranStyle绘制细节,KiranStyle读出属性值进行特殊的绘制 - * 若控件当前style不为kiranstyle,则不会生效 - */ -namespace StylePropertyHelper -{ -/** - * @brief 获取按钮类型 - * @param btn 按钮控件,从该按钮中取出属性 - * @return 该按钮的Style绘制类型,采取什么风格进行绘制 - * @see Kiran::Style::ButtonType - */ -ButtonType getButtonType(const QPushButton *btn); -/** - * @brief 设置按钮类型 - * @param btn 按钮 - * @param type 按钮的Style绘制类型,采取什么风格进行绘制 - * @see Kiran::Style::ButtonType - */ -void setButtonType(QPushButton *btn, ButtonType type); - -/** - * @brief 设置QProgressBar进度文本显示位置 - * @param progressBar 进度条 - * @param textPosition 文本绘制位置 - * @see Kiran::Style::ProgressBarTextPosition - */ -void setProgressBarTextPosition(QProgressBar *progressBar, ProgressBarTextPosition textPosition); -/** - * @brief 获取QProgressBar文本绘制位置 - * @param progressBar 进度条 - * @return 文本绘制位置 - * @see Kiran::Style::ProgressBarTextPosition - */ -ProgressBarTextPosition getProgressBarTextPosition(const QProgressBar *progressBar); -} // namespace PropertyHelper -} // namespace Style diff --git a/style-helper/kiran-style-helper.pc.in b/style-helper/kiran-style-helper.pc.in deleted file mode 100644 index e0380305c6f73a382a9d4288c65943a8cb567703..0000000000000000000000000000000000000000 --- a/style-helper/kiran-style-helper.pc.in +++ /dev/null @@ -1,9 +0,0 @@ -LibDir=@KIRAN_STYLE_HELPER_LIB_DIR@ -IncludeDir=@KIRAN_STYLE_HELPER_INCLUDE_DIR@ - -Name: kiran-style-helper -Description: kiran style helper -Version: @KIRAN_STYLE_HELPER_VERSION@ -Requires: Qt5Core Qt5Gui Qt5Widgets -Libs: -L${LibDir} -l@TARGET_NAME@ -Cflags: -I${IncludeDir} \ No newline at end of file diff --git a/style-helper/kiranstyle-helper.qrc.in b/style-helper/kiranstyle-helper.qrc.in deleted file mode 100644 index 066041fb17089857768439d4120d5b088c8b661f..0000000000000000000000000000000000000000 --- a/style-helper/kiranstyle-helper.qrc.in +++ /dev/null @@ -1,53 +0,0 @@ - - - @KIRAN_DARK_COLORS@ - @KIRAN_LIGHT_COLORS@ - - - - @CMAKE_CURRENT_SOURCE_DIR@/data/images/arrow.svg - @CMAKE_CURRENT_SOURCE_DIR@/data/images/arrow-down.svg - @CMAKE_CURRENT_SOURCE_DIR@/data/images/arrow-down-disabled.svg - @CMAKE_CURRENT_SOURCE_DIR@/data/images/arrow-left.png - @CMAKE_CURRENT_SOURCE_DIR@/data/images/arrow-right.png - @CMAKE_CURRENT_SOURCE_DIR@/data/images/arrow-right-disabled.png - @CMAKE_CURRENT_SOURCE_DIR@/data/images/arrow-up.svg - @CMAKE_CURRENT_SOURCE_DIR@/data/images/checkbox-checked.svg - @CMAKE_CURRENT_SOURCE_DIR@/data/images/checkbox-unchecked.svg - @CMAKE_CURRENT_SOURCE_DIR@/data/images/check-checked-active.svg - @CMAKE_CURRENT_SOURCE_DIR@/data/images/check-checked-disabled.svg - @CMAKE_CURRENT_SOURCE_DIR@/data/images/check-checked-hover.svg - @CMAKE_CURRENT_SOURCE_DIR@/data/images/check-checked-normal.svg - @CMAKE_CURRENT_SOURCE_DIR@/data/images/check-indeterminate-active.svg - @CMAKE_CURRENT_SOURCE_DIR@/data/images/check-indeterminate-disabled.svg - @CMAKE_CURRENT_SOURCE_DIR@/data/images/check-indeterminate-hover.svg - @CMAKE_CURRENT_SOURCE_DIR@/data/images/check-indeterminate-normal.svg - @CMAKE_CURRENT_SOURCE_DIR@/data/images/check-unchecked-active.svg - @CMAKE_CURRENT_SOURCE_DIR@/data/images/check-unchecked-disabled.svg - @CMAKE_CURRENT_SOURCE_DIR@/data/images/check-unchecked-hover.svg - @CMAKE_CURRENT_SOURCE_DIR@/data/images/check-unchecked-normal.svg - @CMAKE_CURRENT_SOURCE_DIR@/data/images/expander-collapsed.png - @CMAKE_CURRENT_SOURCE_DIR@/data/images/expander-expanded.png - @CMAKE_CURRENT_SOURCE_DIR@/data/images/panel-grid-horizontal-symbolic.svg - @CMAKE_CURRENT_SOURCE_DIR@/data/images/panel-grid-vertical-symbolic.svg - @CMAKE_CURRENT_SOURCE_DIR@/data/images/radio-checked-active.svg - @CMAKE_CURRENT_SOURCE_DIR@/data/images/radio-checked-disabled.svg - @CMAKE_CURRENT_SOURCE_DIR@/data/images/radio-checked-hover.svg - @CMAKE_CURRENT_SOURCE_DIR@/data/images/radio-checked-normal.svg - @CMAKE_CURRENT_SOURCE_DIR@/data/images/radio-selected.svg - @CMAKE_CURRENT_SOURCE_DIR@/data/images/radio-unchecked-active.svg - @CMAKE_CURRENT_SOURCE_DIR@/data/images/radio-unchecked-disabled.svg - @CMAKE_CURRENT_SOURCE_DIR@/data/images/radio-unchecked-hover.svg - @CMAKE_CURRENT_SOURCE_DIR@/data/images/radio-unchecked-normal.svg - @CMAKE_CURRENT_SOURCE_DIR@/data/images/scale-disabled.png - @CMAKE_CURRENT_SOURCE_DIR@/data/images/scale-normal.png - @CMAKE_CURRENT_SOURCE_DIR@/data/images/scale-pressed.png - @CMAKE_CURRENT_SOURCE_DIR@/data/images/search.svg - @CMAKE_CURRENT_SOURCE_DIR@/data/images/search-light.svg - @CMAKE_CURRENT_SOURCE_DIR@/data/images/thumbnail.png - @CMAKE_CURRENT_SOURCE_DIR@/data/images/window-close-symbolic.svg - @CMAKE_CURRENT_SOURCE_DIR@/data/images/window-maximum-symbolic.svg - @CMAKE_CURRENT_SOURCE_DIR@/data/images/window-minimum-symbolic.svg - @CMAKE_CURRENT_SOURCE_DIR@/data/images/window-unmaximum-symbolic.svg - - diff --git a/style-helper/src/scheme-loader.cpp b/style-helper/src/scheme-loader.cpp deleted file mode 100644 index 2c71094c889b34ff97c800ea1cc99e8c6270b874..0000000000000000000000000000000000000000 --- a/style-helper/src/scheme-loader.cpp +++ /dev/null @@ -1,535 +0,0 @@ -/** - * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. - * kiran-qt5-integration is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - * - * Author: liuxinhao - */ -#include "scheme-loader.h" -#include "kiran-appearance-monitor.h" - -#include -#include -#include -#include -#include - -using namespace QCss; - - -namespace Kiran -{ -static const QMap pseudoMap = { - {QCss::PseudoClass_Unknown, "unknow"}, - {QCss::PseudoClass_Enabled, "enabled"}, - {QCss::PseudoClass_Disabled, "disabled"}, - {QCss::PseudoClass_Pressed, "pressed"}, - {QCss::PseudoClass_Focus, "focus"}, - {QCss::PseudoClass_Hover, "hover"}, - {QCss::PseudoClass_Checked, "checked"}, - {QCss::PseudoClass_Unchecked, "unchecked"}, - {QCss::PseudoClass_Indeterminate, "indeterminate"}, - {QCss::PseudoClass_Unspecified, "unspecifie"}, - {QCss::PseudoClass_Selected, "selected"}, - {QCss::PseudoClass_Horizontal, "horizontal"}, - {QCss::PseudoClass_Vertical, "vertical"}, - {QCss::PseudoClass_Window, "window"}, - {QCss::PseudoClass_Children, "chindren"}, - {QCss::PseudoClass_Sibling, "sibling"}, - {QCss::PseudoClass_Default, "default"}, - {QCss::PseudoClass_First, "first"}, - {QCss::PseudoClass_Last, "last"}, - {QCss::PseudoClass_Middle, "middle"}, - {QCss::PseudoClass_OnlyOne, "only one"}, - {QCss::PseudoClass_PreviousSelected, "previousSelected"}, - {QCss::PseudoClass_NextSelected, "NextSelected"}, - {QCss::PseudoClass_Flat, "flat"}, - {QCss::PseudoClass_Left, "left"}, - {QCss::PseudoClass_Right, "right"}, - {QCss::PseudoClass_Top, "top"}, - {QCss::PseudoClass_Bottom, "bottom"}, - {QCss::PseudoClass_Exclusive, "exclusive"}, - {QCss::PseudoClass_NonExclusive, "nonExclusive"}, - {QCss::PseudoClass_Frameless, "frameless"}, - {QCss::PseudoClass_ReadOnly, "readOnly"}, - {QCss::PseudoClass_Active, "active"}, - {QCss::PseudoClass_Closable, "closable"}, - {QCss::PseudoClass_Movable, "movable"}, - {QCss::PseudoClass_Floatable, "floatable"}, - {QCss::PseudoClass_Minimized, "minimized"}, - {QCss::PseudoClass_Maximized, "maximized"}, - {QCss::PseudoClass_On, "on"}, - {QCss::PseudoClass_Off, "off"}, - {QCss::PseudoClass_Editable, "editable"}, - {QCss::PseudoClass_Item, "item"}, - {QCss::PseudoClass_Closed, "closed"}, - {QCss::PseudoClass_Open, "open"}, - {QCss::PseudoClass_EditFocus, "editFocus"}, - {QCss::PseudoClass_Alternate, "alternate"}, - {QCss::PseudoClass_Any, "any"}, -}; - -bool FuzzyMatch(const QVector& selectors, quint64 pseudoClass); - -Kiran::SchemeLoader::SchemeLoader(QObject* parent) - : QObject(parent), - m_isValid(false), - m_styleScheme(new QCss::StyleSheet) -{ - -} - -SchemeLoader::~SchemeLoader() -{ - delete m_styleScheme; -} - -QVariant SchemeLoader::fetchPropertyValue(const QWidget* widget, - const QStyleOption* opt, - SchemeLoader::SchemePropertyName name, - SchemeLoader::SchemeValueType valueType, - quint64 specialPseudlClasss) -{ - /// 获取没伪选择器的样式 - QVariant defaultValue = fetchPropertyValue(name, QCss::PseudoClass_Unspecified, valueType); - - /// 获取当前控件的其他状态 用于辅助增加伪状态选择匹配的准确性 - quint64 styleOptionPseudoClass = convertStyleOption2PseudoClass(widget, opt); - quint64 extendPresudoClass = styleOptionPseudoClass | specialPseudlClasss; - - /// 关键状态,做为匹配的关键因素 - quint64 keyClass = 0; - if (!(opt->state & QStyle::State_Enabled)) - { /// disable状态 - keyClass = QCss::PseudoClass_Disabled; - } - else if (opt->state & QStyle::State_Sunken) - { /// 凹陷或按下 - keyClass = QCss::PseudoClass_Pressed; - } - else if (opt->state & QStyle::State_MouseOver) - { /// 鼠标悬浮 - keyClass = QCss::PseudoClass_Hover; - } - else if (opt->state & QStyle::State_HasFocus) - { /// 聚焦  - keyClass = QCss::PseudoClass_Focus; - } - -#if 0 - QMetaEnum enumInfo = QMetaEnum::fromType(); - qInfo() << "fetch style detail:" << "\n" - << " widget class: " << widget->metaObject()->className() << "\n" - << " widget: " << widget->objectName() << "\n" - << " selector: " << enumInfo.valueToKey(name) << "\n" - << " special pseudo:" << pseudoClass2String(specialPseudlClasss) << "\n" - << " key pseudo: " << pseudoClass2String(keyClass) << "\n" - << " extend pseudo: " << pseudoClass2String(extendPresudoClass); -#endif - - if (keyClass != 0) - { - QVariant bestFitVar = fetchPropertyValue(name, keyClass | extendPresudoClass, valueType); - if (bestFitVar.isValid()) - { - return bestFitVar; - } - QVariant keyVar = fetchPropertyValue(name, keyClass, valueType); - if (keyVar.isValid()) - { - return keyVar; - } - } - - if (extendPresudoClass != 0) - { - QVariant extentVar = fetchPropertyValue(name, extendPresudoClass, valueType); - if (extentVar.isValid()) - { - return extentVar; - } - } - - if (specialPseudlClasss != 0) - { - QVariant specialVar = fetchPropertyValue(name, specialPseudlClasss, valueType); - if (specialVar.isValid()) - { - return specialVar; - } - } - - return defaultValue; -} - -QVariant SchemeLoader::fetchPropertyValue(SchemeLoader::SchemePropertyName propertyName, - quint64 pseudoClass, - SchemeLoader::SchemeValueType valueType) -{ - QReadLocker readLocker(&m_rwLock); - QVariant var = searchCacheEntry(propertyName, pseudoClass); - if (var.isValid()) - { - return var; - } - - //使用元对象中的信息将selector转换成字符串 - QMetaEnum metaEnum = QMetaEnum::fromType(); - QString strSelector = metaEnum.valueToKey(propertyName); - - //将字符串拆分成类型选择器和属性名进行匹配 - const QStringList selectors = strSelector.split("_"); - const QString type = selectors.at(0); - const QString property = selectors.at(1); - - auto values = m_styleScheme->nameIndex.values(type); - for (const StyleRule& rule : values) - { - if (!FuzzyMatch(rule.selectors, pseudoClass)) - { - continue; - } - - for (const Declaration& declartion : rule.declarations) - { - if (declartion.d->property != property) - { - continue; - } - QVariant propertyValue; - switch (valueType) - { - case SCHEME_VALUE_COLOR: - { - propertyValue = declartion.colorValue(); -#if 0 - QString pseudoClassStr = pseudoClass2String(pseudoClass); - qInfo() << "fuzzy match selector:" << type << pseudoClassStr << property << declartion.colorValue(); -#endif - break; - } - case SCHEME_VALUE_INT: - { - int i = 0; - declartion.intValue(&i); - propertyValue = i; - break; - } - case SCHEME_VALUE_URL: - propertyValue = declartion.uriValue(); - break; - case SCHEME_VALUE_REAL: - { - qreal real = 0.0; - declartion.realValue(&real); - propertyValue = real; - break; - } - default: - qWarning() << "this type is not supported at this time"; - continue; - } - readLocker.unlock(); - QWriteLocker writeLocker(&m_rwLock); - insertCacheEntry(propertyName, pseudoClass, propertyValue); - return propertyValue; - } - } - - readLocker.unlock(); - QWriteLocker writeLocker(&m_rwLock); - insertCacheEntry(propertyName, pseudoClass, QVariant()); - return QVariant(); -} - -void SchemeLoader::dump() -{ - QMultiHash::iterator iter; - QReadLocker readLocker(&m_rwLock); - for (iter = m_styleScheme->nameIndex.begin(); - iter != m_styleScheme->nameIndex.end(); - iter++) - { - qInfo("//=== %s ====/", iter.key().toStdString().c_str()); - StyleRule rule = iter.value(); - for (auto iter : rule.selectors) - { - qInfo() << "\tselector:" << pseudoClass2String(iter.pseudoClass()) << iter.pseudoClass(); - } - for (const Declaration& declaration : rule.declarations) - { - qInfo("\tproperty:%s", declaration.d->property.toStdString().c_str()); - for (const Value& value : declaration.d->values) - { - qInfo() << "\t\ttype: " << value.type; - qInfo() << "\t\tvalue:" << value.variant; - } - } - } -} - -bool SchemeLoader::load(const QString& schemeFile) -{ - QWriteLocker writeLocker(&m_rwLock); - - //clean cache - m_isValid = false; - m_styleSchemeCache.clear(); - - QCss::Parser parser(schemeFile, true); - if (!parser.parse(m_styleScheme)) - { - qWarning() << "parse style scheme failed!" << parser.errorSymbol().text; - return false; - } - - m_isValid = true; - qDebug() << "load" << schemeFile << "succeed!"; - return true; -} - -QString SchemeLoader::pseudoClass2String(quint64 pseudoClass) -{ - QStringList pseudoClassList; - for (auto iter = pseudoMap.begin(); - iter != pseudoMap.end(); - iter++) - { - if (pseudoClass & iter.key()) - { - pseudoClassList.append(iter.value()); - } - } - return pseudoClassList.join(","); -} - -bool SchemeLoader::isValid() -{ - return m_isValid; -} - -#define PALETTE_COLOR(palette, colorGroup, colorRole, pseudoClass) \ - { \ - palette->setColor(colorGroup, QPalette::colorRole, getColor(Palette_##colorRole, pseudoclass)); \ - } - -void SchemeLoader::polish(QPalette* palette) -{ - // clang-format off - static const QVector< QPair > states = { - {QPalette::Active,QCss::PseudoClass_Active}, - {QPalette::Disabled,QCss::PseudoClass_Disabled}, -// {QPalette::Inactive,QCss::PseudoClass_Unspecified} //不给inactive单独做状态 - {QPalette::Inactive,QCss::PseudoClass_Active} - }; - // clang-format on - - for (const auto& pair : states) - { - QPalette::ColorGroup group = pair.first; - quint64 pseudoclass = pair.second; - - PALETTE_COLOR(palette, group, Window, pseudoclass); - PALETTE_COLOR(palette, group, WindowText, pseudoclass); - - PALETTE_COLOR(palette, group, Base, pseudoclass); - PALETTE_COLOR(palette, group, Text, pseudoclass); - - //FIXME:暂时交替色使用同样的颜色 - palette->setColor(group,QPalette::AlternateBase,palette->color(group,QPalette::Window)); - - PALETTE_COLOR(palette, group, Button, pseudoclass); - PALETTE_COLOR(palette, group, ButtonText, pseudoclass); - - PALETTE_COLOR(palette, group, Highlight, pseudoclass); - PALETTE_COLOR(palette, group, HighlightedText, pseudoclass); - - PALETTE_COLOR(palette, group, ToolTipBase, pseudoclass); - PALETTE_COLOR(palette, group, ToolTipText, pseudoclass); - } -} - -QColor SchemeLoader::getColor(const QWidget* widget, const QStyleOption* opt, SchemeLoader::SchemePropertyName name, quint64 specialPseudoClass) -{ - QVariant var = fetchPropertyValue(widget, opt, name, SCHEME_VALUE_COLOR, specialPseudoClass); - if (var.isValid()) - { - return var.value(); - } - return QColor(); -} - -QColor SchemeLoader::getColor(SchemeLoader::SchemePropertyName propertyName, quint64 pseudoClass) -{ - QVariant var = fetchPropertyValue(propertyName, pseudoClass, SCHEME_VALUE_COLOR); - if (var.isValid()) - { - return var.value(); - } - return QColor(); -} - -QString SchemeLoader::getUrl(const QWidget* widget, const QStyleOption* opt, SchemeLoader::SchemePropertyName name, quint64 specialPseudoClass) -{ - QVariant var = fetchPropertyValue(widget,opt,name,SCHEME_VALUE_URL); - if(var.isValid()) - { - return var.value(); - } - return QString(); -} - -QString SchemeLoader::getUrl(SchemeLoader::SchemePropertyName name, quint64 pseudoClass) -{ - QVariant var = fetchPropertyValue(name, pseudoClass, SCHEME_VALUE_URL); - if (var.isValid()) - { - return var.value(); - } - return QString(); -} - - -/// 模糊匹配,优先完全匹配,再着判断待匹配伪状态包含选择器的伪状态 -/// \param selectors 选择器 -/// \param pseudoClass 待匹配的伪状态 -/// \param fuzzyMatchSelector 模糊匹配到的选择器 -/// \return 是否匹配 -bool FuzzyMatch(const QVector& selectors, - quint64 pseudoClass) -{ - bool isMatch = false; - - ///完整匹配 - for (const Selector& selector : selectors) - { - if (selector.pseudoClass() == pseudoClass) - { - isMatch = true; - break; - } - } - - ///包含 - if (!isMatch) - { - for (const Selector& selector : selectors) - { - if ((selector.pseudoClass() | pseudoClass) == pseudoClass) - { - isMatch = true; - break; - } - } - } - - return isMatch; -} - -quint64 SchemeLoader::convertStyleOption2PseudoClass(const QWidget* widget, - const QStyleOption* opt) -{ - quint64 pesudoClass = 0; - - if (opt->state & QStyle::State_Enabled) - { - pesudoClass |= QCss::PseudoClass_Enabled; - } - - if (opt->state & QStyle::State_Active) - pesudoClass |= QCss::PseudoClass_Active; - - if (opt->state & QStyle::State_Window) - pesudoClass |= QCss::PseudoClass_Window; - - if (opt->state & QStyle::State_On) - pesudoClass |= (QCss::PseudoClass_On | QCss::PseudoClass_Checked); - - if (opt->state & QStyle::State_Off) - pesudoClass |= (QCss::PseudoClass_Off | QCss::PseudoClass_Unchecked); - - if (opt->state & QStyle::State_NoChange) - pesudoClass |= QCss::PseudoClass_Indeterminate; - - if (opt->state & QStyle::State_Selected) - pesudoClass |= QCss::PseudoClass_Selected; - - if (opt->state & QStyle::State_Horizontal) - pesudoClass |= QCss::PseudoClass_Horizontal; - else - pesudoClass |= QCss::PseudoClass_Vertical; - - if (opt->state & (QStyle::State_Open | QStyle::State_On | QStyle::State_Sunken)) - { - if( widget && ( widget->inherits("QPushButton") || widget->inherits("QToolButton") ) ) - { - pesudoClass |= QCss::PseudoClass_Pressed; - } - else - { - pesudoClass |= QCss::PseudoClass_Open; - } - } - else - { - pesudoClass |= QCss::PseudoClass_Closed; - } - - if (opt->state & QStyle::State_Children) - pesudoClass |= QCss::PseudoClass_Children; - - if (opt->state & QStyle::State_Sibling) - pesudoClass |= QCss::PseudoClass_Sibling; - - if (opt->state & QStyle::State_ReadOnly) - pesudoClass |= QCss::PseudoClass_ReadOnly; - - if (opt->state & QStyle::State_Item) - pesudoClass |= QCss::PseudoClass_Item; - - if (opt->state & QStyle::State_HasFocus) - pesudoClass |= QCss::PseudoClass_Focus; - - return pesudoClass; -} - -//NOTE:此处未上锁,上层调用上锁 -void SchemeLoader::insertCacheEntry(SchemeLoader::SchemePropertyName propertyName, - quint64 pseudoStatus, - QVariant var) -{ - QMetaEnum propertyMateEnum = QMetaEnum::fromType(); - QString selectorString = propertyMateEnum.valueToKey(propertyName); - - QString key = QString("%1:%2").arg(selectorString).arg(pseudoStatus); - - if (m_styleSchemeCache.find(key) == m_styleSchemeCache.end()) - { - m_styleSchemeCache.insert(key, var); - } -} - -//NOTE:此处未上锁,上层调用需上锁 -QVariant SchemeLoader::searchCacheEntry(SchemeLoader::SchemePropertyName propertyName, - quint64 pseudoStatus) -{ - QMetaEnum propertyMateEnum = QMetaEnum::fromType(); - QString selectorString = propertyMateEnum.valueToKey(propertyName); - - QString key = QString("%1:%2").arg(selectorString).arg(pseudoStatus); - - QVariant var; - auto iter = m_styleSchemeCache.find(key); - if (iter != m_styleSchemeCache.end()) - { - var = iter.value(); - } - return var; -} -} \ No newline at end of file diff --git a/style-helper/src/scheme-loader.h b/style-helper/src/scheme-loader.h deleted file mode 100644 index 595304bdd9498e8904b0d41f083f16b88b3e009f..0000000000000000000000000000000000000000 --- a/style-helper/src/scheme-loader.h +++ /dev/null @@ -1,261 +0,0 @@ -/** - * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. - * kiran-qt5-integration is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - * - * Author: liuxinhao - */ -#ifndef KIRAN_QT5_PLATFORMTHEME_STYLE_LIB_SRC_SCHEME_LOADER_H_ -#define KIRAN_QT5_PLATFORMTHEME_STYLE_LIB_SRC_SCHEME_LOADER_H_ - -#include -#include -#include -#include -#include -#include -#include "style-global-define.h" - -class QPalette; -class QWidget; -class QStyleOption; - -namespace QCss -{ -class StyleSheet; -} - -namespace Kiran -{ -enum PseudoClassType -{ - PseudoClass_Unknown = Q_UINT64_C(0x0000000000000000), - PseudoClass_Enabled = Q_UINT64_C(0x0000000000000001), - PseudoClass_Disabled = Q_UINT64_C(0x0000000000000002), - PseudoClass_Pressed = Q_UINT64_C(0x0000000000000004), - PseudoClass_Focus = Q_UINT64_C(0x0000000000000008), - PseudoClass_Hover = Q_UINT64_C(0x0000000000000010), - PseudoClass_Checked = Q_UINT64_C(0x0000000000000020), - PseudoClass_Unchecked = Q_UINT64_C(0x0000000000000040), - PseudoClass_Indeterminate = Q_UINT64_C(0x0000000000000080), - PseudoClass_Unspecified = Q_UINT64_C(0x0000000000000100), - PseudoClass_Selected = Q_UINT64_C(0x0000000000000200), - PseudoClass_Horizontal = Q_UINT64_C(0x0000000000000400), - PseudoClass_Vertical = Q_UINT64_C(0x0000000000000800), - PseudoClass_Window = Q_UINT64_C(0x0000000000001000), - PseudoClass_Children = Q_UINT64_C(0x0000000000002000), - PseudoClass_Sibling = Q_UINT64_C(0x0000000000004000), - PseudoClass_Default = Q_UINT64_C(0x0000000000008000), - PseudoClass_First = Q_UINT64_C(0x0000000000010000), - PseudoClass_Last = Q_UINT64_C(0x0000000000020000), - PseudoClass_Middle = Q_UINT64_C(0x0000000000040000), - PseudoClass_OnlyOne = Q_UINT64_C(0x0000000000080000), - PseudoClass_PreviousSelected = Q_UINT64_C(0x0000000000100000), - PseudoClass_NextSelected = Q_UINT64_C(0x0000000000200000), - PseudoClass_Flat = Q_UINT64_C(0x0000000000400000), - PseudoClass_Left = Q_UINT64_C(0x0000000000800000), - PseudoClass_Right = Q_UINT64_C(0x0000000001000000), - PseudoClass_Top = Q_UINT64_C(0x0000000002000000), - PseudoClass_Bottom = Q_UINT64_C(0x0000000004000000), - PseudoClass_Exclusive = Q_UINT64_C(0x0000000008000000), - PseudoClass_NonExclusive = Q_UINT64_C(0x0000000010000000), - PseudoClass_Frameless = Q_UINT64_C(0x0000000020000000), - PseudoClass_ReadOnly = Q_UINT64_C(0x0000000040000000), - PseudoClass_Active = Q_UINT64_C(0x0000000080000000), - PseudoClass_Closable = Q_UINT64_C(0x0000000100000000), - PseudoClass_Movable = Q_UINT64_C(0x0000000200000000), - PseudoClass_Floatable = Q_UINT64_C(0x0000000400000000), - PseudoClass_Minimized = Q_UINT64_C(0x0000000800000000), - PseudoClass_Maximized = Q_UINT64_C(0x0000001000000000), - PseudoClass_On = Q_UINT64_C(0x0000002000000000), - PseudoClass_Off = Q_UINT64_C(0x0000004000000000), - PseudoClass_Editable = Q_UINT64_C(0x0000008000000000), - PseudoClass_Item = Q_UINT64_C(0x0000010000000000), - PseudoClass_Closed = Q_UINT64_C(0x0000020000000000), - PseudoClass_Open = Q_UINT64_C(0x0000040000000000), - PseudoClass_EditFocus = Q_UINT64_C(0x0000080000000000), - PseudoClass_Alternate = Q_UINT64_C(0x0000100000000000), - // The Any specifier is never generated, but can be used as a wildcard in searches. - PseudoClass_Any = Q_UINT64_C(0x0000ffffffffffff) -}; -//提供给KiranStyle以及KiranWidget内部获取颜色表定义 -class SchemeLoaderPrivate; -class SchemeLoader : public QObject -{ - Q_OBJECT -public: - //WARNING:枚举值切勿随意更改 - //该枚举与KiranPalette之中的WidgetType,WidgetColorRule,FlagColorRule相关联 - - //clang-format off - enum SchemePropertyName - { - // === Palette === // - Palette_Window = 0x00000000, - Palette_WindowText = 0x00000001, - Palette_Base = 0x00000002, - Palette_Text = 0x00000003, - Palette_Button = 0x00000004, - Palette_ButtonText = 0x00000005, - Palette_Highlight = 0x00000006, - Palette_HighlightedText = 0x00000007, - Palette_ToolTipBase = 0x00000008, - Palette_ToolTipText = 0x00000009, - - // === Flag === /// - Flag_Warning = 0x00000010, - Flag_Error = 0x00000011, - Flag_Success = 0x00000012, - - // === Window === /// - Window_Background = 0x00000020, - Window_Foreground = 0x00000021, - Window_Border = 0x00000022, - - // === Bare === /// - Bare_Background = 0x00000030, - Bare_Foreground = 0x00000031, - - // === Widget === /// - Widget_Background = 0x00000040, - Widget_Foreground = 0x00000041, - Widget_Border = 0x00000042, - - // === View === /// - View_Background = 0x00000050, - View_Foreground = 0x00000051, - View_Border = 0x00000052, - - // === Selection === /// - Selection_Background = 0x00000060, - Selection_Foreground = 0x00000061, - - // === TitleBar === /// - TitleBar_Background = 0x00000070, - TitleBar_Foreground = 0x00000071, - TitleBar_Border = 0x00000072, - - /// --- 提供给KiranStyle直接使用的相关属性 --- /// - Frame_Background = 0x00001000, - Frame_Border, - - Button_Background, - Button_Border, - - SpecialButton_DefaultBackground, - SpecialButton_WarnningBackground, - - Edit_Background, - Edit_Border, - - Indicator_Arrow, - - Combo_Background, - Combo_Border, - - ItemView_Branch, - - MenuBar_ItemBackground, - MenuBar_EmptyAreaBackground, - - Progress_Groove, - Progress_Content, - - Scroll_Slider, - - Slider_Groove, - Slider_Content, - Slider_HandleBorder, - Slider_HandleBackground, - - SpinBox_Background, - SpinBox_Border, - SpinBox_SignColor, - - Bulk_Background, - }; - //clang-format on - Q_ENUM(SchemePropertyName) - -private: - enum SchemeValueType - { - SCHEME_VALUE_COLOR, - SCHEME_VALUE_INT, - SCHEME_VALUE_URL, - SCHEME_VALUE_REAL - }; - -public: - explicit SchemeLoader(QObject* parent = nullptr); - ~SchemeLoader() override; - - bool isValid(); - void dump(); - /// 将伪类转成字符串 - /// \param qseudoClass 伪类 - /// \return 字符串描述 - static QString pseudoClass2String(quint64 pseudoClass); - - bool load(const QString& schemeFile); - void polish(QPalette* palette); - - // color - QColor getColor(const QWidget* widget, - const QStyleOption* opt, - SchemePropertyName name, - quint64 specialPseudoClass = PseudoClass_Unspecified); - - QColor getColor(SchemePropertyName propertyName, - quint64 pseudoClass); - // url - QString getUrl(const QWidget* widget, - const QStyleOption* opt, - SchemePropertyName name, - quint64 specialPseudoClass = PseudoClass_Unspecified); - - QString getUrl(SchemePropertyName name, - quint64 pseudoClass); - -private: - QVariant fetchPropertyValue(const QWidget* widget, - const QStyleOption* opt, - SchemePropertyName name, - SchemeValueType valueType, - quint64 specialPseudlClasss = PseudoClass_Unspecified); - - QVariant fetchPropertyValue(SchemePropertyName propertyName, - quint64 pseudoClass, - SchemeValueType valueType); - - /// 转换QStyleOption成伪状态选择器 - /// \param widget 控件,特别控件需要添加伪状态 - /// \param styleOption 样式选项,判断控件伪状态 - /// \return 转换后的伪状态 - quint64 convertStyleOption2PseudoClass(const QWidget* widget, const QStyleOption* opt); - - /// 存入缓存 - /// \param selector 选择器 - /// \param pseudoStatus 伪状态 - /// \param var 属性值 - void insertCacheEntry(SchemePropertyName propertyName, - quint64 pseudoStatus, - QVariant var); - - QVariant searchCacheEntry(SchemePropertyName propertyName, - quint64 pseudoStatus); - -private: - bool m_isValid = false; - QCss::StyleSheet* m_styleScheme; - QReadWriteLock m_rwLock; - QMap m_styleSchemeCache; -}; -} // namespace Kiran -#endif //KIRAN_QT5_PLATFORMTHEME_STYLE_LIB_SRC_SCHEME_LOADER_H_ diff --git a/style-helper/src/style-palette-private.cpp b/style-helper/src/style-palette-private.cpp deleted file mode 100644 index 855fd00ac60c1454b65da3347293669c9923b972..0000000000000000000000000000000000000000 --- a/style-helper/src/style-palette-private.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#include "style-palette-private.h" -#include - -namespace Kiran -{ -StylePalettePrivate::StylePalettePrivate(QObject* parent, StylePalette* ptr) - : QObject(parent), - q_ptr(ptr), - m_customSpecialType(false), - m_type(Kiran::PALETTE_DARK), - m_schemeLoader(new Kiran::SchemeLoader) -{ - // 监听Kiran桌面主题变化信号 - connect(KiranAppearanceMonitor::instance(), &KiranAppearanceMonitor::gtkThemeChanged, - this, &StylePalettePrivate::handleGtkThemeChanged); - handleGtkThemeChanged(KiranAppearanceMonitor::instance()->gtkTheme()); -} - -StylePalettePrivate::~StylePalettePrivate() -{ - delete m_schemeLoader; -} - -void StylePalettePrivate::handleGtkThemeChanged(const QString& gtkTheme) -{ - // 手动指定深浅主题 - if (m_customSpecialType) - { - return; - } - else - { - Kiran::PaletteType type; - if (gtkTheme.compare("kiran") == 0) - { - type = Kiran::PALETTE_LIGHT; - } - else - { - type = Kiran::PALETTE_DARK; - } - updatePaletteType(type, false); - } -} - -QString StylePalettePrivate::getSchemeFile(Kiran::PaletteType type) -{ - // clang-format off - static QString schemeFile[Kiran::PALETTE_LAST] = { - QStringLiteral(":/style-helper/colors/light.css"), - QStringLiteral(":/style-helper/colors/dark.css") - }; - // clang-format on - return schemeFile[type]; -} - -void StylePalettePrivate::updatePaletteType(Kiran::PaletteType type, bool customSpecial) -{ - m_customSpecialType = customSpecial; - m_type = type; - QString schemeFile = getSchemeFile(type); - m_schemeLoader->load(schemeFile); - - emit q_ptr->themeChanged(type); -} -} // namespace Kiran diff --git a/style-helper/src/style-palette-private.h b/style-helper/src/style-palette-private.h deleted file mode 100644 index 0931550fb59a5c74e6efefb03039565ed02bffcc..0000000000000000000000000000000000000000 --- a/style-helper/src/style-palette-private.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once -#include -#include "scheme-loader.h" -#include "style-palette.h" - -namespace Kiran -{ -class StylePalettePrivate : public QObject -{ - Q_DECLARE_PUBLIC(StylePalette) -public: - StylePalettePrivate(QObject* parent, StylePalette* ptr);; - ~StylePalettePrivate(); - - QString getSchemeFile(Kiran::PaletteType type); - void updatePaletteType(Kiran::PaletteType type,bool customSpecial=false); - -private slots: - void handleGtkThemeChanged(const QString& gtkTheme); - -private: - StylePalette* q_ptr; - Kiran::SchemeLoader* m_schemeLoader = nullptr; - bool m_customSpecialType = false; - Kiran::PaletteType m_type; -}; -} diff --git a/style-helper/src/style-palette.cpp b/style-helper/src/style-palette.cpp deleted file mode 100644 index 9c11dec44d4f362599818f2d6d577fdb46d986bc..0000000000000000000000000000000000000000 --- a/style-helper/src/style-palette.cpp +++ /dev/null @@ -1,168 +0,0 @@ -#include "style-palette.h" -#include "kiran-appearance-monitor.h" -#include "scheme-loader.h" -#include "style-palette-private.h" - -#include -#include -#include -#include -#include - -namespace Kiran -{ -static const QMap pseudoClassMap = { - {StylePalette::Normal, Kiran::PseudoClass_Unspecified}, - {StylePalette::Active, Kiran::PseudoClass_Active}, - {StylePalette::Checked, Kiran::PseudoClass_Checked}, - {StylePalette::Hover, Kiran::PseudoClass_Hover}, - {StylePalette::Disabled, Kiran::PseudoClass_Disabled}}; - -StylePalette* StylePalette::instance() -{ - static QMutex mutex; - static QScopedPointer pInst; - - if (Q_UNLIKELY(!pInst)) - { - QMutexLocker locker(&mutex); - if (pInst.isNull()) - { - pInst.reset(new StylePalette); - } - } - - return pInst.data(); -} - -StylePalette::StylePalette(QObject* parent) - : QObject(parent), - d_ptr(new StylePalettePrivate(this, this)) -{ -} - -StylePalette::~StylePalette() -{ -} - -void StylePalette::polishPalette(QPalette* palette) -{ - d_ptr->m_schemeLoader->polish(palette); -} - -Kiran::PaletteType StylePalette::paletteType() -{ - return d_ptr->m_type; -} - -void StylePalette::setDesignatedPaletteType(Kiran::PaletteType type) -{ - d_ptr->updatePaletteType(type, true); -} - -QColor StylePalette::color(ColorStateFlags states, WidgetType type, WidgetColorRule rule) -{ - QColor defaultColor; - - static QMetaEnum metaEnum = QMetaEnum::fromType(); - const char* key = metaEnum.valueToKey(type + rule); - if (key == nullptr) - { - qWarning() << "KiranPalette: can't convert -> SchemeLoader::SchemePropertyName!" << type << rule; - return defaultColor; - } - auto propertyEnum = static_cast(type + rule); - - int64_t pseudoClass = PseudoClass_Unspecified; - for (auto iter = pseudoClassMap.begin(); iter != pseudoClassMap.end(); iter++) - { - if (states & iter.key()) - { - pseudoClass |= iter.value(); - } - } - - return d_ptr->m_schemeLoader->getColor(propertyEnum, pseudoClass); -} - -QColor StylePalette::color(FlagColorRule rule) -{ - QColor defaultColor; - - static QMetaEnum metaEnum = QMetaEnum::fromType(); - const char* key = metaEnum.valueToKey(rule); - if (key == nullptr) - { - qWarning() << "KiranPalette: can't convert -> SchemeLoader::SchemePropertyName!" << rule; - return defaultColor; - } - auto propertyEnum = static_cast(rule); - - return d_ptr->m_schemeLoader->getColor(propertyEnum, PseudoClass_Unspecified); -} - -QColor StylePalette::color(const QWidget* widget, - const QStyleOption* option, - StylePalette::WidgetType type, - StylePalette::WidgetColorRule rule, - StylePalette::ColorState specialState) -{ - QColor defaultColor; - - static QMetaEnum metaEnum = QMetaEnum::fromType(); - const char* key = metaEnum.valueToKey(type + rule); - if (key == nullptr) - { - qWarning() << "KiranPalette: can't convert -> SchemeLoader::SchemePropertyName!"; - return defaultColor; - } - auto propertyEnum = static_cast(type + rule); - - auto pseudoIter = pseudoClassMap.find(specialState); - if (pseudoIter == pseudoClassMap.end()) - { - return defaultColor; - } - int64_t pseudoClass = pseudoIter.value(); - - QColor color = d_ptr->m_schemeLoader->getColor(widget, option, propertyEnum, pseudoClass); - if (!color.isValid()) - { - qWarning() << "can't get color for:\n" - << "\twidget: " << widget << "\n" - << "\tproperty: " << type << rule << "-->" << propertyEnum << "\n" - << "\tspecial state:" << specialState << "-->" << pseudoClass << "\n"; - } - return color; -} - -QColor StylePalette::getBulkColor() -{ - QColor defaultColor; - - QColor color = d_ptr->m_schemeLoader->getColor(SchemeLoader::Bulk_Background, PseudoClass_Any); - if (!color.isValid()) - { - qWarning() << "can't get bulk color!"; - return defaultColor; - } - - return color; -} - -void StylePalette::dump() -{ - d_ptr->m_schemeLoader->dump(); -} - -Kiran::SchemeLoader* StylePalette::getSchemeLoader() -{ - return d_ptr->m_schemeLoader; -} - -bool StylePalette::isDesignatedPaletteType() -{ - return d_ptr->m_customSpecialType; -} - -} // namespace Kiran \ No newline at end of file diff --git a/style-helper/src/style-property.cpp b/style-helper/src/style-property.cpp deleted file mode 100644 index b7ec4dbff1924fb54f3bf56ae2899658ff14d733..0000000000000000000000000000000000000000 --- a/style-helper/src/style-property.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#include "style-property.h" -#include -#include -#include - -/// pushbutton -#define KIRAN_STYLE_PROPERTY_BUTTON_TYPE "_kiran_button_type" -/// spinbox -#define KIRAN_STYLE_PROPERTY_SPINBOX_POSITION "_kiran_spinbox_position" -/// progress bar -#define KIRAN_STYLE_PROPERTY_PROGRESSBAR_TEXT_POSITION "_kiran_progressbar_text_position" - -namespace Kiran -{ -namespace StylePropertyHelper -{ -Kiran::ButtonType getButtonType(const QPushButton *btn) -{ - ButtonType buttonType = BUTTON_Normal; - - QVariant var = btn->property(KIRAN_STYLE_PROPERTY_BUTTON_TYPE); - if (var.isValid()) - { - bool toInt = false; - auto temp = static_cast(var.toInt(&toInt)); - if (toInt) - { - buttonType = temp; - } - } - - return buttonType; -} - -void setButtonType(QPushButton *btn, - Kiran::ButtonType type) -{ - btn->setProperty(KIRAN_STYLE_PROPERTY_BUTTON_TYPE, type); -} - -void setProgressBarTextPosition(QProgressBar *progressBar, - Kiran::ProgressBarTextPosition textPosition) -{ - progressBar->setProperty(KIRAN_STYLE_PROPERTY_PROGRESSBAR_TEXT_POSITION, textPosition); -} - -Kiran::ProgressBarTextPosition getProgressBarTextPosition(const QProgressBar *progressBar) -{ - ProgressBarTextPosition progressBarTextPosition = PROGRESS_TEXT_RIGHT; - - QVariant var = progressBar->property(KIRAN_STYLE_PROPERTY_PROGRESSBAR_TEXT_POSITION); - if (var.isValid()) - { - bool toInt = false; - auto temp = static_cast(var.toInt(&toInt)); - if (toInt) - { - progressBarTextPosition = temp; - } - } - - return progressBarTextPosition; -} - -} // namespace StylePropertyHelper -} // namespace Kiran \ No newline at end of file diff --git a/style/CMakeLists.txt b/style/CMakeLists.txt deleted file mode 100644 index 6cb6fa6643656041ba9495760e78bb64feafb297..0000000000000000000000000000000000000000 --- a/style/CMakeLists.txt +++ /dev/null @@ -1,30 +0,0 @@ -set(TARGET_NAME "kiranstyle") - -find_package(Qt5 COMPONENTS Widgets Svg DBus) -file(GLOB_RECURSE SRC "src/*.cpp" "src/*.h" "src/*.ui") - -set(CMAKE_AUTOMOC ON) -set(CMAKE_AUTOUIC ON) -set(CMAKE_AUTORCC ON) - -add_library( ${TARGET_NAME} SHARED - ${SRC} ) - -#获取kiran-style-helper之中的私有的include,kiranstyle之中的绘制需要引用到相关私有头文件 -get_target_property(KIRAN_STYLE_HELPER_INCLUDE_DIRS kiran-style-helper INCLUDE_DIRECTORIES) - -target_include_directories(${TARGET_NAME} PRIVATE - ${CMAKE_CURRENT_BINARY_DIR} - ${Qt5Svg_PRIVATE_INCLUDE_DIRS} - ${Qt5Widgets_PRIVATE_INCLUDE_DIRS} - ${KIRAN_STYLE_HELPER_INCLUDE_DIRS} - src/) - -target_link_libraries(${TARGET_NAME} - kiran-style-helper - Qt5::Widgets - Qt5::DBus - Qt5::Svg) - -#kiran style 插件 -install(TARGETS ${TARGET_NAME} DESTINATION ${QT5_STYLE_INSTALL_DIR}) \ No newline at end of file diff --git a/style/kiran-style-plugin.json b/style/kiran-style-plugin.json deleted file mode 100644 index 569b917d2d4525a0b291e1e93bece341b8ab4236..0000000000000000000000000000000000000000 --- a/style/kiran-style-plugin.json +++ /dev/null @@ -1 +0,0 @@ -{ "Keys": [ "kiran" ] } diff --git a/style/src/draw-helper/draw-button-helper.cpp b/style/src/draw-helper/draw-button-helper.cpp deleted file mode 100644 index ab5fcf46a4a03c2cb315290aae3671793fd94735..0000000000000000000000000000000000000000 --- a/style/src/draw-helper/draw-button-helper.cpp +++ /dev/null @@ -1,669 +0,0 @@ -/** - * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. - * kiran-qt5-integration is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - * - * Author: liuxinhao - */ -#include "draw-button-helper.h" -#include "define.h" -#include "draw-common-helper.h" -#include "metrics.h" -#include "render-helper.h" -#include "scheme-loader-fetcher.h" -#include "style-palette.h" -#include "style-property.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Kiran -{ -// 根据按钮内容计算按钮尺寸 -QSize pushButtonSizeFromContents(const QStyle* style, - const QStyleOption* option, - const QSize& contentSize, - const QWidget* widget) -{ - const auto buttonOption(qstyleoption_cast(option)); - if (!buttonOption) return contentSize; - - QSize size; - - const bool hasText(!buttonOption->text.isEmpty()); - const bool flat(buttonOption->features & QStyleOptionButton::Flat); - bool hasIcon(!buttonOption->icon.isNull()); - - if (!(hasText || hasIcon)) - { - // 没有文本以及图标,采用自定义按钮作为内容大小的起点 - size = contentSize; - } - else - { - // 不管Qt在内容大小如何计算,完全根据按钮选项重新计算按钮大小,保证渲染阶段的一致性 - hasIcon &= (RenderHelper::showIconsOnPushButtons() || flat || !hasText); - - // 文本大小 - if (hasText) - size = buttonOption->fontMetrics.size(Qt::TextShowMnemonic, buttonOption->text); - - // 图标大小 - if (hasIcon) - { - QSize iconSize = buttonOption->iconSize; - if (!iconSize.isValid()) iconSize = QSize(style->pixelMetric(QStyle::PM_SmallIconSize, option, widget), style->pixelMetric(QStyle::PM_SmallIconSize, option, widget)); - - size.setHeight(qMax(size.height(), iconSize.height())); - size.rwidth() += iconSize.width(); - - if (hasText) size.rwidth() += Metrics::Button_ItemSpacing; - } - } - - // 菜单 - const bool hasMenu(buttonOption->features & QStyleOptionButton::HasMenu); - if (hasMenu) - { - size.rwidth() += Metrics::MenuButton_IndicatorWidth; - if (hasText || hasIcon) size.rwidth() += Metrics::Button_ItemSpacing; - } - - // 扩展按钮内边距 - size = RenderHelper::expandSize(size, Metrics::Button_MarginWidth, Metrics::Button_MarginHeight); - // 扩张按钮边框宽度 - size = RenderHelper::expandSize(size, Metrics::Frame_FrameWidth); - - // 确保按钮有最小的宽度 - if (hasText) - { - size.setWidth(qMax(size.width(), int(Metrics::Button_MinWidth))); - } - - // 确保按钮有最小高度 - size.setHeight(qMax(size.height(), int(Metrics::Button_MinHeight))); - - return size; -} - -// 根据ToolButton内容大小获取尺寸 -QSize toolButtonSizeFromContents(const QStyle* style, - const QStyleOption* option, - const QSize& contentSize, - const QWidget* widget) -{ - const auto toolButtonOption = qstyleoption_cast(option); - if (!toolButtonOption) return contentSize; - - QSize size = contentSize; - - const QStyle::State& state(option->state); - - // Auto Raise标志: true表示自动突出,false表示与父窗口齐平 - const bool autoRaise(state & QStyle::State_AutoRaise); - const bool hasPopupMenu(toolButtonOption->features & QStyleOptionToolButton::MenuButtonPopup); - const bool hasInlineIndicator(toolButtonOption->features & QStyleOptionToolButton::HasMenu && toolButtonOption->features & QStyleOptionToolButton::PopupDelay && !hasPopupMenu); - - // 若存在内部指示器,宽度加上一个内部指示器的宽度 - if (hasInlineIndicator) size.rwidth() += Metrics::ToolButton_InlineIndicatorWidth; - - // 总边距宽度=按钮边距宽度+Frame宽度 - int marginWidth = Metrics::Button_MarginWidth + Metrics::Frame_FrameWidth; - // 四周扩展边距宽度 - size = RenderHelper::expandSize(size, marginWidth); - - return size; -} - -bool toolButtonSubControlRect(const QStyle* style, - const QStyleOptionComplex* opt, - QStyle::SubControl sc, - const QWidget* widget, - QRect& controlRect) -{ - const auto toolButtonOption = qstyleoption_cast(opt); - if (!toolButtonOption) return false; - - bool hasPopupMenu(toolButtonOption->features & QStyleOptionToolButton::MenuButtonPopup); - const bool hasInlineIndicator(toolButtonOption->features & QStyleOptionToolButton::HasMenu && - toolButtonOption->features & QStyleOptionToolButton::PopupDelay && - !hasPopupMenu); - - const QRect& rect(opt->rect); - int menuButtonWidth(Metrics::MenuButton_IndicatorWidth); - - switch (sc) - { - case QStyle::SC_ToolButtonMenu: - { - if (!(hasPopupMenu || hasInlineIndicator)) - { - controlRect = QRect(); - break; - } - - QRect menuRect(rect); - // 定位菜单按钮为ToolButton右侧 - menuRect.setLeft(rect.right() - menuButtonWidth + 1); - if (hasInlineIndicator) - { - menuRect.setTop(menuRect.bottom() - menuButtonWidth); - } - controlRect = QStyle::visualRect(opt->direction, opt->rect, menuRect); - break; - } - case QStyle::SC_ToolButton: - { - if (hasPopupMenu) - { - QRect contentsRect(rect); - contentsRect.setRight(rect.right() - menuButtonWidth); - controlRect = QStyle::visualRect(opt->direction, opt->rect, contentsRect); - } - else - { - controlRect = rect; - } - break; - } - default: - return false; - } - - return true; -} - -bool drawPEPanelButtonCommand(const QStyle* style, const QStyleOption* option, QPainter* painter, const QWidget* widget) -{ - const auto buttonOption(qstyleoption_cast(option)); - if (!buttonOption) - return true; - - const QRect& rect(option->rect); - - const QStyle::State& state(option->state); - bool enabled(state & QStyle::State_Enabled); - bool windowActive(state & QStyle::State_Active); - bool mouseOver((state & QStyle::State_Active) && enabled && (state & QStyle::State_MouseOver)); - bool hasFocus((enabled && (state & QStyle::State_HasFocus)) && !(widget && widget->focusProxy())); - bool sunken(state & (QStyle::State_On | QStyle::State_Sunken)); - bool flat(buttonOption->features & QStyleOptionButton::Flat); - - auto schemeLoader = SchemeLoaderFetcher::getSchemeLoader(); - QColor background, border; - if (qobject_cast(widget) && StylePropertyHelper::getButtonType(qobject_cast(widget)) != BUTTON_Normal) - { - ButtonType type = StylePropertyHelper::getButtonType(qobject_cast(widget)); - SchemeLoader::SchemePropertyName backgroundPropertyName = SchemeLoader::SpecialButton_DefaultBackground; - if (type == BUTTON_Warning) - backgroundPropertyName = SchemeLoader::SpecialButton_WarnningBackground; - - background = schemeLoader->getColor(widget, option, backgroundPropertyName); - } - else - { - background = schemeLoader->getColor(widget, option, SchemeLoader::Button_Background); - border = schemeLoader->getColor(widget, option, SchemeLoader::Button_Border); - } - - if (flat) - { - if (!sunken) - { - background = Qt::transparent; - } - } - - RenderHelper::renderFrame(painter, option->rect, 1, 4, background, border); - return true; -} - -bool drawPEPanelButtonTool(const QStyle* style, const QStyleOption* option, QPainter* painter, const QWidget* widget) -{ - const QPalette& palette(option->palette); - QRect rect(option->rect); - - const QStyle::State& state(option->state); - bool autoRaise(state & QStyle::State_AutoRaise); - bool enabled(state & QStyle::State_Enabled); - bool windowActive(state & QStyle::State_Active); - bool sunken(state & (QStyle::State_On | QStyle::State_Sunken)); - bool mouseOver((state & QStyle::State_Active) && enabled && (option->state & QStyle::State_MouseOver)); - bool hasFocus(enabled && (option->state & (QStyle::State_HasFocus | QStyle::State_Sunken))); - - auto schemeLoader = SchemeLoaderFetcher::getSchemeLoader(); - if (!autoRaise || mouseOver || sunken) - { - // need to check widget for popup mode, because option is not set properly - const auto* toolButton(qobject_cast(widget)); - bool hasPopupMenu(toolButton && toolButton->popupMode() == QToolButton::MenuButtonPopup); - - // adjust frame in case of menu - if (hasPopupMenu) - { - painter->setClipRect(rect); - rect.adjust(0, 0, Metrics::Frame_FrameRadius + 2, 0); - rect = QStyle::visualRect(option->direction, option->rect, rect); - } - - auto background = schemeLoader->getColor(widget, option, SchemeLoader::Button_Background); - auto border = schemeLoader->getColor(widget, option, SchemeLoader::Button_Border); - RenderHelper::renderFrame(painter, rect, 1, 4, background, border); - } - else - { - RenderHelper::renderFrame(painter, rect, 1, 4, Qt::transparent); - } - - return true; -} - -bool drawControlToolButtonLabel(const QStyle* style, const QStyleOption* option, QPainter* painter, const QWidget* widget) -{ - const auto toolButtonOption(qstyleoption_cast(option)); - if (!toolButtonOption) - return false; - - const QRect& rect = option->rect; - const QPalette& palette = option->palette; - - const QStyle::State& state(option->state); - bool enabled(state & QStyle::State_Enabled); - bool sunken(state & (QStyle::State_On | QStyle::State_Sunken)); - bool mouseOver((state & QStyle::State_Active) && enabled && (option->state & QStyle::State_MouseOver)); - bool flat(state & QStyle::State_AutoRaise); - - bool hasFocus(false); - if (flat) - hasFocus = enabled && !mouseOver && (option->state & QStyle::State_HasFocus); - else - hasFocus = enabled && !mouseOver && (option->state & (QStyle::State_HasFocus | QStyle::State_Sunken)); - - bool hasArrow = toolButtonOption->features & QStyleOptionToolButton::Arrow; - bool hasIcon(!(hasArrow || toolButtonOption->icon.isNull())); - bool hasText(!toolButtonOption->text.isEmpty()); - - QRect contentsRect(rect); - QSize iconSize(toolButtonOption->iconSize); - int textFlags(RenderHelper::mnemonicsTextFlags()); - QSize textSize(option->fontMetrics.size(textFlags, toolButtonOption->text)); - - QRect iconRect; - QRect textRect; - - if (hasText && (!(hasArrow || hasIcon) || toolButtonOption->toolButtonStyle == Qt::ToolButtonTextOnly)) // 只显示文字 - { - textRect = contentsRect; - textFlags |= Qt::AlignCenter; - } - else if ((hasArrow || hasIcon) && (!hasText || toolButtonOption->toolButtonStyle == Qt::ToolButtonIconOnly)) // 只显示图标 - { - iconRect = contentsRect; - } - else if (toolButtonOption->toolButtonStyle == Qt::ToolButtonTextUnderIcon) // 文字位于图标之下 - { - int contentsHeight(iconSize.height() + textSize.height() + Metrics::ToolButton_ItemSpacing); - iconRect = QRect(QPoint(contentsRect.left() + (contentsRect.width() - iconSize.width()) / 2, contentsRect.top() + (contentsRect.height() - contentsHeight) / 2), iconSize); - textRect = QRect(QPoint(contentsRect.left() + (contentsRect.width() - textSize.width()) / 2, iconRect.bottom() + Metrics::ToolButton_ItemSpacing + 1), textSize); - textFlags |= Qt::AlignCenter; - } - else - { - // bool leftAlign(widget && widget->property(PropertyNames::toolButtonAlignment).toInt() == Qt::AlignLeft); - // if (leftAlign) - // iconRect = QRect(QPoint(contentsRect.left(), contentsRect.top() + (contentsRect.height() - iconSize.height()) / 2), iconSize); - // else - { - int contentsWidth(iconSize.width() + textSize.width() + Metrics::ToolButton_ItemSpacing); - iconRect = QRect(QPoint(contentsRect.left() + (contentsRect.width() - contentsWidth) / 2, contentsRect.top() + (contentsRect.height() - iconSize.height()) / 2), iconSize); - } - - textRect = QRect(QPoint(iconRect.right() + Metrics::ToolButton_ItemSpacing + 1, contentsRect.top() + (contentsRect.height() - textSize.height()) / 2), textSize); - - // handle right to left layouts - iconRect = QStyle::visualRect(option->direction, option->rect, iconRect); - textRect = QStyle::visualRect(option->direction, option->rect, textRect); - - textFlags |= Qt::AlignLeft | Qt::AlignVCenter; - } - - // make sure there is enough room for icon - if (iconRect.isValid()) iconRect = RenderHelper::centerRect(iconRect, iconSize); - - // render arrow or icon - if (hasArrow && iconRect.isValid()) - { - QStyleOptionToolButton copy(*toolButtonOption); - copy.rect = iconRect; - switch (toolButtonOption->arrowType) - { - case Qt::LeftArrow: - style->drawPrimitive(QStyle::PE_IndicatorArrowLeft, ©, painter, widget); - break; - case Qt::RightArrow: - style->drawPrimitive(QStyle::PE_IndicatorArrowRight, ©, painter, widget); - break; - case Qt::UpArrow: - style->drawPrimitive(QStyle::PE_IndicatorArrowUp, ©, painter, widget); - break; - case Qt::DownArrow: - style->drawPrimitive(QStyle::PE_IndicatorArrowDown, ©, painter, widget); - break; - default: - break; - } - } - else if (hasIcon && iconRect.isValid()) - { - // icon state and mode - const QIcon::State iconState(sunken ? QIcon::On : QIcon::Off); - QIcon::Mode iconMode; - if (!enabled) - iconMode = QIcon::Disabled; - else if (!flat && hasFocus) - iconMode = QIcon::Selected; - else if (mouseOver && flat) - iconMode = QIcon::Active; - else - iconMode = QIcon::Normal; - - QPixmap pixmap = toolButtonOption->icon.pixmap(iconSize, iconMode, iconState); - style->drawItemPixmap(painter, iconRect, Qt::AlignCenter, pixmap); - } - - // render text - if (hasText && textRect.isValid()) - { - QPalette::ColorRole textRole(QPalette::ButtonText); - if (flat) - textRole = (hasFocus && sunken && !mouseOver) ? QPalette::HighlightedText : QPalette::WindowText; - else if (hasFocus && !mouseOver) - textRole = QPalette::HighlightedText; - - painter->setFont(toolButtonOption->font); - style->drawItemText(painter, textRect, textFlags, palette, enabled, toolButtonOption->text, textRole); - } - return true; -} - -bool drawControlPushButtonLabel(const QStyle* style, const QStyleOption* option, QPainter* painter, const QWidget* widget) -{ - const auto* buttonOption = qstyleoption_cast(option); - if( !buttonOption) - return false; - - const auto * pushbutton = qobject_cast(widget); - - QRect textRect = buttonOption->rect; - uint tf = Qt::AlignVCenter | Qt::TextShowMnemonic; - if (!style->styleHint(QStyle::SH_UnderlineShortcut, buttonOption, widget)) - tf |= Qt::TextHideMnemonic; - - if (!buttonOption->icon.isNull()) - { - // Center both icon and text - QIcon::Mode mode = buttonOption->state & QStyle::State_Enabled ? QIcon::Normal : QIcon::Disabled; - if (mode == QIcon::Normal && buttonOption->state & QStyle::State_HasFocus) - mode = QIcon::Active; - QIcon::State state = QIcon::Off; - if (buttonOption->state & QStyle::State_On) - state = QIcon::On; - - QPixmap pixmap = buttonOption->icon.pixmap(RenderHelper::getWindow(widget), buttonOption->iconSize, mode, state); - int pixmapWidth = pixmap.width() / pixmap.devicePixelRatio(); - int pixmapHeight = pixmap.height() / pixmap.devicePixelRatio(); - int labelWidth = pixmapWidth; - int labelHeight = pixmapHeight; - int iconSpacing = 4; //### 4 is currently hardcoded in QPushButton::sizeHint() - if (!buttonOption->text.isEmpty()) - { - int textWidth = buttonOption->fontMetrics.boundingRect(option->rect, tf, buttonOption->text).width(); - labelWidth += (textWidth + iconSpacing); - } - - QRect iconRect = QRect(textRect.x() + (textRect.width() - labelWidth) / 2, - textRect.y() + (textRect.height() - labelHeight) / 2, - pixmapWidth, pixmapHeight); - - iconRect = QStyle::visualRect(buttonOption->direction, textRect, iconRect); - - if (buttonOption->direction == Qt::RightToLeft) - { - tf |= Qt::AlignRight; - textRect.setRight(iconRect.left() - iconSpacing / 2); - } - else - { - tf |= Qt::AlignLeft; // left align, we adjust the text-rect instead - textRect.setLeft(iconRect.left() + iconRect.width() + iconSpacing / 2); - } - - if (buttonOption->state & (QStyle::State_On | QStyle::State_Sunken)) - iconRect.translate(style->pixelMetric(QStyle::PM_ButtonShiftHorizontal, option, widget), - style->pixelMetric(QStyle::PM_ButtonShiftVertical, option, widget)); - painter->drawPixmap(iconRect, pixmap); - } - else - { - tf |= Qt::AlignHCenter; - } - - if (buttonOption->state & (QStyle::State_On | QStyle::State_Sunken)) - { - textRect.translate(style->pixelMetric(QStyle::PM_ButtonShiftHorizontal, option, widget), - style->pixelMetric(QStyle::PM_ButtonShiftVertical, option, widget)); - } - - if (buttonOption->features & QStyleOptionButton::HasMenu) - { - int indicatorSize = style->pixelMetric(QStyle::PM_MenuButtonIndicator, buttonOption, widget); - if (buttonOption->direction == Qt::LeftToRight) - textRect = textRect.adjusted(0, 0, -indicatorSize, 0); - else - textRect = textRect.adjusted(indicatorSize, 0, 0, 0); - } - - QPalette palette = buttonOption->palette; - //按钮为高亮或警告色并且为启用状态修改文本颜色 - if( pushbutton && (StylePropertyHelper::getButtonType(pushbutton) != BUTTON_Normal) && (option->state & QStyle::State_Enabled) ) - { - palette.setColor(QPalette::ButtonText,Qt::white); - } - - style->drawItemText(painter, textRect, tf, palette, (buttonOption->state & QStyle::State_Enabled), - buttonOption->text, QPalette::ButtonText); - - return true; -} - -bool drawCCToolButton(const QStyle* style, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget) -{ - const auto* toolButtonOption(qstyleoption_cast(option)); - if (!toolButtonOption) return true; - - const QStyle::State& state(option->state); - bool enabled(state & QStyle::State_Enabled); - bool mouseOver((state & QStyle::State_Active) && enabled && (option->state & QStyle::State_MouseOver)); - bool hasFocus(enabled && (option->state & QStyle::State_HasFocus)); - bool sunken(state & (QStyle::State_On | QStyle::State_Sunken)); - bool flat(state & QStyle::State_AutoRaise); - - bool isDockWidgetTitleButton(widget && widget->inherits("QDockWidgetTitleButton")); - bool inTabBar(widget && qobject_cast(widget->parentWidget())); - bool isMenuTitle(RenderHelper::isMenuTitle(widget)); - - auto schemeLoader = SchemeLoaderFetcher::getSchemeLoader(); - if (isMenuTitle) - { - QStyleOptionToolButton copy(*toolButtonOption); - copy.font.setBold(false); - copy.state = QStyle::State_Enabled; - - auto separatorColor = schemeLoader->getColor(widget, option, SchemeLoader::Widget_Border); - return true; - } - - // copy option and alter palette - QStyleOptionToolButton copy(*toolButtonOption); - - if (isDockWidgetTitleButton) - { - const QAbstractButton* button(qobject_cast(widget)); - if (button->isChecked() || button->isDown()) - { - copy.state |= QStyle::State_Enabled | QStyle::State_On | QStyle::State_Sunken; - } - if (button->underMouse()) - { - copy.state |= QStyle::State_Enabled | QStyle::State_MouseOver | QStyle::State_Active; - } - } - - bool hasPopupMenu(toolButtonOption->features & QStyleOptionToolButton::MenuButtonPopup); - const bool hasInlineIndicator( - toolButtonOption->features & QStyleOptionToolButton::HasMenu && toolButtonOption->features & QStyleOptionToolButton::PopupDelay && !hasPopupMenu); - - QRect buttonRect(style->subControlRect(QStyle::CC_ToolButton, option, QStyle::SC_ToolButton, widget)); - QRect menuRect(style->subControlRect(QStyle::CC_ToolButton, option, QStyle::SC_ToolButtonMenu, widget)); - - // frame - if (toolButtonOption->subControls & QStyle::SC_ToolButton || isDockWidgetTitleButton) - { - copy.rect = buttonRect; - if (inTabBar) - { - QRect rect(option->rect); - - auto background = schemeLoader->getColor(widget, option, SchemeLoader::Widget_Background); - - painter->setPen(background); - painter->setBrush(background); - - switch (toolButtonOption->arrowType) - { - case Qt::UpArrow: - painter->drawRect(rect.adjusted(1, 1, -2, -1)); - break; - case Qt::DownArrow: - painter->drawRect(rect.adjusted(1, 0, -2, -2)); - break; - case Qt::LeftArrow: - painter->drawRect(rect.adjusted(1, 1, -1, -2)); - break; - case Qt::RightArrow: - painter->drawRect(rect.adjusted(0, 1, -2, -2)); - break; - } - -#if 0 - //位于QTabBar之上的QToolButton不绘制边框 - painter->setPen(border); - switch (toolButtonOption->arrowType) - { - case Qt::DownArrow: - painter->drawLine(rect.bottomLeft(), rect.bottomRight()); - break; - case Qt::RightArrow: - painter->drawLine(rect.topRight(), rect.bottomRight()); - break; - } - switch (toolButtonOption->arrowType) - { - case Qt::UpArrow: - case Qt::DownArrow: - painter->drawLine(rect.topLeft(), rect.bottomLeft()); - painter->drawLine(rect.topLeft(), rect.bottomLeft()); - break; - case Qt::LeftArrow: - case Qt::RightArrow: - painter->drawLine(rect.topLeft(), rect.topRight()); - painter->drawLine(rect.bottomLeft(), rect.bottomRight()); - break; - } -#endif - } - else if (sunken && hasPopupMenu && !(toolButtonOption->activeSubControls & QStyle::SC_ToolButton)) - { - // Only menu button is active. so draw left hand side od button raised - QStyleOptionToolButton btn(copy); - btn.state |= QStyle::State_Raised; - btn.state &= ~QStyle::State_Sunken; - btn.state &= ~QStyle::State_AutoRaise; - style->drawPrimitive(QStyle::PE_PanelButtonTool, &btn, painter, widget); - } - else - { - style->drawPrimitive(QStyle::PE_PanelButtonTool, ©, painter, widget); - } - } - - // arrow - if (hasPopupMenu) - { - copy.rect = menuRect; - - if (!flat || mouseOver || sunken) - style->drawPrimitive(QStyle::PE_IndicatorButtonDropDown, ©, painter, widget); - - style->drawPrimitive(QStyle::PE_IndicatorArrowDown, ©, painter, widget); - } - - else if (hasInlineIndicator) - { - copy.rect = menuRect; - - style->drawPrimitive(QStyle::PE_IndicatorArrowDown, ©, painter, widget); - } - - // contents - { - // restore state - copy.state = state; - - // define contents rect - QRect contentsRect(buttonRect); - - // detect dock widget title button - // for dockwidget title buttons, do not take out margins, so that icon do not get scaled down - if (isDockWidgetTitleButton) - { - // cast to abstract button - // adjust state to have correct icon rendered - const QAbstractButton* button(qobject_cast(widget)); - if (button->isChecked() || button->isDown()) - { - copy.state |= QStyle::State_Enabled | QStyle::State_On | QStyle::State_Sunken; - } - if (button->underMouse()) - { - copy.state |= QStyle::State_Enabled | QStyle::State_MouseOver | QStyle::State_Active; - } - } - else if (!inTabBar && hasInlineIndicator) - { - int marginWidth(flat ? Metrics::ToolButton_MarginWidth : Metrics::Button_MarginWidth + Metrics::Frame_FrameWidth); - contentsRect = RenderHelper::insideMargin(contentsRect, marginWidth, 0); - contentsRect.setRight(contentsRect.right() - Metrics::ToolButton_InlineIndicatorWidth); - contentsRect = QStyle::visualRect(option->direction, option->rect, contentsRect); - } - - copy.rect = contentsRect; - - // render - style->drawControl(QStyle::CE_ToolButtonLabel, ©, painter, widget); - } - return true; -} -} // namespace Kiran \ No newline at end of file diff --git a/style/src/draw-helper/draw-button-helper.h b/style/src/draw-helper/draw-button-helper.h deleted file mode 100644 index 2eab3c28ed679514bd63549534fcca682ee6460f..0000000000000000000000000000000000000000 --- a/style/src/draw-helper/draw-button-helper.h +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. - * kiran-qt5-integration is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - * - * Author: liuxinhao - */ -#ifndef KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_DRAW_HELPER_DRAW_BUTTON_HELPER_H_ -#define KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_DRAW_HELPER_DRAW_BUTTON_HELPER_H_ - -#include - -class QStyleOption; -class QPainter; -class QWidget; -class QStyleOptionComplex; -class QStyle; -namespace Kiran -{ -class SchemeLoader; - -// sizeFromContents -QSize pushButtonSizeFromContents(const QStyle* style, const QStyleOption* option, const QSize& contentSize, const QWidget* widget); -QSize toolButtonSizeFromContents(const QStyle* style, const QStyleOption* option, const QSize& contentSize, const QWidget* widget); - -// subControlRect -bool toolButtonSubControlRect(const QStyle* style, const QStyleOptionComplex* opt, QStyle::SubControl sc, const QWidget* widget, QRect& controlRect); - -// drawPrimitive -bool drawPEPanelButtonCommand(const QStyle* style, const QStyleOption* option, QPainter* painter, const QWidget* widget); -bool drawPEPanelButtonTool(const QStyle* style, const QStyleOption* option, QPainter* painter, const QWidget* widget); - -// drawControl -bool drawControlPushButtonLabel(const QStyle* style, const QStyleOption* option, QPainter* painter, const QWidget* widget); -bool drawControlToolButtonLabel(const QStyle* style, const QStyleOption* option, QPainter* painter, const QWidget* widget); - -// drawComplexControl -bool drawCCToolButton(const QStyle* style, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget); -} // namespace Kiran - -#endif // KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_DRAW_HELPER_DRAW_BUTTON_HELPER_H_ diff --git a/style/src/draw-helper/draw-combo-box-helper.cpp b/style/src/draw-helper/draw-combo-box-helper.cpp deleted file mode 100644 index 7844ee5826d4cd51601ce3de4f0ea04b0f36fede..0000000000000000000000000000000000000000 --- a/style/src/draw-helper/draw-combo-box-helper.cpp +++ /dev/null @@ -1,290 +0,0 @@ -/** - * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. - * kiran-qt5-integration is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - * - * Author: liuxinhao - */ -#include "draw-combo-box-helper.h" -#include "draw-common-helper.h" -#include "metrics.h" -#include "render-helper.h" -#include "scheme-loader-fetcher.h" - -#include -#include -#include -#include - -namespace Kiran -{ -QSize comboBoxSizeFromContents(const QStyle *style, const QStyleOption *option, const QSize &contentSize, const QWidget *widget) -{ - const auto comboBoxOption(qstyleoption_cast(option)); - if (!comboBoxOption) return contentSize; - - QSize size(contentSize); - - // 若存在Frame绘制,大小扩展开 FrameWidth - const bool flat(!comboBoxOption->frame); - const int frameWidth(style->pixelMetric(QStyle::PM_ComboBoxFrameWidth, option, widget)); - if (!flat) - { - size = RenderHelper::expandSize(size, frameWidth); - } - - size.rwidth() += Metrics::MenuButton_IndicatorWidth; - size.rwidth() += Metrics::Button_ItemSpacing; - - size.rwidth() += size.height(); - - // 确保有足够的高度绘制下拉按钮指示器 - size.setHeight(qMax(size.height(), int(Metrics::MenuButton_IndicatorWidth))); - - // size = RenderHelper::expandSize(size, Metrics::ComboBox_MarginWidth, Metrics::ComboBox_MarginHeight); - - // 确保至少有最小大小 - size.setHeight(qMax(size.height(), int(Metrics::ComboBox_MinHeight))); - size.setWidth(qMax(size.width(), int(Metrics::ComboBox_MinWidth))); - - return size; -} - -bool comboBoxSubControlRect(const QStyle *style, const QStyleOptionComplex *opt, QStyle::SubControl sc, const QWidget *widget, QRect &controlRect) -{ - const auto comboBoxOption(qstyleoption_cast(opt)); - if (!comboBoxOption) return false; - - const bool editable(comboBoxOption->editable); - const bool flat(editable && !comboBoxOption->frame); - - auto rect(opt->rect); - - const int frameWidth(style->pixelMetric(QStyle::PM_ComboBoxFrameWidth, opt, widget)); - - switch (sc) - { - case QStyle::SC_ComboBoxFrame: - controlRect = flat ? rect : QRect(); - break; - case QStyle::SC_ComboBoxListBoxPopup: - controlRect = rect; - break; - case QStyle::SC_ComboBoxArrow: - controlRect = QRect(rect.right() - rect.height() + 1, - rect.top(), - rect.height(), rect.height()); - break; - case QStyle::SC_ComboBoxEditField: - { - controlRect = QRect(rect.left(), rect.top(), rect.width() - rect.height() - 4, rect.height()); - controlRect.adjust(frameWidth, frameWidth, 0, -frameWidth); - controlRect = QStyle::visualRect(opt->direction, opt->rect, controlRect); - break; - } - default: - return false; - } - return true; -} - -bool drawCCComboBox(const QStyle *style, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) -{ - const auto comboBoxOption(qstyleoption_cast(option)); - if (!comboBoxOption) - { - return true; - } - - const QStyle::State &state(option->state); - bool enabled(state & QStyle::State_Enabled); - bool windowActive(state & QStyle::State_Active); - bool editable(comboBoxOption->editable); - bool arrowActive(comboBoxOption->activeSubControls & QStyle::SC_ComboBoxArrow); - bool flat(!comboBoxOption->frame); - bool sunken; - - auto schemeLoader = SchemeLoaderFetcher::getSchemeLoader(); - - if (editable) - { - sunken = arrowActive && enabled && (state & (QStyle::State_On | QStyle::State_Sunken)); - } - else - { - sunken = enabled && (state & (QStyle::State_On | QStyle::State_Sunken)); - } - - const auto comboBox = qobject_cast(widget); - if (!comboBox) - return true; - - const bool empty(comboBox && !comboBox->count()); - - // TODO: 当ComboBox为空时,应当特别绘制 - // frame - if (option->subControls & QStyle::SC_ComboBoxFrame) - { - if (editable) - { - // FIXME:下拉框编辑状态悬浮判断没有区域 - flat |= (option->rect.height() <= 2 * Metrics::Frame_FrameWidth + Metrics::MenuButton_IndicatorWidth); - if (flat) - { - const auto &background = option->palette.color(QPalette::Base); - painter->setBrush(background); - painter->setPen(Qt::NoPen); - painter->drawRect(option->rect); - } - else - { - QRectF arrowRect = style->subControlRect(QStyle::CC_ComboBox, comboBoxOption, QStyle::SC_ComboBoxArrow, widget); - - // ComboBox 箭头按钮 - arrowRect.adjust(1.5, 1.5, -1.5, -1.5); - QPainterPath indicatorPainterPath = RenderHelper::roundedPath(arrowRect, CornersRight, 4); - - auto background = schemeLoader->getColor(widget, option, SchemeLoader::Combo_Background); - auto border = schemeLoader->getColor(widget, option, SchemeLoader::Combo_Border); - - QPen pen = painter->pen(); - painter->setRenderHints(QPainter::Antialiasing); - painter->setPen(border); - painter->setBrush(background); - painter->drawPath(indicatorPainterPath); - - // 输入框 - QStyleOptionComplex tmpOpt(*option); - // 让输入框长度加上一个宽度进行绘制用来去掉输入框的圆角 - tmpOpt.rect.setWidth(tmpOpt.rect.width() - arrowRect.width() + 3); - style->drawPrimitive(QStyle::PE_FrameLineEdit, &tmpOpt, painter, widget); - } - } - else - { - if (flat) - { - auto background = option->palette.color(QPalette::Base); - if (sunken) - { - background = schemeLoader->getColor(widget, option, SchemeLoader::Combo_Background); - } - RenderHelper::renderFrame(painter, option->rect, 1, 0, background); - } - else - { - QStyleOptionComboBox tempOption(*comboBoxOption); - auto backgroundColor = schemeLoader->getColor(widget, &tempOption, SchemeLoader::Combo_Background); - auto borderColor = schemeLoader->getColor(widget, &tempOption, SchemeLoader::Combo_Border); - RenderHelper::renderFrame(painter, option->rect, 1, 4, backgroundColor, borderColor); - } - } - } - - // arrow - if (option->subControls & QStyle::SC_ComboBoxArrow) - { - auto arrowRect(style->subControlRect(QStyle::CC_ComboBox, option, QStyle::SC_ComboBoxArrow, widget)); - auto arrowColor = schemeLoader->getColor(widget, option, SchemeLoader::Indicator_Arrow); - RenderHelper::renderArrow(painter, arrowRect, Arrow_Down, arrowColor); - } - - return true; -} - -bool drawControlComboBoxLabel(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget) -{ - const auto comboBoxOption(qstyleoption_cast(option)); - if (!comboBoxOption) return false; - if (comboBoxOption->editable) return false; - - const QStyle::State &state(option->state); - const bool enabled(state & QStyle::State_Enabled); - const bool sunken(state & (QStyle::State_On | QStyle::State_Sunken)); - const bool mouseOver(enabled && (option->state & QStyle::State_MouseOver)); - const bool hasFocus(enabled && !mouseOver && (option->state & QStyle::State_HasFocus)); - const bool flat(!comboBoxOption->frame); - - QPalette::ColorRole textRole; - if (flat) - { - textRole = QPalette::WindowText; - } - else if (hasFocus) - { - textRole = QPalette::ButtonText; - } - else - { - textRole = QPalette::ButtonText; - } - - painter->setPen(QPen(option->palette.color(textRole), 1)); - - // 获取文本框位置 - auto editRect = style->subControlRect(QStyle::CC_ComboBox, comboBoxOption, QStyle::SC_ComboBoxEditField, widget); - - painter->save(); - painter->setClipRect(editRect); - // 绘制图标 - if (!comboBoxOption->currentIcon.isNull() && qobject_cast(widget)) - { - QIcon::Mode mode; - - if ((comboBoxOption->state & QStyle::State_Selected) && (comboBoxOption->state & QStyle::State_Active)) - { - mode = QIcon::Selected; - } - else if (comboBoxOption->state & QStyle::State_Enabled) - { - mode = QIcon::Normal; - } - else - { - mode = QIcon::Disabled; - } - - QPixmap pixmap = comboBoxOption->currentIcon.pixmap(comboBoxOption->iconSize, mode); - QRect iconRect(editRect); - iconRect.setWidth(comboBoxOption->iconSize.width() + 4); - iconRect = QStyle::alignedRect(comboBoxOption->direction, - Qt::AlignLeft | Qt::AlignVCenter, - iconRect.size(), editRect); - - if (comboBoxOption->editable) - { - painter->fillRect(iconRect, option->palette.brush(QPalette::Base)); - } - - style->drawItemPixmap(painter, iconRect, Qt::AlignCenter, pixmap); - - if (comboBoxOption->direction == Qt::RightToLeft) - { - editRect.translate(-4 - comboBoxOption->iconSize.width(), 0); - } - else - { - editRect.translate(comboBoxOption->iconSize.width() + 4, 0); - } - } - - // 绘制文本 - if (!comboBoxOption->currentText.isEmpty() && !comboBoxOption->editable) - { - QRect itemTextRect = editRect.adjusted(Metrics::ComboBox_FrameWidth, 0, -1, 0); - int itemTextFlags = QStyle::visualAlignment(comboBoxOption->direction, Qt::AlignLeft | Qt::AlignVCenter); - bool itemTextEnable = comboBoxOption->state & QStyle::State_Enabled; - style->drawItemText(painter, itemTextRect, itemTextFlags, comboBoxOption->palette, itemTextEnable, comboBoxOption->currentText); - } - - painter->restore(); - - return true; -} -} // namespace Kiran \ No newline at end of file diff --git a/style/src/draw-helper/draw-combo-box-helper.h b/style/src/draw-helper/draw-combo-box-helper.h deleted file mode 100644 index 08dc7ef5b22189695808272203596f370705bb2f..0000000000000000000000000000000000000000 --- a/style/src/draw-helper/draw-combo-box-helper.h +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. - * kiran-qt5-integration is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - * - * Author: liuxinhao - */ -#ifndef KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_DRAW_HELPER_DRAW_COMBO_BOX_HELPER_H_ -#define KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_DRAW_HELPER_DRAW_COMBO_BOX_HELPER_H_ - -#include - -class QStyleOptionComplex; -class QStyleOption; -class QWidget; -class QPainter; - -namespace Kiran -{ -class SchemeLoader; - -QSize comboBoxSizeFromContents(const QStyle* style, const QStyleOption* option, const QSize& contentSize, const QWidget* widget); -bool comboBoxSubControlRect(const QStyle* style, const QStyleOptionComplex* opt, QStyle::SubControl sc, const QWidget* widget, QRect& controlRect); -bool drawCCComboBox(const QStyle* style, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget); -bool drawControlComboBoxLabel(const QStyle* style, const QStyleOption* option, QPainter* painter, const QWidget* widget); -} - -#endif //KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_DRAW_HELPER_DRAW_COMBO_BOX_HELPER_H_ diff --git a/style/src/draw-helper/draw-common-helper.cpp b/style/src/draw-helper/draw-common-helper.cpp deleted file mode 100644 index ed946545f824fef5e05d555fc6dd6dc6d72f2565..0000000000000000000000000000000000000000 --- a/style/src/draw-helper/draw-common-helper.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/** - * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. - * kiran-qt5-integration is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - * - * Author: liuxinhao - */ -#include "draw-common-helper.h" -#include "render-helper.h" - -#include "scheme-loader-fetcher.h" -#include "style-palette.h" - -#define private public -#include -#undef private - -#include -#include -#include -#include -#include - -namespace Kiran -{ -bool drawPEFrame(const QStyle *style, - const QStyleOption *option, - QPainter *painter, - const QWidget *widget) -{ - QColor border,background; - - auto schemeLoader = SchemeLoaderFetcher::getSchemeLoader(); - background = schemeLoader->getColor(widget,option,SchemeLoader::Frame_Background); - border = schemeLoader->getColor(widget,option,SchemeLoader::Frame_Border); - - if( qobject_cast(widget) ) - { - RenderHelper::renderFrame(painter, option->rect, 1, 0, Qt::transparent,border ); - } - else - { - RenderHelper::renderFrame(painter, option->rect, 1, 0, background,border ); - } - - return true; -} - -bool drawPEFrameFocusRect(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget) -{ - //TODO:聚焦虚线框 颜色? 增加配置文件聚焦虚线框可配置 - return true; -} - -bool drawPEFrameGroupBox(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget) -{ - const auto frameOption(qstyleoption_cast(option)); - if (!frameOption) return true; - - // no frame for flat groupboxes - if (frameOption->features & QStyleOptionFrame::Flat) return true; - - auto schemeLoader = SchemeLoaderFetcher::getSchemeLoader(); - auto background = schemeLoader->getColor(widget,option,SchemeLoader::Frame_Background); - auto border = schemeLoader->getColor(widget,option,SchemeLoader::Frame_Border); - - RenderHelper::renderFrame(painter, option->rect,1, 0, background, border); - return true; -} - -bool drawControlShapedFrame(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget) -{ - const auto *frameOpt = qstyleoption_cast(option); - if (!frameOpt) - { - return false; - } - - switch (frameOpt->frameShape) - { - case QFrame::Box: - { - if (option->state & QStyle::State_Sunken) - { - return true; - } - else - { - break; - } - - } - case QFrame::HLine: - case QFrame::VLine: - { - const QRect &rect(option->rect); - bool isVertical(frameOpt->frameShape == QFrame::VLine); - - QColor color = StylePalette::instance()->color(widget,option, StylePalette::Window, StylePalette::Border); - RenderHelper::renderSeparator(painter, option->rect, isVertical, color); - return true; - } - case QFrame::StyledPanel: - { - if (RenderHelper::isQtQuickControl(option, widget)) - { - style->drawPrimitive(QStyle::PE_FrameMenu,option,painter,widget); - return true; - } - break; - } - default: - break; - } - - return false; -} - -QSize defaultSizeFromContents(const QStyleOption* option, const QSize &contentSize, const QWidget *widget) -{ - return contentSize; -} -} diff --git a/style/src/draw-helper/draw-common-helper.h b/style/src/draw-helper/draw-common-helper.h deleted file mode 100644 index 4dae6e1ef8b7799122d1e325fff3cb545e9d84fc..0000000000000000000000000000000000000000 --- a/style/src/draw-helper/draw-common-helper.h +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. - * kiran-qt5-integration is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - * - * Author: liuxinhao - */ -#ifndef KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_DRAW_HELPER_DRAW_COMMON_HELPER_H_ -#define KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_DRAW_HELPER_DRAW_COMMON_HELPER_H_ - -#include "define.h" - -#include -#include -#include -#include - -class QStyle; -class QStyleOption; -class QStyleOptionToolButton; - -namespace Kiran -{ -class SchemeLoader; - -bool drawPEFrame(const QStyle* style, const QStyleOption* option, QPainter* painter, const QWidget* widget); -bool drawPEFrameFocusRect(const QStyle* style, const QStyleOption* option, QPainter* painter, const QWidget* widget); -bool drawPEFrameGroupBox(const QStyle* style, const QStyleOption* option, QPainter* painter, const QWidget* widget); - -bool drawControlShapedFrame(const QStyle* style, const QStyleOption* option, QPainter* painter, const QWidget* widget); - -QSize defaultSizeFromContents(const QStyleOption* option, const QSize& contentSize, const QWidget* widget); -} // namespace Kiran - -#endif //KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_DRAW_HELPER_DRAW_COMMON_HELPER_H_ diff --git a/style/src/draw-helper/draw-edit-helper.cpp b/style/src/draw-helper/draw-edit-helper.cpp deleted file mode 100644 index b47e159a0dc6ec6ec8408caeb3bb84f894e0ba29..0000000000000000000000000000000000000000 --- a/style/src/draw-helper/draw-edit-helper.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. - * kiran-qt5-integration is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - * - * Author: liuxinhao - */ -#include "draw-edit-helper.h" -#include "draw-common-helper.h" -#include "render-helper.h" -#include "scheme-loader-fetcher.h" -#include "style-palette.h" - -#include -#include -#include -#include -#include - -namespace Kiran -{ -bool drawPEFrameLineEdit(const QStyle* style, const QStyleOption* option, QPainter* painter, const QWidget* widget) -{ - const auto& rect = option->rect; - - auto schemeLoader = SchemeLoaderFetcher::getSchemeLoader(); - auto background = schemeLoader->getColor(widget, option, SchemeLoader::Edit_Background); - auto border = schemeLoader->getColor(widget, option, SchemeLoader::Edit_Border); - - // 控件高度不足够绘制边框 - if (rect.height() < 2 + option->fontMetrics.height()) - { - painter->save(); - painter->setRenderHint(QPainter::Antialiasing, true); - painter->setPen(Qt::NoPen); - painter->setBrush(background); - painter->drawRect(rect); - painter->restore(); - } - else - { - if (qobject_cast(widget)) - RenderHelper::renderFlatFrame(painter, rect, 4, background, border); - else - RenderHelper::renderFrame(painter, rect, 1, 4, background, border); - } - - return true; -} -} // namespace Kiran diff --git a/style/src/draw-helper/draw-edit-helper.h b/style/src/draw-helper/draw-edit-helper.h deleted file mode 100644 index 869a81d40898390c0a70dabb2c186c8dad83d291..0000000000000000000000000000000000000000 --- a/style/src/draw-helper/draw-edit-helper.h +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. - * kiran-qt5-integration is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - * - * Author: liuxinhao - */ -#ifndef KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_DRAW_HELPER_DRAW_EDIT_HELPER_H_ -#define KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_DRAW_HELPER_DRAW_EDIT_HELPER_H_ - -class QStyle; -class QStyleOption; -class QPainter; -class QWidget; -namespace Kiran -{ -class SchemeLoader; -bool drawPEFrameLineEdit(const QStyle* style, const QStyleOption* option, QPainter* painter, const QWidget* widget); -} // namespace Kiran - -#endif // KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_DRAW_HELPER_DRAW_EDIT_HELPER_H_ diff --git a/style/src/draw-helper/draw-group-box-helper.cpp b/style/src/draw-helper/draw-group-box-helper.cpp deleted file mode 100644 index 6b9fdf8fa5ef16c17b589aa852e30c4e8fbac155..0000000000000000000000000000000000000000 --- a/style/src/draw-helper/draw-group-box-helper.cpp +++ /dev/null @@ -1,201 +0,0 @@ -/** - * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. - * kiran-qt5-integration is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - * - * Author: liuxinhao - */ -#include "draw-group-box-helper.h" -#include -#include -#include -#include - -namespace Kiran -{ -// copy from QCommonStyle -QSize groupBoxSizeFromContents(const QStyle *style, const QStyleOption *option, const QSize &contentSize, const QWidget *widget) -{ - if (!widget || !widget->inherits("QGroupBox")) - { - return {}; - } - - auto groupBox = qobject_cast(widget); - QSize size = contentSize + QSize(groupBox->isFlat() ? 16 : 0, 0); - - return size; -} - -// copy from QCommonStyle -bool groupBoxSubControlRect(const QStyle *style, const QStyleOptionComplex *opt, QStyle::SubControl sc, const QWidget *widget, QRect &controlRect) -{ - const auto groupBox = qstyleoption_cast(opt); - if (!groupBox) - return false; - - switch (sc) - { - case QStyle::SC_GroupBoxFrame: - case QStyle::SC_GroupBoxContents: - { - int topMargin = 0; - int topHeight = 0; - int verticalAlignment = style->styleHint(QStyle::SH_GroupBox_TextLabelVerticalAlignment, groupBox, widget); - if (groupBox->text.size() || (groupBox->subControls & QStyle::SC_GroupBoxCheckBox)) - { - topHeight = groupBox->fontMetrics.height(); - if (verticalAlignment & Qt::AlignVCenter) - topMargin = topHeight / 2; - else if (verticalAlignment & Qt::AlignTop) - topMargin = topHeight; - } - - QRect frameRect = groupBox->rect; - frameRect.setTop(topMargin); - - if (sc == QStyle::SC_GroupBoxFrame) - { - controlRect = frameRect; - break; - } - - int frameWidth = 0; - if ((groupBox->features & QStyleOptionFrame::Flat) == 0) - frameWidth = style->pixelMetric(QStyle::PM_DefaultFrameWidth, groupBox, widget); - controlRect = frameRect.adjusted(frameWidth, frameWidth + topHeight - topMargin, -frameWidth, -frameWidth); - break; - } - case QStyle::SC_GroupBoxCheckBox: - case QStyle::SC_GroupBoxLabel: - { - QFontMetrics fontMetrics = groupBox->fontMetrics; - int h = fontMetrics.height(); - int tw = fontMetrics.size(Qt::TextShowMnemonic, groupBox->text + QLatin1Char(' ')).width(); - int marg = (groupBox->features & QStyleOptionFrame::Flat) ? 0 : 8; - controlRect = groupBox->rect.adjusted(marg, 0, -marg, 0); - controlRect.setHeight(h); - - int indicatorWidth = style->pixelMetric(QStyle::PM_IndicatorWidth, opt, widget); - int indicatorSpace = style->pixelMetric(QStyle::PM_CheckBoxLabelSpacing, opt, widget) - 1; - bool hasCheckBox = groupBox->subControls & QStyle::SC_GroupBoxCheckBox; - int checkBoxSize = hasCheckBox ? (indicatorWidth + indicatorSpace) : 0; - - // Adjusted rect for label + indicatorWidth + indicatorSpace - QRect totalRect = QStyle::alignedRect(groupBox->direction, groupBox->textAlignment, - QSize(tw + checkBoxSize, h), controlRect); - - // Adjust totalRect if checkbox is set - if (hasCheckBox) - { - bool ltr = groupBox->direction == Qt::LeftToRight; - int left = 0; - // Adjust for check box - if (sc == QStyle::SC_GroupBoxCheckBox) - { - int indicatorHeight = style->pixelMetric(QStyle::PM_IndicatorHeight, opt, widget); - left = ltr ? totalRect.left() : (totalRect.right() - indicatorWidth); - int top = totalRect.top() + qMax(0, fontMetrics.height() - indicatorHeight) / 2; - totalRect.setRect(left, top, indicatorWidth, indicatorHeight); - // Adjust for label - } - else - { - left = ltr ? (totalRect.left() + checkBoxSize - 2) : totalRect.left(); - totalRect.setRect(left, totalRect.top(), - totalRect.width() - checkBoxSize, totalRect.height()); - } - } - controlRect = totalRect; - break; - } - default: - return false; - } - - return true; -} - -// copy from QCommonStyle -bool drawCCGroupBox(const QStyle *style, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) -{ - const auto *groupBox = qstyleoption_cast(option); - if (!groupBox) - { - return false; - } - - // Draw frame - QRect textRect = style->subControlRect(QStyle::CC_GroupBox, option, QStyle::SC_GroupBoxLabel, widget); - QRect checkBoxRect = style->subControlRect(QStyle::CC_GroupBox, option, QStyle::SC_GroupBoxCheckBox, widget); - if (groupBox->subControls & QStyle::SC_GroupBoxFrame) - { - QStyleOptionFrame frame; - frame.QStyleOption::operator=(*groupBox); - frame.features = groupBox->features; - frame.lineWidth = groupBox->lineWidth; - frame.midLineWidth = groupBox->midLineWidth; - frame.rect = style->subControlRect(QStyle::CC_GroupBox, option, QStyle::SC_GroupBoxFrame, widget); - painter->save(); - QRegion region(groupBox->rect); - if (!groupBox->text.isEmpty()) - { - bool ltr = groupBox->direction == Qt::LeftToRight; - QRect finalRect; - if (groupBox->subControls & QStyle::SC_GroupBoxCheckBox) - { - finalRect = checkBoxRect.united(textRect); - finalRect.adjust(ltr ? -4 : 0, 0, ltr ? 0 : 4, 0); - } - else - { - finalRect = textRect; - } - region -= finalRect; - } - painter->setClipRegion(region); - style->drawPrimitive(QStyle::PE_FrameGroupBox, &frame, painter, widget); - painter->restore(); - } - - // Draw title - if ((groupBox->subControls & QStyle::SC_GroupBoxLabel) && !groupBox->text.isEmpty()) - { - QColor textColor = groupBox->textColor; - if (textColor.isValid()) - painter->setPen(textColor); - int alignment = int(groupBox->textAlignment); - if (!style->styleHint(QStyle::SH_UnderlineShortcut, option, widget)) - alignment |= Qt::TextHideMnemonic; - - style->drawItemText(painter, textRect, Qt::TextShowMnemonic | Qt::AlignHCenter | alignment, - groupBox->palette, groupBox->state & QStyle::State_Enabled, groupBox->text, - textColor.isValid() ? QPalette::NoRole : QPalette::WindowText); - - if (groupBox->state & QStyle::State_HasFocus) - { - QStyleOptionFocusRect fropt; - fropt.QStyleOption::operator=(*groupBox); - fropt.rect = textRect; - style->drawPrimitive(QStyle::PE_FrameFocusRect, &fropt, painter, widget); - } - } - - // Draw checkbox - if (groupBox->subControls & QStyle::SC_GroupBoxCheckBox) - { - QStyleOptionButton box; - box.QStyleOption::operator=(*groupBox); - box.rect = checkBoxRect; - style->drawPrimitive(QStyle::PE_IndicatorCheckBox, &box, painter, widget); - } - - return true; -} -} // namespace Kiran \ No newline at end of file diff --git a/style/src/draw-helper/draw-group-box-helper.h b/style/src/draw-helper/draw-group-box-helper.h deleted file mode 100644 index 85b1ba9967ffc0cbf31daedf93c3ffe1fb04ba76..0000000000000000000000000000000000000000 --- a/style/src/draw-helper/draw-group-box-helper.h +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. - * kiran-qt5-integration is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - * - * Author: liuxinhao - */ - -#ifndef KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_DRAW_HELPER_DRAW_GROUP_BOX_HELPER_H_ -#define KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_DRAW_HELPER_DRAW_GROUP_BOX_HELPER_H_ - -#include - -class QStyle; -class QWidget; -class QStyleOption; -class QStyleOptionComplex; - -///绘制QGroupBox - -namespace Kiran -{ -class SchemeLoader; -QSize groupBoxSizeFromContents(const QStyle* style,const QStyleOption* option,const QSize& contentSize,const QWidget* widget); -bool groupBoxSubControlRect(const QStyle* style, const QStyleOptionComplex* opt, QStyle::SubControl sc, const QWidget* widget, QRect& controlRect); -bool drawCCGroupBox(const QStyle* style, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget); -} - -#endif //KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_DRAW_HELPER_DRAW_GROUP_BOX_HELPER_H_ diff --git a/style/src/draw-helper/draw-indicator-helper.cpp b/style/src/draw-helper/draw-indicator-helper.cpp deleted file mode 100644 index 00efe7757d9c1c30e3fcdc5d62955925a6c46acc..0000000000000000000000000000000000000000 --- a/style/src/draw-helper/draw-indicator-helper.cpp +++ /dev/null @@ -1,277 +0,0 @@ -/** - * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. - * kiran-qt5-integration is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - * - * Author: liuxinhao - */ -#include "draw-indicator-helper.h" -#include "draw-common-helper.h" -#include "metrics.h" -#include "render-helper.h" -#include "scheme-loader-fetcher.h" - -#include -#include -#include -#include -#include -#include - -namespace Kiran -{ -bool drawPEIndicatorButtonDropDown(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget) -{ - const auto toolButtonOption(qstyleoption_cast(option)); - if (!toolButtonOption) - return true; - - const QStyle::State &state(option->state); - bool autoRaise(state & QStyle::State_AutoRaise); - bool enabled(state & QStyle::State_Enabled); - bool mouseOver((state & QStyle::State_Active) && enabled && (state & QStyle::State_MouseOver)); - bool sunken(enabled && (state & QStyle::State_Sunken)); - - // do nothing for autoraise buttons - if ((autoRaise && !sunken && !mouseOver) || !(toolButtonOption->subControls & QStyle::SC_ToolButtonMenu)) - return true; - - const QPalette &palette(option->palette); - const QRect &rect(option->rect); - - auto schemeLoader = SchemeLoaderFetcher::getSchemeLoader(); - auto backgroundColor = schemeLoader->getColor(widget, option, SchemeLoader::Button_Background); - auto borderColor = schemeLoader->getColor(widget, option, SchemeLoader::Button_Border); - auto separatorColor = borderColor; - - QRect frameRect(rect); - painter->setClipRect(rect); - frameRect.adjust(-Metrics::Frame_FrameRadius - 1, 0, 0, 0); - frameRect = QStyle::visualRect(option->direction, option->rect, frameRect); - - // render - RenderHelper::renderFrame(painter, frameRect, 1, 4, backgroundColor, borderColor); - - // also render separator - QRect separatorRect(rect.adjusted(0, 2, -2, -2)); - separatorRect.setWidth(1); - separatorRect = QStyle::visualRect(option->direction, option->rect, separatorRect); - RenderHelper::renderSeparator(painter, separatorRect, true, separatorColor); - - return true; -} - -bool drawPEIndicatorArrow(ArrowOrientation orientation, const QStyleOption *option, QPainter *painter, const QWidget *widget) -{ - auto schemeLoader = SchemeLoaderFetcher::getSchemeLoader(); - auto arrowColor = schemeLoader->getColor(widget, option, SchemeLoader::Indicator_Arrow); - - RenderHelper::renderArrow(painter, option->rect, orientation, arrowColor); - return true; -} - -bool drawPEIndicatorArrowUp(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget) -{ - return drawPEIndicatorArrow(Arrow_Up, option, painter, widget); -} - -bool drawPEIndicatorArrowDown(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget) -{ - return drawPEIndicatorArrow(Arrow_Down, option, painter, widget); -} - -bool drawPEIndicatorArrowLeft(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget) -{ - return drawPEIndicatorArrow(Arrow_Left, option, painter, widget); -} - -bool drawPEIndicatorArrowRight(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget) -{ - return drawPEIndicatorArrow(Arrow_Right, option, painter, widget); -} - -bool drawPEIndicatorRadioButton(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget) -{ - const auto &rect(option->rect); - - bool checked = option->state & QStyle::State_On; - QString state = "normal"; - if (!(option->state & QStyle::State_Enabled)) - { - state = "disabled"; - } - else if ((option->state & QStyle::State_Sunken)) - { - state = "active"; - } - else if ((option->state & QStyle::State_MouseOver)) - { - state = "hover"; - } - QString iconUrl = QString(":/style-helper/images/radio-%1-%2.svg").arg(checked ? "checked" : "unchecked").arg(state); - - painter->save(); - painter->setRenderHints(QPainter::SmoothPixmapTransform | QPainter::HighQualityAntialiasing); - QSvgRenderer renderer(iconUrl); - renderer.render(painter, rect); - painter->restore(); - return true; -} - -bool drawPEIndicatorCheckBox(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget) -{ - const auto &rect(option->rect); - - bool checked = option->state & QStyle::State_On; - QString state = "normal"; - if (!(option->state & QStyle::State_Enabled)) - { - state = "disabled"; - } - else if ((option->state & QStyle::State_Sunken)) - { - state = "active"; - } - else if ((option->state & QStyle::State_MouseOver)) - { - state = "hover"; - } - QString iconUrl = QString(":/style-helper/images/check-%1-%2.svg").arg(checked ? "checked" : "unchecked").arg(state); - - painter->save(); - painter->setRenderHints(QPainter::SmoothPixmapTransform | QPainter::HighQualityAntialiasing); - QSvgRenderer renderer(iconUrl); - renderer.render(painter, rect); - painter->restore(); - return true; -} - -bool drawPEIndicatorBranch(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget) -{ - const QRect &rect(option->rect); - const QPalette &palette(option->palette); - - const QStyle::State &state(option->state); - bool reverseLayout(option->direction == Qt::RightToLeft); - - auto schemeLoader = SchemeLoaderFetcher::getSchemeLoader(); - - // 绘制扩展的箭头 - int expanderAdjust = 0; - if (state & QStyle::State_Children) - { - // state - bool expanderOpen(state & QStyle::State_Open); - bool enabled(state & QStyle::State_Enabled); - bool mouseOver((state & QStyle::State_Active) && enabled && (state & QStyle::State_MouseOver)); - - // expander rect - int expanderSize = qMin(rect.width(), rect.height()); - expanderSize = qMin(expanderSize, int(Metrics::ItemView_ArrowSize)); - expanderAdjust = expanderSize / 2 + 1; - QRect arrowRect = RenderHelper::centerRect(rect, expanderSize, expanderSize); - - // get orientation from option - ArrowOrientation orientation; - if (expanderOpen) - { - orientation = Arrow_Down; - } - else if (reverseLayout) - { - orientation = Arrow_Left; - } - else - { - orientation = Arrow_Right; - } - auto arrowColor = schemeLoader->getColor(widget, option, SchemeLoader::Indicator_Arrow); - RenderHelper::renderArrow(painter, arrowRect, orientation, arrowColor, QSize(12, 12)); - } - - if (!RenderHelper::drawTreeBranches()) - { - return true; - } - - QPoint center(rect.center()); - auto lineColor = schemeLoader->getColor(widget, option, SchemeLoader::Frame_Border); - painter->save(); - painter->setRenderHint(QPainter::Antialiasing, true); - painter->translate(0.5, 0.5); - painter->setPen(QPen(lineColor, 1)); - if (state & (QStyle::State_Item | QStyle::State_Children | QStyle::State_Sibling)) - { - QLineF line(QPointF(center.x(), rect.top()), QPointF(center.x(), center.y() - expanderAdjust - 1)); - painter->drawLine(line); - } - - // 如果存在Item则绘制左/右取决与方向的线 - if (state & QStyle::State_Item) - { - const QLineF line = reverseLayout ? QLineF(QPointF(rect.left(), center.y()), QPointF(center.x() - expanderAdjust, center.y())) : QLineF(QPointF(center.x() + expanderAdjust, center.y()), QPointF(rect.right(), center.y())); - painter->drawLine(line); - } - - // 如果存在同级节点的话,则绘制上下的线 - if (state & QStyle::State_Sibling) - { - QLineF line(QPointF(center.x(), center.y() + expanderAdjust), QPointF(center.x(), rect.bottom())); - painter->drawLine(line); - } - painter->restore(); - - return true; -} - -bool drawPEIndicatorToolBarSeparator(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget) -{ - const QStyle::State &state = option->state; - bool enable = (state & QStyle::State_Enabled); - bool separatorIsVertical(state & QStyle::State_Horizontal); - - auto schemeLoader = SchemeLoaderFetcher::getSchemeLoader(); - auto separatorColor = schemeLoader->getColor(widget, option, SchemeLoader::Widget_Border); - RenderHelper::renderSeparator(painter, option->rect, separatorIsVertical, separatorColor); - return true; -} - -bool drawPEIndicatorToolBarHandle(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget) -{ - const QStyle::State &state = option->state; - QRect rect(option->rect); - bool separatorIsVertical(state & QStyle::State_Horizontal); - bool enabled(state & QStyle::State_Enabled); - - auto schemeLoader = SchemeLoaderFetcher::getSchemeLoader(); - auto separatorColor = schemeLoader->getColor(widget, option, SchemeLoader::Widget_Border); - if (separatorIsVertical) - { - rect.setWidth(Metrics::ToolBar_HandleWidth); - rect = RenderHelper::centerRect(option->rect, rect.size()); - rect.setWidth(3); - RenderHelper::renderSeparator(painter, rect, separatorIsVertical, separatorColor); - - rect.translate(2, 0); - RenderHelper::renderSeparator(painter, rect, separatorIsVertical, separatorColor); - } - else - { - rect.setHeight(Metrics::ToolBar_HandleWidth); - rect = RenderHelper::centerRect(option->rect, rect.size()); - rect.setHeight(3); - RenderHelper::renderSeparator(painter, rect, separatorIsVertical, separatorColor); - - rect.translate(0, 2); - RenderHelper::renderSeparator(painter, rect, separatorIsVertical, separatorColor); - } - - return true; -} -} // namespace Kiran \ No newline at end of file diff --git a/style/src/draw-helper/draw-indicator-helper.h b/style/src/draw-helper/draw-indicator-helper.h deleted file mode 100644 index d1497d2e548ce08cee4a7fa8aec528cccf6a8bf7..0000000000000000000000000000000000000000 --- a/style/src/draw-helper/draw-indicator-helper.h +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. - * kiran-qt5-integration is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - * - * Author: liuxinhao - */ -#ifndef KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_DRAW_HELPER_DRAW_INDICATOR_HELPER_H_ -#define KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_DRAW_HELPER_DRAW_INDICATOR_HELPER_H_ - -class QStyle; -class QStyleOption; -class QPainter; -class QWidget; - -namespace Kiran -{ -class SchemeLoader; - -bool drawPEIndicatorButtonDropDown(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget); - -bool drawPEIndicatorArrowUp(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget); -bool drawPEIndicatorArrowDown(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget); -bool drawPEIndicatorArrowLeft(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget); -bool drawPEIndicatorArrowRight(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget); - -bool drawPEIndicatorRadioButton(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget); -bool drawPEIndicatorCheckBox(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget); - -bool drawPEIndicatorBranch(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget); - -bool drawPEIndicatorToolBarSeparator(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget); -bool drawPEIndicatorToolBarHandle(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget); -} // namespace Kiran - -#endif // KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_DRAW_HELPER_DRAW_INDICATOR_HELPER_H_ diff --git a/style/src/draw-helper/draw-item-view-helper.cpp b/style/src/draw-helper/draw-item-view-helper.cpp deleted file mode 100644 index 8746df4d42a0eadef0cc8e8648790ac3bb87e00c..0000000000000000000000000000000000000000 --- a/style/src/draw-helper/draw-item-view-helper.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/** - * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. - * kiran-qt5-integration is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - * - * Author: liuxinhao - */ -#include "draw-item-view-helper.h" -#include "scheme-loader-fetcher.h" - -#include -#include -#include - -namespace Kiran -{ -bool drawControlHeaderSection(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget) -{ - const QRect &rect(option->rect); - const QPalette &palette(option->palette); - const QStyle::State &state(option->state); - bool enabled(state & QStyle::State_Enabled); - bool mouseOver((state & QStyle::State_Active) && enabled && (state & QStyle::State_MouseOver)); - - const auto *headerOption(qstyleoption_cast(option)); - if (!headerOption) - { - return true; - } - - bool horizontal(headerOption->orientation == Qt::Horizontal); - bool isFirst(horizontal && (headerOption->position == QStyleOptionHeader::Beginning)); - bool isCorner(widget && widget->inherits("QTableCornerButton")); - bool reverseLayout(option->direction == Qt::RightToLeft); - - auto schemeLoader = SchemeLoaderFetcher::getSchemeLoader(); - - // outline - painter->setBrush(Qt::NoBrush); - auto outlineColor = schemeLoader->getColor(widget, option, SchemeLoader::ItemView_Branch); - painter->setPen(outlineColor); - - if (isCorner) - { - if (reverseLayout) - { - painter->drawPoint(rect.bottomLeft()); - } - else - { - painter->drawPoint(rect.bottomRight()); - } - } - else if (horizontal) - { - painter->drawLine(rect.bottomLeft(), rect.bottomRight()); - } - else - { - if (reverseLayout) - { - painter->drawLine(rect.topLeft(), rect.bottomLeft()); - } - else - { - painter->drawLine(rect.topRight(), rect.bottomRight()); - } - } - - // separators - if (horizontal) - { - if (headerOption->section != 0 || isFirst) - { - if (reverseLayout) - { - painter->drawLine(rect.topLeft(), rect.bottomLeft() - QPoint(0, 1)); - } - else - { - painter->drawLine(rect.topRight(), rect.bottomRight() - QPoint(0, 1)); - } - } - } - else - { - if (reverseLayout) - { - painter->drawLine(rect.bottomLeft() + QPoint(1, 0), rect.bottomRight()); - } - else - { - painter->drawLine(rect.bottomLeft(), rect.bottomRight() - QPoint(1, 0)); - } - } - - return true; -} - -bool drawControlHeaderLabel(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget) -{ - if (const QStyleOptionHeader *header = qstyleoption_cast(option)) - { - QRect rect = header->rect; - if (!header->icon.isNull()) - { - QPixmap pixmap = header->icon.pixmap(style->pixelMetric(QStyle::PM_SmallIconSize), (header->state & QStyle::State_Enabled) ? QIcon::Normal : QIcon::Disabled); - int pixw = pixmap.width(); - - QRect aligned = QStyle::alignedRect(header->direction, QFlag(header->iconAlignment), pixmap.size(), rect); - QRect inter = aligned.intersected(rect); - painter->drawPixmap(inter.x(), inter.y(), pixmap, inter.x() - aligned.x(), inter.y() - aligned.y(), inter.width(), inter.height()); - - if (header->direction == Qt::LeftToRight) - rect.setLeft(rect.left() + pixw + 2); - else - rect.setRight(rect.right() - pixw - 2); - } - - QFont fnt = painter->font(); - painter->setFont(fnt); - QPalette palette(header->palette); - style->drawItemText(painter, rect, header->textAlignment, palette, (header->state & QStyle::State_Active), header->text, QPalette::Text); - } - return true; -} - -bool drawControlHeaderEmptyArea(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget) -{ - // use the same background as in drawHeaderPrimitive - const QRect &rect(option->rect); - QPalette palette(option->palette); - - bool horizontal(option->state & QStyle::State_Horizontal); - bool reverseLayout(option->direction == Qt::RightToLeft); - - auto schemeLoader = SchemeLoaderFetcher::getSchemeLoader(); - - // fill - painter->setRenderHint(QPainter::Antialiasing, false); - painter->setBrush(palette.color(QPalette::Base)); - painter->setPen(Qt::NoPen); - painter->drawRect(rect); - - // outline - auto outlineColor = schemeLoader->getColor(widget,option,SchemeLoader::ItemView_Branch); - painter->setBrush(Qt::NoBrush); - painter->setPen(outlineColor); - - if (horizontal) - { - painter->drawLine(rect.bottomLeft(), rect.bottomRight()); - } - else - { - if (reverseLayout) - { - painter->drawLine(rect.topLeft(), rect.bottomLeft()); - } - else - { - painter->drawLine(rect.topRight(), rect.bottomRight()); - } - } - - return true; -} -} \ No newline at end of file diff --git a/style/src/draw-helper/draw-item-view-helper.h b/style/src/draw-helper/draw-item-view-helper.h deleted file mode 100644 index 2a2eadce8a5bd13f1a604beffeaa01e993c1aa12..0000000000000000000000000000000000000000 --- a/style/src/draw-helper/draw-item-view-helper.h +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. - * kiran-qt5-integration is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - * - * Author: liuxinhao - */ -#ifndef KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_DRAW_HELPER_DRAW_ITEM_VIEW_HELPER_H_ -#define KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_DRAW_HELPER_DRAW_ITEM_VIEW_HELPER_H_ - -class QStyle; -class QStyleOption; -class QPainter; -class QWidget; -namespace Kiran -{ -class SchemeLoader; -bool drawControlHeaderSection(const QStyle* style, const QStyleOption* option, QPainter* painter, const QWidget* widget); -bool drawControlHeaderLabel(const QStyle* style, const QStyleOption* option, QPainter* painter, const QWidget* widget); -bool drawControlHeaderEmptyArea(const QStyle* style, const QStyleOption* option, QPainter* painter, const QWidget* widget); -} - -#endif //KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_DRAW_HELPER_DRAW_ITEM_VIEW_HELPER_H_ diff --git a/style/src/draw-helper/draw-menu-helper.cpp b/style/src/draw-helper/draw-menu-helper.cpp deleted file mode 100644 index d5067933ad42645f16c1a878b747088d03216d09..0000000000000000000000000000000000000000 --- a/style/src/draw-helper/draw-menu-helper.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/** - * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. - * kiran-qt5-integration is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - * - * Author: liuxinhao - */ -#include "draw-menu-helper.h" -#include "render-helper.h" -#include "scheme-loader-fetcher.h" - -#include -#include -#include -#include - -namespace Kiran -{ -bool drawControlMenuBarItem(const QStyle* style, const QStyleOption* option, QPainter* painter, const QWidget* widget) -{ - auto menuItemOption = qstyleoption_cast(option); - const QStyle::State& state = option->state; - const bool enabled(option->state & QStyle::State_Enabled); - const bool mouseOver((option->state & QStyle::State_MouseOver) && enabled); - const bool sunken((option->state & QStyle::State_Sunken) && enabled); - - PainterSaver painterSaver(painter); - auto schemeLoader = SchemeLoaderFetcher::getSchemeLoader(); - -#if 0 - if(mouseOver && sunken) - { - auto background = schemeLoader->getColor(widget,option,SchemeLoader::MenuBar_ItemBackground); - painter->setRenderHints(QPainter::Antialiasing); - painter->setPen(Qt::NoPen); - painter->setBrush(background); - painter->drawRoundedRect(option->rect,4,4); - } -#endif - //TODO: menubaritem 和 menubar背景存在差异 - if( menuItemOption ) - { - int alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine; - - if( !style->styleHint(QStyle::SH_UnderlineShortcut,option,widget) ) - alignment |= Qt::TextHideMnemonic; - - int iconExtent = style->pixelMetric(QStyle::PM_SmallIconSize); - - QPixmap pix = menuItemOption->icon.pixmap(widget?widget->window()->windowHandle(): nullptr,QSize(iconExtent,iconExtent),enabled?(mouseOver?QIcon::Active:QIcon::Normal):QIcon::Disabled); - - if( !pix.isNull() ) - { - style->drawItemPixmap(painter,option->rect,alignment,pix); - } - else - { - QStyleOptionMenuItem itemOption = *menuItemOption; - QColor bgColor; - if( mouseOver || sunken ) - { - bgColor = schemeLoader->getColor(widget,option,SchemeLoader::MenuBar_ItemBackground); - painter->fillRect(option->rect,bgColor); - } - style->drawItemText(painter,itemOption.rect,alignment,itemOption.palette,enabled,itemOption.text,QPalette::ButtonText); - } - } - return true; -} - -bool drawControlMenuBarEmptyArea(const QStyle* style, const QStyleOption* option, QPainter* painter, const QWidget* widget) -{ - auto schemeLoader = SchemeLoaderFetcher::getSchemeLoader(); - QColor background = schemeLoader->getColor(SchemeLoader::MenuBar_EmptyAreaBackground,PseudoClass_Unspecified); - painter->fillRect(option->rect,background); - return true; -} -} \ No newline at end of file diff --git a/style/src/draw-helper/draw-menu-helper.h b/style/src/draw-helper/draw-menu-helper.h deleted file mode 100644 index d088fefedb98a09dc598dffbdd1c7d94807e3ba3..0000000000000000000000000000000000000000 --- a/style/src/draw-helper/draw-menu-helper.h +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. - * kiran-qt5-integration is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - * - * Author: liuxinhao - */ -#ifndef KIRAN_QT5_INTEGRATION_STYLE_SRC_DRAW_HELPER_DRAW_MENU_HELPER_H_ -#define KIRAN_QT5_INTEGRATION_STYLE_SRC_DRAW_HELPER_DRAW_MENU_HELPER_H_ - -class QStyle; -class QStyleOption; -class QPainter; -class QWidget; - -namespace Kiran -{ -class SchemeLoader; -bool drawControlMenuBarItem(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget); -bool drawControlMenuBarEmptyArea(const QStyle* style, const QStyleOption* option, QPainter* painter, const QWidget* widget); -} -#endif //KIRAN_QT5_INTEGRATION_STYLE_SRC_DRAW_HELPER_DRAW_MENU_HELPER_H_ diff --git a/style/src/draw-helper/draw-progress-bar-helper.cpp b/style/src/draw-helper/draw-progress-bar-helper.cpp deleted file mode 100644 index d570c0e72e555d5fb79bd69cf5e66589e3da02f1..0000000000000000000000000000000000000000 --- a/style/src/draw-helper/draw-progress-bar-helper.cpp +++ /dev/null @@ -1,215 +0,0 @@ -/** - * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. - * kiran-qt5-integration is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - * - * Author: liuxinhao - */ - -#include "draw-progress-bar-helper.h" -#include "draw-common-helper.h" -#include "metrics.h" -#include "render-helper.h" -#include "scheme-loader-fetcher.h" - -#include -#include -#include -#include -#include -#include - -namespace Kiran -{ -QSize progressBarSizeFromContents(const QStyle *style, - const QStyleOption *option, - const QSize &contentSize, - const QWidget *widget) -{ - const auto progressBarOption(qstyleoption_cast(option)); - if (!progressBarOption) return contentSize; - - bool horizontal(progressBarOption->orientation == Qt::Horizontal); - - QSize size(contentSize); - - if (horizontal) - { - bool textVisible(progressBarOption->textVisible); - - size.setWidth(qMax(size.width(), int(Metrics::ProgressBar_Thickness))); - size.setHeight(qMax(size.height(), int(Metrics::ProgressBar_Thickness))); - if (textVisible) size.setHeight(qMax(size.height(), option->fontMetrics.height())); - } - else - { - size.setHeight(qMax(size.height(), int(Metrics::ProgressBar_Thickness))); - size.setWidth(qMax(size.width(), int(Metrics::ProgressBar_Thickness))); - } - - return size; -} - -QRect progressBarElementRect(const QStyle *style, - QStyle::SubElement subElement, - const QStyleOption *option, - const QWidget *widget) -{ - const auto progressBarOption(qstyleoption_cast(option)); - if (!progressBarOption) return option->rect; - - bool textVisible(progressBarOption->textVisible); - bool horizontal(progressBarOption->orientation == Qt::Horizontal); - bool inverted(progressBarOption->invertedAppearance); - - QRect rect(option->rect); - int frameWidth(style->pixelMetric(QStyle::PM_DefaultFrameWidth, option, widget)); - - if (horizontal) - rect = RenderHelper::insideMargin(rect, frameWidth, 0); - else - rect = RenderHelper::insideMargin(rect, 0, frameWidth); - - switch (subElement) - { - case QStyle::SE_ProgressBarContents: - { - rect = style->subElementRect(QStyle::SE_ProgressBarGroove, option, widget); - - qreal progress(progressBarOption->progress - progressBarOption->minimum); - int steps(qMax(progressBarOption->maximum - progressBarOption->minimum, 1)); - qreal widthFrac = qMin(qreal(1), progress / steps); - int indicatorSize(widthFrac * (horizontal ? rect.width() : rect.height())); - - if (horizontal) - { - rect = QRect(inverted ? (rect.right() - indicatorSize + 1) : rect.left(), rect.y(), indicatorSize, rect.height()); - rect = QStyle::visualRect(option->direction, rect, rect); - } - else - { - rect = QRect(rect.x(), inverted ? rect.top() : (rect.bottom() - indicatorSize + 1), rect.width(), indicatorSize); - } - break; - } - case QStyle::SE_ProgressBarGroove: - { - if (textVisible && horizontal) - { - QRect textRect(style->subElementRect(QStyle::SE_ProgressBarLabel, option, widget)); - textRect = QStyle::visualRect(option->direction, option->rect, textRect); - rect.setRight(textRect.left() - Metrics::ProgressBar_ItemSpacing - 1); - rect = QStyle::visualRect(option->direction, option->rect, rect); - rect = RenderHelper::centerRect(rect, rect.width(), Metrics::ProgressBar_Thickness); - } - else if (horizontal) - { - rect = RenderHelper::centerRect(rect, rect.width(), Metrics::ProgressBar_Thickness); - } - else - { - rect = RenderHelper::centerRect(rect, Metrics::ProgressBar_Thickness, rect.height()); - } - break; - } - case QStyle::SE_ProgressBarLabel: - { - if (!textVisible) - return QRect(); - - int textWidth = qMax( - option->fontMetrics.size(RenderHelper::mnemonicsTextFlags(), progressBarOption->text).width(), - option->fontMetrics.size(RenderHelper::mnemonicsTextFlags(), QStringLiteral("100%")).width()); - - rect = RenderHelper::insideMargin(option->rect, Metrics::Frame_FrameWidth, 0); - rect.setLeft(rect.right() - textWidth + 1); - rect = QStyle::visualRect(option->direction, option->rect, rect); - break; - } - default: - break; - } - - return rect; -} - -bool drawControlProgressBar(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget) -{ - const auto progressBarOption(qstyleoption_cast(option)); - if (!progressBarOption) return true; - - QStyleOptionProgressBar tempOption(*progressBarOption); - - QRect grooveRect = style->subElementRect(QStyle::SE_ProgressBarGroove, option, widget); - QRect contentsRect = style->subElementRect(QStyle::SE_ProgressBarContents, option, widget); - QRect labelRect = style->subElementRect(QStyle::SE_ProgressBarLabel, option, widget); - - tempOption.rect = grooveRect; - style->drawControl(QStyle::CE_ProgressBarGroove, &tempOption, painter, widget); - - // TODO: BUSY动画 - tempOption.rect = contentsRect; - style->drawControl(QStyle::CE_ProgressBarContents, &tempOption, painter, widget); - - bool textVisible(progressBarOption->textVisible); - bool busy(progressBarOption->minimum == 0 && progressBarOption->maximum == 0); - if (textVisible && !busy) - { - tempOption.rect = labelRect; - style->drawControl(QStyle::CE_ProgressBarLabel, &tempOption, painter, widget); - } - - return true; -} - -bool drawControlProgressBarGroove(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget) -{ - const auto progressBarOption(qstyleoption_cast(option)); - if (!progressBarOption) return true; - - auto schemeLoader = SchemeLoaderFetcher::getSchemeLoader(); - auto grooveColor = schemeLoader->getColor(widget, option, SchemeLoader::Progress_Groove); - - RenderHelper::renderFrame(painter, option->rect, 1, 4, grooveColor); - return true; -} - -bool drawControlProgressBarContents(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget) -{ - const auto progressBarOption(qstyleoption_cast(option)); - if (!progressBarOption) return true; - - auto schemeLoader = SchemeLoaderFetcher::getSchemeLoader(); - auto contentsColor = schemeLoader->getColor(widget, option, SchemeLoader::Progress_Content); - - RenderHelper::renderFrame(painter, option->rect, 1, 4, contentsColor); - return true; -} - -bool drawControlProgressBarLabel(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget) -{ - const auto progressBarOption(qstyleoption_cast(option)); - if (!progressBarOption) return true; - - bool horizontal = progressBarOption->orientation == Qt::Horizontal; - if (!horizontal) return true; - - const QRect &rect(option->rect); - const QPalette &palette(option->palette); - - // store state and direction - const QStyle::State &state(option->state); - bool enabled(state & QStyle::State_Enabled); - - // define text rect - Qt::Alignment hAlign((progressBarOption->textAlignment == Qt::AlignLeft) ? Qt::AlignHCenter : progressBarOption->textAlignment); - style->drawItemText(painter, rect, Qt::AlignVCenter | hAlign, palette, enabled, progressBarOption->text, QPalette::WindowText); - return true; -} -} // namespace Kiran \ No newline at end of file diff --git a/style/src/draw-helper/draw-progress-bar-helper.h b/style/src/draw-helper/draw-progress-bar-helper.h deleted file mode 100644 index 3808e3afe47f064c30744f9f71d984950d40ad5f..0000000000000000000000000000000000000000 --- a/style/src/draw-helper/draw-progress-bar-helper.h +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. - * kiran-qt5-integration is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - * - * Author: liuxinhao - */ - -#ifndef KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_DRAW_HELPER_DRAW_PROGRESS_BAR_HELPER_H_ -#define KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_DRAW_HELPER_DRAW_PROGRESS_BAR_HELPER_H_ - -#include -#include - -class QStyleOption; -class QPainter; -class QWidget; - -namespace Kiran -{ -class SchemeLoader; -QSize progressBarSizeFromContents(const QStyle *style, const QStyleOption *option, const QSize &contentSize, const QWidget *widget); -QRect progressBarElementRect(const QStyle *style, QStyle::SubElement subElement, const QStyleOption *option, const QWidget *widget); - -bool drawControlProgressBar(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget); -bool drawControlProgressBarGroove(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget); -bool drawControlProgressBarContents(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget); -bool drawControlProgressBarLabel(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget); -} // namespace Kiran - -#endif // KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_DRAW_HELPER_DRAW_PROGRESS_BAR_HELPER_H_ diff --git a/style/src/draw-helper/draw-scroll-bar-helper.cpp b/style/src/draw-helper/draw-scroll-bar-helper.cpp deleted file mode 100644 index b5e21aaf0d7deb320c3bfd30ed4d8bdc202fbaa3..0000000000000000000000000000000000000000 --- a/style/src/draw-helper/draw-scroll-bar-helper.cpp +++ /dev/null @@ -1,296 +0,0 @@ -/** - * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. - * kiran-qt5-integration is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - * - * Author: liuxinhao - */ - -#include "draw-scroll-bar-helper.h" -#include "draw-common-helper.h" -#include "metrics.h" -#include "render-helper.h" -#include "scheme-loader-fetcher.h" - -#include -#include -#include -#include -#include -#include -#include - -namespace Kiran -{ -enum ScrollBarButtonType -{ - NoButton, - SingleButton, - DoubleButton -} _subLineButtons = NoButton, - _addLineButtons = NoButton; - -//* returns height for scrollbar buttons depending of button types -int scrollBarButtonHeight(ScrollBarButtonType type) -{ - switch (type) - { - case NoButton: - return Metrics::ScrollBar_NoButtonHeight; - case SingleButton: - return Metrics::ScrollBar_SingleButtonHeight; - case DoubleButton: - return Metrics::ScrollBar_DoubleButtonHeight; - default: - return 0; - } -} - -QRect scrollBarInternalSubControlRect(const QStyleOptionComplex *option, - QStyle::SubControl subControl) -{ - const QRect &rect = option->rect; - const QStyle::State &state(option->state); - bool horizontal(state & QStyle::State_Horizontal); - - switch (subControl) - { - case QStyle::SC_ScrollBarSubLine: - { - int majorSize(scrollBarButtonHeight(_subLineButtons)); - if (horizontal) - { - return QStyle::visualRect(option->direction, option->rect, QRect(rect.left(), rect.top(), majorSize, rect.height())); - } - else - { - return QStyle::visualRect(option->direction, option->rect, QRect(rect.left(), rect.top(), rect.width(), majorSize)); - } - } - case QStyle::SC_ScrollBarAddLine: - { - int majorSize(scrollBarButtonHeight(_addLineButtons)); - if (horizontal) - { - return QStyle::visualRect(option->direction, option->rect, QRect(rect.right() - majorSize + 1, rect.top(), majorSize, rect.height())); - } - else - { - return QStyle::visualRect(option->direction, option->rect, QRect(rect.left(), rect.bottom() - majorSize + 1, rect.width(), majorSize)); - } - } - - default: - return QRect(); - } -} - -bool scrollBarSubControlRect(const QStyle *style, - const QStyleOptionComplex *option, - QStyle::SubControl subControl, - const QWidget *widget, - QRect &controlRect) -{ - const auto sliderOption(qstyleoption_cast(option)); - if (!sliderOption) - return false; - - const QStyle::State &state(option->state); - bool horizontal(state & QStyle::State_Horizontal); - - switch (subControl) - { - case QStyle::SC_ScrollBarAddLine: - case QStyle::SC_ScrollBarSubLine: - case QStyle::SC_ScrollBarAddPage: - case QStyle::SC_ScrollBarSubPage: - controlRect = QRect(); - break; - case QStyle::SC_ScrollBarSlider: - { - // handle RTL here to unreflect things if need be - QRect groove = QStyle::visualRect(option->direction, option->rect, style->subControlRect(QStyle::CC_ScrollBar, option, QStyle::SC_ScrollBarGroove, widget)); - groove.adjust(0, 0, 1, 1); - - if (sliderOption->minimum == sliderOption->maximum) - { - controlRect = groove; - break; - } - - // Figure out how much room there is - int space(horizontal ? groove.width() : groove.height()); - - // Calculate the portion of this space that the slider should occupy - int sliderSize = space * qreal(sliderOption->pageStep) / (sliderOption->maximum - sliderOption->minimum + sliderOption->pageStep); - sliderSize = qMax(sliderSize, static_cast(Metrics::ScrollBar_MinSliderHeight)); - sliderSize = qMin(sliderSize, space); - - space -= sliderSize; - if (space <= 0) - { - controlRect = groove; - break; - } - - int pos = qRound(qreal(sliderOption->sliderPosition - sliderOption->minimum) / (sliderOption->maximum - sliderOption->minimum) * space); - if (sliderOption->upsideDown) - { - pos = space - pos; - } - - if (horizontal) - { - controlRect = QStyle::visualRect(option->direction, option->rect, QRect(groove.left() + pos, groove.top(), sliderSize, groove.height())); - } - else - { - controlRect = QStyle::visualRect(option->direction, option->rect, QRect(groove.left(), groove.top() + pos, groove.width(), sliderSize)); - } - break; - } - case QStyle::SC_ScrollBarGroove: - { - QRect topRect = QStyle::visualRect(option->direction, option->rect, scrollBarInternalSubControlRect(option, QStyle::SC_ScrollBarSubLine)); - QRect bottomRect = QStyle::visualRect(option->direction, option->rect, scrollBarInternalSubControlRect(option, QStyle::SC_ScrollBarAddLine)); - - QPoint topLeftCorner; - QPoint botRightCorner; - - if (horizontal) - { - topLeftCorner = QPoint(topRect.right() + 1, topRect.top()); - botRightCorner = QPoint(bottomRect.left() - 1, topRect.bottom()); - } - else - { - topLeftCorner = QPoint(topRect.left(), topRect.bottom() + 1); - botRightCorner = QPoint(topRect.right(), bottomRect.top() - 1); - } - - // define rect - controlRect = QStyle::visualRect(option->direction, option->rect, QRect(topLeftCorner, botRightCorner)); - break; - } - default: - return true; - } - - return true; -} - -bool drawCCScrollBar(const QStyle *style, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) -{ - const auto scrollbarOption = qstyleoption_cast(option); - if (!scrollbarOption) - { - return true; - } - - bool enabled(option->state & QStyle::State_Enabled); - bool mouseOver((option->state & QStyle::State_Active) && option->state & QStyle::State_MouseOver); - - if (option->subControls & QStyle::SC_ScrollBarGroove) - { - auto grooveRect = style->subControlRect(QStyle::CC_ScrollBar, option, QStyle::SC_ScrollBarGroove, widget); -// 不绘制滑动槽 -#if 0 - if( mouseOver ) - { - QColor grooveColor = KiranPalette::instance()->color(widget,option,KiranPalette::Window,KiranPalette::Background); - painter->save(); - painter->setPen(Qt::NoPen); - painter->setBrush(grooveColor); - painter->drawRect(grooveRect); - painter->restore(); - } -#endif - } - - if (scrollbarOption->subControls & QStyle::SC_ScrollBarSlider) - { - QStyleOptionSlider sliderOption = *scrollbarOption; - sliderOption.state = scrollbarOption->state; - sliderOption.rect = style->subControlRect(QStyle::CC_ScrollBar, &sliderOption, QStyle::SC_ScrollBarSlider, widget); - if (sliderOption.rect.isValid()) - { - style->drawControl(QStyle::CE_ScrollBarSlider, &sliderOption, painter, widget); - } - } - - return true; -} - -bool drawControlScrollBarGroove(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget, Kiran::SchemeLoader *scheme) -{ - return false; -} - -bool drawControlScrollBarSlider(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget) -{ - const QStyleOptionSlider *sliderOption(qstyleoption_cast(option)); - if (!sliderOption) - { - return true; - } - - const QStyle::State &state(option->state); - bool horizontal(state & QStyle::State_Horizontal); - // const QRect &rect(horizontal ? option->rect.adjusted(-1, 4, 0, -4) : option->rect.adjusted(4, -1, -4, 0)); - const QRect &rect(option->rect); - QRect handleRect; - - bool enabled(state & QStyle::State_Enabled); - bool mouseOver((state & QStyle::State_Active) && enabled && (state & QStyle::State_MouseOver)); - bool sunken(enabled && (state & (QStyle::State_On | QStyle::State_Sunken))); - - const QWidget *parent = nullptr; - if ((widget && widget->parentWidget())) - { - auto scrollBar = qobject_cast(widget); - - QAbstractScrollArea *scrollArea = nullptr; - if (!(scrollArea = qobject_cast(widget->parentWidget()))) - { - scrollArea = qobject_cast(widget->parentWidget()->parentWidget()); - } - - if (scrollArea && (scrollBar == scrollArea->verticalScrollBar() || scrollBar == scrollArea->horizontalScrollBar())) - { - parent = scrollArea; - } - } - - bool hasFocus(enabled && parent && parent->hasFocus()); - - handleRect = rect; - if (!mouseOver && horizontal) - { - handleRect = rect.adjusted(0, 1, 0, -1); - } - else if (!mouseOver && !horizontal) - { - handleRect = rect.adjusted(1, 0, -1, 0); - } - - QStyleOption tempOption(*option); - if (sunken) - { - tempOption.state |= QStyle::State_Sunken; - } - - auto schemeLoader = SchemeLoaderFetcher::getSchemeLoader(); - auto sliderColor = schemeLoader->getColor(widget, option, SchemeLoader::Scroll_Slider); - - painter->setRenderHint(QPainter::Antialiasing, true); - QPainterPath painterPath = RenderHelper::roundedPath(handleRect, AllCorners, 2); - painter->fillPath(painterPath, sliderColor); - return true; -} -} // namespace Kiran \ No newline at end of file diff --git a/style/src/draw-helper/draw-scroll-bar-helper.h b/style/src/draw-helper/draw-scroll-bar-helper.h deleted file mode 100644 index 8ee699316afb1782ad4fcc3682a957386be9c7e9..0000000000000000000000000000000000000000 --- a/style/src/draw-helper/draw-scroll-bar-helper.h +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. - * kiran-qt5-integration is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - * - * Author: liuxinhao - */ - -#ifndef KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_DRAW_HELPER_DRAW_SCROLL_BAR_HELPER_H_ -#define KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_DRAW_HELPER_DRAW_SCROLL_BAR_HELPER_H_ - -#include -#include - -class QStyle; -class QStyleOptionComplex; -class QPainter; -class QWidget; -namespace Kiran -{ -class SchemeLoader; - -bool scrollBarSubControlRect(const QStyle *style, const QStyleOptionComplex *option, QStyle::SubControl subControl, const QWidget *widget, QRect &controlRect); - -bool drawCCScrollBar(const QStyle *style, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget); - -bool drawControlScrollBarGroove(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget, Kiran::SchemeLoader *scheme); -bool drawControlScrollBarSlider(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget); -} // namespace Kiran - -#endif // KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_DRAW_HELPER_DRAW_SCROLL_BAR_HELPER_H_ diff --git a/style/src/draw-helper/draw-slider-helper.cpp b/style/src/draw-helper/draw-slider-helper.cpp deleted file mode 100644 index 5aad6ec5607bd35b203b9cbce846aec3559b11c4..0000000000000000000000000000000000000000 --- a/style/src/draw-helper/draw-slider-helper.cpp +++ /dev/null @@ -1,320 +0,0 @@ -/** - * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. - * kiran-qt5-integration is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - * - * Author: liuxinhao - */ -#include "draw-slider-helper.h" -#include "draw-common-helper.h" -#include "metrics.h" -#include "render-helper.h" -#include "scheme-loader-fetcher.h" -#include "style.h" - -#include -#include -#include - -namespace Kiran -{ -// TODO: 之后整合所有的绘制过程中的是否启用的开关 -static const bool sliderDrawTickMarks = true; -enum Side -{ - SideNone = 0x0, - SideLeft = 0x1, - SideTop = 0x2, - SideRight = 0x4, - SideBottom = 0x8, - AllSides = SideLeft | SideTop | SideRight | SideBottom -}; - -QSize sliderSizeFromContents(const QStyle *style, - const QStyleOption *option, - const QSize &contentSize, - const QWidget *widget) -{ - // cast option and check - const auto sliderOption(qstyleoption_cast(option)); - if (!sliderOption) return contentSize; - - // store tick position and orientation - const QSlider::TickPosition &tickPosition(sliderOption->tickPosition); - bool horizontal(sliderOption->orientation == Qt::Horizontal); - bool disableTicks = !sliderDrawTickMarks; - - // do nothing if no ticks are requested - if (tickPosition == QSlider::NoTicks) return contentSize; - - /* - * Qt adds its own tick length directly inside QSlider. - * Take it out and replace by ours, if needed - */ - const int tickLength(disableTicks ? 0 : (Metrics::Slider_TickLength + Metrics::Slider_TickMarginWidth + (Metrics::Slider_GrooveThickness - Metrics::Slider_ControlThickness) / 2)); - - int builtInTickLength(2); - - QSize size(contentSize); - if (horizontal) - { - if (tickPosition & QSlider::TicksAbove) size.rheight() += tickLength - builtInTickLength; - if (tickPosition & QSlider::TicksBelow) size.rheight() += tickLength - builtInTickLength; - } - else - { - if (tickPosition & QSlider::TicksAbove) size.rwidth() += tickLength - builtInTickLength; - if (tickPosition & QSlider::TicksBelow) size.rwidth() += tickLength - builtInTickLength; - } - - return size; -} - -bool drawCCSlider(const QStyle *style, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) -{ - // cast option and check - const auto sliderOption(qstyleoption_cast(option)); - if (!sliderOption) return true; - - // copy rect and palette - const QRect &rect(option->rect); - const QPalette &palette(option->palette); - - // copy state - const QStyle::State &state(option->state); - bool enabled(state & QStyle::State_Enabled); - bool windowActive(state & QStyle::State_Active); - bool mouseOver((state & QStyle::State_Active) && enabled && (state & QStyle::State_MouseOver)); - bool hasFocus(enabled && (state & QStyle::State_HasFocus)); - bool horizontal(sliderOption->orientation == Qt::Horizontal); - Side tickSide{SideNone}; - if (horizontal && sliderOption->tickPosition == QSlider::TicksAbove) tickSide = (Side)((int)tickSide | (int)SideTop); - if (horizontal && sliderOption->tickPosition == QSlider::TicksBelow) tickSide = (Side)((int)tickSide | (int)SideBottom); - if (!horizontal && sliderOption->tickPosition == QSlider::TicksLeft) tickSide = (Side)((int)tickSide | (int)SideLeft); - if (!horizontal && sliderOption->tickPosition == QSlider::TicksRight) tickSide = (Side)((int)tickSide | (int)SideRight); - - auto schemeLoader = SchemeLoaderFetcher::getSchemeLoader(); - auto grooveColor = schemeLoader->getColor(widget, option, SchemeLoader::Slider_Groove); - auto contentColor = schemeLoader->getColor(widget, option, SchemeLoader::Slider_Content); - - // tickmarks - if ( sliderDrawTickMarks && (sliderOption->subControls & QStyle::SC_SliderTickmarks) ) - { - bool upsideDown(sliderOption->upsideDown); - int tickPosition(sliderOption->tickPosition); - int available(style->pixelMetric(QStyle::PM_SliderSpaceAvailable, option, widget)); - int interval = sliderOption->tickInterval; - if (interval < 1) interval = sliderOption->pageStep; - if (interval >= 1) - { - int fudge(style->pixelMetric(QStyle::PM_SliderLength, option, widget) / 2); - int current(sliderOption->minimum); - - // store tick lines - QRect grooveRect(style->subControlRect(QStyle::CC_Slider, sliderOption, QStyle::SC_SliderGroove, widget)); - QList tickLines; - if (horizontal) - { - if (tickPosition & QSlider::TicksAbove) tickLines.append(QLine(rect.left(), grooveRect.top() - Metrics::Slider_TickMarginWidth, rect.left(), grooveRect.top() - Metrics::Slider_TickMarginWidth - Metrics::Slider_TickLength)); - if (tickPosition & QSlider::TicksBelow) tickLines.append(QLine(rect.left(), grooveRect.bottom() + Metrics::Slider_TickMarginWidth, rect.left(), grooveRect.bottom() + Metrics::Slider_TickMarginWidth + Metrics::Slider_TickLength)); - } - else - { - if (tickPosition & QSlider::TicksAbove) tickLines.append(QLine(grooveRect.left() - Metrics::Slider_TickMarginWidth, rect.top(), grooveRect.left() - Metrics::Slider_TickMarginWidth - Metrics::Slider_TickLength, rect.top())); - if (tickPosition & QSlider::TicksBelow) tickLines.append(QLine(grooveRect.right() + Metrics::Slider_TickMarginWidth, rect.top(), grooveRect.right() + Metrics::Slider_TickMarginWidth + Metrics::Slider_TickLength, rect.top())); - } - - while (current <= sliderOption->maximum) - { - // adjust color - QColor color((enabled && current <= sliderOption->sliderPosition) ? contentColor : grooveColor); - painter->setPen(color); - - // calculate positions and draw lines - int position(QStyle::sliderPositionFromValue(sliderOption->minimum, sliderOption->maximum, current, available) + fudge); - foreach (const QLine &tickLine, tickLines) - { - if (horizontal) - painter->drawLine(tickLine.translated(upsideDown ? (rect.width() - position) : position, 0)); - else - painter->drawLine(tickLine.translated(0, upsideDown ? (rect.height() - position) : position)); - } - - // go to next position - current += interval; - } - } - } - - // groove - if (sliderOption->subControls & QStyle::SC_SliderGroove) - { - if (hasFocus) - { - QRect focusRect = style->subElementRect(QStyle::SE_SliderFocusRect, option, widget); - - QStyleOptionFocusRect fropt; - fropt.QStyleOption::operator=(*option); - fropt.rect = focusRect; - style->drawPrimitive(QStyle::PE_FrameFocusRect, &fropt, painter, widget); - } - - // retrieve groove rect - QRect grooveRect(style->subControlRect(QStyle::CC_Slider, sliderOption, QStyle::SC_SliderGroove, widget)); - - if (!enabled) - { - RenderHelper::renderFrame(painter, grooveRect, 1, 0, grooveColor); - } - else - { - bool upsideDown(sliderOption->upsideDown); - - // handle rect - QRect handleRect(style->subControlRect(QStyle::CC_Slider, sliderOption, QStyle::SC_SliderHandle, widget)); - - if (sliderOption->orientation == Qt::Horizontal) - { - QRect leftRect(grooveRect); - QRect rightRect(grooveRect); - leftRect.setRight(handleRect.right() - Metrics::Slider_ControlThickness / 2); - rightRect.setLeft(handleRect.left() + Metrics::Slider_ControlThickness / 2); - - if (upsideDown) - { - RenderHelper::renderFrame(painter, leftRect, 1, 0, grooveColor); - RenderHelper::renderFrame(painter, rightRect, 1, 0, contentColor); - } - else - { - RenderHelper::renderFrame(painter, leftRect, 1, 0, contentColor); - RenderHelper::renderFrame(painter, rightRect, 1, 0, grooveColor); - } - } - else - { - QRect topRect(grooveRect); - topRect.setBottom(handleRect.bottom() - Metrics::Slider_ControlThickness / 2); - QRect bottomRect(grooveRect); - bottomRect.setTop(handleRect.top() + Metrics::Slider_ControlThickness / 2); - - if (upsideDown) - { - RenderHelper::renderFrame(painter, topRect, 1, 0, grooveColor); - RenderHelper::renderFrame(painter, bottomRect, 1, 0, contentColor); - } - else - { - RenderHelper::renderFrame(painter, topRect, 1, 0, contentColor); - RenderHelper::renderFrame(painter, bottomRect, 1, 0, grooveColor); - } - } - } - } - - // handle - if (sliderOption->subControls & QStyle::SC_SliderHandle) - { - // get rect and center - QRectF handleRect(style->subControlRect(QStyle::CC_Slider, sliderOption, QStyle::SC_SliderHandle, widget)); - - // handle state - bool handleActive(sliderOption->activeSubControls & QStyle::SC_SliderHandle); - bool sunken(state & (QStyle::State_On | QStyle::State_Sunken)); - - QColor handleBorder = schemeLoader->getColor(widget, option, SchemeLoader::Slider_HandleBorder); - QColor handleBackground = schemeLoader->getColor(widget, option, SchemeLoader::Slider_HandleBackground); - - // draw handle - painter->setRenderHint(QPainter::Antialiasing); - handleRect.adjust(1, 1, -1, -1); - - if (handleBorder.isValid()) - { - QPen pen; - pen.setCapStyle(Qt::RoundCap); - pen.setColor(handleBorder); - pen.setWidth(2); - painter->setPen(pen); - handleRect = RenderHelper::strokedRect(handleRect, 2); - } - else - { - painter->setPen(Qt::NoPen); - } - painter->setBrush(handleBackground); - painter->drawRoundedRect(handleRect, handleRect.width() / 2, handleRect.width()); - } - - return true; -} - -QRect sliderElementRect(const QStyle *style, QStyle::SubElement subElement, const QStyleOption *option, const QWidget *widget) -{ - QRect rect(option->rect); - - switch (subElement) - { - case QStyle::SE_SliderFocusRect: - { - const auto sliderOption(qstyleoption_cast(option)); - QRect r(option->rect); - if (sliderOption->orientation == Qt::Vertical) - { - int thickness = Metrics::Slider_GrooveThickness + 8; - return QRect(r.center().x() - thickness / 2, r.top() + 1, thickness + 1, r.height() - 1); - } - else - { - int thickness = Metrics::Slider_GrooveThickness + 6; - return QRect(r.left() + 1, r.center().y() - thickness / 2, r.width() - 1, thickness + 1); - } - } - default: - break; - } - - return rect; -} - -bool sliderSubControlRect(const QStyle *style, const QStyleOptionComplex *opt, QStyle::SubControl sc, const QWidget *widget, QRect &controlRect) -{ - // cast option and check - const auto sliderOption(qstyleoption_cast(opt)); - if (!sliderOption) - return false; - - switch (sc) - { - case QStyle::SC_SliderGroove: - { - // direction - bool horizontal(sliderOption->orientation == Qt::Horizontal); - - // get base class rect - // NOTE:该处直接调用父类的方法 - QRect grooveRect = qobject_cast(style)->ParentStyle::subControlRect(QStyle::CC_Slider, opt, sc, widget); - grooveRect = RenderHelper::insideMargin(grooveRect, style->pixelMetric(QStyle::PM_DefaultFrameWidth, opt, widget)); - - // centering - if (horizontal) - grooveRect = RenderHelper::centerRect(grooveRect, grooveRect.width(), Metrics::Slider_GrooveThickness); - else - grooveRect = RenderHelper::centerRect(grooveRect, Metrics::Slider_GrooveThickness, grooveRect.height()); - - controlRect = grooveRect; - break; - } - default: - return false; - } - - return true; -} -} // namespace Kiran \ No newline at end of file diff --git a/style/src/draw-helper/draw-slider-helper.h b/style/src/draw-helper/draw-slider-helper.h deleted file mode 100644 index 99d34ce75eebd511e13ec2b52436248ae3b676a1..0000000000000000000000000000000000000000 --- a/style/src/draw-helper/draw-slider-helper.h +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. - * kiran-qt5-integration is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - * - * Author: liuxinhao - */ -#ifndef KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_DRAW_HELPER_DRAW_SLIDER_HELPER_H_ -#define KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_DRAW_HELPER_DRAW_SLIDER_HELPER_H_ - -#include -#include -#include - -class QStyleOption; -class QWidget; -class QStyleOptionComplex; -class QWidget; -class QPainter; -namespace Kiran -{ -class SchemeLoader; -QSize sliderSizeFromContents(const QStyle *style, const QStyleOption *option, const QSize &contentSize, const QWidget *widget); -bool drawCCSlider(const QStyle *style, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget); -QRect sliderElementRect(const QStyle *style, QStyle::SubElement subElement, const QStyleOption *option, const QWidget *widget); -bool sliderSubControlRect(const QStyle *style, const QStyleOptionComplex *opt, QStyle::SubControl sc, const QWidget *widget, QRect &controlRect); -} // namespace Kiran - -#endif // KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_DRAW_HELPER_DRAW_SLIDER_HELPER_H_ diff --git a/style/src/draw-helper/draw-spin-box-helper.cpp b/style/src/draw-helper/draw-spin-box-helper.cpp deleted file mode 100644 index 6fceef7e05762f416bc502d44f6e27d8579dcce4..0000000000000000000000000000000000000000 --- a/style/src/draw-helper/draw-spin-box-helper.cpp +++ /dev/null @@ -1,233 +0,0 @@ -/** - * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. - * kiran-qt5-integration is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - * - * Author: liuxinhao - */ - -#include "draw-spin-box-helper.h" -#include "define.h" -#include "draw-common-helper.h" -#include "metrics.h" -#include "render-helper.h" -#include "scheme-loader-fetcher.h" - -#include -#include -#include -#include -#include -#include -#include - -namespace Kiran -{ -QSize spinBoxSizeFromContents(const QStyle *style, - const QStyleOption *option, - const QSize &contentSize, - const QWidget *widget) -{ - const auto spinBoxOption(qstyleoption_cast(option)); - if (!spinBoxOption) return contentSize; - - bool flat(!spinBoxOption->frame); - - // copy size - QSize size(contentSize); - - // add editor margins - int frameWidth(style->pixelMetric(QStyle::PM_SpinBoxFrameWidth, option, widget)); - if (!flat) size = RenderHelper::expandSize(size, frameWidth); - - // add button width and spacing - size.rwidth() += 2 * size.height() - 1; - - return size; -} - -bool spinBoxSubControlRect(const QStyle *style, - const QStyleOptionComplex *option, - QStyle::SubControl subControl, - const QWidget *widget, - QRect &controlRect) -{ - const auto spinBoxOption(qstyleoption_cast(option)); - if (!spinBoxOption) return false; - - bool flat(!spinBoxOption->frame); - - QRect rect(option->rect); - switch (subControl) - { - case QStyle::SC_SpinBoxFrame: - controlRect = flat ? QRect() : rect; - break; - case QStyle::SC_SpinBoxUp: - if (rect.width() > 2 * rect.height() + 24) - { - controlRect = QRect(rect.right() - rect.height(), rect.top(), rect.height(), rect.height() - 1); - } - else - { - controlRect = QRect(rect.right() - 0.6 * rect.height() + 1, rect.top(), rect.height() * 0.6, rect.height() / 2 + 3); - } - break; - case QStyle::SC_SpinBoxDown: - if (rect.width() > 2 * rect.height() + 24) - { - controlRect = QRect(rect.right() - 2 * rect.height() + 1, rect.top(), rect.height(), rect.height() - 1); - } - else - { - controlRect = QRect(rect.right() - 0.6 * rect.height() + 1, rect.top() + rect.height() / 2 - 2, rect.height() * 0.6, rect.height() / 2 + 2); - } - break; - case QStyle::SC_SpinBoxEditField: - { - int frameWidth(style->pixelMetric(QStyle::PM_SpinBoxFrameWidth, option, widget)); - if (rect.width() > 2 * rect.height() + 24) - controlRect = QRect( - rect.left(), rect.top(), - rect.width() - 2 * rect.height() - frameWidth, - rect.height()); - else - controlRect = QRect( - rect.left(), rect.top(), - rect.width() - 0.6 * rect.height() - frameWidth, - rect.height()); - - // remove right side line editor margins - if (!flat && controlRect.height() >= option->fontMetrics.height() + 2 * frameWidth) - { - controlRect.adjust(frameWidth, frameWidth, 0, -frameWidth); - } - - controlRect = QStyle::visualRect(option->direction, option->rect, controlRect); - break; - } - default: - return false; - } - - return true; -} - -void renderSpinBoxArrow(const QStyle *style, const QStyle::SubControl &subControl, const QStyleOptionSpinBox *option, QPainter *painter, const QWidget *widget) -{ - const QStyle::State &state(option->state); - - QRectF arrowRect(style->subControlRect(QStyle::CC_SpinBox, option, subControl, widget)); - - bool enabled(state & QStyle::State_Enabled); - const bool atLimit = (subControl == QStyle::SC_SpinBoxUp && !(option->stepEnabled & QAbstractSpinBox::StepUpEnabled)) || - (subControl == QStyle::SC_SpinBoxDown && !(option->stepEnabled & QAbstractSpinBox::StepDownEnabled)); - enabled &= !atLimit; - - const bool mouseOver(enabled && (state & QStyle::State_MouseOver)); - bool sunken(state & QStyle::State_Sunken && option->activeSubControls & subControl); - bool hasFocus(state & QStyle::State_HasFocus); - - const bool subControlHover(enabled && mouseOver && (option->activeSubControls & subControl)); - const bool subControlSunken(enabled && (sunken) && (option->activeSubControls & subControl)); - - const QMap subControlFlagMap = { - {QStyle::State_MouseOver, subControlHover}, - {QStyle::State_Sunken, subControlSunken}, - {QStyle::State_Enabled, enabled}}; - - // 复制一个子控件StyleOption,更新其中的状态 - QStyleOption tempOption(*option); - for (auto iter = subControlFlagMap.begin(); iter != subControlFlagMap.end(); iter++) - { - if (iter.value()) - { - tempOption.state |= iter.key(); - } - else - { - tempOption.state &= ~iter.key(); - } - } - - auto schemeLoader = SchemeLoaderFetcher::getSchemeLoader(); - auto borderColor = schemeLoader->getColor(widget, option, SchemeLoader::SpinBox_Border); - auto backgroundColor = schemeLoader->getColor(widget, option, SchemeLoader::SpinBox_Background); - auto signColor = schemeLoader->getColor(widget, option, SchemeLoader::SpinBox_SignColor); - - // 绘制按钮与输入区域之间的分割线 - if (subControl == QStyle::SC_SpinBoxDown) - { - painter->setBrush(Qt::NoBrush); - painter->setPen(borderColor); - int highlight = hasFocus ? 1 : 0; - painter->drawLine(arrowRect.left(), arrowRect.top() + 2 + highlight, arrowRect.left(), arrowRect.bottom() - 1 - highlight); - } - - if (subControl == QStyle::SC_SpinBoxUp) - { - painter->setBrush(Qt::NoBrush); - painter->setPen(borderColor); - int highlight = hasFocus ? 1 : 0; - painter->drawLine(arrowRect.left(), arrowRect.top() + 2 + highlight, arrowRect.left(), arrowRect.bottom() - 1 - highlight); - } - - // 绘制按钮背景色 - painter->setPen(Qt::NoPen); - QColor background = backgroundColor; - painter->setBrush(background); - painter->drawRect(arrowRect.adjusted(0.5, 0.5, -0.5, -0.5)); - - // 绘制按钮之上的符号 “+”,“-” - QPen pen(signColor, 2); - pen.setCapStyle(Qt::FlatCap); - QRect r = arrowRect.adjusted(1, 2, 0, 0).toRect(); - painter->setPen(pen); - painter->drawLine(r.center() - QPointF(5, 0), r.center() + QPointF(5, 0)); - if (subControl == QStyle::SC_SpinBoxUp) - painter->drawLine(r.center() - QPointF(0, 5), r.center() + QPointF(0, 5)); -} - -bool drawCCSpinBox(const QStyle *style, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) -{ - const auto spinBoxOption(qstyleoption_cast(option)); - if (!spinBoxOption) return true; - - const QPalette &palette(option->palette); - const QRect &rect(option->rect); - - if (option->subControls & QStyle::SC_SpinBoxFrame) - { - // detect flat spinboxes - bool flat(!spinBoxOption->frame); - flat |= (rect.height() < 2 * Metrics::Frame_FrameWidth + Metrics::SpinBox_ArrowButtonWidth); - if (flat) - { - const auto &background = palette.color(QPalette::Base); - - painter->setBrush(background); - painter->setPen(Qt::NoPen); - painter->drawRect(rect); - } - else - { - style->drawPrimitive(QStyle::PE_FrameLineEdit, option, painter, widget); - } - } - - // 裁剪掉按钮露出圆角边框的区域 - QPainterPath catPath = RenderHelper::roundedPath(RenderHelper::insideMargin(option->rect, 1), AllCorners, 4); - PainterSaver painterSaver(painter); - painter->setClipPath(catPath); - if (option->subControls & QStyle::SC_SpinBoxUp) renderSpinBoxArrow(style, QStyle::SC_SpinBoxUp, spinBoxOption, painter, widget); - if (option->subControls & QStyle::SC_SpinBoxDown) renderSpinBoxArrow(style, QStyle::SC_SpinBoxDown, spinBoxOption, painter, widget); - - return true; -} -} // namespace Kiran \ No newline at end of file diff --git a/style/src/draw-helper/draw-spin-box-helper.h b/style/src/draw-helper/draw-spin-box-helper.h deleted file mode 100644 index cd65aa2ec8192a6a531585d22e74b9f2a280c931..0000000000000000000000000000000000000000 --- a/style/src/draw-helper/draw-spin-box-helper.h +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. - * kiran-qt5-integration is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - * - * Author: liuxinhao - */ -#ifndef KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_DRAW_HELPER_DRAW_SPIN_BOX_HELPER_H_ -#define KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_DRAW_HELPER_DRAW_SPIN_BOX_HELPER_H_ - -#include - -class QStyle; -class QStyleOptionComplex; -class QStyleOption; -class QWidget; -class QPainter; -class QSize; -class QRect; -namespace Kiran -{ -class SchemeLoader; -QSize spinBoxSizeFromContents(const QStyle* style, const QStyleOption* option, const QSize& contentSize, const QWidget* widget); -bool spinBoxSubControlRect(const QStyle* style, const QStyleOptionComplex* option, QStyle::SubControl subControl, const QWidget* widget, QRect& controlRect); -bool drawCCSpinBox(const QStyle* style, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget); -} // namespace Kiran -#endif // KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_DRAW_HELPER_DRAW_SPIN_BOX_HELPER_H_ diff --git a/style/src/draw-helper/draw-tab-widget-helper.cpp b/style/src/draw-helper/draw-tab-widget-helper.cpp deleted file mode 100644 index a1411de856ef3d7b9d2c361ee034c7444dd968a9..0000000000000000000000000000000000000000 --- a/style/src/draw-helper/draw-tab-widget-helper.cpp +++ /dev/null @@ -1,358 +0,0 @@ -/** - * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. - * kiran-qt5-integration is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - * - * Author: liuxinhao - */ -#include "draw-tab-widget-helper.h" -#include "draw-common-helper.h" -#include "metrics.h" -#include "render-helper.h" -#include "scheme-loader-fetcher.h" -#include "style-palette.h" - -#include -#include -#include -#include -#include - -// FIXME:需要和sizeFromContents获取的大小对应 - -namespace Kiran -{ - -void tabLayout(const QStyle* style, const QStyleOptionTab* opt, const QWidget* widget, QRect* textRect, QRect* iconRect) -{ - QRect tr = opt->rect; - bool verticalTabs = RenderHelper::isVerticalTab(opt->shape); - - if (verticalTabs) - tr.setRect(0, 0, tr.height(), tr.width()); // 0, 0 as we will have a translate transform - - /// 垂直和水平偏移量,以突出当前选中的Tab标签 - int verticalShift = style->pixelMetric(QStyle::PM_TabBarTabShiftVertical, opt, widget); - int horizontalShift = style->pixelMetric(QStyle::PM_TabBarTabShiftHorizontal, opt, widget); - - int hpadding = style->pixelMetric(QStyle::PM_TabBarTabHSpace, opt, widget) / 2; - int vpadding = style->pixelMetric(QStyle::PM_TabBarTabVSpace, opt, widget) / 2; - - if (opt->shape == QTabBar::RoundedSouth || opt->shape == QTabBar::TriangularSouth) - verticalShift = -verticalShift; - - tr.adjust(hpadding, verticalShift - vpadding, horizontalShift - hpadding, vpadding); - bool selected = opt->state & QStyle::State_Selected; - if (selected) - { - tr.setTop(tr.top() - verticalShift); - tr.setRight(tr.right() - horizontalShift); - } - - // left widget - if (!opt->leftButtonSize.isEmpty()) - { - tr.setLeft(tr.left() + 4 + - (verticalTabs ? opt->leftButtonSize.height() : opt->leftButtonSize.width())); - } - // right widget - if (!opt->rightButtonSize.isEmpty()) - { - tr.setRight(tr.right() - 4 - - (verticalTabs ? opt->rightButtonSize.height() : opt->rightButtonSize.width())); - } - - // icon - if (!opt->icon.isNull()) - { - QSize iconSize = opt->iconSize; - if (!iconSize.isValid()) - { - int iconExtent = style->pixelMetric(QStyle::PM_SmallIconSize); - iconSize = QSize(iconExtent, iconExtent); - } - QSize tabIconSize = opt->icon.actualSize(iconSize, - (opt->state & QStyle::State_Enabled) ? QIcon::Normal : QIcon::Disabled, - (opt->state & QStyle::State_Selected) ? QIcon::On : QIcon::Off); - // High-dpi icons do not need adjustment; make sure tabIconSize is not larger than iconSize - tabIconSize = QSize(qMin(tabIconSize.width(), iconSize.width()), qMin(tabIconSize.height(), iconSize.height())); - - *iconRect = QRect(tr.left(), tr.center().y() - tabIconSize.height() / 2, - tabIconSize.width(), tabIconSize.height()); - if (!verticalTabs) - *iconRect = style->visualRect(opt->direction, opt->rect, *iconRect); - tr.setLeft(tr.left() + tabIconSize.width() + 4); - } - - if (!verticalTabs) - tr = style->visualRect(opt->direction, opt->rect, tr); - - *textRect = tr; -} - -QSize tabBarTabSizeFromContents(const QStyle* style, const QStyleOption* option, const QSize& contentSize, const QWidget* widget) -{ - const auto tabOption(qstyleoption_cast(option)); - const bool hasText(tabOption && !tabOption->text.isEmpty()); - const bool hasIcon(tabOption && !tabOption->icon.isNull()); - const bool hasLeftButton(tabOption && !tabOption->leftButtonSize.isEmpty()); - const bool hasRightButton(tabOption && !tabOption->leftButtonSize.isEmpty()); - - // calculate width increment for horizontal tabs - int widthIncrement = 0; - if (hasIcon && !(hasText || hasLeftButton || hasRightButton)) widthIncrement -= 4; - if (hasText && hasIcon) widthIncrement += Metrics::TabBar_TabItemSpacing; - if (hasLeftButton && (hasText || hasIcon)) widthIncrement += Metrics::TabBar_TabItemSpacing; - if (hasRightButton && (hasText || hasIcon || hasLeftButton)) widthIncrement += Metrics::TabBar_TabItemSpacing; - - // add margins - QSize size(contentSize); - - // compare to minimum size - const bool verticalTabs(tabOption && RenderHelper::isVerticalTab(tabOption->shape)); - if (verticalTabs) - { - size.rheight() += widthIncrement; - if (hasIcon && !hasText) - size = size.expandedTo(QSize(Metrics::TabBar_TabMinHeight, 0)); - else - size = size.expandedTo(QSize(Metrics::TabBar_TabMinHeight, Metrics::TabBar_TabMinWidth)); - } - else - { - size.rwidth() += widthIncrement; - if (hasIcon && !hasText) - size = size.expandedTo(QSize(0, Metrics::TabBar_TabMinHeight)); - else - size = size.expandedTo(QSize(Metrics::TabBar_TabMinWidth, Metrics::TabBar_TabMinHeight)); - } - - return size; -} - -bool drawPEFrameTabWidget(const QStyle* style, const QStyleOption* option, QPainter* painter, const QWidget* widget) -{ - auto schemeLoader = SchemeLoaderFetcher::getSchemeLoader(); - auto background = schemeLoader->getColor(widget, option, SchemeLoader::Frame_Background); - auto border = schemeLoader->getColor(widget, option, SchemeLoader::Frame_Border); - RenderHelper::renderFrame(painter, option->rect, 1, 0, background, border); - return true; -} - -bool drawPEFrameTabBarBase(const QStyle* style, const QStyleOption* option, QPainter* painter, const QWidget* widget) -{ - return true; -} - -bool drawControlTabBarTabLabel(const QStyle* style, const QStyleOption* option, QPainter* painter, const QWidget* widget) -{ - return false; -} - -bool drawControlTabBarTabShape(const QStyle* style, const QStyleOption* option, QPainter* painter, const QWidget* widget) -{ - const auto tabOption(qstyleoption_cast(option)); - if (!tabOption) return true; - - const QPalette& palette(option->palette); - const QStyle::State& state(option->state); - bool enabled(state & QStyle::State_Enabled); - bool selected(state & QStyle::State_Selected); - bool mouseOver((state & QStyle::State_Active) && !selected && (state & QStyle::State_MouseOver) && enabled); - - // check if tab is being dragged - bool isDragged(widget && selected && painter->device() != widget); - // bool isLocked(widget && _tabBarData->isLocked(widget)); - - const QStyleOptionTab::TabPosition& position = tabOption->position; - const bool isSingle(position == QStyleOptionTab::OnlyOneTab); - const bool isQtQuickControl(RenderHelper::isQtQuickControl(option, widget)); - bool isFirst(isSingle || position == QStyleOptionTab::Beginning); - bool isLast(isSingle || position == QStyleOptionTab::End); - bool isLeftOfSelected(/*!isLocked &&*/ tabOption->selectedPosition == QStyleOptionTab::NextIsSelected); - bool isRightOfSelected(/*!isLocked &&*/ tabOption->selectedPosition == QStyleOptionTab::PreviousIsSelected); - - // true if widget is aligned to the frame - // need to check for 'isRightOfSelected' because for some reason the isFirst flag is set when active tab is being moved - isFirst &= !isRightOfSelected; - isLast &= !isLeftOfSelected; - - // 若是反向布局交换状态,改变与方向相关属性 - const bool reverseLayout(option->direction == Qt::RightToLeft); - const bool verticalTabs(RenderHelper::isVerticalTab(tabOption->shape)); - if (reverseLayout && !verticalTabs) - { - qSwap(isFirst, isLast); - qSwap(isLeftOfSelected, isRightOfSelected); - } - - // 根据TabBar方向调整选项卡圆角的位置 - Corners corners; - switch (tabOption->shape) - { - case QTabBar::RoundedNorth: - case QTabBar::TriangularNorth: - corners = CornersTop; - break; - case QTabBar::RoundedSouth: - case QTabBar::TriangularSouth: - corners = CornersBottom; - break; - case QTabBar::RoundedWest: - case QTabBar::TriangularWest: - corners = CornersLeft; - break; - case QTabBar::RoundedEast: - case QTabBar::TriangularEast: - corners = CornersRight; - break; - default: - break; - } - - // quint64 specialPseudoClass = PseudoClass_Unspecified; - // if (selected) - // { - // specialPseudoClass = PseudoClass_Pressed; - // } - // QColor backgroundColor = scheme->getColor(widget, option, SchemeLoader::Button_BackgroundColor, specialPseudoClass); - QStyleOption tempOption(*option); - if (selected) - { - tempOption.state |= QStyle::State_Sunken; - } - QColor backgroundColor = StylePalette::instance()->color(widget, &tempOption, StylePalette::Widget, StylePalette::Background); - RenderHelper::renderTabBarTab(painter, option->rect, corners, 4, backgroundColor); - - return true; -} - -QRect tabBarSubElementRect(const QStyle* style, QStyle::SubElement subElement, const QStyleOption* option, const QWidget* widget) -{ - const auto* tabOption(qstyleoption_cast(option)); - - if (!widget || !widget->inherits("QTabBar")) - { - return QRect(); - } - - const auto tabBar = qobject_cast(widget); - const QRect& rect = option->rect; - - switch (subElement) - { - case QStyle::SE_TabBarTearIndicator: - case QStyle::SE_TabBarTearIndicatorRight: - return QRect(); - - // QTabBar::setTabButton所设置位于单个Tab左右的控件 - case QStyle::SE_TabBarTabLeftButton: - case QStyle::SE_TabBarTabRightButton: - { - if (!tabOption) - { - return QRect(); - } - - bool isLeft = (subElement == QStyle::SE_TabBarTabLeftButton); - - QSize size(isLeft ? tabOption->leftButtonSize : tabOption->rightButtonSize); - if (size.isEmpty()) - { - return QRect(); - } - - QRect buttonRect(QPoint(0, 0), size); - - switch (tabOption->shape) - { - case QTabBar::RoundedNorth: - case QTabBar::TriangularNorth: - - case QTabBar::RoundedSouth: - case QTabBar::TriangularSouth: - if (isLeft) - { - buttonRect.moveLeft(rect.left() + Metrics::TabBar_TabMarginWidth); - } - else - { - buttonRect.moveRight(rect.right() - Metrics::TabBar_TabMarginWidth); - } - buttonRect.moveTop((rect.height() - buttonRect.height()) / 2); - buttonRect = QStyle::visualRect(option->direction, option->rect, buttonRect); - break; - - case QTabBar::RoundedWest: - case QTabBar::TriangularWest: - if (isLeft) - { - buttonRect.moveBottom(rect.bottom() - Metrics::TabBar_TabMarginWidth); - } - else - { - buttonRect.moveTop(rect.top() + Metrics::TabBar_TabMarginWidth); - } - buttonRect.moveLeft((rect.width() - buttonRect.width()) / 2); - break; - - case QTabBar::RoundedEast: - case QTabBar::TriangularEast: - if (isLeft) - { - buttonRect.moveTop(rect.top() + Metrics::TabBar_TabMarginWidth); - } - else - { - buttonRect.moveBottom(rect.bottom() - Metrics::TabBar_TabMarginWidth); - } - buttonRect.moveLeft((rect.width() - buttonRect.width()) / 2); - break; - - default: - break; - } - - return buttonRect; - } - - case QStyle::SE_TabBarTabText: - { - QRect textRect; - QRect iconRect; - tabLayout(style, tabOption, widget, &textRect, &iconRect); - return textRect; - } - - // 当QTabBar过多时,QTabBar左右滑动的按钮 - case QStyle::SE_TabBarScrollLeftButton: - case QStyle::SE_TabBarScrollRightButton: - { - bool isLeft = (subElement == QStyle::SE_TabBarScrollLeftButton); - const int buttonWidth = style->pixelMetric(QStyle::PM_TabBarScrollButtonWidth, nullptr, widget); - QRect scrollButtonRect; - - if (RenderHelper::isVerticalTab(tabBar->shape())) - { - scrollButtonRect = QRect(0, isLeft ? 0 : (rect.height() - buttonWidth), rect.width(), buttonWidth); - } - else - { - scrollButtonRect = QRect(isLeft ? 0 : (rect.width() - buttonWidth), 0, buttonWidth, rect.height()); - QStyle::visualRect(option->direction, option->rect, scrollButtonRect); - } - return scrollButtonRect; - } - default: - break; - } - - return QRect(); -} -} // namespace Kiran \ No newline at end of file diff --git a/style/src/draw-helper/draw-tab-widget-helper.h b/style/src/draw-helper/draw-tab-widget-helper.h deleted file mode 100644 index de7cbb7e238a7412e26e2094b5d9e20996c2d6a0..0000000000000000000000000000000000000000 --- a/style/src/draw-helper/draw-tab-widget-helper.h +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. - * kiran-qt5-integration is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - * - * Author: liuxinhao - */ - -#ifndef KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_DRAW_HELPER_DRAW_TAB_WIDGET_HELPER_H_ -#define KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_DRAW_HELPER_DRAW_TAB_WIDGET_HELPER_H_ - -#include -#include - -class QStyle; -class QStyleOption; -class QStyleOptionComplex; -class QPainter; -class QWidget; -class QRect; -namespace Kiran -{ -class SchemeLoader; - -QSize tabBarTabSizeFromContents(const QStyle *style, const QStyleOption *option, const QSize &contentSize, const QWidget *widget); -QRect tabBarSubElementRect(const QStyle *style, QStyle::SubElement subElement, const QStyleOption *option, const QWidget *widget); - -bool drawPEFrameTabWidget(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget); -bool drawPEFrameTabBarBase(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget); - -bool drawControlTabBarTabLabel(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget); -bool drawControlTabBarTabShape(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget); -} // namespace Kiran - -#endif // KIRAN_QT5_PLATFORMTHEME_STYLE_SRC_DRAW_HELPER_DRAW_TAB_WIDGET_HELPER_H_ diff --git a/style/src/kiran-style-plugin.h b/style/src/kiran-style-plugin.h deleted file mode 100644 index aa088a2be70c770610c8294b6d933ef653be13ac..0000000000000000000000000000000000000000 --- a/style/src/kiran-style-plugin.h +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. - * kiran-qt5-integration is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - * - * Author: liuxinhao - */ -#ifndef KIRAN_QT5_PLATFORMTHEME_STYLE_KIRAN_STYLE_PLUGIN_H_ -#define KIRAN_QT5_PLATFORMTHEME_STYLE_KIRAN_STYLE_PLUGIN_H_ - -#include - -class KiranStylePlugin : public QStylePlugin -{ - Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QStyleFactoryInterface" FILE "../kiran-style-plugin.json") -public: - explicit KiranStylePlugin(QObject* parent = nullptr); - QStyle* create(const QString&) override; -}; - -#endif //KIRAN_QT5_PLATFORMTHEME_STYLE_KIRAN_STYLE_PLUGIN_H_ diff --git a/style/src/scheme-loader-fetcher.cpp b/style/src/scheme-loader-fetcher.cpp deleted file mode 100644 index b3af1f9d7685be808ead501fb1f53fe53d1860a8..0000000000000000000000000000000000000000 --- a/style/src/scheme-loader-fetcher.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "scheme-loader-fetcher.h" - -#include "scheme-loader.h" -#include "style-palette.h" - -namespace Kiran -{ -SchemeLoader* SchemeLoaderFetcher::getSchemeLoader() -{ - return StylePalette::instance()->getSchemeLoader(); -} -} // namespace Kiran diff --git a/style/src/scheme-loader-fetcher.h b/style/src/scheme-loader-fetcher.h deleted file mode 100644 index 5703478c05a2100f5b25cf42cda28f265e392c2d..0000000000000000000000000000000000000000 --- a/style/src/scheme-loader-fetcher.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// Created by liuxinhao on 2022/5/11. -// - -#ifndef KIRAN_QT5_INTEGRATION_SCHEMELOADERFETCHER_H -#define KIRAN_QT5_INTEGRATION_SCHEMELOADERFETCHER_H - -#include "scheme-loader.h" - -namespace Kiran -{ -class SchemeLoaderFetcher -{ -public: - static Kiran::SchemeLoader* getSchemeLoader(); -}; -} // namespace Kiran - -#endif // KIRAN_QT5_INTEGRATION_SCHEMELOADERFETCHER_H diff --git a/style/src/style.cpp b/style/src/style.cpp deleted file mode 100644 index 2161c65530ef2338422e457011cccf0e662e55fa..0000000000000000000000000000000000000000 --- a/style/src/style.cpp +++ /dev/null @@ -1,723 +0,0 @@ -/** - * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. - * kiran-qt5-integration is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - * - * Author: liuxinhao - */ -#include "style.h" -#include "render-helper.h" -#include "scheme-loader.h" - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// TODO: 后期考虑再度整合到几个大类的源文件之中 -#include "draw-helper/draw-button-helper.h" -#include "draw-helper/draw-combo-box-helper.h" -#include "draw-helper/draw-edit-helper.h" -#include "draw-helper/draw-group-box-helper.h" -#include "draw-helper/draw-indicator-helper.h" -#include "draw-helper/draw-item-view-helper.h" -#include "draw-helper/draw-menu-helper.h" -#include "draw-helper/draw-progress-bar-helper.h" -#include "draw-helper/draw-scroll-bar-helper.h" -#include "draw-helper/draw-slider-helper.h" -#include "draw-helper/draw-spin-box-helper.h" -#include "draw-helper/draw-tab-widget-helper.h" - -#if 0 -//调试用 -QDebug operator<<(QDebug dbg, const QColor &color) -{ - QString format = QString("[rgb(%1,%2,%3) #%4%5%6]") - .arg(color.red()).arg(color.green()).arg(color.blue()) - .arg(QString::number(color.red(),16)).arg(QString::number(color.green(),16)).arg(QString::number(color.blue(),16)); - dbg << format; - return dbg; -} -#endif - -using namespace Kiran; - -// FIXME:由于kiran-widgets-qt5之前包含的Kiran::Style重名导致现在暂时不能加入Kiran命名控件,否则将引起崩溃 -Style::Style() - : ParentStyle() -{ -} - -Style::~Style() -{ -} - -int Style::styleHint(QStyle::StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *returnData) const -{ - switch (hint) - { - // 下栏框的下栏列表鼠标追踪 - case SH_ComboBox_ListMouseTracking: - return true; - // 菜单栏鼠标追踪 - case SH_MenuBar_MouseTracking: - return true; - // 菜单鼠标追踪 - case SH_Menu_MouseTracking: - return true; - // 菜单之中子菜单弹出延时时间 - case SH_Menu_SubMenuPopupDelay: - return 150; - // 弹出菜单是否支持用户在跨越菜单的其他项时将鼠标光标移动到子菜单 - case SH_Menu_SloppySubMenus: - return true; -#if (QT_VERSION < QT_VERSION_CHECK(5, 10, 0)) - // 该值目前亦废弃,改用SH_Widget_Animation_Duration - case SH_Widget_Animate: - return true; -#else - // 动画持续时间ms,0代表禁用 - case SH_Widget_Animation_Duration: - return 100; -#endif - // 确定样式是在菜单中显示节,还是将其视为普通分隔符。节是带有文本和图标提示的分隔符 - case SH_Menu_SupportsSections: - return true; - // 指示QDialogButtonBox中的标准按钮是否应具有图标 - case SH_DialogButtonBox_ButtonsHaveIcons: - return false; - // GroupBox文本标签垂直对齐选项 - case SH_GroupBox_TextLabelVerticalAlignment: - return Qt::AlignVCenter; - // TabBar的对齐方式 - case SH_TabBar_Alignment: - return Qt::AlignLeft | Qt::AlignVCenter; - // ToolBox中所选页面标题是否显示粗体 - case SH_ToolBox_SelectedPageTitleBold: - return false; - // 滚动条上单击鼠标中键滑块是否跳转到该绝对位置 - case SH_ScrollBar_MiddleClickAbsolutePosition: - return true; - // ScrollView是仅围绕内容(如Motif)还是围绕内容、滚动条和角部件(如窗口)绘制框架。 - case SH_ScrollView_FrameOnlyAroundContents: - return false; - // FormLayout对齐其内容的默认方式 - case SH_FormLayoutFormAlignment: - return Qt::AlignLeft | Qt::AlignVCenter; - // FormatLayout对齐标签的默认方式 - case SH_FormLayoutLabelAlignment: - return Qt::AlignRight; - // QFormLayout中字段增长方式的默认值。返回QFormLayout::FieldGrowthPolicy枚举 - case SH_FormLayoutFieldGrowthPolicy: - return QFormLayout::ExpandingFieldsGrow; - // QFormLayout中如何换行的默认方式。返回一个QFormLayout::RowWrapPolicy enum。 - case SH_FormLayoutWrapPolicy: - return QFormLayout::DontWrapRows; - // 消息框中的文本是否允许用户交互(如选择) - case SH_MessageBox_TextInteractionFlags: - return Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse; - // 进度对话框按钮取消按钮是否居中对齐,否则右对齐 - case SH_ProgressDialog_CenterCancelButton: - return false; - // 消息框是否按钮居中 - case SH_MessageBox_CenterButtons: - return false; - // 输入控件请求输入面板的时间点,返回类型为QStyle::RequestSoftwareInputPanel。 - case SH_RequestSoftwareInputPanel: - return RSIP_OnMouseClick; - // 标题栏无边框 - case SH_TitleBar_NoBorder: - return true; - // DockWidget的按钮是否有Frame - case SH_DockWidget_ButtonsHaveFrame: - return false; - // ToolTip透明文本标签的透明度 - case SH_ToolTipLabel_Opacity: - return 204; - // Table里网格线的颜色 - case SH_Table_GridLineColor: - return StylePalette::instance()->color(StylePalette::Normal, StylePalette::Widget, StylePalette::Border).rgb(); - default: - return ParentStyle::styleHint(hint, option, widget, returnData); - } -} - -int Style::pixelMetric(QStyle::PixelMetric metric, const QStyleOption *option, const QWidget *widget) const -{ - switch (metric) - { - case PM_DefaultFrameWidth: - return 6; - case PM_SpinBoxFrameWidth: - return 2; - case PM_ToolBarFrameWidth: - return 6; - case PM_ToolTipLabelFrameWidth: - return 3; - case PM_ComboBoxFrameWidth: - return 3; - case PM_FocusFrameVMargin: - case PM_FocusFrameHMargin: - return 2; - - // 布局默认边距 - case PM_LayoutLeftMargin: - case PM_LayoutTopMargin: - case PM_LayoutRightMargin: - case PM_LayoutBottomMargin: - { - // 使用子控件边距或顶层窗口边距,取决于部件类型 - if ((option && (option->state & QStyle::State_Window)) || (widget && widget->isWindow())) - { - return 10; - } - else - { - return 6; - } - } - - // 布局默认间距 - case PM_LayoutHorizontalSpacing: - case PM_LayoutVerticalSpacing: - return 6; - - // 按钮边距 - case PM_ButtonMargin: - return 12; - - // 按钮默认指示器边框宽度 - case PM_ButtonDefaultIndicator: - return 0; - // 当按钮按下时,按钮的内容水平移动偏移量。 - case PM_ButtonShiftHorizontal: - return 0; - // 当按钮按下时,按钮的内容垂直移动偏移量。 - case PM_ButtonShiftVertical: - return 0; - - // 菜单栏默认边框宽度 - case PM_MenuBarPanelWidth: - return 0; - // 菜单栏水平边距 - case PM_MenuBarHMargin: - return 0; - // 菜单栏垂直边距 - case PM_MenuBarVMargin: - return 3; - // 菜单项间距 - case PM_MenuBarItemSpacing: - return 10; - // 桌面菜单边框宽度 - case PM_MenuDesktopFrameWidth: - return 0; - - // 菜单按钮指示器宽度 - case PM_MenuButtonIndicator: - return 24; - - // toolbars - case PM_ToolBarHandleExtent: - return 10; - case PM_ToolBarSeparatorExtent: - return 8; - case PM_ToolBarExtensionExtent: - return pixelMetric(PM_SmallIconSize, option, widget) + 2 * 6; - - case PM_ToolBarItemMargin: - return 0; - case PM_ToolBarItemSpacing: - return 0; - - // tabbars - case PM_TabBarTabShiftVertical: - return 0; - case PM_TabBarTabShiftHorizontal: - return 0; - case PM_TabBarTabOverlap: - return 1; - case PM_TabBarBaseOverlap: - return 2; - case PM_TabBarTabHSpace: - return 2 * 8; - case PM_TabBarTabVSpace: - return 2 * 4; - case PM_TabCloseIndicatorWidth: - case PM_TabCloseIndicatorHeight: - return pixelMetric(PM_SmallIconSize, option, widget); - - // scrollbars - case PM_ScrollBarExtent: - return 5; - case PM_ScrollBarSliderMin: - return 20; - - // scrollview - case PM_ScrollView_ScrollBarOverlap: - return 1; - - // title bar - case PM_TitleBarHeight: - return 2 * 4 + pixelMetric(PM_SmallIconSize, option, widget); - - // sliders - case PM_SliderThickness: - return 16; - case PM_SliderControlThickness: - return 16; - case PM_SliderLength: - return 16; - - // checkboxes and radio buttons - case PM_IndicatorWidth: - case PM_IndicatorHeight: - case PM_ExclusiveIndicatorWidth: - case PM_ExclusiveIndicatorHeight: - return 15; - - // list headers - case PM_HeaderMarkSize: - return 10; - case PM_HeaderMargin: - return 6; - - // dock widget - // return 0 here, since frame is handled directly in polish - case PM_DockWidgetFrameWidth: - return 0; - case PM_DockWidgetTitleMargin: - return 4; - case PM_DockWidgetTitleBarButtonMargin: - return 6; - - case PM_SplitterWidth: - return 1; - case PM_DockWidgetSeparatorExtent: - return 1; - - default: // fallback - break; - } - return ParentStyle::pixelMetric(metric, option, widget); -} - -void Style::drawPrimitive(QStyle::PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const -{ - bool (*func)(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget); - func = nullptr; - - // clang-format off - switch (element) - { - case PE_Frame: func = &drawPEFrame; break; - case PE_FrameFocusRect: func = &drawPEFrameFocusRect; break; - case PE_FrameGroupBox: func = &drawPEFrameGroupBox; break; - - case PE_PanelButtonCommand: func = &drawPEPanelButtonCommand; break; - case PE_PanelButtonTool: func = &drawPEPanelButtonTool; break; - - case PE_FrameLineEdit: func = &drawPEFrameLineEdit; break; - case PE_PanelLineEdit: - { - /*作为QComoBox和QAbstractSpinBox的子控件时不进行绘制*/ - if( widget && widget->parentWidget() ) - { - if( qobject_cast(widget->parentWidget()) || - qobject_cast(widget->parentWidget()) ) - { - return; - } - } - - if (const QStyleOptionFrame *panel = qstyleoption_cast(option)) - { - if (panel->lineWidth > 0) - { - return Style::drawPrimitive(PE_FrameLineEdit, panel, painter, widget); - } - return; - } - - break; - } - case PE_IndicatorButtonDropDown: func = &drawPEIndicatorButtonDropDown; break; - case PE_IndicatorArrowUp: func = &drawPEIndicatorArrowUp; break; - case PE_IndicatorArrowDown: func = &drawPEIndicatorArrowDown; break; - case PE_IndicatorArrowLeft: func = &drawPEIndicatorArrowLeft; break; - case PE_IndicatorArrowRight: func = &drawPEIndicatorArrowRight; break; - case PE_IndicatorRadioButton: func = &drawPEIndicatorRadioButton; break; - case PE_IndicatorCheckBox: func = &drawPEIndicatorCheckBox; break; - case PE_IndicatorBranch: func = &drawPEIndicatorBranch; break; - case PE_FrameTabWidget: func = &drawPEFrameTabWidget; break; - case PE_FrameTabBarBase: func = &drawPEFrameTabBarBase; break; - - case PE_IndicatorToolBarSeparator: func = &drawPEIndicatorToolBarSeparator; break; - case PE_IndicatorToolBarHandle: func = &drawPEIndicatorToolBarHandle; break; - default: break; - } - // clang-format on - - PainterSaver painterSaver(painter); - if (!(func && (*func)(this, option, painter, widget))) - { - ParentStyle::drawPrimitive(element, option, painter, widget); - } -} - -void Style::drawComplexControl(QStyle::ComplexControl control, - const QStyleOptionComplex *option, - QPainter *painter, - const QWidget *widget) const -{ - bool (*func)(const QStyle *style, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget); - func = nullptr; - - // clang-format off - switch (control) - { - case QStyle::CC_ToolButton: func = &drawCCToolButton; break; - case QStyle::CC_ComboBox: func = &drawCCComboBox; break; - case QStyle::CC_ScrollBar: func = &drawCCScrollBar; break; - case QStyle::CC_SpinBox: func = &drawCCSpinBox; break; - case QStyle::CC_GroupBox: func = &drawCCGroupBox; break; - case QStyle::CC_Slider: func = &drawCCSlider; break; - default: break; - } - // clang-format on - - painter->save(); - if (!(func && (*func)(this, option, painter, widget))) - { - ParentStyle::drawComplexControl(control, option, painter, widget); - } - painter->restore(); -} - -QRect Style::subElementRect(QStyle::SubElement element, const QStyleOption *option, const QWidget *widget) const -{ - QRect rect; - - switch (element) - { - case QStyle::SE_TabBarTearIndicator: - case QStyle::SE_TabBarTabLeftButton: - case QStyle::SE_TabBarTabRightButton: - case QStyle::SE_TabBarTabText: - case QStyle::SE_TabBarScrollLeftButton: - case QStyle::SE_TabBarScrollRightButton: - case QStyle::SE_TabBarTearIndicatorRight: - rect = tabBarSubElementRect(this, element, option, widget); - return rect; - - case SE_ProgressBarGroove: - case SE_ProgressBarContents: - case SE_ProgressBarLabel: - rect = progressBarElementRect(this, element, option, widget); - return rect; - - case QStyle::SE_SliderFocusRect: - rect = sliderElementRect(this, element, option, widget); - return rect; - - default: - break; - } - - return ParentStyle::subElementRect(element, option, widget); -} - -QRect Style::subControlRect(QStyle::ComplexControl cc, const QStyleOptionComplex *opt, QStyle::SubControl sc, const QWidget *widget) const -{ - typedef bool (*SubControlRectFunc)(const QStyle *, const QStyleOptionComplex *, QStyle::SubControl, const QWidget *, QRect &); - static const QMap SubControlRectMap = { - {QStyle::CC_ToolButton, &toolButtonSubControlRect}, - {QStyle::CC_ComboBox, &comboBoxSubControlRect}, - {QStyle::CC_ScrollBar, &scrollBarSubControlRect}, - {QStyle::CC_SpinBox, &spinBoxSubControlRect}, - {QStyle::CC_GroupBox, &groupBoxSubControlRect}, - {QStyle::CC_Slider, &sliderSubControlRect}}; - - QRect controlRect; - if ((SubControlRectMap.find(cc) != SubControlRectMap.end()) && - (*SubControlRectMap.find(cc))(this, opt, sc, widget, controlRect)) - { - return controlRect; - } - else - { - return ParentStyle::subControlRect(cc, opt, sc, widget); - } -} - -QSize Style::sizeFromContents(QStyle::ContentsType type, const QStyleOption *option, const QSize &contentSize, const QWidget *widget) const -{ - switch (type) - { - case CT_PushButton: - return pushButtonSizeFromContents(this, option, contentSize, widget); - case CT_ToolButton: - return toolButtonSizeFromContents(this, option, contentSize, widget); - case CT_TabBarTab: - return tabBarTabSizeFromContents(this, option, contentSize, widget); - case CT_ComboBox: - return comboBoxSizeFromContents(this, option, contentSize, widget); - case CT_SpinBox: - return spinBoxSizeFromContents(this, option, contentSize, widget); - case CT_GroupBox: - return groupBoxSizeFromContents(this, option, contentSize, widget); - case CT_ProgressBar: - return progressBarSizeFromContents(this, option, contentSize, widget); - case CT_Slider: - return sliderSizeFromContents(this, option, contentSize, widget); - case CT_CheckBox: - break; - case CT_RadioButton: - break; - case CT_Splitter: - break; - case CT_MenuItem: - break; - case CT_MenuBarItem: - break; - case CT_MenuBar: - break; - case CT_Menu: - break; - case CT_LineEdit: - { - int buttuonMargin = pixelMetric(QStyle::PM_ButtonMargin, option, widget); - QSize size = contentSize + QSize(buttuonMargin, buttuonMargin); - return size; - } - case CT_SizeGrip: - break; - case CT_TabWidget: - break; - case CT_DialogButtons: - break; - case CT_HeaderSection: - break; - case CT_MdiControls: - break; - case CT_ItemViewItem: - break; - default: - break; - } - return ParentStyle::sizeFromContents(type, option, contentSize, widget); -} - -void Style::drawControl(QStyle::ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const -{ - bool (*func)(const QStyle *style, const QStyleOption *option, QPainter *painter, const QWidget *widget); - func = nullptr; - - // 不绘制的控件元素集合 - static QSet emptyControlSet = {CE_ToolBar}; - - // clang-format off - switch (element) - { - case CE_ShapedFrame: func = &drawControlShapedFrame; break; - - case CE_TabBarTabLabel: func = &drawControlTabBarTabLabel; break; - case CE_TabBarTabShape: func = &drawControlTabBarTabShape; break; - - case CE_PushButtonLabel: func = &drawControlPushButtonLabel; break; - case CE_ToolBoxTabLabel: func = &drawControlToolButtonLabel; break; - case CE_ComboBoxLabel: func = &drawControlComboBoxLabel; break; - - case CE_HeaderLabel: func = &drawControlHeaderLabel; break; - case CE_HeaderSection: func = &drawControlHeaderSection; break; - case CE_HeaderEmptyArea: func = &drawControlHeaderEmptyArea; break; - - case CE_ScrollBarSlider: func = &drawControlScrollBarSlider; break; - - case CE_ProgressBar: func = &drawControlProgressBar; break; - case CE_ProgressBarGroove: func = &drawControlProgressBarGroove; break; - case CE_ProgressBarContents: func = &drawControlProgressBarContents; break; - case CE_ProgressBarLabel: func = &drawControlProgressBarLabel; break; - - case CE_MenuBarItem: func = &drawControlMenuBarItem; break; - case CE_MenuBarEmptyArea: func = &drawControlMenuBarEmptyArea; break; - default: break; - } - // clang-format on - - painter->save(); - if (!(func && (*func)(this, option, painter, widget))) - { - if (emptyControlSet.find(element) == emptyControlSet.end()) - { - ParentStyle::drawControl(element, option, painter, widget); - } - } - painter->restore(); -} - -void Style::polishScrollArea(QAbstractScrollArea *scrollArea) -{ - if (!scrollArea) - return; - - // enable mouse over effect in sunken scrollareas that support focus - if (scrollArea->frameShadow() == QFrame::Sunken && scrollArea->focusPolicy() & Qt::StrongFocus) - { - scrollArea->setAttribute(Qt::WA_Hover); - } - - // disable autofill background for flat (== NoFrame) scrollareas, with QPalette::Window as a background - // this fixes flat scrollareas placed in a tinted widget, such as groupboxes, tabwidgets or framed dock-widgets - if (!(scrollArea->frameShape() == QFrame::NoFrame || scrollArea->backgroundRole() == QPalette::Window)) - { - return; - } - - // get viewport and check background role - QWidget *viewport(scrollArea->viewport()); - if (!(viewport && viewport->backgroundRole() == QPalette::Window)) - return; - - // change viewport autoFill background. - // do the same for all children if the background role is QPalette::Window - viewport->setAutoFillBackground(false); - QList children(viewport->findChildren()); - foreach (QWidget *child, children) - { - if (child->parent() == viewport && child->backgroundRole() == QPalette::Window) - { - child->setAutoFillBackground(false); - } - } -} - -void Style::polish(QWidget *widget) -{ - if (!widget) - return; - - // enable mouse over effects for all necessary widgets - if (qobject_cast(widget) || - qobject_cast(widget) || - qobject_cast(widget) || - qobject_cast(widget) || - qobject_cast(widget) || - qobject_cast(widget) || - qobject_cast(widget) || - qobject_cast(widget) || - qobject_cast(widget) || - qobject_cast(widget) || - qobject_cast(widget) || - qobject_cast(widget) || - qobject_cast(widget) || - qobject_cast(widget)) - { - widget->setAttribute(Qt::WA_Hover); - } - - polishScrollArea(qobject_cast(widget)); - - if (QAbstractItemView *itemView = qobject_cast(widget)) - { - // enable mouse over effects in itemviews' viewport - itemView->viewport()->setAttribute(Qt::WA_Hover); - } - - ParentStyle::polish(widget); -} - -void Style::polish(QApplication *app) -{ - ParentStyle::polish(app); - - QPalette palette; - StylePalette::instance()->polishPalette(&palette); - QApplication::setPalette(palette); -} - -void Style::polish(QPalette &palette) -{ - // ParentStyle::polish(palette); - StylePalette::instance()->polishPalette(&palette); -} - -QPixmap Style::standardPixmap(QStyle::StandardPixmap standardPixmap, const QStyleOption *opt, const QWidget *widget) const -{ - switch (standardPixmap) - { - case SP_ArrowUp: - case SP_ArrowDown: - case SP_ArrowLeft: - case SP_ArrowRight: - { - QPalette palette = widget ? widget->palette() : qApp->palette(); - QPalette::ColorRole colorRole = widget ? widget->foregroundRole() : QPalette::ButtonText; - QPixmap arrowPixmap(16, 16); - arrowPixmap.fill(Qt::transparent); - QPainter painter(&arrowPixmap); - RenderHelper::renderArrow(&painter, arrowPixmap.rect(), (Kiran::ArrowOrientation)((int)standardPixmap-SP_ArrowUp), palette.color(colorRole)); - return arrowPixmap; - } - default: - break; - } - return ParentStyle::standardPixmap(standardPixmap, opt, widget); -} - -QIcon Style::standardIcon(QStyle::StandardPixmap standardIcon, const QStyleOption *option, const QWidget *widget) const -{ - static const QMap titleBarIconMap = { - {SP_TitleBarMinButton, ":/style-helper/images/window-minimum-symbolic.svg"}, - {SP_TitleBarMaxButton, ":/style-helper/images/window-maximum-symbolic.svg"}, - {SP_TitleBarCloseButton, ":/style-helper/images/window-close-symbolic.svg"}, - {SP_TitleBarNormalButton, ":/style-helper/images/window-unmaximum-symbolic.svg"}, - - }; - switch (standardIcon) - { - case SP_TitleBarMinButton: - case SP_TitleBarMaxButton: - case SP_TitleBarCloseButton: - case SP_TitleBarNormalButton: - { - QSize defaultTitleBarIconSize(16, 16); - - QIcon res; - auto iter = titleBarIconMap.find(standardIcon); - QString iconPath = iter.value(); - QPalette palette = qApp->palette(); - - QPixmap normal = RenderHelper::changeSVGFillColor(iconPath, palette.color(QPalette::Normal, QPalette::Foreground), defaultTitleBarIconSize); - res.addPixmap(normal, QIcon::Normal); - - QPixmap disable = RenderHelper::changeSVGFillColor(iconPath, palette.color(QPalette::Disabled, QPalette::Foreground), defaultTitleBarIconSize); - res.addPixmap(normal, QIcon::Disabled); - return res; - } - default: - break; - } - return ParentStyle::standardIcon(standardIcon, option, widget); -} \ No newline at end of file diff --git a/style/src/style.h b/style/src/style.h deleted file mode 100644 index 7b3212ce5a8cb4c8793cbbd443f30f00d62ed491..0000000000000000000000000000000000000000 --- a/style/src/style.h +++ /dev/null @@ -1,57 +0,0 @@ -/** - * Copyright (c) 2020 ~ 2022 KylinSec Co., Ltd. - * kiran-qt5-integration is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - * - * Author: liuxinhao - */ - -#ifndef KIRAN_QT5_PLATFORMTHEME_STYLE_KIRAN_STYLE_H_ -#define KIRAN_QT5_PLATFORMTHEME_STYLE_KIRAN_STYLE_H_ - -#include - -#include "draw-helper/draw-common-helper.h" - -#if 1 -#include -#define ParentStyle QFusionStyle -#else -#include -#define ParentStyle QCommonStyle -#endif - -class QAbstractScrollArea; -class Style : public ParentStyle -{ -public: - explicit Style(); - ~Style(); - - int styleHint(StyleHint hint, const QStyleOption* option, const QWidget* widget, QStyleHintReturn* returnData) const override; - int pixelMetric(PixelMetric metric, const QStyleOption* option, const QWidget* widget) const override; - - void drawPrimitive(PrimitiveElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const override; - void drawComplexControl(ComplexControl control, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget) const override; - void drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const override; - - QRect subElementRect(SubElement element, const QStyleOption* option, const QWidget* widget) const override; - QRect subControlRect(ComplexControl cc, const QStyleOptionComplex* opt, SubControl sc, const QWidget* widget) const override; - QSize sizeFromContents(ContentsType type, const QStyleOption* option, const QSize& contentSize, const QWidget* widget) const override; - - QPixmap standardPixmap(StandardPixmap standardPixmap, const QStyleOption* opt, const QWidget* widget) const override; - QIcon standardIcon(StandardPixmap standardIcon, const QStyleOption* option, const QWidget* widget) const override; - - void polishScrollArea(QAbstractScrollArea* scrollArea); - void polish(QWidget* widget) override; - void polish(QApplication* app) override; - void polish(QPalette& pal) override; -}; - -#endif // KIRAN_QT5_PLATFORMTHEME_STYLE_KIRAN_STYLE_H_