add cups printing function
Some checks failed
build_test / build (push) Failing after 1m45s

This commit is contained in:
PoliEcho 2025-04-14 14:50:04 +02:00
parent 8338b7fdc8
commit 2f2ec79575
3 changed files with 200 additions and 2 deletions

View File

@ -1,7 +1,7 @@
# Compiler and flags
CPPC = g++
CPPC_FLAGS = -std=c++23 -s -O3 -Wall -Wextra -Wno-write-strings -lncurses -lmenu -lform
DEBUG_FLAGS = -ggdb -std=c++23 -Wall -Wextra -Wno-write-strings -lncurses -lmenu -lform
CPPC_FLAGS = -std=c++23 -s -O3 -Wall -Wextra -Wno-write-strings -lncurses -lmenu -lform -lcups
DEBUG_FLAGS = -ggdb -std=c++23 -Wall -Wextra -Wno-write-strings -lncurses -lmenu -lform -lcups
SRC_PATH := src

189
src/cups.cpp Normal file
View File

@ -0,0 +1,189 @@
#include <cups/cups.h>
#include <menu.h>
#include <ncurses.h>
#include <cstring>
#include <fstream>
#include <string>
#include <vector>
/**
* Displays a menu of available printers and prints content to the selected one
* @param content The text content to print
* @return true if printing was successful, false otherwise
*/
bool printDocument(const std::string& content) {
// Initialize variables
bool success = false;
cups_dest_t* dests = nullptr;
int num_dests = 0;
ITEM** menu_items = nullptr;
MENU* menu = nullptr;
WINDOW* menu_win = nullptr;
std::vector<char*> item_names;
std::vector<char*> item_descriptions;
// Write content to a temporary file
std::string tempFileName = "/tmp/print_temp_ParaDocs.txt";
std::ofstream tempFile(tempFileName);
if (!tempFile) {
return false; // Failed to create temp file
}
tempFile << content;
tempFile.close();
// Get printer destinations from CUPS
num_dests = cupsGetDests(&dests);
if (num_dests <= 0) {
remove(tempFileName.c_str());
return false; // No printers available
}
// Initialize ncurses
initscr();
start_color();
cbreak();
noecho();
keypad(stdscr, TRUE);
try {
// Allocate memory for menu items
menu_items = new ITEM*[num_dests + 1];
// Prepare menu items for each printer
for (int i = 0; i < num_dests; i++) {
// Create display name
std::string display_name;
if (dests[i].instance) {
display_name = std::string(dests[i].name) + "/" + dests[i].instance;
} else {
display_name = dests[i].name;
}
// Allocate memory for name string
char* name_str = new char[display_name.length() + 1];
std::strcpy(name_str, display_name.c_str());
item_names.push_back(name_str);
// Get description if available
const char* desc =
cupsGetOption("printer-info", dests[i].num_options, dests[i].options);
std::string description = desc ? desc : "";
// Allocate memory for description string
char* desc_str = new char[description.length() + 1];
std::strcpy(desc_str, description.c_str());
item_descriptions.push_back(desc_str);
// Create menu item
menu_items[i] = new_item(name_str, desc_str);
if (!menu_items[i]) {
throw std::runtime_error("Failed to create menu item");
}
}
menu_items[num_dests] = nullptr; // NULL-terminate the array
// Create the menu
menu = new_menu(menu_items);
if (!menu) {
throw std::runtime_error("Failed to create menu");
}
// Set up menu window
int rows, cols;
getmaxyx(stdscr, rows, cols);
menu_win = newwin(rows - 4, cols - 4, 2, 2);
keypad(menu_win, TRUE);
// Set menu window and sub window
set_menu_win(menu, menu_win);
set_menu_sub(menu, derwin(menu_win, rows - 6, cols - 6, 1, 1));
set_menu_format(menu, rows - 8, 1);
set_menu_mark(menu, " * ");
// Post the menu with instructions
mvprintw(0, 0, "Select a printer and press Enter:");
mvprintw(rows - 2, 0, "Press q to cancel");
refresh();
post_menu(menu);
wrefresh(menu_win);
// Menu interaction loop
int c;
while ((c = wgetch(menu_win)) != 'q') {
switch (c) {
case KEY_DOWN:
menu_driver(menu, REQ_DOWN_ITEM);
break;
case KEY_UP:
menu_driver(menu, REQ_UP_ITEM);
break;
case 10: // Enter key
{
ITEM* cur = current_item(menu);
int index = item_index(cur);
// Print the document to the selected printer
int job_id =
cupsPrintFile(dests[index].name, tempFileName.c_str(),
"Document from application",
dests[index].num_options, dests[index].options);
if (job_id > 0) {
success = true;
mvprintw(rows - 1, 0, "Printing job %d submitted successfully",
job_id);
} else {
mvprintw(rows - 1, 0, "Error: %s", cupsLastErrorString());
}
refresh();
napms(2000); // Display message for 2 seconds
c = 'q'; // Exit the loop
goto exit_menu;
break;
}
}
wrefresh(menu_win);
}
} catch (const std::exception& e) {
mvprintw(0, 0, "Error: %s", e.what());
refresh();
napms(2000);
}
exit_menu:
// Clean up resources
if (menu) {
unpost_menu(menu);
free_menu(menu);
}
if (menu_items) {
for (int i = 0; i < num_dests && menu_items[i]; i++) {
free_item(menu_items[i]);
}
delete[] menu_items;
}
// Free allocated strings
for (char* str : item_names) {
delete[] str;
}
for (char* str : item_descriptions) {
delete[] str;
}
if (menu_win) {
delwin(menu_win);
}
// End ncurses
endwin();
// Remove temp file
remove(tempFileName.c_str());
// Free CUPS destinations
cupsFreeDests(num_dests, dests);
return success;
}

9
src/cups.h Normal file
View File

@ -0,0 +1,9 @@
#include <string>
#ifndef PARADOCS_CUPS_H_
#define PARADOCS_CUPS_H_
bool printDocument(const std::string& content);
#endif