From e03012991caaaf008c074f7c76e6631b97e62a73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cl=C3=A9ro?= Date: Sun, 24 Nov 2024 21:03:19 +0100 Subject: [PATCH] Make dependency qlementine_icons not mandatory --- CMakeLists.txt | 9 +- CMakePresets.json | 12 +- lib/CMakeLists.txt | 10 - .../qlementine/style/QlementineStyle.hpp | 11 +- .../oclero/qlementine/utils/IconUtils.hpp | 10 - lib/src/style/EventFilters.cpp | 52 +- lib/src/style/QlementineStyle.cpp | 213 +---- lib/src/style/ThemeManager.cpp | 3 + lib/src/utils/IconUtils.cpp | 10 - sandbox/resources/plus_24.svg | 1 - sandbox/resources/sandbox.qrc | 7 +- sandbox/resources/scene_light.svg | 1 - sandbox/resources/scene_material.svg | 1 - sandbox/resources/scene_object.svg | 1 - sandbox/resources/test_image_16x16.svg | 1 + sandbox/resources/test_image_24x24.svg | 1 + sandbox/resources/test_image_color_16x16.svg | 1 + sandbox/src/CsdWindow.cpp | 766 ------------------ sandbox/src/CsdWindow.hpp | 25 - sandbox/src/SandboxWindow.cpp | 100 +-- sandbox/src/main.cpp | 9 +- showcase/CMakeLists.txt | 12 + showcase/resources/icons/cube-green.svg | 1 + showcase/resources/icons/cube-red.svg | 1 + showcase/resources/icons/cube-yellow.svg | 1 + showcase/resources/icons/scene_light.svg | 1 - showcase/resources/icons/scene_material.svg | 1 - showcase/resources/icons/scene_object.svg | 1 - showcase/resources/showcase.qrc | 18 +- showcase/src/ShowcaseWindow.cpp | 98 ++- showcase/src/main.cpp | 7 +- 31 files changed, 231 insertions(+), 1154 deletions(-) delete mode 100644 sandbox/resources/plus_24.svg delete mode 100644 sandbox/resources/scene_light.svg delete mode 100644 sandbox/resources/scene_material.svg delete mode 100644 sandbox/resources/scene_object.svg create mode 100644 sandbox/resources/test_image_16x16.svg create mode 100644 sandbox/resources/test_image_24x24.svg create mode 100644 sandbox/resources/test_image_color_16x16.svg delete mode 100644 sandbox/src/CsdWindow.cpp delete mode 100644 sandbox/src/CsdWindow.hpp create mode 100644 showcase/resources/icons/cube-green.svg create mode 100644 showcase/resources/icons/cube-red.svg create mode 100644 showcase/resources/icons/cube-yellow.svg delete mode 100644 showcase/resources/icons/scene_light.svg delete mode 100644 showcase/resources/icons/scene_material.svg delete mode 100644 showcase/resources/icons/scene_object.svg diff --git a/CMakeLists.txt b/CMakeLists.txt index 8b816c4..bb53cc1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,13 +41,14 @@ endif() find_package(Qt6 REQUIRED COMPONENTS Core Widgets Svg) qt_standard_project_setup() -# include(DeployQt) - # The library. add_subdirectory(lib) -# Sandbox. -if(${PROJECT_IS_TOP_LEVEL}) +# Example apps using the lib. +if(QLEMENTINE_SANDBOX) add_subdirectory(sandbox) +endif() + +if(QLEMENTINE_SHOWCASE) add_subdirectory(showcase) endif() diff --git a/CMakePresets.json b/CMakePresets.json index 2ae3f20..d18512e 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -13,7 +13,9 @@ "generator": "Xcode", "binaryDir": "${sourceDir}/_build", "cacheVariables": { - "CMAKE_PREFIX_PATH": "/opt/homebrew/opt/qt/lib/cmake/Qt6" + "CMAKE_PREFIX_PATH": "/opt/homebrew/opt/qt/lib/cmake/Qt6", + "QLEMENTINE_SANDBOX": true, + "QLEMENTINE_SHOWCASE": true }, "condition": { "type": "equals", @@ -28,7 +30,9 @@ "generator": "Visual Studio 17 2022", "binaryDir": "${sourceDir}/_build", "cacheVariables": { - "CMAKE_PREFIX_PATH": "C:/Qt/6.8.0/msvc2022_64" + "CMAKE_PREFIX_PATH": "C:/Qt/6.8.0/msvc2022_64", + "QLEMENTINE_SANDBOX": true, + "QLEMENTINE_SHOWCASE": true }, "condition": { "type": "equals", @@ -42,6 +46,10 @@ "description": "Makefile for Linux", "generator": "Unix Makefiles", "binaryDir": "${sourceDir}/_build", + "cacheVariables": { + "QLEMENTINE_SANDBOX": true, + "QLEMENTINE_SHOWCASE": true + }, "condition": { "type": "equals", "lhs": "${hostSystemName}", diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index e3610ab..05ee9a6 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -1,14 +1,5 @@ set(LIB_TARGET_NAME ${PROJECT_NAME}) -# Dependency: qlementine-icons -include(FetchContent) -FetchContent_Declare(qlementine_icons GIT_REPOSITORY "https://github.com/oclero/qlementine-icons.git") -FetchContent_MakeAvailable(qlementine_icons) -set_target_properties(qlementine_icons - PROPERTIES - FOLDER dependencies -) - # Declare files. set(SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/animation/WidgetAnimator.cpp @@ -140,7 +131,6 @@ target_link_libraries(${LIB_TARGET_NAME} Qt::Core Qt::Widgets Qt::Svg - oclero::qlementine_icons ) set_target_properties(${LIB_TARGET_NAME} diff --git a/lib/include/oclero/qlementine/style/QlementineStyle.hpp b/lib/include/oclero/qlementine/style/QlementineStyle.hpp index 67eaa34..45d1256 100644 --- a/lib/include/oclero/qlementine/style/QlementineStyle.hpp +++ b/lib/include/oclero/qlementine/style/QlementineStyle.hpp @@ -72,8 +72,12 @@ class QlementineStyle : public QCommonStyle { QIcon makeThemedIcon( const QString& svgPath, const QSize& size = QSize(16, 16), ColorRole role = ColorRole::Secondary) const; - QIcon makeThemedIcon( - icons::Icons16 id, const QSize& size = QSize(16, 16), ColorRole role = ColorRole::Secondary) const; + + QIcon makeThemedIconFromName( + const QString& name, const QSize& size = QSize(16, 16), ColorRole role = ColorRole::Secondary) const; + + // Allows to customize quickly the way QlementineStyle gets its icons. SVG paths preferred. + void setIconPathGetter(const std::function& func); public: // QStyle overrides. void drawPrimitive( @@ -289,7 +293,4 @@ class QlementineStyle : public QCommonStyle { }; QlementineStyle* appStyle(); - -QIcon makeThemedIcon(icons::Icons16 id, const QSize& size = QSize(16, 16), ColorRole role = ColorRole::Secondary); - } // namespace oclero::qlementine diff --git a/lib/include/oclero/qlementine/utils/IconUtils.hpp b/lib/include/oclero/qlementine/utils/IconUtils.hpp index 2fa33ec..bdc6e16 100644 --- a/lib/include/oclero/qlementine/utils/IconUtils.hpp +++ b/lib/include/oclero/qlementine/utils/IconUtils.hpp @@ -6,10 +6,6 @@ #include #include -#include -#include -#include - namespace oclero::qlementine { struct IconTheme { QColor normal; @@ -30,10 +26,4 @@ struct IconTheme { /// Makes an icon from the file located at the path in parameter and colorizes the QPixmaps. Fixes the standard Qt behavior. [[maybe_unused]] QIcon makeIconFromSvg( const QString& svgPath, const IconTheme& iconTheme, const QSize& size = QSize(16, 16)); - -[[maybe_unused]] QIcon makeIconFromSvg(icons::Icons16 id, const QSize& size = QSize(16, 16)); - -/// Makes an icon from the icon ID in parameter and colorizes the QPixmaps. Fixes the standard Qt behavior. -[[maybe_unused]] QIcon makeIconFromSvg( - icons::Icons16 id, const IconTheme& iconTheme, const QSize& size = QSize(16, 16)); } // namespace oclero::qlementine diff --git a/lib/src/style/EventFilters.cpp b/lib/src/style/EventFilters.cpp index ada888e..a341a82 100644 --- a/lib/src/style/EventFilters.cpp +++ b/lib/src/style/EventFilters.cpp @@ -9,8 +9,6 @@ #include #include -#include - #include #include #include @@ -502,45 +500,48 @@ class LineEditMenuIconsBehavior : public QObject { }; static std::vector iconList(IconListMode mode) { - using Icons16 = icons::Icons16; + const auto* qlem = oclero::qlementine::appStyle(); + if (!qlem) + return {}; + // The order follows the one defined QLineEdit.cpp and QSpinBox.cpp (Qt6). switch (mode) { case IconListMode::LineEdit: return { QIcon(), // Separator - makeThemedIcon(Icons16::Action_Undo), - makeThemedIcon(Icons16::Action_Redo), + qlem->makeThemedIconFromName("edit-undo"), + qlem->makeThemedIconFromName("edit-redo"), QIcon(), // Separator - makeThemedIcon(Icons16::Action_Cut), - makeThemedIcon(Icons16::Action_Copy), - makeThemedIcon(Icons16::Action_Paste), - makeThemedIcon(Icons16::Action_Erase), + qlem->makeThemedIconFromName("edit-cut"), + qlem->makeThemedIconFromName("edit-copy"), + qlem->makeThemedIconFromName("edit-paste"), + qlem->makeThemedIconFromName("edit-delete"), QIcon(), // Separator - makeThemedIcon(Icons16::Action_SelectAll), + qlem->makeThemedIconFromName("edit-select-all"), }; case IconListMode::ReadOnlyLineEdit: return { QIcon(), // Separator - makeThemedIcon(Icons16::Action_Copy), + qlem->makeThemedIconFromName("edit-copy"), QIcon(), // Separator - makeThemedIcon(Icons16::Action_SelectAll), + qlem->makeThemedIconFromName("edit-select-all"), }; case IconListMode::SpinBox: return { QIcon(), // Separator - makeThemedIcon(Icons16::Action_Undo), - makeThemedIcon(Icons16::Action_Redo), + qlem->makeThemedIconFromName("edit-undo"), + qlem->makeThemedIconFromName("edit-redo"), QIcon(), // Separator - makeThemedIcon(Icons16::Action_Cut), - makeThemedIcon(Icons16::Action_Copy), - makeThemedIcon(Icons16::Action_Paste), - makeThemedIcon(Icons16::Action_Erase), + qlem->makeThemedIconFromName("edit-cut"), + qlem->makeThemedIconFromName("edit-copy"), + qlem->makeThemedIconFromName("edit-paste"), + qlem->makeThemedIconFromName("edit-delete"), QIcon(), // Separator QIcon(), // Separator - makeThemedIcon(Icons16::Action_SelectAll), + qlem->makeThemedIconFromName("edit-select-all"), QIcon(), // Separator - makeThemedIcon(Icons16::Navigation_ChevronUp), - makeThemedIcon(Icons16::Navigation_ChevronDown), + qlem->makeThemedIconFromName("go-up"), + qlem->makeThemedIconFromName("go-down"), }; default: return {}; @@ -562,12 +563,15 @@ class LineEditMenuIconsBehavior : public QObject { const auto actions = _menu->findChildren(); if (!actions.empty()) { const auto icons = iconList(getMode(_menu)); - for (auto i = 0; i < static_cast(icons.size()) && i < static_cast(actions.size()); ++i) { - if (auto* action = actions.at(i)) { - action->setIcon(icons.at(i)); + if (!icons.empty()) { + for (auto i = 0; i < static_cast(icons.size()) && i < static_cast(actions.size()); ++i) { + if (auto* action = actions.at(i)) { + action->setIcon(icons.at(i)); + } } } } + _menu->adjustSize(); } public: diff --git a/lib/src/style/QlementineStyle.cpp b/lib/src/style/QlementineStyle.cpp index 500e887..b1de573 100644 --- a/lib/src/style/QlementineStyle.cpp +++ b/lib/src/style/QlementineStyle.cpp @@ -23,7 +23,6 @@ #include #include #include -#include #include "EventFilters.hpp" @@ -66,14 +65,6 @@ QlementineStyle* appStyle() { return qobject_cast(qApp->style()); } -QIcon makeThemedIcon(icons::Icons16 id, const QSize& size, ColorRole role) { - if (const auto* style = appStyle()) { - return style->makeThemedIcon(id, size, role); - } else { - return makeIconFromSvg(id, size); - } -} - /// Used to initializeResources from .qrc only once. std::once_flag qlementineOnceFlag; @@ -256,13 +247,13 @@ struct QlementineStyleImpl { std::unordered_map standardIconCache; std::unordered_map standardIconExtCache; AutoIconColor autoIconColor{ AutoIconColor::None }; + std::function iconPathFunc; }; QlementineStyle::QlementineStyle(QObject* parent) : _impl(new QlementineStyleImpl{ *this }) { setParent(parent); setObjectName(QStringLiteral("QlementineStyle")); - oclero::qlementine::icons::initializeIconTheme(); triggerCompleteRepaint(); } @@ -371,9 +362,17 @@ QIcon QlementineStyle::makeThemedIcon(const QString& svgPath, const QSize& size, return makeIconFromSvg(svgPath, iconTheme, size); } -QIcon QlementineStyle::makeThemedIcon(icons::Icons16 id, const QSize& size, ColorRole role) const { - const auto iconTheme = _impl->iconThemeFromTheme(role); - return makeIconFromSvg(id, iconTheme, size); +QIcon QlementineStyle::makeThemedIconFromName(const QString& name, const QSize& size, ColorRole role) const { + if (_impl->iconPathFunc) { + const auto iconPath = _impl->iconPathFunc(name); + return makeThemedIcon(iconPath, size, role); + } else { + return QIcon::fromTheme(name); + } +} + +void QlementineStyle::setIconPathGetter(const std::function& func) { + _impl->iconPathFunc = func; } /* QStyle overrides. */ @@ -1832,31 +1831,31 @@ void QlementineStyle::drawControl(ControlElement ce, const QStyleOption* opt, QP p->fillRect(line_rect, lineColor); } return; - case CE_RubberBand: - break; - case CE_DockWidgetTitle: - break; - case CE_ScrollBarAddLine: - // TODO - break; - case CE_ScrollBarSubLine: - // TODO - break; - case CE_ScrollBarAddPage: - // TODO - break; - case CE_ScrollBarSubPage: - // TODO - break; - case CE_ScrollBarSlider: - // TODO - break; - case CE_ScrollBarFirst: - // TODO - break; - case CE_ScrollBarLast: - // TODO - break; + // case CE_RubberBand: + // break; + // case CE_DockWidgetTitle: + // break; + // case CE_ScrollBarAddLine: + // // TODO + // break; + // case CE_ScrollBarSubLine: + // // TODO + // break; + // case CE_ScrollBarAddPage: + // // TODO + // break; + // case CE_ScrollBarSubPage: + // // TODO + // break; + // case CE_ScrollBarSlider: + // // TODO + // break; + // case CE_ScrollBarFirst: + // // TODO + // break; + // case CE_ScrollBarLast: + // // TODO + // break; case CE_FocusFrame: if (const auto* focusFrame = qobject_cast(w)) { const auto* monitoredWidget = focusFrame->widget(); @@ -4583,144 +4582,6 @@ QIcon QlementineStyle::standardIcon(StandardPixmap sp, const QStyleOption* opt, case SP_ArrowRight: case SP_LineEditClearButton: return _impl->getStandardIcon(sp, _impl->theme.iconSize); - // case SP_TitleBarMenuButton: - // break; - // case SP_TitleBarMinButton: - // break; - // case SP_TitleBarMaxButton: - // break; - // case SP_TitleBarCloseButton: - // break; - // case SP_TitleBarNormalButton: - // break; - // case SP_TitleBarShadeButton: - // break; - // case SP_TitleBarUnshadeButton: - // break; - // case SP_TitleBarContextHelpButton: - // break; - // case SP_DockWidgetCloseButton: - // break; - // case SP_DesktopIcon: - // break; - case SP_TrashIcon: - return makeIconFromSvg(icons::Icons16::Action_Trash, _impl->iconThemeFromTheme(), _impl->theme.iconSize); - // case SP_ComputerIcon: - // break; - // case SP_DriveFDIcon: - // break; - // case SP_DriveHDIcon: - // break; - // case SP_DriveCDIcon: - // break; - // case SP_DriveDVDIcon: - // break; - // case SP_DriveNetIcon: - // break; - // case SP_DirOpenIcon: - // break; - // case SP_DirClosedIcon: - // break; - // case SP_DirLinkIcon: - // break; - // case SP_DirLinkOpenIcon: - // break; - // case SP_FileIcon: - // break; - // case SP_FileLinkIcon: - // break; - // case SP_FileDialogStart: - // break; - // case SP_FileDialogEnd: - // break; - // case SP_FileDialogToParent: - // break; - // case SP_FileDialogNewFolder: - // break; - // case SP_FileDialogDetailedView: - // break; - // case SP_FileDialogInfoView: - // break; - // case SP_FileDialogContentsView: - // break; - // case SP_FileDialogListView: - // break; - // case SP_FileDialogBack: - // break; - // case SP_DirIcon: - // break; - // case SP_DialogOkButton: - // break; - // case SP_DialogCancelButton: - // break; - // case SP_DialogHelpButton: - // break; - // case SP_DialogOpenButton: - // break; - // case SP_DialogSaveButton: - // break; - // case SP_DialogCloseButton: - // break; - // case SP_DialogApplyButton: - // break; - // case SP_DialogResetButton: - // break; - // case SP_DialogDiscardButton: - // break; - // case SP_DialogYesButton: - // break; - // case SP_DialogNoButton: - // break; - // case SP_DialogYesToAllButton: - // break; - // case SP_DialogNoToAllButton: - // break; - // case SP_DialogSaveAllButton: - // break; - // case SP_DialogAbortButton: - // break; - // case SP_DialogRetryButton: - // break; - // case SP_DialogIgnoreButton: - // break; - // case SP_ArrowUp: - // break; - // case SP_ArrowDown: - // break; - // case SP_ArrowBack: - // break; - // case SP_ArrowForward: - // break; - // case SP_DirHomeIcon: - // break; - // case SP_CommandLink: - // break; - // case SP_VistaShield: - // break; - // case SP_BrowserReload: - // break; - // case SP_BrowserStop: - // break; - // case SP_MediaPlay: - // break; - // case SP_MediaStop: - // break; - // case SP_MediaPause: - // break; - // case SP_MediaSkipForward: - // break; - // case SP_MediaSkipBackward: - // break; - // case SP_MediaSeekForward: - // break; - // case SP_MediaSeekBackward: - // break; - // case SP_MediaVolume: - // break; - // case SP_MediaVolumeMuted: - // break; - // case SP_RestoreDefaultsButton: - // break; default: break; } diff --git a/lib/src/style/ThemeManager.cpp b/lib/src/style/ThemeManager.cpp index d20e1f1..4e2c12b 100644 --- a/lib/src/style/ThemeManager.cpp +++ b/lib/src/style/ThemeManager.cpp @@ -12,6 +12,9 @@ ThemeManager::ThemeManager(QObject* parent) ThemeManager::ThemeManager(QlementineStyle* style, QObject* parent) : QObject(parent) { setStyle(style); + if (parent == nullptr) { + setParent(style); + } } QlementineStyle* ThemeManager::style() const { diff --git a/lib/src/utils/IconUtils.cpp b/lib/src/utils/IconUtils.cpp index 67f2cee..cc33a6d 100644 --- a/lib/src/utils/IconUtils.cpp +++ b/lib/src/utils/IconUtils.cpp @@ -8,8 +8,6 @@ #include #include -#include - namespace oclero::qlementine { IconTheme::IconTheme(const QColor& normal, const QColor& disabled, const QColor& checkedNormal, QColor checkedDisabled) : normal(normal) @@ -94,12 +92,4 @@ QIcon makeIconFromSvg(const QString& svgPath, const IconTheme& iconTheme, const return icon; } - -QIcon makeIconFromSvg(icons::Icons16 id, const QSize& size) { - return makeIconFromSvg(icons::iconPath(id), size); -} - -QIcon makeIconFromSvg(icons::Icons16 id, const IconTheme& iconTheme, const QSize& size) { - return makeIconFromSvg(icons::iconPath(id), iconTheme, size); -} } // namespace oclero::qlementine diff --git a/sandbox/resources/plus_24.svg b/sandbox/resources/plus_24.svg deleted file mode 100644 index 1bcc698..0000000 --- a/sandbox/resources/plus_24.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/sandbox/resources/sandbox.qrc b/sandbox/resources/sandbox.qrc index 694cbba..df575d2 100644 --- a/sandbox/resources/sandbox.qrc +++ b/sandbox/resources/sandbox.qrc @@ -4,10 +4,9 @@ themes/light.json qlementine_icon.ico qlementine_icon.icns - plus_24.svg test_image_16x16.png - scene_light.svg - scene_material.svg - scene_object.svg + test_image_16x16.svg + test_image_24x24.svg + test_image_color_16x16.svg diff --git a/sandbox/resources/scene_light.svg b/sandbox/resources/scene_light.svg deleted file mode 100644 index 5e46abf..0000000 --- a/sandbox/resources/scene_light.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/sandbox/resources/scene_material.svg b/sandbox/resources/scene_material.svg deleted file mode 100644 index e46b631..0000000 --- a/sandbox/resources/scene_material.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/sandbox/resources/scene_object.svg b/sandbox/resources/scene_object.svg deleted file mode 100644 index 57bf3b9..0000000 --- a/sandbox/resources/scene_object.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/sandbox/resources/test_image_16x16.svg b/sandbox/resources/test_image_16x16.svg new file mode 100644 index 0000000..b4b1bb2 --- /dev/null +++ b/sandbox/resources/test_image_16x16.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/sandbox/resources/test_image_24x24.svg b/sandbox/resources/test_image_24x24.svg new file mode 100644 index 0000000..e306dad --- /dev/null +++ b/sandbox/resources/test_image_24x24.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/sandbox/resources/test_image_color_16x16.svg b/sandbox/resources/test_image_color_16x16.svg new file mode 100644 index 0000000..c8e978e --- /dev/null +++ b/sandbox/resources/test_image_color_16x16.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/sandbox/src/CsdWindow.cpp b/sandbox/src/CsdWindow.cpp deleted file mode 100644 index f395bc8..0000000 --- a/sandbox/src/CsdWindow.cpp +++ /dev/null @@ -1,766 +0,0 @@ -// SPDX-FileCopyrightText: Olivier Cléro -// SPDX-License-Identifier: MIT - -#include "CsdWindow.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -CsdWindow::CsdWindow(QWidget* parent) - : oclero::qlementine::FramelessWindow(parent) { - setWindowIcon(QIcon(":/qlementine_icon.ico")); - setupUi(); - resize(600, 400); - setWindowTitle("Custom native window"); - populateMenuBar(menuBar()); -} - -void CsdWindow::paintEvent(QPaintEvent* event) { - if (_useDefaultColor) { - FramelessWindow::paintEvent(event); - } else { - QPainter painter(this); - painter.fillRect(rect(), _backgroundColor); - } -} - -void CsdWindow::setupUi() { - auto* content = new QTabWidget(this); - - auto addseg = [](const QString& caption, QWidget* parent) { - auto* segTitle = new QWidget(parent); - auto layout = new QHBoxLayout; - segTitle->setLayout(layout); - layout->addWidget(new QLabel(caption, segTitle)); - auto* hline = new QFrame(segTitle); - hline->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum); - hline->setFrameShape(QFrame::HLine); - layout->addWidget(hline); - return segTitle; - }; - - // Basic Widget - { - auto* page = new QScrollArea(content); - - auto* root = new QWidget(page); - page->setWidget(root); - page->setWidgetResizable(true); - page->setAlignment(Qt::AlignHCenter); - auto* layout = new QVBoxLayout(); - root->setLayout(layout); - - // QCheckBox - { - auto* widget = new QWidget(root); - auto* llayout = new QHBoxLayout; - widget->setLayout(llayout); - - auto* checkbox = new QCheckBox("Normal", widget); - llayout->addWidget(checkbox); - - auto* checkbox2 = new QCheckBox("Disabled", widget); - checkbox2->setDisabled(true); - llayout->addWidget(checkbox2); - - auto* checkbox3 = new QCheckBox("WithIcon", widget); - checkbox3->setIcon(QIcon(QStringLiteral(":/plus_24.svg"))); - llayout->addWidget(checkbox3); - - auto* checkbox4 = new QCheckBox("NoneCheckable", widget); - checkbox4->setCheckable(false); - llayout->addWidget(checkbox4); - - auto* checkbox5 = new QCheckBox("PartiallyChecked", widget); - checkbox5->setCheckState(Qt::CheckState::PartiallyChecked); - llayout->addWidget(checkbox5); - - layout->addWidget(addseg("QCheckBox", root)); - layout->addWidget(widget); - } - - // QComboBox - { - auto createCombo = [](QWidget* parent) { - auto* widget = new QComboBox(parent); - widget->addItems({ "North", "South", "West", "East" }); - widget->addItem(QIcon(QStringLiteral(":/plus_24.svg")), "Directions"); - return widget; - }; - - auto* widget = new QWidget(root); - auto* llayout = new QHBoxLayout; - widget->setLayout(llayout); - - auto* normal = createCombo(widget); - llayout->addWidget(normal); - auto* editable = createCombo(widget); - editable->setEditable(true); - llayout->addWidget(editable); - - layout->addWidget(addseg("QComboBox", root)); - layout->addWidget(widget); - } - - // QCommandLinkButton - { - auto* widget = new QCommandLinkButton("ClickMe", "A vista style button", root); - - layout->addWidget(addseg("QCommandLinkButton", root)); - layout->addWidget(widget); - } - - // QDateEdit - { - auto* widget = new QDateEdit(root); - - layout->addWidget(addseg("QDateEdit", root)); - layout->addWidget(widget); - } - - // QDateTimeEdit - { - auto* widget = new QDateTimeEdit(root); - - layout->addWidget(addseg("QDateTimeEdit", root)); - layout->addWidget(widget); - } - - // QDial - { - auto* widget = new QDial(root); - - layout->addWidget(addseg("QDial", root)); - layout->addWidget(widget); - } - - // QDoubleSpinBox - { - auto* widget = new QDoubleSpinBox(root); - - layout->addWidget(addseg("QDoubleSpinBox", root)); - layout->addWidget(widget); - } - - // QFontComboBox - { - auto* widget = new QFontComboBox(root); - - layout->addWidget(addseg("QFontComboBox", root)); - layout->addWidget(widget); - } - - // QLCDNumber - { - auto* widget = new QLCDNumber(root); - widget->setDigitCount(1000); - widget->setMaximumWidth(200); - - layout->addWidget(addseg("QLCDNumber", root)); - layout->addWidget(widget); - } - - // QLabel - { - auto* widget = new QLabel(root); - widget->setText("This is a label"); - - layout->addWidget(addseg("QLabel", root)); - layout->addWidget(widget); - } - - // QLineEdit - { - auto* widget = new QWidget(root); - auto* llayout = new QHBoxLayout; - widget->setLayout(llayout); - - auto* normal = new QLineEdit(widget); - llayout->addWidget(normal); - auto* placeHold = new QLineEdit(widget); - placeHold->setPlaceholderText("typing..."); - llayout->addWidget(placeHold); - - layout->addWidget(addseg("QLineEdit", root)); - layout->addWidget(widget); - } - - // QMenu - { - auto* widget = new QMenuBar(root); - auto* menu = new QMenu("Menu", widget); - menu->addAction(QIcon(QStringLiteral(":/plus_24.svg")), "Item1"); - - - layout->addWidget(addseg("QMenu", root)); - layout->addWidget(widget); - } - - // QProgressBar - { - auto* widget = new QProgressBar(root); - widget->setValue(42); - - layout->addWidget(addseg("QProgressBar", root)); - layout->addWidget(widget); - } - - // QPushButton - { - auto* widget = new QWidget(root); - auto* llayout = new QHBoxLayout; - widget->setLayout(llayout); - - auto* pushButton = new QPushButton("Normal", widget); - llayout->addWidget(pushButton); - - auto* pushButton2 = new QPushButton("Disabled", widget); - pushButton2->setDisabled(true); - llayout->addWidget(pushButton2); - - auto* pushButton3 = new QPushButton("WithIcon", widget); - pushButton3->setIcon(QIcon(QStringLiteral(":/plus_24.svg"))); - llayout->addWidget(pushButton3); - - auto* pushButton4 = new QPushButton("Flat", widget); - pushButton4->setFlat(true); - llayout->addWidget(pushButton4); - - layout->addWidget(addseg("QPushButton", root)); - layout->addWidget(widget); - } - - // QRadioButton - { - auto* widget = new QWidget(root); - auto* llayout = new QHBoxLayout; - widget->setLayout(llayout); - - auto* radiobutton = new QRadioButton("Normal", widget); - llayout->addWidget(radiobutton); - - auto* radiobutton2 = new QRadioButton("Disabled", widget); - radiobutton2->setDisabled(true); - llayout->addWidget(radiobutton2); - - auto* radiobutton3 = new QRadioButton("WithIcon", widget); - radiobutton3->setIcon(QIcon(QStringLiteral(":/plus_24.svg"))); - llayout->addWidget(radiobutton3); - - auto* radiobutton4 = new QRadioButton("NoneCheckable", widget); - radiobutton4->setCheckable(false); - llayout->addWidget(radiobutton4); - - layout->addWidget(addseg("QRadioButton", root)); - layout->addWidget(widget); - } - - // QScrollBar - { - auto* widget = new QScrollBar(Qt::Horizontal, root); - - layout->addWidget(addseg("QScrollBar", root)); - layout->addWidget(widget); - } - - // QSlider - { - auto* widget = new QSlider(Qt::Horizontal, root); - auto* widget2 = new QSlider(Qt::Vertical, root); - - layout->addWidget(addseg("QSlider", root)); - layout->addWidget(widget); - layout->addWidget(widget2); - } - - // QSpinBox - { - auto* widget = new QSpinBox(root); - - layout->addWidget(addseg("QSpinBox", root)); - layout->addWidget(widget); - } - - // QTabBar - { - auto* widget = new QTabBar(root); - widget->addTab("Page1"); - widget->addTab(QIcon(QStringLiteral(":/plus_24.svg")), "Page2"); - widget->addTab(QIcon(QStringLiteral(":/plus_24.svg")), "Page3"); - widget->setExpanding(false); - - layout->addWidget(addseg("QTabBar", root)); - layout->addWidget(widget); - } - - // QTimeEdit - { - auto* widget = new QTimeEdit(root); - - layout->addWidget(addseg("QTimeEdit", root)); - layout->addWidget(widget); - } - - // QToolBox - { - auto* widget = new QToolBox(root); - widget->addItem(new QWidget(), QIcon(QStringLiteral(":/plus_24.svg")), "Item1"); - widget->addItem(new QWidget(), QIcon(QStringLiteral(":/plus_24.svg")), "Item2"); - - layout->addWidget(addseg("QToolBox", root)); - layout->addWidget(widget); - } - - // QToolButton - { - auto* widget = new QToolBar(root); - - auto icon = QIcon(QStringLiteral(":/plus_24.svg")); - - auto* toolbutton1 = new QToolButton(widget); - toolbutton1->setIcon(icon); - toolbutton1->setToolTip("with actions"); - toolbutton1->addAction(new QAction(icon, "Item1")); - toolbutton1->addAction(new QAction(icon, "Item2")); - widget->addWidget(toolbutton1); - - auto* toolbutton2 = new QToolButton(widget); - toolbutton2->setIcon(icon); - toolbutton2->setToolTip("QToolButton::DelayedPopup"); - toolbutton2->setPopupMode(QToolButton::DelayedPopup); - widget->addWidget(toolbutton2); - - auto* toolbutton3 = new QToolButton(widget); - toolbutton3->setIcon(icon); - toolbutton3->setToolTip("QToolButton::MenuButtonPopup"); - toolbutton3->setPopupMode(QToolButton::MenuButtonPopup); - widget->addWidget(toolbutton3); - - auto* toolbutton4 = new QToolButton(widget); - toolbutton4->setIcon(icon); - toolbutton4->setToolTip("QToolButton::InstantPopup"); - toolbutton4->setPopupMode(QToolButton::InstantPopup); - widget->addWidget(toolbutton4); - - auto* toolbutton5 = new QToolButton(widget); - toolbutton5->setIcon(icon); - toolbutton5->setToolTip("Qt::UpArrow"); - toolbutton5->setArrowType(Qt::UpArrow); - widget->addWidget(toolbutton5); - - auto* toolbutton6 = new QToolButton(widget); - toolbutton6->setIcon(icon); - toolbutton6->setToolTip("Qt::DownArrow"); - toolbutton6->setArrowType(Qt::DownArrow); - widget->addWidget(toolbutton6); - - auto* toolbutton7 = new QToolButton(widget); - toolbutton7->setIcon(icon); - toolbutton7->setToolTip("Qt::LeftArrow"); - toolbutton7->setArrowType(Qt::LeftArrow); - widget->addWidget(toolbutton7); - - auto* toolbutton8 = new QToolButton(widget); - toolbutton8->setIcon(icon); - toolbutton8->setToolTip("Qt::RightArrow"); - toolbutton8->setArrowType(Qt::RightArrow); - widget->addWidget(toolbutton8); - - auto* toolbutton9 = new QToolButton(widget); - toolbutton9->setIcon(icon); - toolbutton9->setToolTip("AutoRaise enabled"); - toolbutton9->setAutoRaise(true); - widget->addWidget(toolbutton9); - - layout->addWidget(addseg("QToolBox", root)); - layout->addWidget(widget); - } - - layout->addStretch(); - content->addTab(page, "Basic Widget"); - } - - - // Advanced Widget - { - auto* page = new QScrollArea(content); - - auto* root = new QWidget(page); - page->setWidget(root); - page->setWidgetResizable(true); - page->setAlignment(Qt::AlignHCenter); - auto* layout = new QVBoxLayout(); - root->setLayout(layout); - - // QCalendarWidget - { - auto* calendar = new QCalendarWidget(root); - layout->addWidget(addseg("QCalendarWidget", root)); - layout->addWidget(calendar); - } - - // QDialogButtonBox - { - auto* widget = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, root); - layout->addWidget(addseg("QDialogButtonBox", root)); - layout->addWidget(widget); - } - - - // QDialog - { - auto* widget = new QWidget(root); - auto* llayout = new QHBoxLayout; - widget->setLayout(llayout); - - auto* colorDialog = new QPushButton("QColorDialog", root); - connect(colorDialog, &QPushButton::clicked, []() { - QColorDialog dialog; - dialog.exec(); - }); - llayout->addWidget(colorDialog); - - auto* fileDialog = new QPushButton("QFileDialog", root); - connect(fileDialog, &QPushButton::clicked, []() { - QFileDialog dialog; - dialog.exec(); - }); - llayout->addWidget(fileDialog); - - auto* fontDialog = new QPushButton("QFontDialog", root); - connect(fontDialog, &QPushButton::clicked, []() { - QFontDialog dialog; - dialog.exec(); - }); - llayout->addWidget(fontDialog); - - layout->addWidget(addseg("QDialog(s)", root)); - layout->addWidget(widget); - } - - layout->addStretch(); - content->addTab(page, "Advanced Widget"); - } - - // Organizer Widget - { - auto* page = new QScrollArea(content); - - auto* root = new QWidget(page); - page->setWidget(root); - page->setWidgetResizable(true); - page->setAlignment(Qt::AlignHCenter); - auto* layout = new QVBoxLayout(); - root->setLayout(layout); - - // QButtonGroup - { - auto* buttonGroup = new QButtonGroup(root); - buttonGroup->addButton(new QCheckBox("Button1")); - buttonGroup->addButton(new QCheckBox("Button2")); - buttonGroup->setExclusive(true); - layout->addWidget(addseg("QButtonGroup(checkbox list)", root)); - for (auto* button : buttonGroup->buttons()) { - layout->addWidget(button); - } - } - - // QGroupBox - { - auto* widget = new QGroupBox("Group", root); - - auto* llayout = new QHBoxLayout; - widget->setLayout(llayout); - - llayout->addWidget(new QPushButton("Button1", widget)); - llayout->addWidget(new QPushButton("Button2", widget)); - - layout->addWidget(addseg("QGroupBox", root)); - layout->addWidget(widget); - } - - // QSplitter - { - auto* widget = new QSplitter(root); - - layout->addWidget(addseg("QSplitter", root)); - layout->addWidget(widget); - } - - // QTabWidget - { - auto* widget = new QTabWidget(root); - widget->addTab(new QLabel("Page1"), "Page1"); - widget->addTab(new QLabel("Page2"), QIcon(QStringLiteral(":/plus_24.svg")), "Page2"); - widget->addTab(new QLabel("Page3"), QIcon(QStringLiteral(":/plus_24.svg")), "Page3"); - - layout->addWidget(addseg("QTabWidget", root)); - layout->addWidget(widget); - } - - layout->addStretch(); - content->addTab(page, "Organizer Widget"); - } - - // Model/View - { - auto* page = new QScrollArea(content); - - auto* root = new QWidget(page); - page->setWidget(root); - page->setWidgetResizable(true); - page->setAlignment(Qt::AlignHCenter); - auto* layout = new QVBoxLayout(); - root->setLayout(layout); - - // QListWidget - { - auto* widget = new QListWidget(root); - - widget->addItems({ "Item1", "Item2", "Item3" }); - - layout->addWidget(addseg("QListWidget", root)); - layout->addWidget(widget); - } - - // QTableWidget - { - auto* widget = new QTableWidget(root); - - constexpr int rows = 100; - constexpr int cols = 10; - - widget->setColumnCount(cols); - widget->setRowCount(rows); - - for (int row = 0; row < rows; row++) { - for (int col = 0; col < cols; col++) { - widget->setItem(row, col, new QTableWidgetItem(QString::number(row) + ":" + QString::number(col))); - } - } - - layout->addWidget(addseg("QTableWidget", root)); - layout->addWidget(widget); - } - - // QTreeView - { - auto* widget = new QTreeView(root); - auto* model = new QFileSystemModel(root); - widget->setModel(model); - model->setRootPath(QCoreApplication::applicationDirPath()); - - layout->addWidget(addseg("QTreeView", root)); - layout->addWidget(widget); - } - - - layout->addStretch(); - content->addTab(page, "Model/View"); - } - - // Main Window - { - auto* page = new QScrollArea(content); - - auto* root = new QWidget(page); - page->setWidget(root); - page->setWidgetResizable(true); - page->setAlignment(Qt::AlignHCenter); - auto* layout = new QVBoxLayout(); - root->setLayout(layout); - - - // MainWindow - { - auto icon = QIcon(QStringLiteral(":/plus_24.svg")); - - auto* widget = new QMainWindow(); - auto* focus = new QFocusFrame(); - focus->setWidget(widget); - - auto* status = new QStatusBar(widget); - status->addWidget(new QLabel("Status1")); - status->addWidget(new QLabel("Status2"), 100); - status->addWidget(new QLabel("Status3")); - widget->setStatusBar(status); - - auto* menu = new QMenuBar(widget); - auto* fmenu = menu->addMenu("File"); - auto* emenu = menu->addMenu("Edit"); - auto* vmenu = menu->addMenu("View"); - menu->addMenu("Window"); - auto* hmenu = menu->addMenu("Help"); - widget->setMenuBar(menu); - auto* anew = fmenu->addAction(icon, "New"); - auto* aopen = fmenu->addAction(icon, "Open"); - auto* asave = fmenu->addAction(icon, "Save"); - auto* asaveas = fmenu->addAction(icon, "Save As"); - fmenu->addSeparator(); - auto* aclose = fmenu->addAction(icon, "Close"); - auto* acopy = emenu->addAction(icon, "Copy"); - auto* acut = emenu->addAction(icon, "Cut"); - auto* apaste = emenu->addAction(icon, "Paste"); - auto* ahelp = hmenu->addAction(icon, "Help"); - auto* aabout = hmenu->addAction(icon, "About"); - - auto* ftoolbar = widget->addToolBar("File"); - ftoolbar->setAllowedAreas(Qt::ToolBarArea::AllToolBarAreas); - ftoolbar->setMovable(true); - ftoolbar->setIconSize({ 24, 24 }); - ftoolbar->addActions({ anew, aopen, asave, asaveas, aclose }); - - auto* etoolbar = widget->addToolBar("Edit"); - etoolbar->setAllowedAreas(Qt::ToolBarArea::AllToolBarAreas); - etoolbar->setMovable(true); - etoolbar->setIconSize({ 24, 24 }); - etoolbar->addActions({ acopy, acut, apaste }); - - auto* htoolbar = widget->addToolBar("Help"); - htoolbar->setAllowedAreas(Qt::ToolBarArea::AllToolBarAreas); - htoolbar->setMovable(true); - htoolbar->setIconSize({ 24, 24 }); - htoolbar->addActions({ ahelp, aabout }); - - widget->setDockOptions(QMainWindow::DockOption::AllowTabbedDocks); - auto* treeview = new QTreeView(); - auto* treemodel = new QFileSystemModel(); - treeview->setModel(treemodel); - treemodel->setRootPath(QCoreApplication::applicationDirPath()); - auto* dock1 = new QDockWidget("Browser", widget); - dock1->setWidget(treeview); - dock1->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); - vmenu->addAction(dock1->toggleViewAction()); - widget->addDockWidget(Qt::RightDockWidgetArea, dock1); - - auto* docs = new QListWidget(); - docs->addItems( - QStringList() - << "A custom QStyle named QlementineStyle, that implements all the necessary API to give a modern look and feel to your Qt application. It's a drop-in replacement for the default QStyle." - << "An actual way to have client-side decoration (CSD) on your Qt window, with actual OS window animations and effects. (Windows only, at the moment)" - << "Lots of utilities to help you write beautiful Qt widgets."); - docs->setWordWrap(true); - auto* dock2 = new QDockWidget(tr("Features"), this); - dock2->setWidget(docs); - dock2->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); - vmenu->addAction(dock2->toggleViewAction()); - widget->addDockWidget(Qt::RightDockWidgetArea, dock2); - - - auto* mdiarea = new QMdiArea(widget); - widget->setCentralWidget(mdiarea); - - auto* subwnd1 = mdiarea->addSubWindow(new QTextEdit(), Qt::Window); - subwnd1->setWindowTitle("Window1"); - auto* subwnd2 = mdiarea->addSubWindow(new QTextEdit(), Qt::Window); - subwnd2->setWindowTitle("Window2"); - - layout->addWidget(widget); - } - - layout->addStretch(); - content->addTab(page, "Main Window "); - } - - // window color - { - auto* page = new QWidget(content); - auto* verticalLayout = new QVBoxLayout(page); - - // Slider to modify the window background color. - auto* slider = new QSlider(page); - slider->setRange(0, 255); - slider->setValue(_backgroundColor.red()); - QObject::connect(slider, &QSlider::valueChanged, this, [this](int value) { - _backgroundColor.setRed(value); - if (!_useDefaultColor) { - update(); - } - }); - slider->setMinimumWidth(255); - slider->setMaximumWidth(350); - verticalLayout->addWidget(slider, 0, Qt::AlignmentFlag::AlignCenter); - - // Checkbox to use or not the default background color. - auto* checkbox = new QCheckBox("Use default window color", page); - checkbox->setChecked(false); - - QObject::connect(checkbox, &QCheckBox::toggled, this, [this](bool checked) { - _useDefaultColor = checked; - update(); - }); - verticalLayout->addWidget(checkbox, 0, Qt::AlignmentFlag::AlignCenter); - - content->addTab(page, QStringLiteral("WindowColor")); - } - - setContentWidget(content); -} - -void CsdWindow::populateMenuBar(QMenuBar* menuBar) { - auto* fileMenu = new QMenu("&File", menuBar); - { - auto* quitAction = new QAction("&Quit", fileMenu); - quitAction->setMenuRole(QAction::MenuRole::QuitRole); - quitAction->setShortcut(Qt::CTRL + Qt::Key_Q); - quitAction->setShortcutContext(Qt::ShortcutContext::ApplicationShortcut); - QObject::connect(quitAction, &QAction::triggered, this, []() { - QApplication::quit(); - }); - fileMenu->addAction(quitAction); - } - - menuBar->addMenu(fileMenu); - - auto* windowMenu = new QMenu("&Window", menuBar); - { - auto minimizeAction = new QAction("Minimize", windowMenu); - QObject::connect(minimizeAction, &QAction::triggered, this, [this]() { - windowHandle()->showMinimized(); - }); - windowMenu->addAction(minimizeAction); - - auto* maximizeAction = new QAction("Maximize", windowMenu); - QObject::connect(maximizeAction, &QAction::triggered, this, [this]() { - if (auto window = this->window()) { - if (window->windowState() & Qt::WindowMaximized) { - window->showNormal(); - } else { - window->showMaximized(); - } - } - }); - windowMenu->addAction(maximizeAction); - - auto* closeAction = new QAction("&Close", windowMenu); - QObject::connect(closeAction, &QAction::triggered, this, [this]() { - windowHandle()->close(); - }); - windowMenu->addAction(closeAction); - } - menuBar->addMenu(windowMenu); - - auto* helpMenu = new QMenu("&Help", menuBar); - { - auto* aboutAction = new QAction("&About", windowMenu); - aboutAction->setMenuRole(QAction::AboutRole); - QObject::connect(aboutAction, &QAction::triggered, this, [this]() { - QMessageBox msgBox( - QMessageBox::Icon::Information, "About", "Example of frameless window", QMessageBox::NoButton, this); - msgBox.exec(); - }); - helpMenu->addAction(aboutAction); - } - menuBar->addMenu(helpMenu); -} diff --git a/sandbox/src/CsdWindow.hpp b/sandbox/src/CsdWindow.hpp deleted file mode 100644 index 81bc455..0000000 --- a/sandbox/src/CsdWindow.hpp +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-FileCopyrightText: Olivier Cléro -// SPDX-License-Identifier: MIT - -#pragma once - -#include - -class CsdWindow : public oclero::qlementine::FramelessWindow { - Q_OBJECT - -public: - explicit CsdWindow(QWidget* parent = nullptr); - ~CsdWindow() = default; - -protected: - void paintEvent(QPaintEvent* event) override; - -private: - void populateMenuBar(QMenuBar* menuBar); - void setupUi(); - -private: - QColor _backgroundColor{ 255, 192, 0 }; - bool _useDefaultColor{ false }; -}; diff --git a/sandbox/src/SandboxWindow.cpp b/sandbox/src/SandboxWindow.cpp index ae175b0..05609d0 100644 --- a/sandbox/src/SandboxWindow.cpp +++ b/sandbox/src/SandboxWindow.cpp @@ -58,11 +58,19 @@ #include namespace oclero::qlementine::sandbox { -using Icons16 = oclero::qlementine::icons::Icons16; -static QIcon makeQIcon(Icons16 id, const QSize& size = { 16, 16 }) { - return oclero::qlementine::makeThemedIcon(id, size); + +static QIcon getTestQIcon(const QSize& size = { 16, 16 }, bool colored = false) { + if (size.height() == 24) { + return QIcon(":/sandbox/test_image_24x24.svg"); + } else { + return colored ? QIcon(":/sandbox/test_image_color_16x16.svg") : QIcon(":/sandbox/test_image_16x16.svg"); + } } +// static QIcon makeQIcon(Icons16 id, const QSize& size = { 16, 16 }) { +// return oclero::qlementine::makeThemedIcon(id, size); +// } + class ContextMenuEventFilter : public QObject { private: std::function _cb; @@ -350,7 +358,7 @@ struct SandboxWindow::Impl { void setupUI_button() { auto* button = new QPushButton(windowContent); button->setText("Button with a very long text that can be elided"); - button->setIcon(makeQIcon(Icons16::Action_Save)); + button->setIcon(getTestQIcon()); button->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed); button->setDefault(true); windowContentLayout->addWidget(button); @@ -368,7 +376,7 @@ struct SandboxWindow::Impl { { // Icon, fixed size auto* button = new QPushButton(windowContent); - button->setIcon(makeQIcon(Icons16::Action_Save)); + button->setIcon(getTestQIcon()); button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); windowContentLayout->addWidget(button); } @@ -376,7 +384,7 @@ struct SandboxWindow::Impl { // Text+Icon, fixed size auto* button = new QPushButton(windowContent); button->setText("Button"); - button->setIcon(makeQIcon(Icons16::Action_Save)); + button->setIcon(getTestQIcon()); button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); windowContentLayout->addWidget(button); } @@ -384,7 +392,7 @@ struct SandboxWindow::Impl { // Text+Icon+Menu, fixed size auto* button = new QPushButton(windowContent); button->setText("Button"); - button->setIcon(makeQIcon(Icons16::Action_Save)); + button->setIcon(getTestQIcon()); button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); auto* menu = new QMenu(button); @@ -404,21 +412,21 @@ struct SandboxWindow::Impl { { // Icon, expanding size. auto* button = new QPushButton(windowContent); - button->setIcon(makeQIcon(Icons16::Action_Save)); + button->setIcon(getTestQIcon()); windowContentLayout->addWidget(button); } { // Text+Icon, expanding size. auto* button = new QPushButton(windowContent); button->setText("Button"); - button->setIcon(makeQIcon(Icons16::Action_Save)); + button->setIcon(getTestQIcon()); windowContentLayout->addWidget(button); } { // Text+Icon+Menu, expanding size auto* button = new QPushButton(windowContent); button->setText("Button"); - button->setIcon(makeQIcon(Icons16::Action_Save)); + button->setIcon(getTestQIcon()); auto* menu = new QMenu("ButtonMenu"); for (auto i = 0; i < 3; ++i) { @@ -436,7 +444,7 @@ struct SandboxWindow::Impl { const auto tristate = i > 1; checkbox->setChecked(checked); - checkbox->setIcon(makeQIcon(Icons16::Action_Save)); + checkbox->setIcon(getTestQIcon()); checkbox->setText(QString("%1 checkbox %2 with a very long text").arg(tristate ? "Tristate" : "Normal").arg(i)); checkbox->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed); checkbox->setTristate(tristate); @@ -450,7 +458,7 @@ struct SandboxWindow::Impl { for (auto i = 0; i < 2; ++i) { auto* radiobutton = new QRadioButton(windowContent); radiobutton->setChecked(true); - radiobutton->setIcon(makeQIcon(Icons16::Action_Save)); + radiobutton->setIcon(getTestQIcon()); radiobutton->setText(QString("RadioButton %1 with a very long text").arg(i)); radiobutton->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed); radioGroup->addButton(radiobutton); @@ -460,21 +468,19 @@ struct SandboxWindow::Impl { void setupUI_commandLinkButton() { { - const QIcon icon(":/sandbox/plus_24.svg"); auto* button = new CommandLinkButton(windowContent); button->setText("First Line with a very long text that should be cropped"); button->setDescription("Second Line that could be very long and should be cropped"); - button->setIcon(icon); + button->setIcon(getTestQIcon({ 24, 24 })); button->setDefault(true); button->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed); windowContentLayout->addWidget(button); } { - const QIcon icon(":/sandbox/plus_24.svg"); auto* button = new CommandLinkButton(windowContent); button->setText("First Line with a very long text that should be cropped"); button->setDescription("Second Line that could be very long and should be cropped"); - button->setIcon(icon); + button->setIcon(getTestQIcon({ 24, 24 })); button->setDefault(false); button->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed); windowContentLayout->addWidget(button); @@ -600,7 +606,7 @@ struct SandboxWindow::Impl { combobox->setEditable(true); for (auto i = 0; i < 4; ++i) { - combobox->addItem(makeQIcon(Icons16::Action_Save), QString("Editable comboBox item %1").arg(i)); + combobox->addItem(getTestQIcon(), QString("Editable comboBox item %1").arg(i)); } auto* model = qobject_cast(combobox->model()); auto* item = model->item(2); @@ -615,7 +621,7 @@ struct SandboxWindow::Impl { combobox->setFocusPolicy(Qt::StrongFocus); for (auto i = 0; i < 4; ++i) { - combobox->addItem(makeQIcon(Icons16::Action_Save), QString("ComboBox item %1").arg(i)); + combobox->addItem(getTestQIcon(), QString("ComboBox item %1").arg(i)); } windowContentLayout->addWidget(combobox); @@ -637,7 +643,7 @@ struct SandboxWindow::Impl { for (auto i = 0; i < 2; ++i) { auto* item = new QListWidgetItem( - makeQIcon(Icons16::Action_Save), QString("Item #%1 with very long text that can be elided").arg(i), listView); + getTestQIcon(), QString("Item #%1 with very long text that can be elided").arg(i), listView); item->setFlags(item->flags() | Qt::ItemFlag::ItemIsUserCheckable); item->setCheckState(i % 2 ? Qt ::CheckState::Checked : Qt::CheckState::Unchecked); //item->setForeground(i % 2 ? Qt::red : Qt::blue); @@ -680,7 +686,6 @@ struct SandboxWindow::Impl { constexpr auto rowCount = 3; tableView->setColumnCount(columnCount); tableView->setRowCount(rowCount); - const QIcon icon(":/sandbox/scene_object.svg"); std::vector columnAlignments; columnAlignments.resize(columnCount); @@ -691,21 +696,21 @@ struct SandboxWindow::Impl { for (auto col = 0; col < columnCount; ++col) { auto* item = new QTableWidgetItem(QString("Column %1").arg(col + 1)); - item->setIcon(icon); + item->setIcon(getTestQIcon({ 16, 16 }, true)); item->setTextAlignment(columnAlignments.at(col)); tableView->setHorizontalHeaderItem(col, item); } for (auto row = 0; row < rowCount; ++row) { auto* item = new QTableWidgetItem(QString("Row %1").arg(row + 1)); - item->setIcon(icon); + item->setIcon(getTestQIcon({ 16, 16 }, true)); tableView->setVerticalHeaderItem(row, item); } for (auto row = 0; row < rowCount; ++row) { for (auto col = 0; col < columnCount; ++col) { auto* item = new QTableWidgetItem(QString("Item at %1, %2").arg(row + 1).arg(col + 1)); - item->setIcon(icon); + item->setIcon(getTestQIcon({ 16, 16 }, true)); item->setTextAlignment(columnAlignments.at(col)); item->setFlags(Qt::ItemFlag::ItemIsEditable | Qt::ItemFlag::ItemIsSelectable | Qt::ItemFlag::ItemIsEnabled); item->setData(Qt::DisplayRole, QVariant::fromValue(true)); @@ -729,19 +734,19 @@ struct SandboxWindow::Impl { for (auto i = 0; i < 3; ++i) { auto* root = new QTreeWidgetItem(treeWidget); root->setText(0, QString("Root %1").arg(i + 1)); - root->setIcon(0, QIcon(":/sandbox/scene_object.svg")); + root->setIcon(0, getTestQIcon({ 16, 16 }, true)); root->setText(1, QString("Column 2 of Root %1").arg(i + 1)); for (auto j = 0; j < 3; ++j) { auto* child = new QTreeWidgetItem(root); child->setText(0, QString("Child %1 of Root %2").arg(j).arg(i)); - child->setIcon(0, j == 2 ? QIcon(":/sandbox/scene_light.svg") : QIcon(":/sandbox/scene_object.svg")); + child->setIcon(0, getTestQIcon({ 16, 16 }, true)); child->setText(1, QString("Column 2 of Child %1 of Root %2").arg(j).arg(i)); for (auto k = 0; k < 3; ++k) { auto* subChild = new QTreeWidgetItem(child); subChild->setText(0, QString("Child %1 of Child %2 of Root %3").arg(k).arg(j).arg(i)); - subChild->setIcon(0, QIcon(":/sandbox/scene_material.svg")); + subChild->setIcon(0, getTestQIcon({ 16, 16 }, true)); subChild->setText(1, QString("Column 2 of Child %1 of Child %2 of Root %3").arg(k).arg(j).arg(i)); } } @@ -755,7 +760,7 @@ struct SandboxWindow::Impl { auto* menuBar = owner.menuBar(); // NB: it looks like MacOS' native menu bar has an issue with QIcon, so we have to force // it to generate icons for High-DPI screens. - const auto icon = makeQIcon(Icons16::Action_Save); + const auto icon = getTestQIcon(); for (auto i = 0; i < 5; ++i) { auto* menu = menuBar->addMenu(QString("Menu &%1").arg(i)); @@ -798,14 +803,14 @@ struct SandboxWindow::Impl { void setupUI_toolButton() { auto* toolButton = new QToolButton(toolbar); - toolButton->setIcon(makeQIcon(Icons16::Action_Save)); + toolButton->setIcon(getTestQIcon()); toolButton->setText(QString("Button with a very long text that can be elided")); toolButton->setToolButtonStyle(Qt::ToolButtonIconOnly); toolButton->setCheckable(false); toolButton->setChecked(false); { - const auto icon = makeQIcon(Icons16::Action_Save); + const auto icon = getTestQIcon(); auto* subMenu = new QMenu("Menu title", toolButton); toolButton->setMenu(subMenu); subMenu->addAction(icon, "Sub Action 1"); @@ -819,7 +824,7 @@ struct SandboxWindow::Impl { } void setupUI_toolButtonsVariants() { - const auto icon = makeQIcon(Icons16::Action_Save); + const auto icon = getTestQIcon(); toolbar = owner.addToolBar("ToolBar name"); //toolbar->set @@ -906,7 +911,6 @@ struct SandboxWindow::Impl { } void setupUI_tabBar() { - const QIcon icon(":/sandbox/scene_object.svg"); auto* tabBar = new QTabBar(windowContent); tabBar->setFocusPolicy(Qt::NoFocus); tabBar->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed); @@ -931,7 +935,7 @@ struct SandboxWindow::Impl { const auto tabText = QString(tabTextList.join(" ").append(QString(" %1").arg(i + 1))); if (i % 3 == 0) { - tabBar->addTab(icon, tabText); + tabBar->addTab(getTestQIcon({ 16, 16 }, true), tabText); } else { tabBar->addTab(tabText); } @@ -957,8 +961,6 @@ struct SandboxWindow::Impl { } void setupUI_tabWidget() { - const QStringList icons = { ":/sandbox/scene_object.svg", ":/sandbox/scene_light.svg", - ":/sandbox/scene_material.svg" }; auto* tabWidget = new QTabWidget(windowContent); tabWidget->setDocumentMode(false); @@ -987,7 +989,7 @@ struct SandboxWindow::Impl { tabTextList.append("Tab"); } const auto tabText = QString(tabTextList.join(" ").append(QString(" %1").arg(i + 1))); - const auto icon = QIcon(icons.at(i % icons.size())); + const auto icon = getTestQIcon(); tabWidget->addTab(tabContent, icon, tabText); } } @@ -1095,19 +1097,19 @@ Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deseru for (auto i = 0; i < 3; ++i) { auto* root = new QTreeWidgetItem(treeWidget); root->setText(0, QString("Root %1").arg(i + 1)); - root->setIcon(0, QIcon(":/sandbox/scene_object.svg")); + root->setIcon(0, getTestQIcon({ 16, 16 }, true)); root->setText(1, QString("Column 2 of Root %1").arg(i + 1)); for (auto j = 0; j < 3; ++j) { auto* child = new QTreeWidgetItem(root); child->setText(0, QString("Child %1 of Root %2").arg(j).arg(i)); - child->setIcon(0, j == 2 ? QIcon(":/sandbox/scene_light.svg") : QIcon(":/sandbox/scene_object.svg")); + child->setIcon(0, getTestQIcon({ 16, 16 }, true)); child->setText(1, QString("Column 2 of Child %1 of Root %2").arg(j).arg(i)); for (auto k = 0; k < 3; ++k) { auto* subChild = new QTreeWidgetItem(child); subChild->setText(0, QString("Child %1 of Child %2 of Root %3").arg(k).arg(j).arg(i)); - subChild->setIcon(0, QIcon(":/sandbox/scene_material.svg")); + subChild->setIcon(0, getTestQIcon({ 16, 16 }, true)); subChild->setText(1, QString("Column 2 of Child %1 of Child %2 of Root %3").arg(k).arg(j).arg(i)); } } @@ -1125,7 +1127,7 @@ Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deseru for (auto i = 0; i < 3; ++i) { auto* item = new QListWidgetItem( - makeQIcon(Icons16::Action_Save), QString("Item #%1 with very long text that can be elided").arg(i), listView); + getTestQIcon(), QString("Item #%1 with very long text that can be elided").arg(i), listView); item->setFlags(item->flags() | Qt::ItemFlag::ItemIsUserCheckable); item->setCheckState(i % 2 ? Qt ::CheckState::Checked : Qt::CheckState::Unchecked); @@ -1143,7 +1145,7 @@ Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deseru tableView->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Expanding); tableView->setColumnCount(columnCount); tableView->setRowCount(rowCount); - auto icon = makeQIcon(Icons16::Action_Save); + auto icon = getTestQIcon(); auto* headerItem = new QTableWidgetItem(icon, "A veeeeeery long header label"); tableView->setHorizontalHeaderItem(0, headerItem); tableView->setSelectionBehavior(QTableView::SelectionBehavior::SelectRows); @@ -1368,7 +1370,7 @@ Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deseru } void setupUI_navigationBar() { - const auto dummyIcon = makeQIcon(Icons16::Action_Save); + const auto dummyIcon = getTestQIcon(); auto* navBar = new NavigationBar(windowContent); for (auto i = 0; i < 3; ++i) { @@ -1384,7 +1386,7 @@ Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deseru } void setupUI_switch() { - const auto dummyIcon = makeQIcon(Icons16::Action_Save); + const auto dummyIcon = getTestQIcon(); auto* switchWidget = new Switch(windowContent); switchWidget->setText("Label of the Switch"); switchWidget->setIcon(dummyIcon); @@ -1483,7 +1485,7 @@ Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deseru } void setupUI_lineEditStatus() { - const auto dummyIcon = makeQIcon(Icons16::Action_Save); + const auto dummyIcon = getTestQIcon(); auto* lineEdit = new LineEdit(windowContent); lineEdit->setText("Label of the Switch"); @@ -1613,7 +1615,7 @@ SandboxWindow::SandboxWindow(ThemeManager* themeManager, QWidget* parent) // Uncomment the line to show the corresponding widget. // _impl->setupUI_label(); // _impl->setupUI_button(); - _impl->setupUI_buttonVariants(); + // _impl->setupUI_buttonVariants(); // _impl->setupUI_checkbox(); // _impl->setupUI_radioButton(); // _impl->setupUI_commandLinkButton(); @@ -1645,15 +1647,15 @@ SandboxWindow::SandboxWindow(ThemeManager* themeManager, QWidget* parent) // _impl->setupUI_switch(); // _impl->setupUI_expander(); // _impl->setupUI_popover(); - _impl->setupUI_navigationBar(); + // _impl->setupUI_navigationBar(); // _impl->setupUI_badge(); // _impl->setupUI_colorButton(); // _impl->setupUI_messageBoxIcons(); - // _impl->setupUI_fontMetricsTests(); - // _impl->setupUI_blur(); - // _impl->setupUI_themeEditor(); - // _impl->setupUI_messageBox(); + // _impl->setupUI_fontMetricsTests(); + // _impl->setupUI_blur(); + // _impl->setupUI_themeEditor(); + // _impl->setupUI_messageBox(); } _impl->endSetupUI(); oclero::qlementine::centerWidget(this); diff --git a/sandbox/src/main.cpp b/sandbox/src/main.cpp index a2bc3b3..cc0dd0c 100644 --- a/sandbox/src/main.cpp +++ b/sandbox/src/main.cpp @@ -25,20 +25,15 @@ int main(int argc, char* argv[]) { QCoreApplication::setApplicationVersion("1.0.0"); QApplication::setWindowIcon(QIcon(QStringLiteral(":/qlementine_icon.ico"))); - // Set custom QStyle. #if USE_CUSTOM_STYLE - oclero::qlementine::ThemeManager* themeManager{ nullptr }; - + // Set custom QStyle. auto* style = new oclero::qlementine::QlementineStyle(&qApplication); style->setAnimationsEnabled(true); style->setAutoIconColor(oclero::qlementine::AutoIconColor::TextColor); qApplication.setStyle(style); - // Custom icon theme. - QIcon::setThemeName("qlementine"); - // Theme manager. - themeManager = new oclero::qlementine::ThemeManager(style); + auto* themeManager = new oclero::qlementine::ThemeManager(style); themeManager->loadDirectory(":/showcase/themes"); // Define theme on QStyle. diff --git a/showcase/CMakeLists.txt b/showcase/CMakeLists.txt index 2d935af..ca1a1aa 100644 --- a/showcase/CMakeLists.txt +++ b/showcase/CMakeLists.txt @@ -1,5 +1,17 @@ set(SHOWCASE_NAME "showcase") +# Dependency: qlementine-icons +include(FetchContent) +FetchContent_Declare(qlementine_icons + GIT_REPOSITORY "https://github.com/oclero/qlementine-icons.git" + GIT_TAG 0a269d7c4eb77fdc8ca92a7fb2ceae1baae29727 #v1.5.0 +) +FetchContent_MakeAvailable(qlementine_icons) +set_target_properties(qlementine_icons + PROPERTIES + FOLDER dependencies +) + if(APPLE) set(APP_ICON_MACOS "${CMAKE_SOURCE_DIR}/branding/icon/icon.icns") set_source_files_properties(${APP_ICON_MACOS} diff --git a/showcase/resources/icons/cube-green.svg b/showcase/resources/icons/cube-green.svg new file mode 100644 index 0000000..c3c2b4a --- /dev/null +++ b/showcase/resources/icons/cube-green.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/showcase/resources/icons/cube-red.svg b/showcase/resources/icons/cube-red.svg new file mode 100644 index 0000000..de7c25a --- /dev/null +++ b/showcase/resources/icons/cube-red.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/showcase/resources/icons/cube-yellow.svg b/showcase/resources/icons/cube-yellow.svg new file mode 100644 index 0000000..48e79d2 --- /dev/null +++ b/showcase/resources/icons/cube-yellow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/showcase/resources/icons/scene_light.svg b/showcase/resources/icons/scene_light.svg deleted file mode 100644 index 5e46abf..0000000 --- a/showcase/resources/icons/scene_light.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/showcase/resources/icons/scene_material.svg b/showcase/resources/icons/scene_material.svg deleted file mode 100644 index e46b631..0000000 --- a/showcase/resources/icons/scene_material.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/showcase/resources/icons/scene_object.svg b/showcase/resources/icons/scene_object.svg deleted file mode 100644 index 57bf3b9..0000000 --- a/showcase/resources/icons/scene_object.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/showcase/resources/showcase.qrc b/showcase/resources/showcase.qrc index 31a3fe0..55f4ce2 100644 --- a/showcase/resources/showcase.qrc +++ b/showcase/resources/showcase.qrc @@ -1,11 +1,11 @@ - - icons/scene_light.svg - icons/scene_material.svg - icons/scene_object.svg - themes/dark.json - themes/light.json - qlementine_icon.ico - qlementine_icon.icns - + + icons/cube-green.svg + icons/cube-red.svg + icons/cube-yellow.svg + themes/dark.json + themes/light.json + qlementine_icon.ico + qlementine_icon.icns + diff --git a/showcase/src/ShowcaseWindow.cpp b/showcase/src/ShowcaseWindow.cpp index beef36e..6ceb9e8 100644 --- a/showcase/src/ShowcaseWindow.cpp +++ b/showcase/src/ShowcaseWindow.cpp @@ -18,7 +18,9 @@ #include #include +#include #include +#include #include #include @@ -55,8 +57,13 @@ namespace oclero::qlementine::showcase { using Icons16 = oclero::qlementine::icons::Icons16; -static QIcon makeQIcon(Icons16 id, const QSize& size = { 16, 16 }) { - return oclero::qlementine::makeThemedIcon(id, size); +static QIcon makeThemedIcon(Icons16 id, const QSize& size = { 16, 16 }) { + const auto svgPath = oclero::qlementine::icons::iconPath(id); + if (auto* style = oclero::qlementine::appStyle()) { + return style->makeThemedIcon(svgPath, size); + } else { + return QIcon(svgPath); + } } class DummyWorkspace : public QWidget { @@ -103,9 +110,9 @@ static QString getDummyText(const unsigned int minWords = 3, const unsigned int static QIcon getDummyColoredIcon() { static const auto icons = std::array{ - QIcon(":/showcase/icons/scene_object.svg"), - QIcon(":/showcase/icons/scene_light.svg"), - QIcon(":/showcase/icons/scene_material.svg"), + QIcon(":/showcase/icons/cube-green.svg"), + QIcon(":/showcase/icons/cube-red.svg"), + QIcon(":/showcase/icons/cube-yellow.svg"), }; auto rd = std::random_device(); @@ -125,7 +132,7 @@ static QIcon getDummyMonochromeIcon(const QSize& size = { 16, 16 }) { std::uniform_int_distribution>(1, 410 - 1); // TODO use a constexpr variable. const auto randomIndex = randomDistrib(gen); const auto randomIcon = static_cast(randomIndex); - return makeQIcon(randomIcon, size); + return makeThemedIcon(randomIcon, size); } struct ShowcaseWindow::Impl { @@ -185,24 +192,24 @@ struct ShowcaseWindow::Impl { auto* menu = menuBar->addMenu("File"); { // TODO: Use the enum provided by Qt6 instead of strings for icon IDs. - menu->addAction(makeQIcon(Icons16::Document_New), "New", QKeySequence::StandardKey::New, cb); - menu->addAction(makeQIcon(Icons16::Document_Open), "Open...", QKeySequence::StandardKey::Open, cb); + menu->addAction(makeThemedIcon(Icons16::Document_New), "New", QKeySequence::StandardKey::New, cb); + menu->addAction(makeThemedIcon(Icons16::Document_Open), "Open...", QKeySequence::StandardKey::Open, cb); - auto* recentFilesMenu = menu->addMenu(makeQIcon(Icons16::Document_OpenRecent), "Recent Files"); + auto* recentFilesMenu = menu->addMenu(makeThemedIcon(Icons16::Document_OpenRecent), "Recent Files"); for (auto i = 0; i < 5; ++i) { recentFilesMenu->addAction( - makeQIcon(Icons16::File_File), QString("Recent File %1").arg(i + 1), QKeySequence{}, cb); + makeThemedIcon(Icons16::File_File), QString("Recent File %1").arg(i + 1), QKeySequence{}, cb); } menu->addSeparator(); - menu->addAction(makeQIcon(Icons16::Action_Save), "Save", QKeySequence::StandardKey::Save, cb); - menu->addAction(makeQIcon(Icons16::Action_Close), "Close", QKeySequence::StandardKey::Close, cb); - menu->addAction(makeQIcon(Icons16::Action_Print), "Print...", QKeySequence::StandardKey::Print, cb); - menu->addAction(makeQIcon(Icons16::Action_PrintPreview), "Print Preview...", QKeySequence{}, cb); + menu->addAction(makeThemedIcon(Icons16::Action_Save), "Save", QKeySequence::StandardKey::Save, cb); + menu->addAction(makeThemedIcon(Icons16::Action_Close), "Close", QKeySequence::StandardKey::Close, cb); + menu->addAction(makeThemedIcon(Icons16::Action_Print), "Print...", QKeySequence::StandardKey::Print, cb); + menu->addAction(makeThemedIcon(Icons16::Action_PrintPreview), "Print Preview...", QKeySequence{}, cb); menu->addSeparator(); menu->addAction( - makeQIcon(Icons16::Navigation_Settings), "Preferences...", QKeySequence::StandardKey::Preferences, cb); + makeThemedIcon(Icons16::Navigation_Settings), "Preferences...", QKeySequence::StandardKey::Preferences, cb); menu->addSeparator(); #ifdef Q_OS_WIN @@ -211,7 +218,7 @@ struct ShowcaseWindow::Impl { #else const auto quitShortcut = QKeySequence(QKeySequence::Quit); #endif - menu->addAction(makeQIcon(Icons16::Action_Close), "Quit", quitShortcut, []() { + menu->addAction(makeThemedIcon(Icons16::Action_Close), "Quit", quitShortcut, []() { qApp->quit(); }); } @@ -219,29 +226,31 @@ struct ShowcaseWindow::Impl { { auto* menu = menuBar->addMenu("Edit"); { - menu->addAction(makeQIcon(Icons16::Action_Undo), "Undo", QKeySequence::StandardKey::Undo, cb); - menu->addAction(makeQIcon(Icons16::Action_Redo), "Redo", QKeySequence::StandardKey::Redo, cb); + menu->addAction(makeThemedIcon(Icons16::Action_Undo), "Undo", QKeySequence::StandardKey::Undo, cb); + menu->addAction(makeThemedIcon(Icons16::Action_Redo), "Redo", QKeySequence::StandardKey::Redo, cb); menu->addSeparator(); - menu->addAction(makeQIcon(Icons16::Action_Cut), "Cut", QKeySequence::StandardKey::Cut, cb); - menu->addAction(makeQIcon(Icons16::Action_Copy), "Copy", QKeySequence::StandardKey::Copy, cb); - menu->addAction(makeQIcon(Icons16::Action_Paste), "Paste", QKeySequence::StandardKey::Paste, cb); - menu->addAction(makeQIcon(Icons16::Action_Trash), "Delete", QKeySequence::StandardKey::Delete, cb); + menu->addAction(makeThemedIcon(Icons16::Action_Cut), "Cut", QKeySequence::StandardKey::Cut, cb); + menu->addAction(makeThemedIcon(Icons16::Action_Copy), "Copy", QKeySequence::StandardKey::Copy, cb); + menu->addAction(makeThemedIcon(Icons16::Action_Paste), "Paste", QKeySequence::StandardKey::Paste, cb); + menu->addAction(makeThemedIcon(Icons16::Action_Trash), "Delete", QKeySequence::StandardKey::Delete, cb); } } { auto* menu = menuBar->addMenu("View"); { - menu->addAction(makeQIcon(Icons16::Action_ZoomIn), "Zoom In", QKeySequence::StandardKey::ZoomIn, cb); - menu->addAction(makeQIcon(Icons16::Action_ZoomOut), "Zoom Out", QKeySequence::StandardKey::ZoomOut, cb); - menu->addAction(makeQIcon(Icons16::Action_ZoomFit), "Fit", QKeySequence{}, cb); + menu->addAction(makeThemedIcon(Icons16::Action_ZoomIn), "Zoom In", QKeySequence::StandardKey::ZoomIn, cb); + menu->addAction(makeThemedIcon(Icons16::Action_ZoomOut), "Zoom Out", QKeySequence::StandardKey::ZoomOut, cb); + menu->addAction(makeThemedIcon(Icons16::Action_ZoomFit), "Fit", QKeySequence{}, cb); menu->addSeparator(); menu->addAction( - makeQIcon(Icons16::Action_Fullscreen), "Full Screen", QKeySequence::StandardKey::FullScreen, cb); + makeThemedIcon(Icons16::Action_Fullscreen), "Full Screen", QKeySequence::StandardKey::FullScreen, cb); if (themeManager) { auto* themeMenu = menu->addMenu("Theme"); + themeMenu->setIcon(makeThemedIcon(Icons16::Misc_PaintPalette)); + auto* themeActionGroup = new QActionGroup(themeMenu); themeActionGroup->setExclusive(true); @@ -250,7 +259,8 @@ struct ShowcaseWindow::Impl { for (const auto& theme : themes) { const auto name = theme.meta.name; - auto* action = themeMenu->addAction(name); + const auto icon = name == "Dark" ? makeThemedIcon(Icons16::Misc_Moon) : makeThemedIcon(Icons16::Misc_Sun); + auto* action = themeMenu->addAction(icon, name); action->setCheckable(true); themeActionGroup->addAction(action); action->setChecked(name == currentTheme); @@ -267,17 +277,18 @@ struct ShowcaseWindow::Impl { } themeMenu->addSeparator(); - themeMenu->addAction("Switch Theme", { Qt::CTRL | Qt::Key_T }, [this]() { - switchTheme(); - }); + themeMenu->addAction( + makeThemedIcon(Icons16::Action_Swap), "Switch Theme", { Qt::CTRL | Qt::Key_T }, [this]() { + switchTheme(); + }); } } } { auto* menu = menuBar->addMenu("Help"); { - menu->addAction(makeQIcon(Icons16::Misc_Mail), "Contact", QKeySequence{}, cb); - menu->addAction(makeQIcon(Icons16::Misc_Info), "About...", QKeySequence{}, cb); + menu->addAction(makeThemedIcon(Icons16::Misc_Mail), "Contact", QKeySequence{}, cb); + menu->addAction(makeThemedIcon(Icons16::Misc_Info), "About...", QKeySequence{}, cb); } } } @@ -296,7 +307,7 @@ struct ShowcaseWindow::Impl { qlementineStyle->setAutoIconColor(tabBar, oclero::qlementine::AutoIconColor::ForegroundColor); for (auto i = 0; i < 4; ++i) { - tabBar->addTab(makeQIcon(Icons16::File_File), getDummyText()); + tabBar->addTab(makeThemedIcon(Icons16::File_File), getDummyText()); } QObject::connect(tabBar, &QTabBar::tabCloseRequested, tabBar, [this](int index) { @@ -316,7 +327,7 @@ struct ShowcaseWindow::Impl { const auto addButton = [this](const Icons16 icon, const QString& tooltip, const QString& text = {}) { auto* toolButton = new QToolButton(toolBar); toolButton->setFocusPolicy(Qt::NoFocus); - toolButton->setIcon(makeQIcon(icon)); + toolButton->setIcon(makeThemedIcon(icon)); toolButton->setToolTip(tooltip); if (!text.isEmpty()) { toolButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); @@ -354,10 +365,10 @@ struct ShowcaseWindow::Impl { auto* exportButton = addButton(Icons16::Action_Export, "Export", "Export"); { auto* menu = new QMenu(exportButton); - menu->addAction(new QAction(makeQIcon(Icons16::File_Movie), "Movie", menu)); - menu->addAction(new QAction(makeQIcon(Icons16::File_Picture), "Picture", menu)); + menu->addAction(new QAction(makeThemedIcon(Icons16::File_Movie), "Movie", menu)); + menu->addAction(new QAction(makeThemedIcon(Icons16::File_Picture), "Picture", menu)); menu->addSeparator(); - menu->addAction(new QAction(makeQIcon(Icons16::File_Archive), "Archive", menu)); + menu->addAction(new QAction(makeThemedIcon(Icons16::File_Archive), "Archive", menu)); exportButton->setMenu(menu); exportButton->setPopupMode(QToolButton::ToolButtonPopupMode::MenuButtonPopup); @@ -381,7 +392,7 @@ struct ShowcaseWindow::Impl { themeLayout->setContentsMargins(0, 0, 0, 0); themeWidget->setLayout(themeLayout); - auto* lightIconWidget = new oclero::qlementine::IconWidget(makeQIcon(Icons16::Misc_Sun), themeWidget); + auto* lightIconWidget = new oclero::qlementine::IconWidget(makeThemedIcon(Icons16::Misc_Sun), themeWidget); themeLayout->addWidget(lightIconWidget); themeSwitch = new oclero::qlementine::Switch(toolBar); @@ -394,7 +405,7 @@ struct ShowcaseWindow::Impl { }); themeLayout->addWidget(themeSwitch); - auto* darkIconWidget = new oclero::qlementine::IconWidget(makeQIcon(Icons16::Misc_Moon), themeWidget); + auto* darkIconWidget = new oclero::qlementine::IconWidget(makeThemedIcon(Icons16::Misc_Moon), themeWidget); themeLayout->addWidget(darkIconWidget); updateThemeSwitch(); @@ -419,12 +430,12 @@ struct ShowcaseWindow::Impl { topBarLayout->setContentsMargins({ 12, 8, 12, 8 }); auto* lineEdit = new LineEdit(widget); - lineEdit->setIcon(makeQIcon(Icons16::Navigation_Search)); + lineEdit->setIcon(makeThemedIcon(Icons16::Navigation_Search)); lineEdit->setClearButtonEnabled(true); lineEdit->setPlaceholderText("Search..."); topBarLayout->addWidget(lineEdit, 1); - auto* button = new QPushButton(makeQIcon(Icons16::Action_Filter), "", widget); + auto* button = new QPushButton(makeThemedIcon(Icons16::Action_Filter), "", widget); button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); topBarLayout->addWidget(button); } @@ -540,8 +551,9 @@ struct ShowcaseWindow::Impl { auto* segmentedControl = new SegmentedControl(topBar); topBarLayout->addWidget(segmentedControl); segmentedControl->setItemsShouldExpand(false); - segmentedControl->addItem("Properties", makeQIcon(Icons16::Navigation_SlidersVertical), QString("%1").arg(4)); - segmentedControl->addItem("Scene", makeQIcon(Icons16::Misc_Globe), QString("%1").arg(2)); + segmentedControl->addItem( + "Properties", makeThemedIcon(Icons16::Navigation_SlidersVertical), QString("%1").arg(4)); + segmentedControl->addItem("Scene", makeThemedIcon(Icons16::Misc_Globe), QString("%1").arg(2)); } } diff --git a/showcase/src/main.cpp b/showcase/src/main.cpp index 282218a..4cd3521 100644 --- a/showcase/src/main.cpp +++ b/showcase/src/main.cpp @@ -5,6 +5,7 @@ #include #include +#include #include "ShowcaseWindow.hpp" @@ -26,19 +27,19 @@ int main(int argc, char* argv[]) { QApplication::setWindowIcon(QIcon(QStringLiteral(":/showcase/qlementine_icon.ico"))); #if USE_CUSTOM_STYLE - oclero::qlementine::ThemeManager* themeManager{ nullptr }; - // Custom QStyle. auto* style = new oclero::qlementine::QlementineStyle(&qApplication); style->setAnimationsEnabled(true); style->setAutoIconColor(oclero::qlementine::AutoIconColor::TextColor); + style->setIconPathGetter(oclero::qlementine::icons::fromFreeDesktop); qApplication.setStyle(style); // Custom icon theme. + oclero::qlementine::icons::initializeIconTheme(); QIcon::setThemeName("qlementine"); // Theme manager. - themeManager = new oclero::qlementine::ThemeManager(style); + auto* themeManager = new oclero::qlementine::ThemeManager(style); themeManager->loadDirectory(":/showcase/themes"); // Define theme on QStyle.