A powerful text search and navigation tool built with Qt6 and modern C++
Features β’ Installation β’ Usage β’ Contributing
TextMatcher is a cross-platform desktop application for efficient text search and navigation. Built with Qt6 and C++17, it provides regex-powered search with real-time visual feedback and intuitive keyboard-driven navigation.
Key Highlights:
- β‘ Fast Search - Regex-based pattern matching with instant results
- π¨ Visual Excellence - Smart dual-color highlighting system that distinguishes current match from all matches
- π§ Intelligent Search - Whole-word matching, case sensitivity control, and automatic wraparound
- β¨οΈ Keyboard Control - Complete keyboard-driven workflow with intuitive shortcuts
- π― Precision Navigation - Real-time match counter shows your exact position (e.g., "3 of 47 matches")
- π State Aware - Smart caching avoids redundant searches when navigating same results
- π Cross-Platform - Native look and feel on Windows, Linux, and macOS
- Pattern Matching - Full QRegularExpression (PCRE2) support
- Whole Word Search - Match complete words only using word boundaries
- Case Sensitivity - Toggle case-sensitive/insensitive matching
- Bidirectional - Navigate forward and backward through results
- Wraparound - Seamlessly cycle through matches at document boundaries
- Multi-Match Highlighting - All matches highlighted simultaneously
- Current Match Emphasis - Distinct color for active result
- Match Counter - Shows position like "Matches: 3/47"
- File Loading - Native file dialogs with directory memory
- Keyboard Shortcuts - Arrow keys, Enter, Ctrl+O, Ctrl+L, Ctrl+Q, Alt+W, Alt+S
- Optimized Counting - Early exit algorithm for current position
- State Caching - Avoids re-counting when navigating same search
- Efficient Rendering - QTextEdit extraSelections for highlighting
- Responsive - Handles 1000+ matches smoothly
Click to view screenshots
Ensure you have the following installed:
| Requirement | Minimum Version | Recommended | Download |
|---|---|---|---|
| C++ Compiler | C++17 | C++20 | GCC / Clang / MSVC |
| Qt Framework | 6.0 | 6.5+ | Qt Downloads |
| CMake | 3.16 | 3.25+ | CMake |
| Git | Any | Latest | Git |
Optional but Recommended:
- Qt Creator - Integrated development environment
# 1. Clone the repository git clone https://github.com/orkhan-muradov-dev/qt-text-matcher.git cd qt-text-matcher # 2. Create build directory mkdir build && cd build # 3. Configure (replace /path/to/Qt with your Qt installation) cmake .. -DCMAKE_PREFIX_PATH=/path/to/Qt/6.x.x/gcc_64 -DCMAKE_BUILD_TYPE=Release # 4. Build cmake --build . --parallel # 5. Run! ./TextMatcherπͺ Windows (Click to expand)
# Open PowerShell or Command Prompt git clone https://github.com/orkhan-muradov-dev/qt-text-matcher.git cd qt-text-matcher mkdir build cd build # Configure with MinGW cmake .. -G "MinGW Makefiles" ^ -DCMAKE_PREFIX_PATH=C:/Qt/6.5.0/mingw_64 ^ -DCMAKE_BUILD_TYPE=Release # Build cmake --build . --config Release --parallel # Run Release\TextMatcher.exe# Configure with Visual Studio 2022 cmake .. -G "Visual Studio 17 2022" ^ -DCMAKE_PREFIX_PATH=C:/Qt/6.5.0/msvc2019_64 ^ -DCMAKE_BUILD_TYPE=Release # Build cmake --build . --config Release # Run Release\TextMatcher.exeπ§ Linux (Click to expand)
# Install dependencies (Ubuntu/Debian) sudo apt update sudo apt install build-essential cmake qt6-base-dev # Or on Fedora sudo dnf install gcc-c++ cmake qt6-qtbase-devel # Clone and build git clone https://github.com/orkhan-muradov-dev/qt-text-matcher.git cd qt-text-matcher mkdir build && cd build # Configure cmake .. -DCMAKE_BUILD_TYPE=Release # Build with all cores cmake --build . --parallel $(nproc) # Run ./TextMatcherAdding to Applications Menu:
# Create desktop entry cat > ~/.local/share/applications/textmatcher.desktop << EOF [Desktop Entry] Name=TextMatcher Exec=/path/to/TextMatcher/build/TextMatcher Icon=/path/to/TextMatcher/media/app-overview.png Type=Application Categories=Utility;TextEditor; EOFπ macOS (Click to expand)
# Install dependencies via Homebrew brew install cmake qt@6 # Clone and build git clone https://github.com/orkhan-muradov-dev/qt-text-matcher.git cd qt-text-matcher mkdir build && cd build # Configure (may need to specify Qt path) export Qt6_DIR=/usr/local/opt/qt@6/lib/cmake/Qt6 cmake .. -DCMAKE_BUILD_TYPE=Release # Build cmake --build . --parallel # Run ./TextMatcher.app/Contents/MacOS/TextMatcherCreating .app Bundle:
# Use macdeployqt to create standalone application /path/to/Qt/6.x.x/macos/bin/macdeployqt TextMatcher.app -dmgπ¨ Qt Creator (Recommended for Development)
-
Open Project
- Launch Qt Creator
File β Open File or Project...- Select
CMakeLists.txtfrom the cloned repository
-
Configure Kit
- Choose your Qt6 kit (Desktop Qt 6.x.x)
- Click "Configure Project"
-
Build & Run
- Press
Ctrl+B(Cmd+B on macOS) to build - Press
Ctrl+R(Cmd+R on macOS) to run
- Press
-
Debug
- Set breakpoints by clicking line numbers
- Press
F5to start debugging
Customize your build with CMake options:
# Debug build with symbols cmake .. -DCMAKE_BUILD_TYPE=Debug # Release with debug info cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo # Static linking (where applicable) cmake .. -DBUILD_SHARED_LIBS=OFF # Custom install prefix cmake .. -DCMAKE_INSTALL_PREFIX=/opt/textmatcher # Specify compiler cmake .. -DCMAKE_CXX_COMPILER=g++-12# Check the built executable ./TextMatcher --version # (if version flag implemented) # Or simply run it ./TextMatcher # Expected: Application window opens with sample text loaded-
Start Searching
- Type your search term in the "Keyword" field
- Press
Enteror clickβbutton to find first match - Current match highlighted in orange, others in yellow
-
Navigate Results
- Press
βorEnterfor next match - Press
βfor previous match - Watch the counter update (e.g., "Matches: 5/23")
- Press
-
Refine Search
- Check Whole Word (
Alt+W) to match complete words only - Check Case Sensitive (
Alt+S) for exact case matching - Search automatically updates
- Check Whole Word (
-
Load Your Files
- Click
πbutton or pressCtrl+O - Select any
.txtfile - Start searching immediately
- Click
| Option | Behavior | Example |
|---|---|---|
| Default | Substring match, case-insensitive | "cat" finds "cat", "Cat", "category" |
| Whole Word | Complete words only | "cat" finds "cat" but NOT "category" |
| Case Sensitive | Exact case required | "Cat" finds "Cat" but NOT "cat" |
| Both Enabled | Complete words, exact case | Most restrictive search |
| Shortcut | Action | Description |
|---|---|---|
Enter | Find Next | Search forward from current position |
β | Find Next | Alternative to Enter |
β | Find Previous | Search backward from current position |
Ctrl+O | Open File | Load a new text file |
Ctrl+L | Clear Search | Remove search term and reset highlights |
Ctrl+Q | Quit | Exit application |
Alt+W | Toggle Whole Word | Toggle the "Whole Word" checkbox |
Alt+S | Toggle Case Sens. | Toggle the "Case Sensitive" checkbox |
Tip: Arrow keys work from anywhere in the application, making navigation seamless.
Core Technologies:
- Language: C++17 (modern features: structured bindings, if-init statements)
- GUI Framework: Qt6 Widgets (cross-platform native UI)
- Regex Engine: QRegularExpression (PCRE2 backend)
- Build System: CMake 3.16+ (modern target-based)
- Design Tool: Qt Designer (
.uiXML format)
TextMatcher/ βββ π README.md # This file βββ π CHANGELOG.md # Version history βββ π LICENSE # MIT License βββ π .gitignore # Git ignore rules β βββ π src/ # Source code β βββ π CMakeLists.txt # Build configuration β βββ π main.cpp # Application entry point β βββ π textmatcher.h # Class declaration β βββ π textmatcher.cpp # Implementation β βββ π textmatcher.ui # Qt Designer UI (XML) β βββ π textmatcher.qrc # Qt resources (embedded files) β βββ π input.txt # Embedded sample text β βββ π media/ # Screenshots, gifs SearchOptions Struct
- Encapsulates QRegularExpression, FindFlags, and PatternOptions
- Handles regex compilation with automatic escaping
- Provides validation via
isValid()method
State Management
m_totalMatches- Cached count to avoid recalculationm_lastRegexPattern- Detects when new search is neededm_lastFolder- Remembers last opened directory
Search Algorithm
- Forward/backward iteration with same core logic
- Early exit when counting to current position
- Wraparound at document start/end
Highlighting System
- QTextEdit::ExtraSelection for non-invasive overlay
- Dual colors: orange for current, yellow for others
- Single-pass rendering for efficiency
Class Design (Click to expand)
class TextMatcher : public QWidget { // --- Nested Types --- struct SearchOptions { QRegularExpression regex; // Compiled pattern QTextDocument::FindFlags flags; // Search direction & options QRegularExpression::PatternOptions patternOptions; SearchOptions(const QString& text, bool wholeWord, bool caseSensitive); bool isValid() const; }; // --- State Management --- size_t m_totalMatches; // Cached match count QString m_lastRegexPattern; // Previous search pattern QRegularExpression::PatternOptions m_lastPatternOptions; QString m_lastFolder; // Last opened directory // --- Core Search Logic --- void performFind(bool backwards); // Main search orchestration size_t countMatches(...); // Efficient match counting void highlightAllMatches(...); // Visual feedback system // --- State Optimization --- bool isNewSearch(...) const; // Avoid redundant work void resetSearchState(); // Clean slate };Key Design Principles:
- Encapsulation: SearchOptions bundles regex + flags
- State Caching: Avoid re-counting matches on navigation
- Separation of Concerns: UI, search logic, state management decoupled
- RAII: Qt's parent-child ownership handles cleanup
Search Algorithm (Click to expand)
Match Counting Strategy:
// Optimized counting stops early when finding current position size_t countMatches(search, stopAtCurrentSelection) { iterate through document with regex if (stopAtCurrentSelection && cursor matches current selection) break; // Found our position return count; }Highlighting System:
// Dual-color system for visual feedback QTextEdit::ExtraSelection { cursor: match_position format.background: (isCurrent ? Orange : Yellow) }State Machine:
New Search β Count Total β Highlight All β Navigate β β βββββββββ Same Search ββββββββββ Edit textmatcher.cpp to change highlight colors:
namespace { const QColor HighlightColor(100, 92, 17); // All matches (yellow) const QColor CurrentHighlightColor(100, 52, 17); // Current match (orange) }Modify input.txt to change the embedded sample text:
Your custom sample text here. This will be embedded in the application binary.Rebuild after changes: cmake --build . --parallel
Fine-tune compilation:
# Enable compiler warnings cmake .. -DCMAKE_CXX_FLAGS="-Wall -Wextra -Wpedantic" # Optimize for size cmake .. -DCMAKE_BUILD_TYPE=MinSizeRel # Link-time optimization cmake .. -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON # Generate compile_commands.json for LSP cmake .. -DCMAKE_EXPORT_COMPILE_COMMANDS=ON-
Basic Search
Input: "the" Expected: Multiple matches highlighted -
Whole Word
Input: "test" (Whole Word enabled) Should NOT match: "testing", "attest" Should match: "test", "Test" -
Case Sensitive
Input: "Test" (Case Sensitive enabled) Should NOT match: "test" Should match: "Test" -
Navigation
- Verify wraparound at document start/end - Check counter updates correctly (e.g., 1/5 β 2/5 β ...) -
Edge Cases
- Empty search term (should reset) - No matches found (should show 0/0) - Single match (wraparound should work)
Planned additions:
- Qt Test framework integration
- Automated UI testing
- Performance benchmarks
- Regression test suite
- Core search functionality
- Dual-color highlighting
- Keyboard shortcuts
- File loading
- Search History - Dropdown of recent searches
- Replace Functionality - Find and replace text
- Custom Themes - User-configurable colors
See GitHub Issues for detailed feature requests and bugs.
Build Errors
Problem: CMake Error: Could not find Qt6
Solution:
# Specify Qt6 path explicitly cmake .. -DCMAKE_PREFIX_PATH=/path/to/Qt/6.x.x/gcc_64Problem: error: 'QString' has not been declared
Solution: Ensure you're using C++17:
cmake .. -DCMAKE_CXX_STANDARD=17Runtime Issues
Problem: Application won't start - missing Qt libraries
Solution (Linux):
# Add Qt libraries to LD_LIBRARY_PATH export LD_LIBRARY_PATH=/path/to/Qt/6.x.x/gcc_64/lib:$LD_LIBRARY_PATHSolution (Windows):
- Copy Qt DLLs to executable directory, or
- Add Qt bin directory to PATH, or
- Use
windeployqt.exe TextMatcher.exe
Problem: File dialog doesn't appear
Solution: Install platform plugins:
# Linux sudo apt install qt6-qpa-pluginsSearch Not Working
Problem: No matches found despite visible text
Check:
- Case sensitivity setting (try disabling)
- Whole word setting (try disabling)
- Verify text is in the text edit widget
- Check for trailing spaces in search term
We welcome contributions of all kinds! Whether you're fixing bugs, adding features, improving documentation, or suggesting ideas, your input is valued.
-
Fork the Repository
# Click 'Fork' on GitHub, then clone your fork git clone https://github.com/YOUR_USERNAME/qt-text-matcher.git -
Create a Feature Branch
git checkout -b feature/amazing-new-feature
-
Make Your Changes
- Write clean, documented code
- Follow existing code style
- Test thoroughly
-
Commit with Clear Messages
git commit -m "feat: add search history dropdown" -
Push and Create Pull Request
git push origin feature/amazing-new-feature # Then open PR on GitHub
Code Style (Click to expand)
- Indentation: 4 spaces
- Naming:
- Classes:
PascalCase - Functions:
camelCase - Variables:
camelCase - Member variables:
m_camelCase - Constants:
UPPER_SNAKE_CASE
- Classes:
- Braces: Allman style (braces on new line)
- Comments: Use
//for single-line,/* */for multi-line - Headers: Include guards with
#ifndef FILENAME_H
Commit Message Format
Use Conventional Commits:
type(scope): short description Longer description if needed. Fixes #123 Types:
feat: New featurefix: Bug fixdocs: Documentation onlystyle: Code style (formatting, no logic change)refactor: Code restructuringperf: Performance improvementtest: Adding testschore: Maintenance tasks
Examples:
feat(search): add regex mode toggle fix(ui): correct match counter display docs(readme): update build instructions - π Bug Fixes: Check open issues
- β¨ New Features: See roadmap
- π Documentation: Improve README, add tutorials
- π Translations: Internationalization support
- π¨ UI/UX: Design improvements, accessibility
- β‘ Performance: Optimization opportunities
- π§ͺ Testing: Write unit/integration tests
We follow the Contributor Covenant Code of Conduct. Please be respectful and constructive in all interactions.
This project is licensed under the MIT License - see the LICENSE file for full details.
TL;DR: You can do almost anything with this code. Attribution appreciated but not required.
- π Documentation: You're reading it!
- π¬ Discussions: GitHub Discussions
- π Bug Reports: GitHub Issues
- π§ Email: orkhan.muradov.business@gmail.com
- β Star this repo if you find it useful!
- π¦ Follow for updates: orkhan-muradov-dev
- π£ Share with others who might benefit
When reporting bugs, please include:
- Operating system and version
- Qt version
- Steps to reproduce
- Expected vs actual behavior
- Screenshots if applicable
Example (Click to expand)
**Environment:** - OS: Ubuntu 22.04 LTS - Qt: 6.5.0 - Compiler: GCC 11.3.0 **Steps:** 1. Load file with 1000+ lines 2. Search for "test" 3. Click "Find Next" rapidly **Expected:** Smooth navigation **Actual:** UI freezes for 2 seconds **Screenshots:** [attached] This project is built on the shoulders of giants:
- Qt Project - Exceptional cross-platform framework
- PCRE2 - Powerful regex engine
- CMake - Build system that doesn't make you cry
- Keep a Changelog - Changelog format
- Semantic Versioning - Version numbering scheme
Special thanks to:
- All contributors
- Everyone who reports bugs and suggests features
- The Qt and C++ communities for endless learning resources
Made with β€οΈ by Orkhan Muradov
If this project helped you, consider giving it a β!
Report Bug β’ Request Feature β’ Contribute



