├── creeper-qt ├── layout │ ├── form.hh │ ├── mixer.cc │ ├── stacked.hh │ ├── flow.hh │ ├── grid.hh │ ├── mixer.hh │ ├── mutual-exclusion-group.hh │ ├── linear.hh │ ├── group.hh │ ├── scroll.hh │ └── flow.cc ├── widget │ ├── snackbar.cc │ ├── widget.cc │ ├── cards │ │ ├── filled-card.hh │ │ ├── outlined-card.hh │ │ ├── elevated-card.hh │ │ └── basic-card.hh │ ├── widget.hh │ ├── snackbar.hh │ ├── main-window.cc │ ├── shape │ │ ├── shape.hh │ │ ├── ellipse.hh │ │ ├── rounded-rect.hh │ │ └── wave-circle.hh │ ├── indicator │ │ └── circular-progress-indicator.hh │ ├── buttons │ │ ├── button.hh │ │ ├── text-button.hh │ │ ├── filled-tonal-button.hh │ │ ├── outlined-button.hh │ │ ├── filled-button.hh │ │ ├── icon-button.cc │ │ └── icon-button.hh │ ├── sliders.cc │ ├── image.cc │ ├── text.hh │ ├── dropdown-menu.cc │ ├── text-fields.cc │ ├── main-window.hh │ ├── switch.cc │ ├── image.impl.hh │ ├── image.hh │ ├── custom │ │ └── widget.hh │ ├── sliders.hh │ ├── switch.hh │ ├── text-fields.hh │ └── dropdown-menu.hh ├── utility │ ├── qt_wrapper │ │ ├── margin-setter.hh │ │ └── enter-event.hh │ ├── animation │ │ ├── state │ │ │ ├── accessor.hh │ │ │ ├── linear.hh │ │ │ ├── spring.hh │ │ │ └── pid.hh │ │ ├── animatable.hh │ │ ├── animatable.cc │ │ ├── water-ripple.hh │ │ ├── transition.hh │ │ └── math.hh │ ├── painter │ │ ├── helper.cc │ │ └── common.hh │ ├── wrapper │ │ ├── singleton.hh │ │ ├── pimpl.hh │ │ ├── layout.hh │ │ ├── mutable.hh │ │ ├── property.hh │ │ └── mutable-value.hh │ ├── solution │ │ ├── round-angle.hh │ │ └── round-angle.cc │ ├── math │ │ └── lattice.hh │ ├── trait │ │ └── widget.hh │ ├── theme │ │ ├── color-scheme.hh │ │ ├── theme.cc │ │ ├── theme.hh │ │ └── preset │ │ │ ├── blue-miku.hh │ │ │ ├── gloden-harvest.hh │ │ │ └── green.hh │ ├── mini-bus.hh │ ├── content-scale.hh │ └── painter-resource.hh └── core │ └── application.hh ├── example ├── widgets │ ├── components │ │ ├── display-board.cc │ │ ├── display-board.hh │ │ ├── list.cc │ │ └── nav.cc │ └── component.hh ├── widgets.cmake ├── deploy-windows.sh └── deploy-linux.sh ├── .clangd ├── .gitignore ├── cmake ├── creeper-qtConfig.cmake.in ├── package.cmake └── install.cmake ├── .clang-format ├── test ├── CMakeLists.txt └── utility │ └── mini-bus.cc ├── export └── archlinux │ └── PKGBUILD ├── CMakeLists.txt ├── LICENSE └── .github └── workflows ├── nightly-build.yml └── example-build.yml /creeper-qt/layout/form.hh: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /creeper-qt/widget/snackbar.cc: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/widgets/components/display-board.cc: -------------------------------------------------------------------------------- 1 | #include "display-board.hh" 2 | -------------------------------------------------------------------------------- /.clangd: -------------------------------------------------------------------------------- 1 | CompileFlags: 2 | Add: 3 | Remove: 4 | - -mno-direct-extern-access 5 | -------------------------------------------------------------------------------- /creeper-qt/widget/widget.cc: -------------------------------------------------------------------------------- 1 | #include "widget.hh" 2 | 3 | using namespace creeper; 4 | -------------------------------------------------------------------------------- /creeper-qt/layout/mixer.cc: -------------------------------------------------------------------------------- 1 | #include "mixer.hh" 2 | 3 | using namespace creeper::mixer::internal; 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .cache/ 2 | .vscode/ 3 | .vs/ 4 | .idea/ 5 | .claude/ 6 | 7 | cmake-build-*/ 8 | build/ 9 | output/ 10 | AppDir/ 11 | out/ 12 | 13 | CMakeSettings.json 14 | 15 | *.tar.gz 16 | *.deb 17 | *.pkg 18 | *.zip 19 | -------------------------------------------------------------------------------- /cmake/creeper-qtConfig.cmake.in: -------------------------------------------------------------------------------- 1 | @PACKAGE_INIT@ 2 | 3 | include(CMakeFindDependencyMacro) 4 | find_dependency(Qt5Widgets "@REQUIRED_QT_VERSION@") 5 | 6 | include("${CMAKE_CURRENT_LIST_DIR}/creeper-qtTargets.cmake") 7 | 8 | check_required_components(Spix) 9 | -------------------------------------------------------------------------------- /creeper-qt/widget/cards/filled-card.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "basic-card.hh" 3 | 4 | namespace creeper { 5 | namespace filled_card::pro { 6 | using namespace card::pro; 7 | } 8 | using FilledCard = Declarative; 9 | } 10 | -------------------------------------------------------------------------------- /creeper-qt/widget/widget.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "creeper-qt/utility/wrapper/widget.hh" 3 | 4 | namespace creeper::widget::internal { 5 | 6 | class Widget : public QWidget { }; 7 | 8 | } 9 | namespace creeper { 10 | using Widget = Declarative; 11 | } 12 | -------------------------------------------------------------------------------- /creeper-qt/widget/snackbar.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace creeper::snackbar::details { 5 | 6 | struct Message { 7 | std::string text; 8 | }; 9 | 10 | class Snackbar { }; 11 | 12 | } 13 | namespace creeper::snackbar::pro { } 14 | namespace creeper { 15 | 16 | using SnackbarMessage = snackbar::details::Message; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /creeper-qt/widget/main-window.cc: -------------------------------------------------------------------------------- 1 | #include "main-window.hh" 2 | 3 | using namespace creeper::main_window::internal; 4 | 5 | struct MainWindow::Impl { }; 6 | 7 | auto MainWindow::paintEvent(QPaintEvent* e) -> void { QMainWindow::paintEvent(e); } 8 | 9 | MainWindow::MainWindow() 10 | : pimpl { std::make_unique() } { } 11 | 12 | MainWindow::~MainWindow() = default; 13 | -------------------------------------------------------------------------------- /creeper-qt/utility/qt_wrapper/margin-setter.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace creeper::qt { 6 | 7 | inline auto margin_setter = [](auto& self, const auto& margin) { 8 | #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) 9 | self.setContentsMargins(margin, margin, margin, margin); 10 | #else 11 | self.setMargin(margin); 12 | #endif 13 | }; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /creeper-qt/utility/qt_wrapper/enter-event.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) 6 | #include 7 | #else 8 | #include 9 | #endif 10 | 11 | namespace creeper::qt { 12 | 13 | #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) 14 | using EnterEvent = QEnterEvent; 15 | #else 16 | using EnterEvent = QEvent; 17 | #endif 18 | 19 | } 20 | -------------------------------------------------------------------------------- /creeper-qt/utility/animation/state/accessor.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace creeper { 4 | 5 | struct NormalAccessor { 6 | auto get_value(this auto const& self) { return self.value; } 7 | auto set_value(this auto& self, auto const& t) { self.value = t; } 8 | auto get_target(this auto const& self) { return self.target; } 9 | auto set_target(this auto& self, auto const& t) { self.target = t; } 10 | }; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /example/widgets.cmake: -------------------------------------------------------------------------------- 1 | if(BUILD_EXAMPLE) 2 | set(APP_NAME widgets) 3 | file( 4 | GLOB_RECURSE APP_SOURCE 5 | CONFIGURE_DEPENDS "example/widgets/*.cc" 6 | ) 7 | add_executable( 8 | ${APP_NAME} 9 | ${APP_SOURCE} 10 | ) 11 | target_link_libraries( 12 | ${APP_NAME} PRIVATE 13 | ${QT_VERSION}::Widgets 14 | ${QT_VERSION}::Network 15 | ${PROJECT_NAME} 16 | ) 17 | endif() -------------------------------------------------------------------------------- /creeper-qt/utility/painter/helper.cc: -------------------------------------------------------------------------------- 1 | #include "creeper-qt/utility/painter/helper.hh" 2 | #include 3 | 4 | namespace creeper::util { 5 | 6 | constexpr auto enable_print_paint_event_count = bool { false }; 7 | 8 | auto print_paint_event_count() noexcept -> void { 9 | if constexpr (enable_print_paint_event_count) { 10 | static auto count = std::size_t { 0 }; 11 | qDebug() << "[PainterHelper] Paint Event:" << count++; 12 | } 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /creeper-qt/utility/wrapper/singleton.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace creeper::util { 5 | 6 | template class Singleton { 7 | public: 8 | static T& instance(); 9 | 10 | Singleton(const Singleton&) = delete; 11 | Singleton& operator=(const Singleton&) = delete; 12 | 13 | protected: 14 | struct token { }; 15 | Singleton() = default; 16 | }; 17 | 18 | template inline T& Singleton::instance() { 19 | static const std::unique_ptr instance { new T { token {} } }; 20 | return *instance; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /creeper-qt/utility/solution/round-angle.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace creeper { 7 | 8 | struct RoundAngleSolution { 9 | 10 | /// @brief 给定原点和端点,按逆时针方向计算圆弧 11 | /// @note 圆弧注意按照逆时针算 12 | /// @param e0 两切线交点 13 | /// @param e1 圆弧起始点切线 14 | /// @param e2 圆弧终点切线 15 | /// @param radius 半径 16 | RoundAngleSolution(QPointF e0, QPointF e1, QPointF e2, double radius) noexcept; 17 | 18 | QRectF rect; 19 | QPointF start; 20 | QPointF end; 21 | double angle_begin; 22 | double angle_length; 23 | }; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /creeper-qt/widget/shape/shape.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace creeper { 7 | 8 | class Shape : public QWidget { 9 | public: 10 | using QWidget::QWidget; 11 | 12 | void set_background(const QColor& color) { background_ = color; } 13 | 14 | void set_border_color(const QColor& color) { border_color_ = color; } 15 | void set_border_width(double width) { border_width_ = width; } 16 | 17 | protected: 18 | QColor background_ = Qt::gray; 19 | QColor border_color_ = Qt::black; 20 | double border_width_ = 0.; 21 | }; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | Language: Cpp 2 | 3 | BasedOnStyle: WebKit 4 | 5 | # 使用空格而不是 Tab 6 | UseTab: Never 7 | 8 | # 缩进 4 字符 9 | IndentWidth: 4 10 | TabWidth: 4 11 | 12 | # 访问修饰符(public)等靠左对齐 13 | AccessModifierOffset: -4 14 | AlignTrailingComments: true 15 | 16 | # 大括号的换行规则 17 | BreakBeforeBraces: Attach 18 | 19 | # 模板定义的换行规则 20 | BreakTemplateDeclarations: true 21 | 22 | # 最大列宽度 23 | ColumnLimit: 100 24 | 25 | # 是否允许短的函数,语句块等单独一行 26 | AllowShortIfStatementsOnASingleLine: AllIfsAndElse 27 | AllowShortBlocksOnASingleLine: Empty 28 | AllowShortFunctionsOnASingleLine: All 29 | 30 | BreakBeforeBinaryOperators: NonAssignment 31 | PenaltyBreakAssignment: 2 32 | PenaltyBreakString: 2 33 | AlignConsecutiveAssignments: true 34 | -------------------------------------------------------------------------------- /cmake/package.cmake: -------------------------------------------------------------------------------- 1 | set(CPACK_PACKAGE_NAME "${PROJECT_NAME}") 2 | set(CPACK_PACKAGE_VERSION "${PROJECT_VERSION}") 3 | set(CPACK_PACKAGE_CONTACT "github@creeper5820") 4 | set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE") 5 | 6 | set(CPACK_PACKAGING_INSTALL_PREFIX "/usr/local/") 7 | 8 | if(WIN32) 9 | set(CPACK_GENERATOR "ZIP") 10 | set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION}-windows") 11 | else() 12 | set(CPACK_GENERATOR "TGZ;DEB") 13 | set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION}-linux") 14 | set(CPACK_DEBIAN_PACKAGE_MAINTAINER "creeper5820") 15 | set(CPACK_DEBIAN_PACKAGE_DEPENDS "qt6-base-dev, libeigen3-dev") 16 | endif() 17 | 18 | include(CPack) 19 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.20) 2 | project(creeper-qt-test) 3 | 4 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 5 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 6 | set(CMAKE_CXX_STANDARD 23) 7 | set(CMAKE_BUILD_TYPE "Release") 8 | add_compile_options(-Os -O2) 9 | 10 | set(CMAKE_AUTOMOC ON) 11 | 12 | set(QT_VERSION Qt6) 13 | find_package(${QT_VERSION} REQUIRED COMPONENTS Widgets Network) 14 | find_package(Eigen3 REQUIRED) 15 | 16 | # For #include "creeper-qt/..." 17 | include_directories(..) 18 | 19 | enable_testing() 20 | 21 | add_executable( 22 | mini-bus 23 | utility/mini-bus.cc 24 | ) 25 | target_link_libraries( 26 | mini-bus 27 | ${QT_VERSION}::Widgets 28 | ) 29 | add_test(NAME mini-bus COMMAND mini-bus) 30 | -------------------------------------------------------------------------------- /creeper-qt/widget/indicator/circular-progress-indicator.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "creeper-qt/utility/wrapper/common.hh" 3 | #include "creeper-qt/utility/wrapper/pimpl.hh" 4 | #include "creeper-qt/widget/widget.hh" 5 | 6 | namespace creeper::circular_progress_indicator::internal { 7 | 8 | class CircularProgressIndicator : public Widget { 9 | CREEPER_PIMPL_DEFINITION(CircularProgressIndicator); 10 | 11 | public: 12 | }; 13 | 14 | } 15 | namespace creeper::circular_progress_indicator::pro { 16 | 17 | using Token = common::Token; 18 | 19 | template 20 | concept trait = std::derived_from; 21 | 22 | CREEPER_DEFINE_CHECKER(trait); 23 | using namespace widget::pro; 24 | } 25 | namespace creeper { } 26 | -------------------------------------------------------------------------------- /creeper-qt/utility/animation/animatable.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "creeper-qt/utility/wrapper/pimpl.hh" 4 | #include 5 | 6 | namespace creeper { 7 | 8 | /// @note 9 | /// Ends after the calculation is completed or the controller call ends 10 | struct ITransitionTask { 11 | virtual ~ITransitionTask() noexcept = default; 12 | virtual auto update() noexcept -> bool = 0; 13 | }; 14 | 15 | class Animatable { 16 | CREEPER_PIMPL_DEFINITION(Animatable) 17 | 18 | public: 19 | explicit Animatable(QWidget& widget) noexcept; 20 | 21 | auto set_frame_rate(int hz) noexcept -> void; 22 | auto get_frame_rate() const noexcept -> int; 23 | 24 | auto push_transition_task(std::unique_ptr task) noexcept -> void; 25 | }; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /export/archlinux/PKGBUILD: -------------------------------------------------------------------------------- 1 | repname=creeper-qt 2 | pkgname=${repname}-git 3 | pkgver=0c918d8 4 | pkgrel=1 5 | pkgdesc="A lightweight Qt UI integration library that simplifies UI development." 6 | arch=('x86_64') 7 | url="https://github.com/creeper5820/${repname}" 8 | license=('MIT') 9 | depends=('qt6-base' 'eigen') 10 | makedepends=('git' 'cmake') 11 | source=() 12 | 13 | prepare() { 14 | cd "$srcdir" 15 | git clone --depth=1 https://github.com/creeper5820/${repname}.git 16 | } 17 | pkgver() { 18 | cd "$srcdir/${repname}" 19 | git rev-parse --short HEAD 20 | } 21 | build() { 22 | cmake -B build -S "$srcdir/${repname}" \ 23 | -DCMAKE_BUILD_TYPE=Release \ 24 | -DCMAKE_INSTALL_PREFIX=/usr \ 25 | -Wno-dev 26 | cmake --build build -j 27 | } 28 | package() { 29 | DESTDIR="$pkgdir" cmake --install build 30 | } 31 | -------------------------------------------------------------------------------- /creeper-qt/widget/buttons/button.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "creeper-qt/utility/wrapper/common.hh" 4 | #include "creeper-qt/utility/wrapper/property.hh" 5 | 6 | namespace creeper::button::pro { 7 | 8 | struct Button { }; 9 | using Token = common::Token