# Repository: vnotex/vnote # Stars: 12771 ## CLAUDE.md # CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview VNote is a Qt-based, cross-platform (Windows/Linux/macOS) note-taking application focused on Markdown. It uses C++14, Qt 6, and CMake 3.20+. The project is undergoing a major architectural migration from singletons to dependency injection via `ServiceLocator`. ## Build Commands ```bash # Setup (first time after clone) bash scripts/init.sh # Linux/macOS scripts\init.cmd # Windows # Configure + build (Release) mkdir build && cd build cmake .. -GNinja # Windows with MSVC: run from VS Developer Command Prompt cmake --build . --config Release # Debug build cmake .. -DCMAKE_BUILD_TYPE=Debug cmake --build . --config Debug # Clean rebuild rm -rf build && mkdir build && cd build && cmake .. && cmake --build . ``` ## Testing Tests use Qt Test framework. **Always call `vxcore_set_test_mode(1)` before `vxcore_context_create()` in tests** to prevent corrupting real user data. ```bash # Build all tests cmake --build build --config Release # Run all tests via CTest ctest --test-dir build --output-on-failure # Run a single test (pattern match) ctest --test-dir build -R test_error # Run test executable directly (Windows: Qt DLLs must be in PATH) ./build/tests/core/test_error.exe ``` ### Adding a New Test Use the `add_qt_test()` helper in `tests//CMakeLists.txt`: ```cmake add_qt_test(test_myclass SOURCES test_myclass.cpp ${CMAKE_SOURCE_DIR}/src/module/myclass.cpp LINKS core_services vxcore # Optional extra link libraries GUILESS # Optional: headless (QCoreApplication) ) ``` Test files use `QTEST_GUILESS_MAIN(tests::TestClassName)` and must end with `#include "test_filename.moc"`. ## Architecture ### Dual Architecture (Legacy + New) The codebase has two coexisting architectures: - **Legacy:** Singleton-based (`VNoteX::getInst()`, `ConfigMgr::getInst()`) — do NOT use for new code - **New (files with `2` suffix):** Dependency injection via `ServiceLocator` passed through constructors New files coexist with legacy via the `2` suffix convention (e.g., `MainWindow2`, `ConfigMgr2`, `Buffer2`). ### MVC + Service Layer ``` Controllers (src/controllers/) — business logic, QObject (not QWidget), testable ↕ signals/slots Models (src/models/) — QAbstractItemModel subclasses, no UI logic Views (src/views/) — QTreeView/delegates, display only, emit signals ↕ ServiceLocator — DI container (non-owning pointers, NOT a singleton) ↕ Services (src/core/services/) — wrap vxcore C API with Qt-friendly interface ↕ vxcore (libs/vxcore/) — C library: notebook/config/search backend ``` **MVC rules:** Models must not contain UI logic. Views must not modify data directly. Controllers must not inherit QWidget. All layers receive `ServiceLocator&` via constructor. ### Key Types | Type | Role | |------|------| | `ServiceLocator` | DI container; stores non-owning `void*` pointers keyed by `type_index` | | `NodeIdentifier` | Lightweight value type: `notebookId` (GUID) + `relativePath` | | `Buffer2` | Lightweight copyable handle (like `QModelIndex`), returned by `BufferService::openBuffer()` | | `XXXCoreService` | Low-level services wrapping vxcore C API (hold `VxCoreContextHandle`) | | `BufferService` | Hook-aware wrapper over `BufferCoreService`; fires `vnote.file.*` hooks | | `HookManager` | WordPress-style hook system: actions (cancellable events) + filters (data transforms) | ### Service Registration (main.cpp) Services are stack-allocated in `main()` within a scoped block, registered as non-owning pointers in `ServiceLocator`, and destroyed before `vxcore_context_destroy()`. Order matters. ### Hook System Plugins use `HookManager::addAction()` / `addFilter()` with priority ordering. Hook names are constants in `src/core/hooknames.h` (e.g., `vnote.notebook.before_open`, `vnote.file.before_save`). Actions can cancel operations via `HookContext::cancel()`. When adding hooks to existing code, use the WRAP pattern: fire before-hook → original signal → after-hook. ### Git Submodules Three submodules in `libs/`: - **vtextedit** — Rich text/Markdown editor widget - **QHotkey** — Cross-platform global hotkey support - **vxcore** — C library backend (built as static lib, tests/CLI disabled) ## Code Style Enforced by `.clang-format` via pre-commit hook. Key conventions: - **C++14**, 2-space indent, 100-char line limit - **Naming:** `CamelCase` classes, `camelCase` methods, `p_` params, `m_` members, `c_` constants - **Pointer alignment:** right (`int *ptr`) - **Include order:** own header → Qt → local/project → `using namespace vnotex;` in `.cpp` only - **Header guards:** `#ifndef CLASSNAME_H` / `#define CLASSNAME_H` - **Namespace:** single `vnotex` namespace; never `using namespace` in headers - `libs/` directory is excluded from formatting (third-party code) ### Manual formatting ```bash clang-format -i src/core/myfile.cpp ``` ## Directory Layout (New Architecture) | Directory | Contents | |-----------|----------| | `src/core/services/` | Service layer (`core_services` static library, links `vxcore`) | | `src/core/` | Core types, legacy code, config, hook system | | `src/controllers/` | MVC controllers | | `src/models/` | MVC models | | `src/views/` | MVC views and delegates | | `src/widgets/` | UI widgets (receive `ServiceLocator&`), including `dialogs/` | | `src/gui/services/` | GUI-aware services (`ThemeService`, `ViewWindowFactory`) | | `src/gui/utils/` | GUI utility helpers | | `tests/` | Qt Test suites; `helpers/` has `TempDirFixture` and common includes | | `libs/` | Git submodules (vtextedit, QHotkey, vxcore) | ## Migration Patterns When migrating legacy code to new architecture: 1. Create new file with `2` suffix 2. Replace `ConfigMgr::getInst()` → `m_services.get()` 3. Replace `VNoteX::getInst().getNotebookMgr()` → `m_services.get()` 4. Add `ServiceLocator &p_services` constructor parameter, store as `m_services` 5. Add to appropriate `CMakeLists.txt` ## CI GitHub Actions workflows in `.github/workflows/`: `ci-win.yml`, `ci-linux.yml`, `ci-macos.yml`. Trigger on push/PR to `master`. Windows builds use Ninja + MSVC 2022 with Qt 6.8.3. ## README.md # VNote ![CI-Windows](https://github.com/vnotex/vnote/actions/workflows/ci-win.yml/badge.svg?branch=master) ![CI-Linux](https://github.com/vnotex/vnote/actions/workflows/ci-linux.yml/badge.svg?branch=master) ![CI-MacOS](https://github.com/vnotex/vnote/actions/workflows/ci-macos.yml/badge.svg?branch=master) [简体中文](README_zh_CN.md) [Project on Gitee](https://gitee.com/vnotex/vnote) A pleasant note-taking platform. For more information, please visit [**VNote's Home Page**](https://vnotex.github.io/vnote). ![VNote](pics/vnote.png) ## Description **VNote** is a Qt-based, free and open source note-taking application, focusing on Markdown now. VNote is designed to provide a pleasant note-taking platform with excellent editing experience. VNote is **NOT** just a simple editor for Markdown. By providing notes management, VNote makes taking notes in Markdown simpler. In the future, VNote will support more formats besides Markdown. Utilizing Qt, VNote could run on **Linux**, **Windows**, and **macOS**. ![Main](pics/main.png) ![Main2](pics/main2.png) ## Downloads Continuous builds on `master` branch could be found at the [Continuous Build](https://github.com/vnotex/vnote/releases/tag/continuous-build) release. Latest stable builds could be found at the [latest release](https://github.com/vnotex/vnote/releases/latest). Alternative download services are available: * [Tianyi Netdisk](https://cloud.189.cn/t/Av67NvmEJVBv) * [Baidu Netdisk](https://pan.baidu.com/s/1lX69oMBw8XuJshQDN3HiHw?pwd=f8fk) ## Supports * [GitHub Issues](https://github.com/vnotex/vnote/issues); * Email: `tamlokveer at gmail.com`; * [Telegram](https://t.me/vnotex); * WeChat Public Account: vnotex; Thank [users who donated to VNote](https://github.com/vnotex/vnote/wiki/Donate-List)! ## Development After cloning the repository, run the initialization script to set up your development environment: **Linux/macOS:** ```bash bash scripts/init.sh ``` **Windows:** ```cmd scripts\init.cmd ``` This script will: * Initialize and update all git submodules * Install pre-commit hooks for automatic code formatting with clang-format * Set up the vtextedit submodule pre-commit hook For more development guidelines, see [AGENTS.md](AGENTS.md). ## License VNote is licensed under [GNU LGPLv3](https://opensource.org/licenses/LGPL-3.0). Code base of VNote could be used freely by VNoteX.