From cd05b6ecdf27373dc76e79fd845495cccddfbe8b Mon Sep 17 00:00:00 2001 From: Yuhang Zhao <2546789017@qq.com> Date: Sat, 16 Apr 2022 09:52:38 +0800 Subject: [PATCH] quick: finish qml -> cpp migrating Convert all qml files to pure c++ implementation. Signed-off-by: Yuhang Zhao <2546789017@qq.com> --- examples/quick/CMakeLists.txt | 29 +--- examples/quick/main.cpp | 8 +- examples/quick/qml.qrc | 5 + .../Core/framelesshelpercore_global.h | 1 + .../Quick/FramelessHelperImageProvider | 1 - .../Quick/FramelessQuickHelper | 1 + ...imageprovider.h => framelessquickhelper.h} | 20 +-- .../Quick/framelessquickutils.h | 3 + .../Quick/framelessquickwindow.h | 2 + src/quick/CMakeLists.txt | 81 ++++----- src/quick/framelesshelperimageprovider.cpp | 125 -------------- src/quick/framelesshelperquick.qrc | 12 ++ src/quick/framelessquickhelper.cpp | 79 +++++++++ ...imageprovider.h => framelessquickhelper.h} | 2 +- src/quick/plugin.cpp | 99 ----------- src/quick/quickstandardclosebutton.cpp | 42 ++++- src/quick/quickstandardclosebutton_p.h | 8 + src/quick/quickstandardmaximizebutton.cpp | 50 +++++- src/quick/quickstandardmaximizebutton_p.h | 12 +- src/quick/quickstandardminimizebutton.cpp | 38 ++++- src/quick/quickstandardminimizebutton_p.h | 8 + src/quick/quickstandardtitlebar.cpp | 159 ++++++++++++++++++ src/quick/quickstandardtitlebar_p.h | 43 ++++- src/widgets/standardsystembutton.cpp | 10 +- 24 files changed, 507 insertions(+), 331 deletions(-) create mode 100644 examples/quick/qml.qrc delete mode 100644 include/FramelessHelper/Quick/FramelessHelperImageProvider create mode 100644 include/FramelessHelper/Quick/FramelessQuickHelper rename include/FramelessHelper/Quick/{framelesshelperimageprovider.h => framelessquickhelper.h} (73%) delete mode 100644 src/quick/framelesshelperimageprovider.cpp create mode 100644 src/quick/framelesshelperquick.qrc create mode 100644 src/quick/framelessquickhelper.cpp rename src/quick/{framelesshelperimageprovider.h => framelessquickhelper.h} (93%) delete mode 100644 src/quick/plugin.cpp diff --git a/examples/quick/CMakeLists.txt b/examples/quick/CMakeLists.txt index afaf54a..b406ea5 100644 --- a/examples/quick/CMakeLists.txt +++ b/examples/quick/CMakeLists.txt @@ -25,28 +25,22 @@ find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS QuickControls2) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS QuickControls2) -qt_add_executable(Quick main.cpp) - -qt_add_qml_module(Quick - URI Demo - VERSION 1.0 - DEPENDENCIES - org.wangwenx190.FramelessHelper - QML_FILES - MainWindow.qml +set(SOURCES + qml.qrc + main.cpp ) if(WIN32) enable_language(RC) - target_sources(Quick PRIVATE - ../example.rc ../example.manifest - ) + list(APPEND SOURCES ../example.rc ../example.manifest) endif() +add_executable(Quick WIN32 ${SOURCES}) + target_link_libraries(Quick PRIVATE Qt${QT_VERSION_MAJOR}::Quick Qt${QT_VERSION_MAJOR}::QuickControls2 - FramelessHelperCore + FramelessHelperQuick ) target_compile_definitions(Quick PRIVATE @@ -57,13 +51,4 @@ target_compile_definitions(Quick PRIVATE QT_DEPRECATED_WARNINGS QT_DISABLE_DEPRECATED_BEFORE=0x060400 $<$,$>:QT_QML_DEBUG> - DEMO_IMPORT_DIR="${PROJECT_BINARY_DIR}/imports" -) - -set_target_properties(Quick PROPERTIES - MACOSX_BUNDLE_GUI_IDENTIFIER org.wangwenx190.framelesshelper.quick - MACOSX_BUNDLE_BUNDLE_VERSION 1.0.0.0 - MACOSX_BUNDLE_SHORT_VERSION_STRING 1.0 - MACOSX_BUNDLE TRUE - WIN32_EXECUTABLE TRUE ) diff --git a/examples/quick/main.cpp b/examples/quick/main.cpp index 4b189e0..ebe7b87 100644 --- a/examples/quick/main.cpp +++ b/examples/quick/main.cpp @@ -26,7 +26,7 @@ #include #include #include -#include +#include FRAMELESSHELPER_USE_NAMESPACE @@ -54,7 +54,9 @@ int main(int argc, char *argv[]) } QQmlApplicationEngine engine; - engine.addImportPath(QUtf8String(DEMO_IMPORT_DIR)); + + // Don't forget to register our custom QML types! + FramelessHelper::Quick::registerTypes(&engine); // This line is not relevant to FramelessHelper, we change the default // Qt Quick Controls theme to "Basic" (Qt6) or "Default" (Qt5) just @@ -66,7 +68,7 @@ int main(int argc, char *argv[]) QQuickStyle::setStyle(FRAMELESSHELPER_STRING_LITERAL("Default")); #endif - const QUrl homepageUrl(FRAMELESSHELPER_STRING_LITERAL("qrc:///Demo/MainWindow.qml")); + const QUrl homepageUrl(FRAMELESSHELPER_STRING_LITERAL("qrc:///Demo/qml/MainWindow.qml")); const QMetaObject::Connection connection = QObject::connect( &engine, &QQmlApplicationEngine::objectCreated, &application, [&homepageUrl, &connection](QObject *object, const QUrl &url) { diff --git a/examples/quick/qml.qrc b/examples/quick/qml.qrc new file mode 100644 index 0000000..c426390 --- /dev/null +++ b/examples/quick/qml.qrc @@ -0,0 +1,5 @@ + + + MainWindow.qml + + diff --git a/include/FramelessHelper/Core/framelesshelpercore_global.h b/include/FramelessHelper/Core/framelesshelpercore_global.h index 7eb0369..5e34151 100644 --- a/include/FramelessHelper/Core/framelesshelpercore_global.h +++ b/include/FramelessHelper/Core/framelesshelpercore_global.h @@ -160,6 +160,7 @@ Q_NAMESPACE_EXPORT(FRAMELESSHELPER_CORE_API) [[maybe_unused]] static constexpr const int kDefaultCaptionHeight = 23; [[maybe_unused]] static constexpr const int kDefaultTitleBarHeight = 30; [[maybe_unused]] static constexpr const int kDefaultWindowFrameBorderThickness = 1; +[[maybe_unused]] static constexpr const int kDefaultTitleBarFontPointSize = 11; [[maybe_unused]] static constexpr const QColor kDefaultBlackColor = {0, 0, 0}; // #000000 [[maybe_unused]] static constexpr const QColor kDefaultWhiteColor = {255, 255, 255}; // #FFFFFF diff --git a/include/FramelessHelper/Quick/FramelessHelperImageProvider b/include/FramelessHelper/Quick/FramelessHelperImageProvider deleted file mode 100644 index 99e4503..0000000 --- a/include/FramelessHelper/Quick/FramelessHelperImageProvider +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/include/FramelessHelper/Quick/FramelessQuickHelper b/include/FramelessHelper/Quick/FramelessQuickHelper new file mode 100644 index 0000000..1cbb62f --- /dev/null +++ b/include/FramelessHelper/Quick/FramelessQuickHelper @@ -0,0 +1 @@ +#include diff --git a/include/FramelessHelper/Quick/framelesshelperimageprovider.h b/include/FramelessHelper/Quick/framelessquickhelper.h similarity index 73% rename from include/FramelessHelper/Quick/framelesshelperimageprovider.h rename to include/FramelessHelper/Quick/framelessquickhelper.h index f9a044a..5a0a2ab 100644 --- a/include/FramelessHelper/Quick/framelesshelperimageprovider.h +++ b/include/FramelessHelper/Quick/framelessquickhelper.h @@ -25,22 +25,16 @@ #pragma once #include "framelesshelperquick_global.h" -#include + +QT_BEGIN_NAMESPACE +class QQmlEngine; +QT_END_NAMESPACE FRAMELESSHELPER_BEGIN_NAMESPACE -class FRAMELESSHELPER_QUICK_API FramelessHelperImageProvider : public QQuickImageProvider +namespace FramelessHelper::Quick { -#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) - Q_OBJECT -#endif - Q_DISABLE_COPY_MOVE(FramelessHelperImageProvider) - -public: - explicit FramelessHelperImageProvider(); - ~FramelessHelperImageProvider() override; - - Q_NODISCARD QPixmap requestPixmap(const QString &id, QSize *size, const QSize &requestedSize) override; -}; +FRAMELESSHELPER_QUICK_API void registerTypes(QQmlEngine *engine); +} FRAMELESSHELPER_END_NAMESPACE diff --git a/include/FramelessHelper/Quick/framelessquickutils.h b/include/FramelessHelper/Quick/framelessquickutils.h index adc6760..be4bff8 100644 --- a/include/FramelessHelper/Quick/framelessquickutils.h +++ b/include/FramelessHelper/Quick/framelessquickutils.h @@ -27,6 +27,7 @@ #include "framelesshelperquick_global.h" #include #include +#include QT_BEGIN_NAMESPACE class QQuickWindow; @@ -86,3 +87,5 @@ Q_SIGNALS: }; FRAMELESSHELPER_END_NAMESPACE + +QML_DECLARE_TYPE(FRAMELESSHELPER_PREPEND_NAMESPACE(FramelessQuickUtils)) diff --git a/include/FramelessHelper/Quick/framelessquickwindow.h b/include/FramelessHelper/Quick/framelessquickwindow.h index 7549fe3..1750d2f 100644 --- a/include/FramelessHelper/Quick/framelessquickwindow.h +++ b/include/FramelessHelper/Quick/framelessquickwindow.h @@ -91,3 +91,5 @@ private: }; FRAMELESSHELPER_END_NAMESPACE + +QML_DECLARE_TYPE(FRAMELESSHELPER_PREPEND_NAMESPACE(FramelessQuickWindow)) diff --git a/src/quick/CMakeLists.txt b/src/quick/CMakeLists.txt index be8f2ec..1b05529 100644 --- a/src/quick/CMakeLists.txt +++ b/src/quick/CMakeLists.txt @@ -22,58 +22,51 @@ SOFTWARE. ]] -set(PROJ_TARGET framelesshelperplugin) -set(PROJ_CLASS FramelessHelperPlugin) -set(PROJ_URI org.wangwenx190.FramelessHelper) -set(PROJ_VERSION 1.0) -set(PROJ_IMPORTS_DIR ${PROJECT_BINARY_DIR}/imports/org/wangwenx190/FramelessHelper) +find_package(QT NAMES Qt6 Qt5 COMPONENTS QuickTemplates2) +find_package(Qt${QT_VERSION_MAJOR} COMPONENTS QuickTemplates2) + +set(SUB_PROJ_NAME FramelessHelperQuick) set(INCLUDE_PREFIX ../../include/FramelessHelper/Quick) -find_package(Qt6 REQUIRED COMPONENTS QuickTemplates2) - -qt_add_qml_module(${PROJ_TARGET} - URI ${PROJ_URI} - VERSION ${PROJ_VERSION} - PLUGIN_TARGET ${PROJ_TARGET} - CLASS_NAME ${PROJ_CLASS} - OUTPUT_DIRECTORY ${PROJ_IMPORTS_DIR} - NO_PLUGIN_OPTIONAL - NO_GENERATE_PLUGIN_SOURCE - SOURCES - ${INCLUDE_PREFIX}/framelesshelperquick_global.h - ${INCLUDE_PREFIX}/framelessquickutils.h - ${INCLUDE_PREFIX}/framelesshelperimageprovider.h - ${INCLUDE_PREFIX}/framelessquickwindow.h - quickstandardminimizebutton_p.h - quickstandardminimizebutton.cpp - quickstandardmaximizebutton_p.h - quickstandardmaximizebutton.cpp - quickstandardclosebutton_p.h - quickstandardclosebutton.cpp - quickstandardtitlebar_p.h - quickstandardtitlebar.cpp - framelessquickwindow_p.h - framelessquickutils.cpp - framelesshelperimageprovider.cpp - framelessquickwindow.cpp - plugin.cpp +set(SOURCES + framelesshelperquick.qrc + ${INCLUDE_PREFIX}/framelesshelperquick_global.h + ${INCLUDE_PREFIX}/framelessquickutils.h + ${INCLUDE_PREFIX}/framelessquickhelper.h + ${INCLUDE_PREFIX}/framelessquickwindow.h + quickstandardminimizebutton_p.h + quickstandardminimizebutton.cpp + quickstandardmaximizebutton_p.h + quickstandardmaximizebutton.cpp + quickstandardclosebutton_p.h + quickstandardclosebutton.cpp + quickstandardtitlebar_p.h + quickstandardtitlebar.cpp + framelessquickwindow_p.h + framelessquickhelper.cpp + framelessquickutils.cpp + framelessquickwindow.cpp ) if(WIN32 AND NOT FRAMELESSHELPER_BUILD_STATIC) enable_language(RC) - target_sources(${PROJ_TARGET} PRIVATE - framelesshelperquick.rc - ) + list(APPEND SOURCES framelesshelperquick.rc) endif() if(FRAMELESSHELPER_BUILD_STATIC) - target_compile_definitions(${PROJ_TARGET} PUBLIC + add_library(${SUB_PROJ_NAME} STATIC ${SOURCES}) +else() + add_library(${SUB_PROJ_NAME} SHARED ${SOURCES}) +endif() + +if(FRAMELESSHELPER_BUILD_STATIC) + target_compile_definitions(${SUB_PROJ_NAME} PUBLIC FRAMELESSHELPER_QUICK_STATIC ) endif() -target_compile_definitions(${PROJ_TARGET} PRIVATE +target_compile_definitions(${SUB_PROJ_NAME} PRIVATE QT_NO_CAST_FROM_ASCII QT_NO_CAST_TO_ASCII QT_NO_URL_CAST_FROM_STRING @@ -90,31 +83,31 @@ target_compile_definitions(${PROJ_TARGET} PRIVATE if(MSVC) set(_WIN32_WINNT_WIN10 0x0A00) set(NTDDI_WIN10_CO 0x0A00000B) - target_compile_definitions(${PROJ_TARGET} PRIVATE + target_compile_definitions(${SUB_PROJ_NAME} PRIVATE _CRT_NON_CONFORMING_SWPRINTFS _CRT_SECURE_NO_WARNINGS _ENABLE_EXTENDED_ALIGNED_STORAGE NOMINMAX UNICODE _UNICODE WIN32_LEAN_AND_MEAN WINRT_LEAN_AND_MEAN WINVER=${_WIN32_WINNT_WIN10} _WIN32_WINNT=${_WIN32_WINNT_WIN10} _WIN32_IE=${_WIN32_WINNT_WIN10} NTDDI_VERSION=${NTDDI_WIN10_CO} ) - target_compile_options(${PROJ_TARGET} PRIVATE + target_compile_options(${SUB_PROJ_NAME} PRIVATE /utf-8 /W4 /WX ) else() - target_compile_options(${PROJ_TARGET} PRIVATE + target_compile_options(${SUB_PROJ_NAME} PRIVATE -Wall -Wextra -Werror ) endif() -target_link_libraries(${PROJ_TARGET} PRIVATE +target_link_libraries(${SUB_PROJ_NAME} PRIVATE Qt${QT_VERSION_MAJOR}::QuickPrivate Qt${QT_VERSION_MAJOR}::QuickTemplates2Private ) -target_link_libraries(${PROJ_TARGET} PUBLIC +target_link_libraries(${SUB_PROJ_NAME} PUBLIC FramelessHelperCore ) -target_include_directories(${PROJ_TARGET} PUBLIC +target_include_directories(${SUB_PROJ_NAME} PUBLIC "$/${INCLUDE_PREFIX}" ) diff --git a/src/quick/framelesshelperimageprovider.cpp b/src/quick/framelesshelperimageprovider.cpp deleted file mode 100644 index fad3704..0000000 --- a/src/quick/framelesshelperimageprovider.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/* - * MIT License - * - * Copyright (C) 2022 by wangwenx190 (Yuhang Zhao) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "framelesshelperimageprovider.h" -#include - -FRAMELESSHELPER_BEGIN_NAMESPACE - -using namespace Global; - -FRAMELESSHELPER_STRING_CONSTANT(light) -FRAMELESSHELPER_STRING_CONSTANT(dark) -FRAMELESSHELPER_STRING_CONSTANT(highcontrast) -FRAMELESSHELPER_STRING_CONSTANT(windowicon) -FRAMELESSHELPER_STRING_CONSTANT(help) -FRAMELESSHELPER_STRING_CONSTANT(minimize) -FRAMELESSHELPER_STRING_CONSTANT(maximize) -FRAMELESSHELPER_STRING_CONSTANT(restore) -FRAMELESSHELPER_STRING_CONSTANT(close) - -[[nodiscard]] static inline SystemTheme strToTheme(const QString &str) -{ - Q_ASSERT(!str.isEmpty()); - if (str.isEmpty()) { - return SystemTheme::Unknown; - } - if (str.compare(klight, Qt::CaseInsensitive) == 0) { - return SystemTheme::Light; - } - if (str.compare(kdark, Qt::CaseInsensitive) == 0) { - return SystemTheme::Dark; - } - if (str.compare(khighcontrast, Qt::CaseInsensitive) == 0) { - return SystemTheme::HighContrast; - } - return SystemTheme::Unknown; -} - -[[nodiscard]] static inline SystemButtonType strToButton(const QString &str) -{ - Q_ASSERT(!str.isEmpty()); - if (str.isEmpty()) { - return SystemButtonType::Unknown; - } - if (str.compare(kwindowicon, Qt::CaseInsensitive) == 0) { - return SystemButtonType::WindowIcon; - } - if (str.compare(khelp, Qt::CaseInsensitive) == 0) { - return SystemButtonType::Help; - } - if (str.compare(kminimize, Qt::CaseInsensitive) == 0) { - return SystemButtonType::Minimize; - } - if (str.compare(kmaximize, Qt::CaseInsensitive) == 0) { - return SystemButtonType::Maximize; - } - if (str.compare(krestore, Qt::CaseInsensitive) == 0) { - return SystemButtonType::Restore; - } - if (str.compare(kclose, Qt::CaseInsensitive) == 0) { - return SystemButtonType::Close; - } - return SystemButtonType::Unknown; -} - -FramelessHelperImageProvider::FramelessHelperImageProvider() : QQuickImageProvider(QQuickImageProvider::Pixmap) {} - -FramelessHelperImageProvider::~FramelessHelperImageProvider() = default; - -QPixmap FramelessHelperImageProvider::requestPixmap(const QString &id, QSize *size, const QSize &requestedSize) -{ - Q_ASSERT(!id.isEmpty()); - if (id.isEmpty()) { - return {}; - } - const QStringList params = id.split(u'/', Qt::SkipEmptyParts, Qt::CaseInsensitive); - Q_ASSERT(!params.isEmpty()); - if (params.isEmpty()) { - return {}; - } - Q_ASSERT(params.count() >= 2); - if (params.count() < 2) { - return {}; - } - const SystemTheme theme = strToTheme(params.at(0)); - const SystemButtonType button = strToButton(params.at(1)); - const QVariant pixmapVar = Utils::getSystemButtonIconResource(button, theme, ResourceType::Pixmap); - if (!pixmapVar.isValid()) { - return {}; - } - if (static_cast(pixmapVar.userType()) != QMetaType::QPixmap) { - return {}; - } - if (size) { - *size = kDefaultSystemButtonIconSize; - } - const auto pixmap = qvariant_cast(pixmapVar); - if (!requestedSize.isEmpty() && (pixmap.size() != requestedSize)) { - return pixmap.scaled(requestedSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); - } - return pixmap; -} - -FRAMELESSHELPER_END_NAMESPACE diff --git a/src/quick/framelesshelperquick.qrc b/src/quick/framelesshelperquick.qrc new file mode 100644 index 0000000..08ce3ab --- /dev/null +++ b/src/quick/framelesshelperquick.qrc @@ -0,0 +1,12 @@ + + + ../core/images/dark/chrome-close.svg + ../core/images/dark/chrome-maximize.svg + ../core/images/dark/chrome-minimize.svg + ../core/images/dark/chrome-restore.svg + ../core/images/light/chrome-close.svg + ../core/images/light/chrome-maximize.svg + ../core/images/light/chrome-minimize.svg + ../core/images/light/chrome-restore.svg + + diff --git a/src/quick/framelessquickhelper.cpp b/src/quick/framelessquickhelper.cpp new file mode 100644 index 0000000..33c1a15 --- /dev/null +++ b/src/quick/framelessquickhelper.cpp @@ -0,0 +1,79 @@ +/* + * MIT License + * + * Copyright (C) 2022 by wangwenx190 (Yuhang Zhao) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "framelessquickhelper.h" +#include "framelessquickutils.h" +#include "framelessquickwindow.h" +#include "quickstandardminimizebutton_p.h" +#include "quickstandardmaximizebutton_p.h" +#include "quickstandardclosebutton_p.h" +#include "quickstandardtitlebar_p.h" + +#ifndef QUICK_URI_SHORT +# define QUICK_URI_SHORT FRAMELESSHELPER_QUICK_URI, 1 +#endif + +#ifndef QUICK_URI_FULL +# define QUICK_URI_FULL QUICK_URI_SHORT, 0 +#endif + +#ifndef QUICK_URI_EXPAND +# define QUICK_URI_EXPAND(name) QUICK_URI_FULL, name +#endif + +#ifndef qmlRegisterAnonymousType2 +# if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) +# define qmlRegisterAnonymousType2(Class, ...) qmlRegisterAnonymousType(__VA_ARGS__) +# else +# define qmlRegisterAnonymousType2(Class, ...) qmlRegisterAnonymousType(__VA_ARGS__) +# endif +#endif + +FRAMELESSHELPER_BEGIN_NAMESPACE + +void FramelessHelper::Quick::registerTypes(QQmlEngine *engine) +{ + Q_ASSERT(engine); + if (!engine) { + return; + } + qmlRegisterModule(QUICK_URI_FULL); + qmlRegisterUncreatableMetaObject(Global::staticMetaObject, QUICK_URI_EXPAND("FramelessHelper"), + FRAMELESSHELPER_STRING_LITERAL("The FramelessHelper namespace is not creatable, you can only use it to access its enums.")); + qmlRegisterSingletonType(QUICK_URI_EXPAND("FramelessUtils"), + [](QQmlEngine *engine, QJSEngine *scriptEngine) -> QObject * { + Q_UNUSED(engine); + Q_UNUSED(scriptEngine); + return new FramelessQuickUtils; + }); + qmlRegisterAnonymousType2(QWindow, QUICK_URI_SHORT); + qmlRegisterAnonymousType2(QQuickWindow, QUICK_URI_SHORT); + qmlRegisterType(QUICK_URI_EXPAND("FramelessWindow")); + qmlRegisterType(QUICK_URI_EXPAND("StandardMinimizeButton")); + qmlRegisterType(QUICK_URI_EXPAND("StandardMaximizeButton")); + qmlRegisterType(QUICK_URI_EXPAND("StandardCloseButton")); + qmlRegisterType(QUICK_URI_EXPAND("StandardTitleBar")); +} + +FRAMELESSHELPER_END_NAMESPACE diff --git a/src/quick/framelesshelperimageprovider.h b/src/quick/framelessquickhelper.h similarity index 93% rename from src/quick/framelesshelperimageprovider.h rename to src/quick/framelessquickhelper.h index 1be1054..4f4e9b3 100644 --- a/src/quick/framelesshelperimageprovider.h +++ b/src/quick/framelessquickhelper.h @@ -22,4 +22,4 @@ * SOFTWARE. */ -#include "../../include/FramelessHelper/Quick/framelesshelperimageprovider.h" +#include "../../include/FramelessHelper/Quick/framelessquickhelper.h" diff --git a/src/quick/plugin.cpp b/src/quick/plugin.cpp deleted file mode 100644 index 9dfa72d..0000000 --- a/src/quick/plugin.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - * MIT License - * - * Copyright (C) 2022 by wangwenx190 (Yuhang Zhao) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "framelesshelperquick_global.h" -#include -#include "framelesshelperimageprovider.h" -#include "framelessquickutils.h" -#include "framelessquickwindow.h" -#include "quickstandardminimizebutton_p.h" -#include "quickstandardmaximizebutton_p.h" -#include "quickstandardclosebutton_p.h" -#include "quickstandardtitlebar_p.h" - -#ifndef QUICK_URI_SHORT -# define QUICK_URI_SHORT FRAMELESSHELPER_QUICK_URI, 1 -#endif - -#ifndef QUICK_URI_FULL -# define QUICK_URI_FULL QUICK_URI_SHORT, 0 -#endif - -#ifndef QUICK_URI_EXPAND -# define QUICK_URI_EXPAND(name) QUICK_URI_FULL, name -#endif - -#ifndef qmlRegisterAnonymousType2 -# if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) -# define qmlRegisterAnonymousType2(Class, ...) qmlRegisterAnonymousType(__VA_ARGS__) -# else -# define qmlRegisterAnonymousType2(Class, ...) qmlRegisterAnonymousType(__VA_ARGS__) -# endif -#endif - -FRAMELESSHELPER_BEGIN_NAMESPACE - -class FramelessHelperPlugin : public QQmlEngineExtensionPlugin -{ - Q_OBJECT - Q_PLUGIN_METADATA(IID QQmlEngineExtensionInterface_iid) - -public: - explicit FramelessHelperPlugin(QObject *parent = nullptr) : QQmlEngineExtensionPlugin(parent) {} - ~FramelessHelperPlugin() override = default; - - void initializeEngine(QQmlEngine *engine, const char *uri) override - { - Q_ASSERT(engine); - Q_ASSERT(uri); - if (!engine || !uri) { - return; - } - Q_ASSERT(qstrcmp(uri, FRAMELESSHELPER_QUICK_URI) == 0); - if (qstrcmp(uri, FRAMELESSHELPER_QUICK_URI) != 0) { - return; - } - engine->addImageProvider(FRAMELESSHELPER_STRING_LITERAL("framelesshelper"), new FramelessHelperImageProvider); - qmlRegisterModule(QUICK_URI_FULL); - qmlRegisterUncreatableMetaObject(Global::staticMetaObject, QUICK_URI_EXPAND("FramelessHelper"), - FRAMELESSHELPER_STRING_LITERAL("The FramelessHelper namespace is not creatable, you can only use it to access its enums.")); - qmlRegisterSingletonType(QUICK_URI_EXPAND("FramelessUtils"), - [](QQmlEngine *engine, QJSEngine *scriptEngine) -> QObject * { - Q_UNUSED(engine); - Q_UNUSED(scriptEngine); - return new FramelessQuickUtils; - }); - qmlRegisterAnonymousType2(QWindow, QUICK_URI_SHORT); - qmlRegisterAnonymousType2(QQuickWindow, QUICK_URI_SHORT); - qmlRegisterType(QUICK_URI_EXPAND("FramelessWindow")); - qmlRegisterType(QUICK_URI_EXPAND("StandardMinimizeButton")); - qmlRegisterType(QUICK_URI_EXPAND("StandardMaximizeButton")); - qmlRegisterType(QUICK_URI_EXPAND("StandardCloseButton")); - qmlRegisterType(QUICK_URI_EXPAND("StandardTitleBar")); - } -}; - -FRAMELESSHELPER_END_NAMESPACE - -#include "plugin.moc" diff --git a/src/quick/quickstandardclosebutton.cpp b/src/quick/quickstandardclosebutton.cpp index e46526c..7a7db78 100644 --- a/src/quick/quickstandardclosebutton.cpp +++ b/src/quick/quickstandardclosebutton.cpp @@ -24,16 +24,24 @@ #include "quickstandardclosebutton_p.h" #include "framelessquickutils.h" +#include +#include #include #include #include +#include + +static inline void initResource() +{ + Q_INIT_RESOURCE(framelesshelperquick); +} FRAMELESSHELPER_BEGIN_NAMESPACE using namespace Global; -FRAMELESSHELPER_STRING_CONSTANT2(DarkUrl, "image://framelesshelper/dark/close") -FRAMELESSHELPER_STRING_CONSTANT2(LightUrl, "image://framelesshelper/light/close") +FRAMELESSHELPER_STRING_CONSTANT2(DarkUrl, "qrc:///org.wangwenx190.FramelessHelper/images/dark/chrome-close.svg") +FRAMELESSHELPER_STRING_CONSTANT2(LightUrl, "qrc:///org.wangwenx190.FramelessHelper/images/light/chrome-close.svg") QuickStandardCloseButton::QuickStandardCloseButton(QQuickItem *parent) : QQuickButton(parent) { @@ -45,7 +53,8 @@ QuickStandardCloseButton::~QuickStandardCloseButton() = default; void QuickStandardCloseButton::updateForeground() { const bool dark = (FramelessQuickUtils::darkModeEnabled() || FramelessQuickUtils::titleBarColorized()); - const auto url = QUrl(dark ? kDarkUrl : kLightUrl); + const auto url = QUrl((dark || isHovered() || isPressed()) ? kDarkUrl : kLightUrl); + initResource(); m_image->setSource(url); } @@ -58,14 +67,27 @@ void QuickStandardCloseButton::updateBackground() m_backgroundItem->setVisible(visible); } +void QuickStandardCloseButton::updateToolTip() +{ + const bool visible = (isHovered() && !isPressed()); + const int delay = QGuiApplication::styleHints()->mousePressAndHoldInterval(); + m_tooltip->setVisible(visible); + m_tooltip->setDelay(delay); +} + void QuickStandardCloseButton::initialize() { + setImplicitWidth(kDefaultSystemButtonSize.width()); + setImplicitHeight(kDefaultSystemButtonSize.height()); + m_contentItem.reset(new QQuickItem(this)); - m_contentItem->setImplicitWidth(kDefaultSystemButtonSize.width()); - m_contentItem->setImplicitHeight(kDefaultSystemButtonSize.height()); + m_contentItem->setImplicitWidth(kDefaultSystemButtonIconSize.width()); + m_contentItem->setImplicitHeight(kDefaultSystemButtonIconSize.height()); m_image.reset(new QQuickImage(m_contentItem.data())); const auto imageAnchors = new QQuickAnchors(m_image.data(), m_image.data()); imageAnchors->setCenterIn(m_contentItem.data()); + connect(this, &QuickStandardCloseButton::hoveredChanged, this, &QuickStandardCloseButton::updateForeground); + connect(this, &QuickStandardCloseButton::pressedChanged, this, &QuickStandardCloseButton::updateForeground); const FramelessQuickUtils * const utils = FramelessQuickUtils::instance(); connect(utils, &FramelessQuickUtils::darkModeEnabledChanged, this, &QuickStandardCloseButton::updateForeground); connect(utils, &FramelessQuickUtils::titleBarColorizedChanged, this, &QuickStandardCloseButton::updateForeground); @@ -77,8 +99,18 @@ void QuickStandardCloseButton::initialize() connect(this, &QuickStandardCloseButton::hoveredChanged, this, &QuickStandardCloseButton::updateBackground); connect(this, &QuickStandardCloseButton::pressedChanged, this, &QuickStandardCloseButton::updateBackground); + m_tooltip.reset(new QQuickToolTip(this)); + m_tooltip->setText(tr("Close")); + connect(QGuiApplication::styleHints(), &QStyleHints::mousePressAndHoldIntervalChanged, this, [this](int interval){ + Q_UNUSED(interval); + updateToolTip(); + }); + connect(this, &QuickStandardCloseButton::hoveredChanged, this, &QuickStandardCloseButton::updateToolTip); + connect(this, &QuickStandardCloseButton::pressedChanged, this, &QuickStandardCloseButton::updateToolTip); + updateBackground(); updateForeground(); + updateToolTip(); setContentItem(m_contentItem.data()); setBackground(m_backgroundItem.data()); diff --git a/src/quick/quickstandardclosebutton_p.h b/src/quick/quickstandardclosebutton_p.h index c7a97df..26e1794 100644 --- a/src/quick/quickstandardclosebutton_p.h +++ b/src/quick/quickstandardclosebutton_p.h @@ -30,6 +30,7 @@ QT_BEGIN_NAMESPACE class QQuickImage; class QQuickRectangle; +class QQuickToolTip; QT_END_NAMESPACE FRAMELESSHELPER_BEGIN_NAMESPACE @@ -37,6 +38,9 @@ FRAMELESSHELPER_BEGIN_NAMESPACE class FRAMELESSHELPER_QUICK_API QuickStandardCloseButton : public QQuickButton { Q_OBJECT +#ifdef QML_NAMED_ELEMENT + QML_NAMED_ELEMENT(StandardCloseButton) +#endif Q_DISABLE_COPY_MOVE(QuickStandardCloseButton) public: @@ -46,6 +50,7 @@ public: public Q_SLOTS: void updateForeground(); void updateBackground(); + void updateToolTip(); private: void initialize(); @@ -54,6 +59,9 @@ private: QScopedPointer m_contentItem; QScopedPointer m_image; QScopedPointer m_backgroundItem; + QScopedPointer m_tooltip; }; FRAMELESSHELPER_END_NAMESPACE + +QML_DECLARE_TYPE(FRAMELESSHELPER_PREPEND_NAMESPACE(QuickStandardCloseButton)) diff --git a/src/quick/quickstandardmaximizebutton.cpp b/src/quick/quickstandardmaximizebutton.cpp index c6c0871..a757482 100644 --- a/src/quick/quickstandardmaximizebutton.cpp +++ b/src/quick/quickstandardmaximizebutton.cpp @@ -24,18 +24,26 @@ #include "quickstandardmaximizebutton_p.h" #include "framelessquickutils.h" +#include +#include #include #include #include +#include + +static inline void initResource() +{ + Q_INIT_RESOURCE(framelesshelperquick); +} FRAMELESSHELPER_BEGIN_NAMESPACE using namespace Global; -FRAMELESSHELPER_STRING_CONSTANT2(DarkMaxUrl, "image://framelesshelper/dark/maximize") -FRAMELESSHELPER_STRING_CONSTANT2(LightMaxUrl, "image://framelesshelper/light/maximize") -FRAMELESSHELPER_STRING_CONSTANT2(DarkRestoreUrl, "image://framelesshelper/dark/restore") -FRAMELESSHELPER_STRING_CONSTANT2(LightRestoreUrl, "image://framelesshelper/light/restore") +FRAMELESSHELPER_STRING_CONSTANT2(DarkMaxUrl, "qrc:///org.wangwenx190.FramelessHelper/images/dark/chrome-maximize.svg") +FRAMELESSHELPER_STRING_CONSTANT2(LightMaxUrl, "qrc:///org.wangwenx190.FramelessHelper/images/light/chrome-maximize.svg") +FRAMELESSHELPER_STRING_CONSTANT2(DarkRestoreUrl, "qrc:///org.wangwenx190.FramelessHelper/images/dark/chrome-restore.svg") +FRAMELESSHELPER_STRING_CONSTANT2(LightRestoreUrl, "qrc:///org.wangwenx190.FramelessHelper/images/light/chrome-restore.svg") QuickStandardMaximizeButton::QuickStandardMaximizeButton(QQuickItem *parent) : QQuickButton(parent) { @@ -44,7 +52,7 @@ QuickStandardMaximizeButton::QuickStandardMaximizeButton(QQuickItem *parent) : Q QuickStandardMaximizeButton::~QuickStandardMaximizeButton() = default; -bool QuickStandardMaximizeButton::maximized() const +bool QuickStandardMaximizeButton::isMaximized() const { return m_max; } @@ -61,24 +69,38 @@ void QuickStandardMaximizeButton::setMaximized(const bool max) void QuickStandardMaximizeButton::updateForeground() { const bool dark = (FramelessQuickUtils::darkModeEnabled() || FramelessQuickUtils::titleBarColorized()); - const auto url = QUrl(dark ? (m_max ? kDarkMaxUrl : kDarkRestoreUrl) : (m_max ? kLightMaxUrl : kLightRestoreUrl)); + const auto url = QUrl(dark ? (m_max ? kDarkRestoreUrl : kDarkMaxUrl) : (m_max ? kLightRestoreUrl : kLightMaxUrl)); + initResource(); m_image->setSource(url); } void QuickStandardMaximizeButton::updateBackground() { - const SystemButtonType button = (m_max ? SystemButtonType::Maximize : SystemButtonType::Restore); + const SystemButtonType button = (m_max ? SystemButtonType::Restore : SystemButtonType::Maximize); const ButtonState state = (isPressed() ? ButtonState::Pressed : ButtonState::Hovered); const bool visible = (isHovered() || isPressed()); m_backgroundItem->setColor(FramelessQuickUtils::getSystemButtonBackgroundColor(button, state)); m_backgroundItem->setVisible(visible); } +void QuickStandardMaximizeButton::updateToolTip() +{ + const bool visible = (isHovered() && !isPressed()); + const int delay = QGuiApplication::styleHints()->mousePressAndHoldInterval(); + const QString text = (m_max ? tr("Restore") : tr("Maximize")); + m_tooltip->setVisible(visible); + m_tooltip->setDelay(delay); + m_tooltip->setText(text); +} + void QuickStandardMaximizeButton::initialize() { + setImplicitWidth(kDefaultSystemButtonSize.width()); + setImplicitHeight(kDefaultSystemButtonSize.height()); + m_contentItem.reset(new QQuickItem(this)); - m_contentItem->setImplicitWidth(kDefaultSystemButtonSize.width()); - m_contentItem->setImplicitHeight(kDefaultSystemButtonSize.height()); + m_contentItem->setImplicitWidth(kDefaultSystemButtonIconSize.width()); + m_contentItem->setImplicitHeight(kDefaultSystemButtonIconSize.height()); m_image.reset(new QQuickImage(m_contentItem.data())); const auto imageAnchors = new QQuickAnchors(m_image.data(), m_image.data()); imageAnchors->setCenterIn(m_contentItem.data()); @@ -94,8 +116,18 @@ void QuickStandardMaximizeButton::initialize() connect(this, &QuickStandardMaximizeButton::hoveredChanged, this, &QuickStandardMaximizeButton::updateBackground); connect(this, &QuickStandardMaximizeButton::pressedChanged, this, &QuickStandardMaximizeButton::updateBackground); + m_tooltip.reset(new QQuickToolTip(this)); + connect(QGuiApplication::styleHints(), &QStyleHints::mousePressAndHoldIntervalChanged, this, [this](int interval){ + Q_UNUSED(interval); + updateToolTip(); + }); + connect(this, &QuickStandardMaximizeButton::hoveredChanged, this, &QuickStandardMaximizeButton::updateToolTip); + connect(this, &QuickStandardMaximizeButton::pressedChanged, this, &QuickStandardMaximizeButton::updateToolTip); + connect(this, &QuickStandardMaximizeButton::maximizedChanged, this, &QuickStandardMaximizeButton::updateToolTip); + updateBackground(); updateForeground(); + updateToolTip(); setContentItem(m_contentItem.data()); setBackground(m_backgroundItem.data()); diff --git a/src/quick/quickstandardmaximizebutton_p.h b/src/quick/quickstandardmaximizebutton_p.h index e661d70..126296e 100644 --- a/src/quick/quickstandardmaximizebutton_p.h +++ b/src/quick/quickstandardmaximizebutton_p.h @@ -30,6 +30,7 @@ QT_BEGIN_NAMESPACE class QQuickImage; class QQuickRectangle; +class QQuickToolTip; QT_END_NAMESPACE FRAMELESSHELPER_BEGIN_NAMESPACE @@ -37,19 +38,23 @@ FRAMELESSHELPER_BEGIN_NAMESPACE class FRAMELESSHELPER_QUICK_API QuickStandardMaximizeButton : public QQuickButton { Q_OBJECT +#ifdef QML_NAMED_ELEMENT + QML_NAMED_ELEMENT(StandardMaximizeButton) +#endif Q_DISABLE_COPY_MOVE(QuickStandardMaximizeButton) - Q_PROPERTY(bool maximized READ maximized WRITE setMaximized NOTIFY maximizedChanged FINAL) + Q_PROPERTY(bool maximized READ isMaximized WRITE setMaximized NOTIFY maximizedChanged FINAL) public: explicit QuickStandardMaximizeButton(QQuickItem *parent = nullptr); ~QuickStandardMaximizeButton() override; - Q_NODISCARD bool maximized() const; + Q_NODISCARD bool isMaximized() const; void setMaximized(const bool max); public Q_SLOTS: void updateForeground(); void updateBackground(); + void updateToolTip(); Q_SIGNALS: void maximizedChanged(); @@ -62,6 +67,9 @@ private: QScopedPointer m_contentItem; QScopedPointer m_image; QScopedPointer m_backgroundItem; + QScopedPointer m_tooltip; }; FRAMELESSHELPER_END_NAMESPACE + +QML_DECLARE_TYPE(FRAMELESSHELPER_PREPEND_NAMESPACE(QuickStandardMaximizeButton)) diff --git a/src/quick/quickstandardminimizebutton.cpp b/src/quick/quickstandardminimizebutton.cpp index e781531..31c22f4 100644 --- a/src/quick/quickstandardminimizebutton.cpp +++ b/src/quick/quickstandardminimizebutton.cpp @@ -24,16 +24,24 @@ #include "quickstandardminimizebutton_p.h" #include "framelessquickutils.h" +#include +#include #include #include #include +#include + +static inline void initResource() +{ + Q_INIT_RESOURCE(framelesshelperquick); +} FRAMELESSHELPER_BEGIN_NAMESPACE using namespace Global; -FRAMELESSHELPER_STRING_CONSTANT2(DarkUrl, "image://framelesshelper/dark/minimize") -FRAMELESSHELPER_STRING_CONSTANT2(LightUrl, "image://framelesshelper/light/minimize") +FRAMELESSHELPER_STRING_CONSTANT2(DarkUrl, "qrc:///org.wangwenx190.FramelessHelper/images/dark/chrome-minimize.svg") +FRAMELESSHELPER_STRING_CONSTANT2(LightUrl, "qrc:///org.wangwenx190.FramelessHelper/images/light/chrome-minimize.svg") QuickStandardMinimizeButton::QuickStandardMinimizeButton(QQuickItem *parent) : QQuickButton(parent) { @@ -46,6 +54,7 @@ void QuickStandardMinimizeButton::updateForeground() { const bool dark = (FramelessQuickUtils::darkModeEnabled() || FramelessQuickUtils::titleBarColorized()); const auto url = QUrl(dark ? kDarkUrl : kLightUrl); + initResource(); m_image->setSource(url); } @@ -58,11 +67,22 @@ void QuickStandardMinimizeButton::updateBackground() m_backgroundItem->setVisible(visible); } +void QuickStandardMinimizeButton::updateToolTip() +{ + const bool visible = (isHovered() && !isPressed()); + const int delay = QGuiApplication::styleHints()->mousePressAndHoldInterval(); + m_tooltip->setVisible(visible); + m_tooltip->setDelay(delay); +} + void QuickStandardMinimizeButton::initialize() { + setImplicitWidth(kDefaultSystemButtonSize.width()); + setImplicitHeight(kDefaultSystemButtonSize.height()); + m_contentItem.reset(new QQuickItem(this)); - m_contentItem->setImplicitWidth(kDefaultSystemButtonSize.width()); - m_contentItem->setImplicitHeight(kDefaultSystemButtonSize.height()); + m_contentItem->setImplicitWidth(kDefaultSystemButtonIconSize.width()); + m_contentItem->setImplicitHeight(kDefaultSystemButtonIconSize.height()); m_image.reset(new QQuickImage(m_contentItem.data())); const auto imageAnchors = new QQuickAnchors(m_image.data(), m_image.data()); imageAnchors->setCenterIn(m_contentItem.data()); @@ -77,8 +97,18 @@ void QuickStandardMinimizeButton::initialize() connect(this, &QuickStandardMinimizeButton::hoveredChanged, this, &QuickStandardMinimizeButton::updateBackground); connect(this, &QuickStandardMinimizeButton::pressedChanged, this, &QuickStandardMinimizeButton::updateBackground); + m_tooltip.reset(new QQuickToolTip(this)); + m_tooltip->setText(tr("Minimize")); + connect(QGuiApplication::styleHints(), &QStyleHints::mousePressAndHoldIntervalChanged, this, [this](int interval){ + Q_UNUSED(interval); + updateToolTip(); + }); + connect(this, &QuickStandardMinimizeButton::hoveredChanged, this, &QuickStandardMinimizeButton::updateToolTip); + connect(this, &QuickStandardMinimizeButton::pressedChanged, this, &QuickStandardMinimizeButton::updateToolTip); + updateBackground(); updateForeground(); + updateToolTip(); setContentItem(m_contentItem.data()); setBackground(m_backgroundItem.data()); diff --git a/src/quick/quickstandardminimizebutton_p.h b/src/quick/quickstandardminimizebutton_p.h index 5a32b60..941e8e2 100644 --- a/src/quick/quickstandardminimizebutton_p.h +++ b/src/quick/quickstandardminimizebutton_p.h @@ -30,6 +30,7 @@ QT_BEGIN_NAMESPACE class QQuickImage; class QQuickRectangle; +class QQuickToolTip; QT_END_NAMESPACE FRAMELESSHELPER_BEGIN_NAMESPACE @@ -37,6 +38,9 @@ FRAMELESSHELPER_BEGIN_NAMESPACE class FRAMELESSHELPER_QUICK_API QuickStandardMinimizeButton : public QQuickButton { Q_OBJECT +#ifdef QML_NAMED_ELEMENT + QML_NAMED_ELEMENT(StandardMinimizeButton) +#endif Q_DISABLE_COPY_MOVE(QuickStandardMinimizeButton) public: @@ -46,6 +50,7 @@ public: public Q_SLOTS: void updateForeground(); void updateBackground(); + void updateToolTip(); private: void initialize(); @@ -54,6 +59,9 @@ private: QScopedPointer m_contentItem; QScopedPointer m_image; QScopedPointer m_backgroundItem; + QScopedPointer m_tooltip; }; FRAMELESSHELPER_END_NAMESPACE + +QML_DECLARE_TYPE(FRAMELESSHELPER_PREPEND_NAMESPACE(QuickStandardMinimizeButton)) diff --git a/src/quick/quickstandardtitlebar.cpp b/src/quick/quickstandardtitlebar.cpp index f6ec16f..3f74761 100644 --- a/src/quick/quickstandardtitlebar.cpp +++ b/src/quick/quickstandardtitlebar.cpp @@ -23,9 +23,20 @@ */ #include "quickstandardtitlebar_p.h" +#include "quickstandardminimizebutton_p.h" +#include "quickstandardmaximizebutton_p.h" +#include "quickstandardclosebutton_p.h" +#include "framelessquickutils.h" +#include +#include +#include +#include +#include FRAMELESSHELPER_BEGIN_NAMESPACE +using namespace Global; + QuickStandardTitleBar::QuickStandardTitleBar(QQuickItem *parent) : QQuickRectangle(parent) { initialize(); @@ -33,9 +44,157 @@ QuickStandardTitleBar::QuickStandardTitleBar(QQuickItem *parent) : QQuickRectang QuickStandardTitleBar::~QuickStandardTitleBar() = default; +bool QuickStandardTitleBar::isActive() const +{ + return m_active; +} + +void QuickStandardTitleBar::setActive(const bool value) +{ + if (m_active == value) { + return; + } + m_active = value; + Q_EMIT activeChanged(); +} + +bool QuickStandardTitleBar::isMaximized() const +{ + return m_maxBtn->isMaximized(); +} + +void QuickStandardTitleBar::setMaximized(const bool value) +{ + m_maxBtn->setMaximized(value); +} + +Qt::Alignment QuickStandardTitleBar::titleLabelAlignment() const +{ + return m_labelAlignment; +} + +void QuickStandardTitleBar::setTitleLabelAlignment(const Qt::Alignment value) +{ + if (m_labelAlignment == value) { + return; + } + m_labelAlignment = value; + QQuickAnchors * const labelAnchors = QQuickItemPrivate::get(m_label.data())->anchors(); + const QQuickItemPrivate * const titleBarPriv = QQuickItemPrivate::get(this); + if (m_labelAlignment & Qt::AlignTop) { + labelAnchors->setTop(titleBarPriv->top()); + labelAnchors->setTopMargin(10); + } + if (m_labelAlignment & Qt::AlignBottom) { + labelAnchors->setBottom(titleBarPriv->bottom()); + labelAnchors->setBottomMargin(10); + } + if (m_labelAlignment & Qt::AlignLeft) { + labelAnchors->setLeft(titleBarPriv->left()); + labelAnchors->setLeftMargin(10); + } + if (m_labelAlignment & Qt::AlignRight) { + labelAnchors->setRight(QQuickItemPrivate::get(m_row.data())->left()); + labelAnchors->setRightMargin(10); + } + if (m_labelAlignment & Qt::AlignVCenter) { + labelAnchors->setTopMargin(0); + labelAnchors->setBottomMargin(0); + labelAnchors->setVerticalCenter(titleBarPriv->verticalCenter()); + } + if (m_labelAlignment & Qt::AlignHCenter) { + labelAnchors->setLeftMargin(0); + labelAnchors->setRightMargin(0); + labelAnchors->setHorizontalCenter(titleBarPriv->horizontalCenter()); + } + Q_EMIT titleLabelAlignmentChanged(); +} + +QString QuickStandardTitleBar::title() const +{ + return m_label->text(); +} + +void QuickStandardTitleBar::setTitle(const QString &value) +{ + m_label->setText(value); +} + +QuickStandardMinimizeButton *QuickStandardTitleBar::minimizeButton() const +{ + return m_minBtn.data(); +} + +QuickStandardMaximizeButton *QuickStandardTitleBar::maximizeButton() const +{ + return m_maxBtn.data(); +} + +QuickStandardCloseButton *QuickStandardTitleBar::closeButton() const +{ + return m_closeBtn.data(); +} + +void QuickStandardTitleBar::updateTitleBarColor() +{ + QColor backgroundColor = {}; + QColor foregroundColor = {}; + if (m_active) { + if (FramelessQuickUtils::titleBarColorized()) { + backgroundColor = FramelessQuickUtils::systemAccentColor(); + foregroundColor = kDefaultWhiteColor; + } else { + if (FramelessQuickUtils::darkModeEnabled()) { + backgroundColor = kDefaultBlackColor; + foregroundColor = kDefaultWhiteColor; + } else { + backgroundColor = kDefaultWhiteColor; + foregroundColor = kDefaultBlackColor; + } + } + } else { + if (FramelessQuickUtils::darkModeEnabled()) { + backgroundColor = FramelessQuickUtils::defaultSystemDarkColor(); + } else { + backgroundColor = kDefaultWhiteColor; + } + foregroundColor = kDefaultDarkGrayColor; + } + setColor(backgroundColor); + m_label->setColor(foregroundColor); +} + void QuickStandardTitleBar::initialize() { + QQuickPen * const _border = border(); + _border->setWidth(0.0); + _border->setColor(kDefaultTransparentColor); + setHeight(FramelessQuickUtils::titleBarHeight()); + m_label.reset(new QQuickLabel(this)); + QFont f = m_label->font(); + f.setPointSize(kDefaultTitleBarFontPointSize); + m_label->setFont(f); + + m_row.reset(new QQuickRow(this)); + QQuickAnchors * const rowAnchors = QQuickItemPrivate::get(m_row.data())->anchors(); + const QQuickItemPrivate * const thisPriv = QQuickItemPrivate::get(this); + rowAnchors->setTop(thisPriv->top()); + rowAnchors->setRight(thisPriv->right()); + m_minBtn.reset(new QuickStandardMinimizeButton(m_row.data())); + m_maxBtn.reset(new QuickStandardMaximizeButton(m_row.data())); + m_closeBtn.reset(new QuickStandardCloseButton(m_row.data())); + + const FramelessQuickUtils * const utils = FramelessQuickUtils::instance(); + connect(utils, &FramelessQuickUtils::darkModeEnabledChanged, this, &QuickStandardTitleBar::updateTitleBarColor); + connect(utils, &FramelessQuickUtils::systemAccentColorChanged, this, &QuickStandardTitleBar::updateTitleBarColor); + connect(utils, &FramelessQuickUtils::titleBarColorizedChanged, this, &QuickStandardTitleBar::updateTitleBarColor); + connect(this, &QuickStandardTitleBar::activeChanged, this, &QuickStandardTitleBar::updateTitleBarColor); + connect(m_label.data(), &QQuickLabel::textChanged, this, &QuickStandardTitleBar::titleChanged); + connect(m_maxBtn.data(), &QuickStandardMaximizeButton::maximizedChanged, this, &QuickStandardTitleBar::maximizedChanged); + + setTitleLabelAlignment(Qt::AlignLeft | Qt::AlignVCenter); + updateTitleBarColor(); } FRAMELESSHELPER_END_NAMESPACE diff --git a/src/quick/quickstandardtitlebar_p.h b/src/quick/quickstandardtitlebar_p.h index dacde4d..c7a517f 100644 --- a/src/quick/quickstandardtitlebar_p.h +++ b/src/quick/quickstandardtitlebar_p.h @@ -29,6 +29,7 @@ QT_BEGIN_NAMESPACE class QQuickLabel; +class QQuickRow; QT_END_NAMESPACE FRAMELESSHELPER_BEGIN_NAMESPACE @@ -37,23 +38,63 @@ class QuickStandardMinimizeButton; class QuickStandardMaximizeButton; class QuickStandardCloseButton; -class QuickStandardTitleBar : public QQuickRectangle +class FRAMELESSHELPER_QUICK_API QuickStandardTitleBar : public QQuickRectangle { Q_OBJECT +#ifdef QML_NAMED_ELEMENT + QML_NAMED_ELEMENT(StandardTitleBar) +#endif Q_DISABLE_COPY_MOVE(QuickStandardTitleBar) + Q_PROPERTY(bool active READ isActive WRITE setActive NOTIFY activeChanged FINAL) + Q_PROPERTY(bool maximized READ isMaximized WRITE setMaximized NOTIFY maximizedChanged FINAL) + Q_PROPERTY(Qt::Alignment titleLabelAlignment READ titleLabelAlignment WRITE setTitleLabelAlignment NOTIFY titleLabelAlignmentChanged FINAL) + Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged FINAL) + Q_PROPERTY(QuickStandardMinimizeButton* minimizeButton READ minimizeButton CONSTANT FINAL) + Q_PROPERTY(QuickStandardMaximizeButton* maximizeButton READ maximizeButton CONSTANT FINAL) + Q_PROPERTY(QuickStandardCloseButton* closeButton READ closeButton CONSTANT FINAL) public: explicit QuickStandardTitleBar(QQuickItem *parent = nullptr); ~QuickStandardTitleBar() override; + Q_NODISCARD bool isActive() const; + void setActive(const bool value); + + Q_NODISCARD bool isMaximized() const; + void setMaximized(const bool value); + + Q_NODISCARD Qt::Alignment titleLabelAlignment() const; + void setTitleLabelAlignment(const Qt::Alignment value); + + Q_NODISCARD QString title() const; + void setTitle(const QString &value); + + Q_NODISCARD QuickStandardMinimizeButton *minimizeButton() const; + Q_NODISCARD QuickStandardMaximizeButton *maximizeButton() const; + Q_NODISCARD QuickStandardCloseButton *closeButton() const; + +public Q_SLOTS: + void updateTitleBarColor(); + +Q_SIGNALS: + void activeChanged(); + void maximizedChanged(); + void titleLabelAlignmentChanged(); + void titleChanged(); + private: void initialize(); private: + bool m_active = false; + Qt::Alignment m_labelAlignment = {}; QScopedPointer m_label; + QScopedPointer m_row; QScopedPointer m_minBtn; QScopedPointer m_maxBtn; QScopedPointer m_closeBtn; }; FRAMELESSHELPER_END_NAMESPACE + +QML_DECLARE_TYPE(FRAMELESSHELPER_PREPEND_NAMESPACE(QuickStandardTitleBar)) diff --git a/src/widgets/standardsystembutton.cpp b/src/widgets/standardsystembutton.cpp index 92a7e94..86a5402 100644 --- a/src/widgets/standardsystembutton.cpp +++ b/src/widgets/standardsystembutton.cpp @@ -72,7 +72,12 @@ void StandardSystemButtonPrivate::refreshButtonTheme(const bool force) if (m_buttonType == SystemButtonType::Unknown) { return; } - const SystemTheme systemTheme = Utils::getSystemTheme(); + const SystemTheme systemTheme = []() -> SystemTheme { + if (Utils::isTitleBarColorized()) { + return SystemTheme::Dark; + } + return Utils::getSystemTheme(); + }(); if ((m_buttonTheme == systemTheme) && !force) { return; } @@ -261,7 +266,8 @@ void StandardSystemButtonPrivate::paintEventHandler(QPaintEvent *event) if (!m_icon.isNull()) { painter.drawPixmap(g_buttonIconX, g_buttonIconY, - ((m_buttonType == SystemButtonType::Close) && m_hovered + ((m_buttonType == SystemButtonType::Close) + && (m_buttonTheme == SystemTheme::Light) && m_hovered && !m_reversedIcon.isNull()) ? m_reversedIcon : m_icon);