A simple and fast local text editor with Markdown support. It combines QScintilla-based pure-text editing with embedded cmark-gfm parsing and real-time browser preview, offering low memory usage, background residency, and one-key invocation via a global hotkey.
KBQuick is a local, native Markdown editor for Windows, built around the principles of fast startup, smooth editing, and background residency. It follows a "Source Editor + cmark-gfm C API + External Browser Live Preview" architecture: the editor focuses on plain-text input, cmark-gfm performs high-performance Markdown→HTML fragment conversion, and the system browser handles rendering — avoiding heavyweight runtimes such as embedded Chromium/WebView.
Beta notice: The current build is a beta version; data persistence may be unstable. It is intended for daily, non-critical use only!
- QScintilla text engine: A production-grade text editor based on QScintilla 2.14.1 with native IME support, Undo/Redo, large-file editing, and syntax highlighting
- Embedded cmark-gfm parsing: Press Ctrl+B to launch browser preview instantly; the cmark-gfm 0.29.0.gfm.13 C API converts Markdown to HTML fragments directly (no external process), with support for GFM extensions (tables, strikethrough, task lists, autolinks, etc.)
- GitHub-style rendering: Bundles github-markdown-css + Prism.js syntax highlighting + KaTeX math rendering + automatic code-block wrapping for a preview consistent with GitHub
- Runtime rendering runtime: A complete front-end asset directory (CSS/JS/KaTeX/Mermaid/Prism) referenced by the browser through absolute
file://URLs (unaffected by<base>tags); leverages browser caching and keeps the HTML files extremely small - Template injection: cmark-gfm emits HTML fragments →
preview_template.htmlplaceholders{{CONTENT}}/{{CSS_DIR}}/{{JS_DIR}}are substituted → complete page - Live reload:
version.js+<script>tag injection (the only reliable approach under thefile://protocol): C++ bumps the version number → the browser polls for changes → autolocation.reload() - Working-directory mechanism: A single folder acts as the working directory (implicitly determined by the working document); all new documents are created inside it
- One folder, one document: Each document is a
.kbqnotefolder (backward-compatible with the legacy.note), keeping Markdown text and image assets together for easy packaging, transfer, and backup - Background residency: After startup, minimizes to the system tray and takes no taskbar space
- Global hotkey: Press
Alt + Zto summon/hide the window - Autosave: Debounced save 500 ms after typing stops (with a dirty-flag check); documents are saved before switching
- Floating line-number overlay: Double-click the line/column area on the right side of the status bar to toggle the overlay; it auto-hides while scrolling (performance optimization) and can be dismissed by clicking it
- Search: Ctrl+Alt+/ opens the search bar with text search, case-sensitive, whole-word, and regex matching plus match highlighting; F3/Shift+F3 navigate matches; plain-text search uses the native Scintilla API (zero copy)
- Editor enhancements: Bracket-match highlighting, visual line-wrap markers, whitespace visualization (indentation trailing spaces shown as small dots), current-line highlighting, multiple cursors/rectangular selection (Ctrl+click for multiple cursors, Alt+drag for rectangular selection), zoom (Ctrl+wheel / Ctrl+= / Ctrl+- / Ctrl+0), and a dark-gray background for selected text
- File management: Double-click the file name in the status bar to enter the file-management view; the left pane lists working-directory files and the right pane lists recently opened files; double-click to open, Esc to exit
- File renaming: Rename the current file from the editor's context menu; in file-management mode, Ctrl+double-click a list item or the status-bar file name to enter rename mode; Enter confirms, Esc cancels, and duplicate names are detected
- Status indicator: The status color block at the far left of the status bar reflects the document's save state in real time (green = saved, red = unsaved); double-click it to open the pending-items view for details
- Recent files: Automatically records the 20 most recently opened documents, persisted to the configuration file
- Launch at startup: Can register a Windows startup entry to silently reside in the background after boot
- Clipboard history: Monitors the system clipboard in the background, automatically recording text, images, and file/folder list history; single-click the tray icon or the "Clipboard History" menu item to show the floating panel; single-click an entry to copy it back to the clipboard; supports pausing monitoring and clearing history
- Always on top: The main editor window stays above all other windows by default, so it is immediately visible when summoned with Alt+Z; the "Always on Top" tray menu toggle can be switched at any time and its state is persisted
- Performance optimizations: Eliminates full-text deep copies on keystroke, caches cmark-gfm extensions, caches HTML templates, fetches text on demand, single-instance detection via QLockFile, removes fsync from preview files, caches resource paths, line-number fonts, and HtmlTemplate URLs, migrates MetaJson to QJsonDocument, defers ConfigManager saves, optimizes new-document name checks and cmark-gfm encoding conversion, achieves a zero-copy UTF-8 preview pipeline, eliminates dual text storage in Document, writes UTF-8 directly on save, and optimizes search-container memory
All settings are stored in setting/config.json (JSON format) in the same directory as the executable:
- Window position and size
- Working-document path (implicitly determines the working directory = the document's parent directory)
- Recently opened files list (up to 20 entries)
- Always-on-top toggle (
always_on_top, enabled by default) - Clipboard history entry limit (default 2000 entries)
- Clipboard monitoring toggle (enabled by default)
- Clipboard history display window (default 180 days; disk data is retained)
- Maximum lines per clipboard history shard (default 10000 lines)
{
"window_x": 100,
"window_y": 100,
"window_w": 800,
"window_h": 600,
"work_document": "D:/Notes/快速笔记.kbqnote",
"recent_files": [
"D:/Notes/快速笔记.kbqnote",
"D:/Notes/会议记录.kbqnote"
],
"always_on_top": true,
"clipboard_max_entries": 2000,
"clipboard_monitor_enabled": true,
"clipboard_history_days": 180,
"clipboard_file_max_lines": 10000
}MyDoc.kbqnote/
├── content.md # Markdown content
├── meta.json # Document metadata (title, creation time, etc.)
└── assets/ # Asset files (images, etc.)
- On launch, the welcome screen is shown first, displaying hints, a shortcut overview, and the version number.
- Click anywhere on the welcome screen or press Esc to proceed.
- The app checks whether a working document is already set:
- First run (not set): the "Select Working Directory" dialog appears → the user chooses a folder → the app creates a new
.kbqnotedocument in that folder → opens it in the editor - Working document already set: the editor opens directly and loads that document
- First run (not set): the "Select Working Directory" dialog appears → the user chooses a folder → the app creates a new
- To the welcome screen: press Esc in the editor
- Back to the editor: click anywhere on the welcome screen or press Esc
| Shortcut | Action | Auto-save before switching |
|---|---|---|
Ctrl+S |
Manually save the current document | — |
Ctrl+N |
Create a new .kbqnote document in the current working directory and switch to it |
✓ |
Ctrl+O |
Choose an existing document, set its parent directory as the new working directory, and open it | ✓ |
Ctrl+Shift+S |
Set a new working directory, create a .kbqnote document there, and switch to it |
✓ |
Ctrl+B |
Start/stop browser preview | — |
Ctrl+Alt+/ |
Open/close the search bar | — |
Ctrl+= |
Zoom in | — |
Ctrl+- |
Zoom out | — |
Ctrl+0 |
Reset zoom | — |
F3 / Shift+F3 |
Search: next/previous match | — |
- Activation: press
Ctrl+Alt+/in normal editing mode; the status bar switches to the search bar - Search bar: input box (incremental matching) + ↑↓ navigation + Aa (case) / ab (whole word) / .* (regex) toggle buttons + ✕ to close
- Match highlighting: all matches get a light-yellow background; the current match gets an orange border
- Navigation: F3 / Shift+F3 / Enter / Shift+Enter to jump between matches
- Exit: ✕ button / Ctrl+Alt+/ (toggle) / Esc
- Entering: double-click the file name on the left side of the status bar; the edit area is replaced by a two-pane file list
- Left pane: all
.kbqnotedocuments in the working directory - Right pane: recently opened documents (newest first, up to 20)
- Left pane: all
- Open a file: double-click an entry to open it and exit file management
- Select a file: single-click an entry; the status bar shows the selected file name
- Rename: Ctrl+double-click an entry or the status-bar file name → inline editing → Enter to confirm / Esc to cancel (duplicate names show a prompt)
- Exit: close button / Esc
The status color block at the far left of the status bar reflects the current document's save state in real time:
- Green: the document is saved with no unsaved changes
- Red: the document has unsaved changes (turns red automatically after editing and back to green after saving)
When the color changes:
- Opening a document → green
- After editing (the autosave timer is armed) → red
- After saving (manual Ctrl+S or autosave) → green
Pending-items view: double-click the status color block to replace the edit area with the pending-items panel, which shows:
- Document save state (saved/unsaved)
- Last save time (read from
meta.json) - Document save path
Currently the pending-items view only contains the document save state as a notification; it does not affect the color block (the block always stays green). More pending-item types can be added in the future.
Exit: close button / Esc
Whenever the current document is switched via Ctrl+N, Ctrl+O, Ctrl+Shift+S, or similar operations, the current document is always saved first, and only then does the switch proceed.
- Summoning: single-click the tray icon or the "Clipboard History" item in the tray context menu
- Panel: a borderless floating panel above the tray (about 1/4 of the screen width); entries are ordered oldest → newest, and the newest entry is auto-selected when the panel opens
- Copying: single-click an entry to copy it to the clipboard and close the panel; Ctrl+click copies without closing; Enter copies the selected entry and closes; Ctrl+C copies only
- Navigation: ↑/↓ to select entries, Esc to close; the panel closes automatically when it loses focus and restores focus to the previously active window
- Management: the tray menu's "Pause Monitoring" pauses recording (no backfill after resuming); "Clear History" wipes the recorded history
- Data storage:
clipboard_data/history/stores text/file-list entries as JSONL shards;clipboard_data/images/stores image originals and thumbnails in date-based directories
- The main editor window is always on top by default, staying above all other windows; it remains on top after being summoned/hidden with Alt+Z and is visible as soon as the hotkey is pressed
- The "Always on Top" tray menu toggle can be enabled/disabled at any time; the state is saved to
always_on_topinsetting/config.json(enabled by default) - Only the main editor window is always on top; the clipboard panel, browser preview, and other windows are not
- Visual Studio 2022 Community (with the "Desktop development with C++" workload)
- Qt 6.8.3 for MSVC 2022 64-bit
- CMake ≥ 3.16
# Configure (spdlog logging enabled by default; links spdlog + fmt)
cmake -B build -G "Visual Studio 17 2022" -DCMAKE_PREFIX_PATH="C:/Qt/6.8.3/msvc2022_64" "-DCMAKE_POLICY_VERSION_MINIMUM=3.5"
# Configure (logging disabled; zero-overhead release mode; does not link spdlog + fmt)
# cmake -B build -G "Visual Studio 17 2022" -DCMAKE_PREFIX_PATH="C:/Qt/6.8.3/msvc2022_64" "-DCMAKE_POLICY_VERSION_MINIMUM=3.5" -DKBQUICK_ENABLE_LOGGING=OFF
cmake --build build --config Release
# Deploys the Qt runtime + runtime/ automaticallyLogging build switch: the
KBQUICK_ENABLE_LOGGINGoption controls whether spdlog logging is enabled (defaultON). After toggling it, you must re-runcmake -B build; running onlycmake --buildis not enough.
Or use the build scripts (committed as templates with empty environment paths; fill in your local paths at the top before running: $vcvars, $cmake, $windeployqt, $qtPrefix):
.\build-release.ps1 # Release build
.\build-debug.ps1 # Debug buildBoth scripts are equivalent to the manual commands above and automatically perform "clean → configure → build → windeployqt Qt runtime deployment". Differences:
| Script | CMake config | windeployqt | Output directory | Use case |
|---|---|---|---|---|
build-release.ps1 |
--config Release |
--release |
build-release\Release\KBQuick.exe |
Release / distribution |
build-debug.ps1 |
--config Debug |
--debug |
build-debug\Debug\KBQuick.exe |
Development / debugging (with debug symbols) |
Notes:
build-release.ps1/build-debug.ps1replace the legacybuild.ps1/build.bat; the old scripts are no longer used.- The scripts contain no machine-specific paths; environment paths (MSVC
vcvarsall.bat,cmake.exe,windeployqt6.exe, and the Qt prefix) must be filled in by each developer.- Both scripts are committed to the repository as templates (allowed by the
!build-release.ps1/!build-debug.ps1rules in.gitignore). After filling in local paths, do not commit your personal paths; restore them before committing, or rungit update-index --skip-worktree build-release.ps1 build-debug.ps1to ignore local changes.- They use separate build directories (
build-release/build-debug), so both sets of artifacts can coexist without overwriting each other; these directories remain ignored by the*build-*rule in.gitignore.
The output directory depends on the build method:
- Manual build:
build/Release/ build-release.ps1:build-release/Release/build-debug.ps1:build-debug/Debug/
The directory layout is identical (shown here for the Release output):
build-release/Release/
├── KBQuick.exe
├── runtime/
│ ├── css/
│ ├── js/
│ ├── templates/
│ └── preview/
├── Qt6Core.dll / Qt6Gui.dll / Qt6Widgets.dll / ...
└── platforms/ iconengines/ ...
| Shortcut | Action | Save before switching |
|---|---|---|
Click / Esc |
Enter the editor from the welcome screen | — |
Esc |
Return to the welcome screen from the editor / exit search / exit file management | — |
Ctrl+S |
Save the current document | — |
Ctrl+N |
Create a new document in the working directory | ✓ |
Ctrl+O |
Open a document (sets its parent directory as the working directory) | ✓ |
Ctrl+Shift+S |
Set a new working directory | ✓ |
Ctrl+B |
Start/stop browser preview | — |
Ctrl+Alt+/ |
Open/close the search bar | — |
F3 / Shift+F3 |
Search: next/previous match | — |
Ctrl+Z / Ctrl+Y |
Undo/redo | — |
Alt+Z |
Summon/hide the window globally | — |
| Action | Effect | Applicable state |
|---|---|---|
| Double-click status color block | Open the pending-items view | Normal editing |
| Double-click file name in the status bar | Enter file management | Normal editing |
| Double-click line/column numbers in the status bar | Toggle the line-number overlay | Normal editing |
| Drag the status bar | Move the window | Any |
| Ctrl+double-click file name in the status bar | Enter rename mode | File management |
| Ctrl+double-click list item | Enter rename mode | File management |
| Esc | Close search / exit file management / exit pending items / cancel rename | Search / file management / pending items |
| Action | Effect |
|---|---|
| Double-click the line/column area in the status bar | Toggle the line-number overlay |
| Scroll the page | Auto-hide the line-number overlay (performance optimization) |
| Click the line-number overlay | Close the line-number overlay |
| Ctrl+wheel | Zoom the editor font |
| Ctrl+click | Add multiple cursors |
| Alt+drag | Rectangular selection |
| Context menu | Rename the current file |
| Hover over the right edge | Show the scrollbar |
| Move the mouse away from the right edge | Hide the scrollbar after 800 ms |
| Action | Effect |
|---|---|
| Single-click the tray icon | Open the clipboard panel |
| Single-click an entry | Copy to the clipboard and close the panel |
| Ctrl+single-click an entry | Copy only, keep the panel open |
| ↑ / ↓ | Select previous / next entry |
| Enter | Copy the selected entry and close the panel |
| Ctrl+C | Copy the selected entry |
| Esc | Close the panel |
| Argument | Description |
|---|---|
--autostart |
Autostart mode: the app launches silently and minimizes to the system tray without showing the main window. Passed automatically by the Windows startup entry; not needed for normal launches. |
Examples:
KBQuick.exe # Normal launch; shows the main window
KBQuick.exe --autostart # Silent launch; minimized to the trayIf the "Select Working Directory" dialog is canceled, the app exits. In normal use, please select a folder as the working directory.
cmark-gfm is embedded in KBQuick.exe as a static library and requires no external files. If the preview returns empty results, check the logs for a "cmark-gfm extension not found" warning.
Make sure the runtime/ directory is in the same directory as KBQuick.exe. The CMake build copies it automatically. The preview HTML references CSS/JS/KaTeX and other assets through absolute file:// URLs, so it is unaffected by <base> tags.
cmark-gfm does not process math formulas; $...$ and $$...$$ are preserved as plain text. KaTeX's auto-render.min.js scans text nodes and renders the formulas. If formulas still do not render, check the browser console for font-loading errors.
Mermaid is enabled. Write diagrams in Markdown using a fenced code block labeled mermaid, and they render in the browser preview. The runtime artifact runtime/mermaid/mermaid.min.js ships with the app; no extra build is required.
Run the program as administrator. Some security software may block global hotkey registration.
KBQuick needs write access to its application directory for logs (log/) and preview temporary files (runtime/preview/). If installed in a protected directory such as Program Files, non-admin users lack write permission. On startup the app detects this and shows a prompt; choose "Rerun as administrator", or install to an unprotected directory (e.g., D:\KBQuick).
KBQuick uses std::wstring (UTF-16) throughout to construct std::filesystem::path, ensuring Chinese paths and document names (e.g., "未命名文档.kbqnote" / "Untitled Document.kbqnote") work correctly on Windows MSVC. meta.title is stored in UTF-8 and converted with QString::toUtf8() / QString::fromUtf8() when reading and writing.
KBQuick creates clipboard_data/ next to the executable to store clipboard history: history/ holds JSONL shards (one record per line; text/file lists), and images/ stores image originals and thumbnails in date-based directories. The display window (default 180 days), entry limit (default 2000), and shard line limit (default 10000) can be adjusted in setting/config.json. Delete the clipboard_data/ directory to clear all history.
- Media insertion by drag & drop / paste: Dropping image or video files onto the editor window, or pasting copied files with Ctrl+V, inserts a Markdown reference at the cursor and copies the asset into the current document bundle under
assets/images/orassets/videos/; name collisions are resolved by generating a unique file name instead of overwriting. - Media size threshold: Files exceeding the configurable limit (default 10 MB, key
media_size_limit_mbinsetting/config.json) prompt a choice between copying the file into the document or referencing its absolute path, with an explicit warning that an absolute reference breaks once the source file is moved, renamed, or deleted. - Video preview: Video references use the same standard Markdown syntax as images —
— and are rendered as a playable<video>element in the browser preview based on the file extension, with no proprietary markup introduced. - Mermaid diagram rendering:
```mermaidfenced code blocks are rendered as diagrams in the browser preview, powered by a local UMD build of Mermaid (runtime/mermaid/mermaid.min.js) that works fully offline; when rendering fails, the original code block is kept so the source stays visible for troubleshooting.
- Optimized web rendering of Markdown
- Clipboard history: Added a clipboard-history subsystem (monitor/storage/panel) that runs in the background to record copied content, supporting text, images, and file/folder lists.
- Clipboard monitoring: QClipboard
dataChangedas the primary channel with a 500 msGetClipboardSequenceNumberpolling fallback, 200 ms debounce merging, and three-layer deduplication (sequence number / content fingerprint / self-write-back) to avoid duplicate records. - Clipboard storage: In-memory sliding window (default up to 2000 entries) + JSONL shard persistence in
clipboard_data/history/(up to 10000 lines per shard); image originals and thumbnails stored in date-based directories; disk history is retained permanently, with a default display window of 180 days. - Clipboard panel: Borderless floating panel above the tray (1/4 of screen width) with entries ordered oldest → newest; single-click copies and closes, Ctrl+click copies only; supports ↑/↓/Enter/Ctrl+C/Esc keyboard navigation; auto-closes on focus loss and restores focus to the previously active window; thumbnails are lazily loaded and cached.
- Tray integration: Added "Clipboard History", "Pause Monitoring", and "Clear History" to the tray menu; single-clicking the tray icon opens the clipboard panel directly.
- Main-window always on top: The main editor window stays above all other windows by default, so it is immediately visible when summoned with Alt+Z and is never obscured; added an "Always on Top" toggle to the tray menu.
- Always-on-top persistence: The toggle state is saved to the
always_on_topfield insetting/config.jsonand restored on restart (enabled by default).
