diff --git a/README.md b/README.md index a74f4f7..55ce9fc 100644 --- a/README.md +++ b/README.md @@ -1,218 +1,319 @@ ![QDiffX Demo](assets/qdiffx_demo.svg) -# QDiffX -## The Diff Widget Qt Should Have Built +### The Diff Widget Qt Should Have Built -**QDiffX** is a plug-and-play **diff visualization widget for Qt applications**, designed to make content comparison effortless and native. Whether you're building a file manager, a version control GUI, a config editor, or an IDE QDiffX brings a clean, intuitive diff viewer directly into your Qt interface, no web views or external dependencies required. +**QDiffX** is a lightweight, extensible **diff viewer widget for Qt**. +It is designed to be dropped into existing Qt applications without web views, heavy dependencies, or complex setup. -**Finally.** A production-ready, drop-in diff visualization widget for Qt applications. Because handling file conflicts shouldn't require reinventing the wheel. +The project focuses on two core ideas: +- A **clean, usable diff UI** (inline and side-by-side) +- A **pluggable algorithm system** so diff logic stays flexible and replaceable +- **Synchronous and asynchronous execution** for both responsive UIs and immediate results +--- -## Why QDiffX Changes Everything +## What It Is -**Qt developers have been waiting for this.** Every file manager, code editor, version control GUI, and configuration tool needs diff visualization. Until now, you had to build it from scratch or compromise with web-based solutions. +- A ready-to-use **Qt Widgets diff component** +- Supports **side-by-side** and **inline** diff views +- Built with **Qt Widgets** (Qt 5.15+ and Qt 6.x) +- Written in **C++17** +- Can be embedded or extended easily -**QDiffX ends that pain.** +This is meant to be infrastructure something you don't have to rewrite for every Qt project. --- -## Perfect For +## Typical Use Cases -* **πŸ“ File Managers** Show users exactly what changed when files conflict -* **βš™οΈ Configuration Tools** Let users merge settings intelligently -* **πŸ”§ Development IDEs** Built-in diff without external dependencies -* **πŸ“Š Database GUIs** (Redis, MongoDB tools) - Compare configurations -* **🏒 Business Tools** Solid diff widget in your Qt stack +- File managers and sync tools +- IDEs and code editors +- Configuration and settings comparison +- Database and DevOps tools +- Any Qt application that needs to show "what changed" --- -## What Makes It Special - +## Quick Example ```cpp -// Literally this simple #include "QDiffWidget.h" -QDiffX::QDiffWidget* diff = new QDiffX::QDiffWidget(); -diff->setLeftContent(originalFile); -diff->setRightContent(modifiedFile); +auto* diff = new QDiffX::QDiffWidget(this); +diff->setLeftContent(originalText); +diff->setRightContent(modifiedText); layout->addWidget(diff); -// Done. Ready to use. ``` -Built with a pluggable algorithm architecture: write a bridge for your algorithm, register it, and integrate directly. + +That's it the widget handles rendering, scrolling, and highlighting. + --- +## Display Modes +```cpp +// Side-by-side (default) +diff->setDisplayMode(QDiffX::QDiffWidget::SideBySide); -## The Problem It Solves +// Inline +diff->setDisplayMode(QDiffX::QDiffWidget::Inline); +``` -Every Qt developer has faced this: +--- -* ❌ User opens a file that changed on disk -* ❌ Application needs to show differences -* ❌ No built-in Qt solution exists -* ❌ Weeks spent building custom diff logic -* ❌ Inconsistent UX across applications -* ❌ Integration of heavy diffing algorithms like myers can be overkill sometimes and takes huge time and effort +## Algorithm Plugin System -**QDiffX eliminates this entirely.** +QDiffX cleanly separates diff visualization from diff algorithms. +Algorithms are implemented as small, self-contained classes and registered with the system. -## πŸ› οΈ Installation +### Why This Matters -### Quick Start +- Swap algorithms without touching UI code +- Use simple algorithms for small files +- Plug in advanced algorithms for large or structured content +- Easy to experiment or customize behavior -```bash -git clone https://github.com/yourusername/QDiffX.git -cmake -S QDiffX -B QDiffX/build -cmake --build QDiffX/build -# Run the demo app from the build output +### Adding a New Algorithm + +1. Create a class that inherits from `QDiffX::QDiffAlgorithm` +2. Implement: + - `calculateDiff(...)` + - `getName()` + - `getDescription()` +3. Register it with the algorithm manager or registry +```cpp +registry.registerAlgorithm( + std::make_shared() +); ``` -### CMake Integration (embed the widget) +Once registered, the algorithm appears in the UI automatically and can be selected at runtime. -```cmake -# Add QDiffX as a subproject -add_subdirectory(QDiffX) +--- -# Add widget sources to your target and link core library -target_sources(your_target PRIVATE - QDiffX/src/QDiffWidget.cpp - QDiffX/src/QDiffTextBrowser.cpp - QDiffX/src/QLineNumberArea.cpp -) -target_include_directories(your_target PRIVATE ${CMAKE_SOURCE_DIR}/QDiffX/src) -target_link_libraries(your_target PRIVATE - QDiffXCore - Qt${QT_VERSION_MAJOR}::Core - Qt${QT_VERSION_MAJOR}::Widgets -) +## Algorithm Management +```cpp +auto* manager = new QDiffX::QAlgorithmManager(diff); +manager->setSelectionMode(QDiffX::QAlgorithmSelectionMode::Auto); +diff->setAlgorithmManager(manager); ``` -### qmake Integration - -Not supported yet (planned). +Manual selection is also supported if a specific algorithm is required. --- -## Use Cases That Work +### Algorithm Capabilities -1. **File Sync Apps** When Dropbox meets Qt -2. **Configuration Managers** Docker Compose, Kubernetes configs -3. **Database Tools** Redis config comparisons, SQL migrations -4. **Game Development** Asset version control, save file debugging -5. **IoT Dashboards** Device configuration drift detection +Each algorithm declares its capabilities: -### Basic Usage +- Support for large files +- Unicode and binary content support +- Line-by-line, character-by-character, or word-by-word diffing +- Maximum recommended file size +- Performance complexity estimation -```cpp -#include "QDiffWidget.h" +The algorithm manager uses these capabilities for intelligent automatic selection. + +--- -// Create the widget -auto* diffWidget = new QDiffX::QDiffWidget(this); +## Execution Modes -// Set content to compare -diffWidget->setLeftContent("Original content\nLine 2\nLine 3"); -diffWidget->setRightContent("Modified content\nLine 2 changed\nLine 3"); +QDiffX supports both synchronous and asynchronous diff calculation. -// Add to your layout -layout->addWidget(diffWidget); +### Asynchronous Execution (Recommended) +```cpp +manager->setExecutionMode(QDiffX::QExecutionMode::Asynchronous); + +auto future = manager->calculateDiffAsync(leftText, rightText); +// UI remains responsive while calculation runs in background ``` -### Display Modes +Connect to signals to receive results: +```cpp +connect(manager, &QDiffX::QAlgorithmManager::diffCalculated, + this, [](const QDiffX::QDiffResult& result) { + if (result.success()) { + // Use the result + } +}); +``` +### Synchronous Execution ```cpp -// Side-by-side (default) -diffWidget->setDisplayMode(QDiffX::QDiffWidget::DisplayMode::SideBySide); +manager->setExecutionMode(QDiffX::QExecutionMode::Synchronous); -// Inline -diffWidget->setDisplayMode(QDiffX::QDiffWidget::DisplayMode::Inline); +auto result = manager->calculateDiffSync(leftText, rightText); +if (result.success()) { + // Process immediately +} ``` -### Load From Files +--- + +## Error Handling + +QDiffX provides comprehensive error handling through typed error codes and detailed error messages. +### Error Types ```cpp -diffWidget->setContentFromFiles("/path/to/left.txt", "/path/to/right.txt"); +enum class QAlgorithmManagerError { + None, // No error + AlgorithmNotFound, // Requested algorithm doesn't exist + AlgorithmCreationFailed, // Failed to instantiate algorithm + InvalidAlgorithmId, // Invalid algorithm identifier + DiffExecutionFailed, // Algorithm execution failed + ConfigurationError, // Invalid algorithm configuration + Timeout, // Operation exceeded time limit + OperationCancelled, // User cancelled operation + Unknown // Unexpected error +}; ``` -### Algorithm Management +### Handling Errors +```cpp +auto result = manager->calculateDiffSync(leftText, rightText); + +if (!result.success()) { + QString error = result.errorMessage(); + qWarning() << "Diff failed:" << error; + + // Check specific error type + auto errorType = manager->lastError(); + if (errorType == QDiffX::QAlgorithmManagerError::AlgorithmNotFound) { + // Handle missing algorithm + } +} +``` +### Error Signals ```cpp -#include "QAlgorithmRegistry.h" -#include "QAlgorithmManager.h" -#include "DMPAlgorithm.h" +connect(manager, &QDiffX::QAlgorithmManager::errorOccurred, + this, [](QDiffX::QAlgorithmManagerError error, const QString& message) { + qCritical() << "Algorithm error:" << message; +}); +``` -// Register algorithm -QDiffX::QAlgorithmRegistry::get_Instance().registerAlgorithm("dmp"); +### Fallback Algorithm -// Configure manager -auto* manager = new QDiffX::QAlgorithmManager(diffWidget); -manager->setSelectionMode(QDiffX::QAlgorithmSelectionMode::Auto); -manager->setExecutionMode(QDiffX::QExecutionMode::Synchronous); -diffWidget->setAlgorithmManager(manager); +Configure a fallback algorithm for automatic recovery: +```cpp +manager->setCurrentAlgorithm("advanced-algorithm"); +manager->setFallBackAlgorithm("simple-algorithm"); -// Or manual selection -manager->setSelectionMode(QDiffX::QAlgorithmSelectionMode::Manual); -manager->setCurrentAlgorithm("dmp"); +// If advanced-algorithm fails, simple-algorithm is automatically tried ``` -### Supported Versions +--- -- Qt 5.15+ and Qt 6.x -- C++17 +## Thread Safety -## Contributing +QDiffX is designed with thread safety in mind: -Join the movement and help make QDiffX even better: +- Algorithm registry uses `QMutex` for concurrent access +- Algorithm manager supports asynchronous execution via `QFuture` +- Safe to call from multiple threads when using the registry +- UI updates are handled on the main thread -* **Bug Reports** Help us make it bulletproof -* **Feature Requests** What's your dream diff widget? -* **Code Contributions** Let's build the future of Qt together -* **Documentation** Help others discover the power +--- -- Pull requests automatically trigger cross‑platform builds and tests on Ubuntu, Windows, and macOS. -- CI installs a compatible Qt version, configures CMake with `BUILD_TESTING=ON`, builds, and runs `ctest`. -- Failing tests and build errors block merges to protected branches. -- Static analysis (`cppcheck`, `clang-tidy`) runs on Linux and reports are uploaded as artifacts. -- Release tags (`v*`) package build outputs per OS and publish them to GitHub Releases. -- See workflow configuration in `.github/workflows/build.yml`. +## Algorithm Configuration +Algorithms can be configured at runtime: +```cpp +// Get current configuration +auto config = manager->getAlgorithmConfiguration("dmp"); -### How to Contribute +// Modify settings +config["timeout"] = 5000; +config["checklines"] = true; -1. Fork the repository -2. Create a feature branch (`git checkout -b feature/X-feature`) -3. Make your changes -4. Commit your changes (`git commit -m 'Add X feature'`) -5. Push to the branch (`git push origin feature/X-feature`) -6. Open a Pull Request +// Apply new configuration +manager->setAlgorithmConfiguration("dmp", config); +``` +Configuration changes emit signals for reactive updates: +```cpp +connect(manager, &QDiffX::QAlgorithmManager::algorithmConfigurationChanged, + this, [](const QString& algorithmId, const QMap& config) { + qDebug() << "Algorithm" << algorithmId << "reconfigured"; +}); +``` +--- -### Upcoming Features -ideas that will be made in the future +## Side-by-Side Diff Results -- [ ] **Inline Editing** Edit differences directly in the widget -- [ ] **Directory Comparison** Compare entire folder structures -- [ ] **Advanced Merge Tools** Three-way merge support -- [ ] **More themes** -- [ ] **Better UI with customizable buttons** to handle different algorithms choice and inline / side-by-side directly from the widget -- [ ] **Smart algorithm choice learning system** can be trained as it is used to always pick the best possible algorithm depending on the file size and structure +QDiffX provides specialized support for side-by-side diffs: +```cpp +auto sideBySideResult = manager->calculateSideBySideDiffSync(leftText, rightText); + +if (sideBySideResult.success()) { + // Left side contains Equal + Delete operations + auto leftChanges = sideBySideResult.leftSide.changes(); + + // Right side contains Equal + Insert operations + auto rightChanges = sideBySideResult.rightSide.changes(); + + // Algorithm used for calculation + QString algorithm = sideBySideResult.algorithmUsed; +} +``` +--- -## License +## Metadata and Performance -This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. +Diff results include metadata for analysis: +```cpp +auto result = manager->calculateDiffSync(leftText, rightText); -### Testing +// Access metadata +auto metadata = result.allMetaData(); +int executionTime = metadata["executionTime"].toInt(); +QString algorithmUsed = metadata["algorithm"].toString(); +int changeCount = metadata["changeCount"].toInt(); +``` +--- +## Building ```bash -cmake -S . -B build +git clone https://github.com/yourusername/QDiffX.git +cmake -S QDiffX -B build cmake --build build -ctest --test-dir build --output-on-failure ``` +A demo application is included to test the widget and available algorithms. + +--- + +## Contributing + +Contributions are welcome and should be small and focused. + +**Key points:** +- Unit tests are required for new algorithms and logic changes +- Tests run automatically in CI +- Builds and tests run on Linux, Windows, and macOS +- Failing tests block merges to protected branches + +**If you add:** +- A new algorithm β†’ include tests +- A bug fix β†’ include a regression test + +This keeps the core stable and predictable. +--- + +## Roadmap +- Add More themes +- Direct editing +- Directory comparison +- Three-way merge +- Additional themes +- Smarter automatic algorithm selection +--- +## License -**⭐ Star this repository if QDiffX solves your Qt diff headaches!** +MIT License β€” see the [LICENSE](LICENSE) file for details.