From f8a008a105e9581ede73b68f58498f1432a2cb26 Mon Sep 17 00:00:00 2001 From: Moritz Martinius Date: Mon, 13 Oct 2025 21:00:16 +0200 Subject: [PATCH] Reorganize folders, interface for both cli parser and core module --- src/PrinterDriverFactory.hpp | 2 +- src/PtouchPrint.cpp | 11 ++- src/PtouchPrint.hpp | 23 ++++-- src/cli/CliParser.cpp | 9 ++- src/cli/CliParser.hpp | 37 +++------- src/cli/interface/ICliParser.hpp | 73 ++++++++++++++++++ src/core/PrinterService.hpp | 20 ++--- src/core/interface/IPrinterService.hpp | 74 +++++++++++++++++++ src/libusbwrap/interface/IUsbDevice.hpp | 6 +- src/printers/FakePrinter.hpp | 4 +- src/printers/P700Printer.hpp | 8 +- .../interface/IPrinterDriver.hpp | 10 +-- .../interface/IPrinterTypes.hpp | 0 13 files changed, 213 insertions(+), 64 deletions(-) create mode 100644 src/cli/interface/ICliParser.hpp create mode 100644 src/core/interface/IPrinterService.hpp rename src/{ => printers}/interface/IPrinterDriver.hpp (90%) rename src/{ => printers}/interface/IPrinterTypes.hpp (100%) diff --git a/src/PrinterDriverFactory.hpp b/src/PrinterDriverFactory.hpp index a20cd7b..9cec0eb 100644 --- a/src/PrinterDriverFactory.hpp +++ b/src/PrinterDriverFactory.hpp @@ -21,7 +21,7 @@ #include #include -#include "interface/IPrinterDriver.hpp" +#include "printers/interface/IPrinterDriver.hpp" #include "libusbwrap/LibUsbTypes.hpp" namespace ptprnt { diff --git a/src/PtouchPrint.cpp b/src/PtouchPrint.cpp index bff590f..a58ffdb 100644 --- a/src/PtouchPrint.cpp +++ b/src/PtouchPrint.cpp @@ -25,16 +25,21 @@ #include "PrinterDriverFactory.hpp" #include "cli/CliParser.hpp" +#include "cli/interface/ICliParser.hpp" #include "constants.hpp" #include "core/PrinterService.hpp" +#include "core/interface/IPrinterService.hpp" #include "graphics/LabelBuilder.hpp" namespace ptprnt { PtouchPrint::PtouchPrint(const char* versionString) - : mVersionString(versionString), - mCliParser(std::make_unique(ptprnt::APP_DESC, versionString)), - mPrinterService(std::make_unique()) {} + : PtouchPrint(versionString, std::make_unique(ptprnt::APP_DESC, versionString), + std::make_unique()) {} + +PtouchPrint::PtouchPrint(const char* versionString, std::unique_ptr cliParser, + std::unique_ptr printerService) + : mVersionString(versionString), mCliParser(std::move(cliParser)), mPrinterService(std::move(printerService)) {} PtouchPrint::~PtouchPrint() = default; diff --git a/src/PtouchPrint.hpp b/src/PtouchPrint.hpp index 2c4b420..38c5c97 100644 --- a/src/PtouchPrint.hpp +++ b/src/PtouchPrint.hpp @@ -23,11 +23,11 @@ #include namespace ptprnt::cli { -class CliParser; +class ICliParser; } namespace ptprnt::core { -class PrinterService; +class IPrinterService; } namespace ptprnt { @@ -37,14 +37,27 @@ namespace ptprnt { * * Acts as a thin glue layer coordinating CLI parsing and core printer functionality. * Separates CLI frontend concerns from the core library. + * + * Uses interfaces (ICliParser, IPrinterService) to enable dependency injection + * and facilitate unit testing with mocks. */ class PtouchPrint { public: /** - * @brief Construct the application + * @brief Construct the application with default implementations * @param versionString Version string to display */ PtouchPrint(const char* versionString); + + /** + * @brief Construct with custom implementations (for testing) + * @param versionString Version string to display + * @param cliParser Custom CLI parser implementation + * @param printerService Custom printer service implementation + */ + PtouchPrint(const char* versionString, std::unique_ptr cliParser, + std::unique_ptr printerService); + ~PtouchPrint(); // Must be defined in .cpp where complete types are visible // This is basically a singleton application class, no need to copy or move @@ -73,8 +86,8 @@ class PtouchPrint { bool handlePrinting(); std::string mVersionString; - std::unique_ptr mCliParser; - std::unique_ptr mPrinterService; + std::unique_ptr mCliParser; + std::unique_ptr mPrinterService; }; } // namespace ptprnt diff --git a/src/cli/CliParser.cpp b/src/cli/CliParser.cpp index 318f567..275b1b3 100644 --- a/src/cli/CliParser.cpp +++ b/src/cli/CliParser.cpp @@ -23,8 +23,8 @@ namespace ptprnt::cli { -CliParser::CliParser(const std::string& appDescription, std::string versionString) - : mApp(appDescription), mVersionString(std::move(versionString)) { +CliParser::CliParser(std::string appDescription, std::string versionString) + : mApp(std::move(appDescription)), mVersionString(std::move(versionString)) { setupParser(); } @@ -67,8 +67,9 @@ void CliParser::setupParser() { // Text printing options // Note: CLI11 options are processed in order when using ->each() with callbacks - mApp.add_option("-t,--text", - "Text to print (can be used multiple times, use formatting options before to influence text layout)") + mApp.add_option( + "-t,--text", + "Text to print (can be used multiple times, use formatting options before to influence text layout)") ->multi_option_policy(CLI::MultiOptionPolicy::TakeAll) ->each([this](const std::string& text) { mOptions.commands.emplace_back(CommandType::Text, text); }); diff --git a/src/cli/CliParser.hpp b/src/cli/CliParser.hpp index 148b4a3..d4b83cd 100644 --- a/src/cli/CliParser.hpp +++ b/src/cli/CliParser.hpp @@ -22,47 +22,28 @@ #include #include -#include + +#include "interface/ICliParser.hpp" namespace ptprnt::cli { -/** - * @brief Types of CLI commands that can be issued - */ -enum class CommandType { None = 0, Text = 1, FontSize = 2, Font = 3, VAlign = 4, HAlign = 5 }; - -/** - * @brief A command with its type and value - */ -using Command = std::pair; - -/** - * @brief Parsed CLI options and commands - */ -struct CliOptions { - bool verbose{false}; - bool trace{false}; - bool listDrivers{false}; - std::string printerSelection{"auto"}; - std::vector commands{}; -}; - /** * @brief CLI argument parser for ptprnt * - * Handles all command-line argument parsing using CLI11. + * Concrete implementation of ICliParser using CLI11. + * Handles all command-line argument parsing. * Separates CLI concerns from core library functionality. */ -class CliParser { +class CliParser : public ICliParser { public: /** * @brief Construct a CLI parser * @param appDescription Application description for help text * @param versionString Version string to display */ - CliParser(const std::string& appDescription, std::string versionString); + CliParser(std::string appDescription, std::string versionString); - ~CliParser() = default; + ~CliParser() override = default; CliParser(const CliParser&) = delete; CliParser& operator=(const CliParser&) = delete; @@ -75,13 +56,13 @@ class CliParser { * @param argv Argument values * @return 0 on success, positive value if should exit immediately (help/version), negative on error */ - int parse(int argc, char** argv); + int parse(int argc, char** argv) override; /** * @brief Get the parsed options * @return Reference to parsed options */ - [[nodiscard]] const CliOptions& getOptions() const { return mOptions; } + [[nodiscard]] const CliOptions& getOptions() const override { return mOptions; } private: void setupParser(); diff --git a/src/cli/interface/ICliParser.hpp b/src/cli/interface/ICliParser.hpp new file mode 100644 index 0000000..aa1b278 --- /dev/null +++ b/src/cli/interface/ICliParser.hpp @@ -0,0 +1,73 @@ +/* + ptrnt - print labels on linux + Copyright (C) 2025 Moritz Martinius + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + */ + +#pragma once + +#include +#include + +namespace ptprnt::cli { + +/** + * @brief Types of CLI commands that can be issued + */ +enum class CommandType { None = 0, Text = 1, FontSize = 2, Font = 3, VAlign = 4, HAlign = 5 }; + +/** + * @brief A command with its type and value + */ +using Command = std::pair; + +/** + * @brief Parsed CLI options and commands + */ +struct CliOptions { + bool verbose{false}; + bool trace{false}; + bool listDrivers{false}; + std::string printerSelection{"auto"}; + std::vector commands{}; +}; + +/** + * @brief Interface for CLI argument parsing + * + * This interface allows for mocking CLI parsing in unit tests + * and provides a clear contract for CLI parser implementations. + */ +class ICliParser { + public: + virtual ~ICliParser() = default; + + /** + * @brief Parse command line arguments + * @param argc Argument count + * @param argv Argument values + * @return 0 on success, positive value if should exit immediately (help/version), negative on error + */ + virtual int parse(int argc, char** argv) = 0; + + /** + * @brief Get the parsed options + * @return Reference to parsed options + */ + [[nodiscard]] virtual const CliOptions& getOptions() const = 0; +}; + +} // namespace ptprnt::cli diff --git a/src/core/PrinterService.hpp b/src/core/PrinterService.hpp index 142e82a..0d96921 100644 --- a/src/core/PrinterService.hpp +++ b/src/core/PrinterService.hpp @@ -23,23 +23,25 @@ #include #include -#include "interface/IPrinterDriver.hpp" -#include "libusbwrap/UsbDeviceFactory.hpp" +#include "../printers/interface/IPrinterDriver.hpp" +#include "interface/IPrinterService.hpp" +#include "../libusbwrap/UsbDeviceFactory.hpp" namespace ptprnt::core { /** * @brief Core service for printer operations * + * Concrete implementation of IPrinterService. * Provides the core library functionality for: * - Detecting printers * - Selecting printers * - Building and printing labels */ -class PrinterService { +class PrinterService : public IPrinterService { public: PrinterService(); - ~PrinterService() = default; + ~PrinterService() override = default; PrinterService(const PrinterService&) = delete; PrinterService& operator=(const PrinterService&) = delete; @@ -50,33 +52,33 @@ class PrinterService { * @brief Initialize USB device factory * @return true on success, false on failure */ - bool initialize(); + bool initialize() override; /** * @brief Detect all compatible printers * @return Vector of detected printers */ - std::vector> detectPrinters(); + std::vector> detectPrinters() override; /** * @brief Select a printer by name or auto-detect * @param printerName Printer driver name, or "auto" for first detected * @return Printer driver, or nullptr if not found */ - std::shared_ptr selectPrinter(const std::string& printerName); + std::shared_ptr selectPrinter(const std::string& printerName) override; /** * @brief Get the currently selected printer * @return Current printer, or nullptr if none selected */ - [[nodiscard]] std::shared_ptr getCurrentPrinter() const { return mCurrentPrinter; } + [[nodiscard]] std::shared_ptr getCurrentPrinter() const override { return mCurrentPrinter; } /** * @brief Print a label * @param label The label to print * @return true on success, false on failure */ - bool printLabel(std::unique_ptr label); + bool printLabel(std::unique_ptr label) override; private: libusbwrap::UsbDeviceFactory mUsbDeviceFactory; diff --git a/src/core/interface/IPrinterService.hpp b/src/core/interface/IPrinterService.hpp new file mode 100644 index 0000000..b8ba5d9 --- /dev/null +++ b/src/core/interface/IPrinterService.hpp @@ -0,0 +1,74 @@ +/* + ptrnt - print labels on linux + Copyright (C) 2025 Moritz Martinius + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + */ + +#pragma once + +#include +#include +#include + +#include "../../printers/interface/IPrinterDriver.hpp" +#include "../../graphics/interface/ILabel.hpp" + +namespace ptprnt::core { + +/** + * @brief Interface for core printer service operations + * + * This interface allows for mocking printer operations in unit tests + * and provides a clear contract for printer service implementations. + */ +class IPrinterService { + public: + virtual ~IPrinterService() = default; + + /** + * @brief Initialize the printer service + * @return true on success, false on failure + */ + virtual bool initialize() = 0; + + /** + * @brief Detect all compatible printers + * @return Vector of detected printers + */ + virtual std::vector> detectPrinters() = 0; + + /** + * @brief Select a printer by name or auto-detect + * @param printerName Printer driver name, or "auto" for first detected + * @return Printer driver, or nullptr if not found + */ + virtual std::shared_ptr selectPrinter(const std::string& printerName) = 0; + + /** + * @brief Get the currently selected printer + * @return Current printer, or nullptr if none selected + */ + [[nodiscard]] virtual std::shared_ptr getCurrentPrinter() const = 0; + + /** + * @brief Print a label + * @param label The label to print + * @return true on success, false on failure + */ + virtual bool printLabel(std::unique_ptr label) = 0; +}; + +} // namespace ptprnt::core diff --git a/src/libusbwrap/interface/IUsbDevice.hpp b/src/libusbwrap/interface/IUsbDevice.hpp index fe80de7..c72d949 100644 --- a/src/libusbwrap/interface/IUsbDevice.hpp +++ b/src/libusbwrap/interface/IUsbDevice.hpp @@ -22,7 +22,6 @@ #include #include -#include #include #include @@ -44,8 +43,9 @@ enum class Speed { class IUsbDevice { public: virtual ~IUsbDevice() = default; - virtual bool open() = 0; - virtual void close() = 0; + + virtual bool open() = 0; + virtual void close() = 0; // libusb wrappers virtual bool detachKernelDriver(int interfaceNo) = 0; diff --git a/src/printers/FakePrinter.hpp b/src/printers/FakePrinter.hpp index 12cd1ff..ba4f3d9 100644 --- a/src/printers/FakePrinter.hpp +++ b/src/printers/FakePrinter.hpp @@ -23,8 +23,8 @@ #include #include -#include "../interface/IPrinterDriver.hpp" -#include "../interface/IPrinterTypes.hpp" +#include "interface/IPrinterDriver.hpp" +#include "interface/IPrinterTypes.hpp" #include "../libusbwrap/LibUsbTypes.hpp" #include "../libusbwrap/interface/IUsbDevice.hpp" #include "../graphics/Bitmap.hpp" diff --git a/src/printers/P700Printer.hpp b/src/printers/P700Printer.hpp index e14f500..855915e 100644 --- a/src/printers/P700Printer.hpp +++ b/src/printers/P700Printer.hpp @@ -17,6 +17,8 @@ */ +#pragma once + #include #include @@ -25,10 +27,8 @@ #include "interface/IPrinterDriver.hpp" #include "interface/IPrinterTypes.hpp" -#include "libusbwrap/LibUsbTypes.hpp" -#include "libusbwrap/interface/IUsbDevice.hpp" - -#pragma once +#include "../libusbwrap/LibUsbTypes.hpp" +#include "../libusbwrap/interface/IUsbDevice.hpp" namespace ptprnt::printer { namespace p700::commands { diff --git a/src/interface/IPrinterDriver.hpp b/src/printers/interface/IPrinterDriver.hpp similarity index 90% rename from src/interface/IPrinterDriver.hpp rename to src/printers/interface/IPrinterDriver.hpp index 48106fb..485b7d9 100644 --- a/src/interface/IPrinterDriver.hpp +++ b/src/printers/interface/IPrinterDriver.hpp @@ -22,11 +22,11 @@ #include #include -#include "graphics/Bitmap.hpp" -#include "graphics/Monochrome.hpp" -#include "graphics/interface/ILabel.hpp" -#include "interface/IPrinterTypes.hpp" -#include "libusbwrap/interface/IUsbDevice.hpp" +#include "../../graphics/Bitmap.hpp" +#include "../../graphics/Monochrome.hpp" +#include "../../graphics/interface/ILabel.hpp" +#include "../../libusbwrap/interface/IUsbDevice.hpp" +#include "IPrinterTypes.hpp" namespace ptprnt { class IPrinterDriver { diff --git a/src/interface/IPrinterTypes.hpp b/src/printers/interface/IPrinterTypes.hpp similarity index 100% rename from src/interface/IPrinterTypes.hpp rename to src/printers/interface/IPrinterTypes.hpp