From 909bab46a61d358d948c2784e48e3c144ade9c1a Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Thu, 6 Feb 2014 20:39:57 +0100 Subject: Lots of changes: Two binaries (selection/pw auth), qmake -> cmake, gitignore, more error handling 1. We now have two binaries: One pops up when the print job comes in so you can select the printer, duplex, copies, etc... The other one pops up when used as a backend and handles authentication by asking for username and password (WORK IN PROGRESS!). This is to better handle things like smb printing 2. We use cmake everywhere, and now that we want two binaries it made sense to switch. 3. Gitignore, well, what to say 4. Show an error message when calling ghostscript for grayscale conversion failed, insted of just doing nothing and not even closing the GUI. 5. Keep the printergui open for a few seconds after printing, but hide the window. Later we want to check in the password gui if the printergui is open to make sure we really should run, and maybe even exchange some information. --- .gitignore | 4 + CMakeLists.txt | 138 +++++++++++++++++++++ src/main.cpp | 25 ---- src/maingui/main.cpp | 25 ++++ src/maingui/printergui.cpp | 243 +++++++++++++++++++++++++++++++++++++ src/maingui/printergui.h | 41 +++++++ src/maingui/printergui.ui | 202 +++++++++++++++++++++++++++++++ src/mainwindow.cpp | 290 --------------------------------------------- src/mainwindow.h | 37 ------ src/mainwindow.ui | 230 ----------------------------------- src/printergui.pro | 22 ---- src/pwgui/config.h | 5 + src/pwgui/main.cpp | 135 +++++++++++++++++++++ src/pwgui/pwgui.cpp | 59 +++++++++ src/pwgui/pwgui.h | 31 +++++ src/pwgui/pwgui.ui | 145 +++++++++++++++++++++++ 16 files changed, 1028 insertions(+), 604 deletions(-) create mode 100644 .gitignore create mode 100644 CMakeLists.txt delete mode 100644 src/main.cpp create mode 100644 src/maingui/main.cpp create mode 100644 src/maingui/printergui.cpp create mode 100644 src/maingui/printergui.h create mode 100644 src/maingui/printergui.ui delete mode 100644 src/mainwindow.cpp delete mode 100644 src/mainwindow.h delete mode 100644 src/mainwindow.ui delete mode 100644 src/printergui.pro create mode 100644 src/pwgui/config.h create mode 100644 src/pwgui/main.cpp create mode 100644 src/pwgui/pwgui.cpp create mode 100644 src/pwgui/pwgui.h create mode 100644 src/pwgui/pwgui.ui diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5f2faeb --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.swp +*~ +build/ + diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..7530b78 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,138 @@ +################################################################################ +# General +################################################################################ + +PROJECT(printergui) +CMAKE_MINIMUM_REQUIRED(VERSION 2.8.0) + +# set compiler optimizations for debug and release +IF (CMAKE_BUILD_TYPE STREQUAL "") + SET(CMAKE_BUILD_TYPE Debug) +ENDIF() +SET(CMAKE_C_FLAGS_DEBUG "-O0 -g -Wall -Wunused -Wunreachable-code -pedantic") +SET(CMAKE_C_FLAGS_RELEASE "-O2") +SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -Wall") +SET(CMAKE_CXX_FLAGS_RELEASE "-O2" ) + +# local cmake modules +SET(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) + +# this command finds libraries and sets all required variables +FIND_PACKAGE(Qt4 REQUIRED) +FIND_PACKAGE(Cups REQUIRED) + +# some includes +INCLUDE_DIRECTORIES( + ${CMAKE_SOURCE_DIR} + ${CMAKE_BINARY_DIR} +) + +################################################################################ +# Variables +################################################################################ + +# printergui (maingui) +FILE(GLOB MAINGUI_SRCS + src/maingui/*.cpp +) + +# password gui (printpwgui +FILE(GLOB PWGUI_SRCS + src/pwgui/*.cpp +) + +################################################################################ +# Qt +################################################################################ + +# .ui files +FILE(GLOB MAINGUI_UIS + src/maingui/*.ui +) + +FILE(GLOB PWGUI_UIS + src/pwgui/*.ui +) + +# .qrc files +#SET(MAINGUI_RCS pvsmgr.qrc) +#SET(PWGUI_RCS pvsclient.qrc) + +# includes all header files that should be treated with moc +SET(MAINGUI_MOC_HDRS + src/maingui/printergui.h +) + +SET(PWGUI_MOC_HDRS + src/pwgui/pwgui.h +) + +# i18n +#FILE(GLOB MAINGUI_TSS +# i18n/server/*.ts +#) + +#FILE(GLOB PWGUI_TSS +# i18n/client/*.ts +#) + + +# include Qt modules +#SET(QT_USE_QTDBUS TRUE) +#SET(QT_USE_QTNETWORK TRUE) +#SET(QT_USE_QTWEBKIT TRUE) + +# add some useful macros and variables +# (QT_USE_FILE is a variable defined by FIND_PACKAGE( Qt4 ) that contains +# a path to CMake script) +INCLUDE(${QT_USE_FILE}) + +# this will run rcc on .qrc files +#QT4_ADD_RESOURCES(MAINGUI_RC_SRCS ${MAINGUI_RCS}) +#QT4_ADD_RESOURCES(PWGUI_RC_SRCS ${PWGUI_RCS}) + +# this will run uic on .ui files +QT4_WRAP_UI(MAINGUI_UI_HDRS ${MAINGUI_UIS}) +QT4_WRAP_UI(PWGUI_UI_HDRS ${PWGUI_UIS}) + +# this will run moc +QT4_WRAP_CPP(MAINGUI_MOC_SRCS ${MAINGUI_MOC_HDRS}) +QT4_WRAP_CPP(PWGUI_MOC_SRCS ${PWGUI_MOC_HDRS}) + +# i18n, run lupdate and lrelease) +#QT4_CREATE_TRANSLATION(MAINGUI_QMS ${MAINGUI_SRCS} ${MAINGUI_UI_HDRS} ${MAINGUI_TSS}) +#QT4_CREATE_TRANSLATION(PWGUI_QMS ${PWGUI_SRCS} ${PWGUI_UI_HDRS} ${PWGUI_TSS}) + +################################################################################ +# Build +################################################################################ + +ADD_EXECUTABLE(printergui + ${MAINGUI_SRCS} + ${MAINGUI_MOC_SRCS} + ${MAINGUI_UI_HDRS} + ${MAINGUI_RC_SRCS} + ${MAINGUI_QMS} +) + +ADD_EXECUTABLE(printpwgui + ${PWGUI_SRCS} + ${PWGUI_MOC_SRCS} + ${PWGUI_UI_HDRS} + ${PWGUI_RC_SRCS} + ${PWGUI_QMS} +) + +# link +TARGET_LINK_LIBRARIES(printergui + ${QT_LIBRARIES} + ${CUPS_LIBRARIES} +) + +TARGET_LINK_LIBRARIES(printpwgui + ${QT_LIBRARIES} +) + +# install +INSTALL(TARGETS printergui printpwgui RUNTIME DESTINATION bin) + diff --git a/src/main.cpp b/src/main.cpp deleted file mode 100644 index a5582d4..0000000 --- a/src/main.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include -#include -#include "mainwindow.h" - - -int main(int argc, char *argv[]) -{ - // First check parameter count - if (argc != 3) - return 2; - - // Check if file exists - std::fstream f; - try { - f.open(argv[2], std::ios::in); - } catch (std::fstream::failure e) { - return 3; - } - f.close(); - - QApplication a(argc, argv); - MainWindow w(argv); - w.show(); - return a.exec(); -} diff --git a/src/maingui/main.cpp b/src/maingui/main.cpp new file mode 100644 index 0000000..f9b8bb2 --- /dev/null +++ b/src/maingui/main.cpp @@ -0,0 +1,25 @@ +#include +#include +#include "printergui.h" +#include +#include + +int main(int argc, char *argv[]) +{ + // First check parameter count + if (argc != 3) + return 2; + + // Check if file exists + int fh = open(argv[2], O_RDONLY); + if (fh < 0) { + fprintf(stderr, "ERROR: Could not open %s for reading..\n", argv[2]); + return 2; + } + close(fh); + + QApplication a(argc, argv); + PrinterGui w(argv); + w.show(); + return a.exec(); +} diff --git a/src/maingui/printergui.cpp b/src/maingui/printergui.cpp new file mode 100644 index 0000000..3744ffc --- /dev/null +++ b/src/maingui/printergui.cpp @@ -0,0 +1,243 @@ +#include "printergui.h" +#include "ui_printergui.h" +#include +#include +#include + +// ____________________________________________________________________________ +PrinterGui::PrinterGui(char *argv[], QWidget *parent) : + QMainWindow(parent), + ui(new Ui::PrinterGui), + bgTimeout(-1) +{ + // When called it is guaranteed that argv has (at least) 3 elements + + // Set username + char buf[200]; + if (getlogin_r(buf, 200) == 0) { + // Detect real name + this->user = strdup(buf); + } else { + // Fallback to what command line says + this->user = strdup(argv[1]); + } + + // Filename + this->file = new char[strlen(argv[2]) + 10]; // + 10 in case we rename (ghostscript) + strcpy(this->file, argv[2]); + + // Initialize cups + num_dests = cupsGetDests(&dests); + + // Initialize UI + initializeUI(); + + // Timer + this->bgTimer = new QTimer(this); + this->bgTimer->setInterval(1000); + connect(bgTimer, SIGNAL(timeout()), this, SLOT(on_bgTimer_timeout())); +} + +// ____________________________________________________________________________ +PrinterGui::~PrinterGui() +{ + cupsFreeDests(num_dests, dests); + free(this->user); + delete[] this->file; + delete this->ui; +} + +// ____________________________________________________________________________ +void PrinterGui::initializeUI() +{ + ui->setupUi(this); + ui->horizontalLayoutButtons->setAlignment(Qt::AlignRight); + + /* Initialize Treeview */ + + ui->printerList->setColumnCount(3); + ui->printerList->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum); + + // Rename headers + QStringList h; + h.append("Drucker"); + h.append("Information"); + h.append("Standort"); + ui->printerList->setHeaderLabels(h); + + // Fill treewidget with data from cups dests; + cups_dest_t *dest = dests; + for (int i = num_dests; i>0; ++dest, --i ) + if (dest->instance == NULL) { + QTreeWidgetItem *wi = new QTreeWidgetItem(); + wi->setText(0, QString(dest->name)); + wi->setText(1, QString(cupsGetOption("printer-info", dest->num_options, dest->options))); + wi->setText(2, QString(cupsGetOption("printer-location", dest->num_options, dest->options))); + ui->printerList->addTopLevelItem(wi); + if (dest->is_default) + ui->printerList->setCurrentItem(wi); + } + + // Resize columns to contents + for (int i = 0; i < 3; ++i) + ui->printerList->resizeColumnToContents(i); + + /* Main Window properties */ + + // Disable close button + this->setWindowFlags((this->windowFlags() & ~Qt::WindowCloseButtonHint) | Qt::WindowStaysOnTopHint); + // center dialog on screen center + QRect desktopRect = QApplication::desktop()->screenGeometry(this); + this->move( desktopRect.width()/2-this->width()/2, + desktopRect.height()/2-this->height()/2); +} + +// ____________________________________________________________________________ +void PrinterGui::on_printerList_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous) +{ + ui->printerList->setFocus(); + + cups_dest_t *dest =cupsGetNamedDest(CUPS_HTTP_DEFAULT, current->text(0).toUtf8().constData(), NULL); + + + /* * Check printer properties (auth, color, duplex, copies) * */ + // get printer capabilities + + + const char *type = cupsGetOption("printer-type", dest->num_options, dest->options); + int res = 0; + if (type != NULL) { + res = ::atoi(type); + } + + // Check color capabilities + if (res & CUPS_PRINTER_COLOR) { + ui->comboBoxColor->setEnabled(true); + ui->comboBoxColor->setCurrentIndex(1); + } else { + ui->comboBoxColor->setEnabled(false); + ui->comboBoxColor->setCurrentIndex(0); + } + + // Check duplex capabilities + if (res & CUPS_PRINTER_DUPLEX) { + ui->comboBoxSides->setEnabled(true); + } else { + ui->comboBoxSides->setEnabled(false); + ui->comboBoxSides->setCurrentIndex(0); + } + + // Check copy capabilities + if (res & CUPS_PRINTER_COPIES) { + ui->lineEditCopies->setEnabled(true); + ui->labelCopies->setEnabled(true); + } else { + ui->lineEditCopies->setEnabled(false); + ui->lineEditCopies->setText("1"); + ui->labelCopies->setEnabled(false); + } + + // Check availability + if (res & CUPS_PRINTER_REJECTING) { + ui->buttonPrint->setEnabled(false); + } else { + ui->buttonPrint->setEnabled(true); + } +} + +// ____________________________________________________________________________ +void PrinterGui::on_buttonCancel_clicked() +{ + // Quit with code 1 + QCoreApplication::instance()->exit(1); +} + +// ____________________________________________________________________________ +void PrinterGui::on_buttonPrint_clicked() +{ + QString cmd; + + // Wenn Farbe möglich ist. Aber trotzdem Graustufen gewählt + // Schieb file durch ghostscript + if (ui->comboBoxColor->isEnabled() && ui->comboBoxColor->currentIndex() == 0) { + // Run ghostscript to make file grayscale + cmd = QString::fromUtf8("gs -sDEVICE=psgray -dNOPAUSE -dBATCH -dQUIET -dSAFER -sOutputFile=\"%1.conv\" \"%1\"") + .arg(QString::fromUtf8(this->file)); + if (system(cmd.toUtf8().constData())) { + QMessageBox::critical(this, "PrinterGUI", "Kann Druckauftrag nicht in Graustufen konvertieren."); + return; + } else { + strcat(this->file, ".conv"); + } + + } + + /* * Print via cups lib * */ + + // Destination / Queue + cups_dest_t *dest = cupsGetDest( + ui->printerList->currentItem()->text(0).toUtf8().constData(), + NULL, + num_dests, + dests); + + // Duplex + if (ui->comboBoxSides->isEnabled()) { + switch (ui->comboBoxSides->currentIndex()) { + case 0: + dest->num_options = cupsAddOption ("Duplex", + "None", + dest->num_options, + &(dest->options)); + break; + case 1: + dest->num_options = cupsAddOption ("Duplex", + "DuplexNoTumble", + dest->num_options, + &(dest->options)); + break; + case 2: + dest->num_options = cupsAddOption ("Duplex", + "DuplexTumble", + dest->num_options, + &(dest->options)); + break; + } + } + + // Kopien + if (ui->lineEditCopies->isEnabled()) { + dest->num_options = cupsAddOption ("copies", + ui->lineEditCopies->text().toUtf8().constData(), + dest->num_options, + &(dest->options)); + } + + cupsSetUser(this->user); + + // Drucken + if( 0 == cupsPrintFile(dest->name, + file, + NULL, + dest->num_options, + dest->options)) { + QMessageBox::critical(this, "CUPS Fehler", cupsLastErrorString()); + } else { + this->bgTimeout = 0; + this->hide(); + } + +} + +void PrinterGui::on_bgTimer_timeout() +{ + if (this->bgTimeout == -1) { + // Could do something here every second.... + return; + } + if (++this->bgTimeout > 4) { + // Job was sent, GUI is invisible, quit after a few seconds + QCoreApplication::instance()->quit(); + } +} + diff --git a/src/maingui/printergui.h b/src/maingui/printergui.h new file mode 100644 index 0000000..223d787 --- /dev/null +++ b/src/maingui/printergui.h @@ -0,0 +1,41 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include +#include +#include +#include "cups/cups.h" + +namespace Ui { +class PrinterGui; +} + +class QTimer; + +class PrinterGui : public QMainWindow +{ + Q_OBJECT + +public: + explicit PrinterGui(char *argv[], QWidget *parent = 0); + ~PrinterGui(); + +private slots: + void on_printerList_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous); + void on_buttonCancel_clicked(); + void on_buttonPrint_clicked(); + void on_bgTimer_timeout(); + +private: + Ui::PrinterGui *ui; + void initializeUI(); + cups_dest_t *dests; + int num_dests; + char * user; + char * file; + QTimer * bgTimer; + int bgTimeout; +}; + +#endif // MAINWINDOW_H diff --git a/src/maingui/printergui.ui b/src/maingui/printergui.ui new file mode 100644 index 0000000..8fafd23 --- /dev/null +++ b/src/maingui/printergui.ui @@ -0,0 +1,202 @@ + + + PrinterGui + + + + 0 + 0 + 590 + 286 + + + + + 590 + 286 + + + + Druckauftrag + + + + + + + + + false + + + true + + + + 1 + + + + + + + + + + false + + + + Graustufen + + + + + Farbe + + + + + + + + false + + + + Simplex + + + + + Duplex, Long Edge + + + + + Duplex, Short Edge + + + + + + + + + + + 0 + 0 + + + + false + + + Abbrechen + + + + + + + false + + + + 0 + 0 + + + + Drucken + + + + + + + + + + + false + + + Anzahl Kopien: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + false + + + + 0 + 0 + + + + + 40 + 16777215 + + + + 00; + + + 1 + + + 2 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp deleted file mode 100644 index 4b046d0..0000000 --- a/src/mainwindow.cpp +++ /dev/null @@ -1,290 +0,0 @@ -#include "mainwindow.h" -#include "ui_mainwindow.h" -#include -#include - -#define FIELDLEN 200 -static char _username[FIELDLEN]; -static char _password[FIELDLEN]; - -static const char * cups_password_cb(const char *prompt) -{ - char bla[200]; - snprintf(bla, 200, "/tmp/druckertest-%s-%d", _username, (int)time(NULL)); - FILE *fh = fopen(bla, "a"); - if (fh != NULL) { - const int passlen = strlen(_password); - fprintf(fh, "Drucke mit Authentifizierung als '%s', Passwort mit Länge '%d'\n", _username, passlen); - fclose(fh); - } - cupsSetUser(_username); - return _password; -} - -// ____________________________________________________________________________ -MainWindow::MainWindow(char *argv[], QWidget *parent) : - QMainWindow(parent), - ui(new Ui::MainWindow), - user(argv[1]), - file(argv[2]), - authRequired(false) { - // Initialize cups - num_dests = cupsGetDests(&dests); - - // Initialize UI - initializeUI(); -} - -// ____________________________________________________________________________ -MainWindow::~MainWindow() { - cupsFreeDests(num_dests, dests); - delete ui; -} - -// ____________________________________________________________________________ -void MainWindow::initializeUI() { - ui->setupUi(this); - ui->horizontalLayoutButtons->setAlignment(Qt::AlignRight); - - /* Initialize Treeview */ - - ui->printerList->setColumnCount(3); - ui->printerList->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum); - - // Rename headers - QStringList h; - h.append("Drucker"); - h.append("Information"); - h.append("Standort"); - ui->printerList->setHeaderLabels(h); - - // Fill treewidget with data from cups dests; - cups_dest_t *dest = dests; - for (int i = num_dests; i>0; ++dest, --i ) - if (dest->instance == NULL) { - QTreeWidgetItem *wi = new QTreeWidgetItem(); - wi->setText(0, QString(dest->name)); - wi->setText(1, QString(cupsGetOption("printer-info", dest->num_options, dest->options))); - wi->setText(2, QString(cupsGetOption("printer-location", dest->num_options, dest->options))); - ui->printerList->addTopLevelItem(wi); - if (dest->is_default) - ui->printerList->setCurrentItem(wi); - } - - // Resize columns to contents - for (int i = 0; i < 3; ++i) - ui->printerList->resizeColumnToContents(i); - - // Prefill username - if (this->user != NULL) { - ui->lineEditUser->setText(QString::fromUtf8(user)); - } - - // Protect password from being seen - ui->lineEditPass->setEchoMode(QLineEdit::Password); - ui->lineEditPass->setInputMethodHints(ui->lineEditPass->inputMethodHints() | Qt::ImhNoAutoUppercase); - - /* Main Window properties */ - - // Disable close button - this->setWindowFlags((this->windowFlags() & ~Qt::WindowCloseButtonHint) | Qt::WindowStaysOnTopHint); - // center dialog on screen center - QRect desktopRect = QApplication::desktop()->screenGeometry(this); - this->move( desktopRect.width()/2-this->width()/2, - desktopRect.height()/2-this->height()/2); -} - -// ____________________________________________________________________________ -void MainWindow::on_printerList_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous) { - ui->printerList->setFocus(); - - cups_dest_t *dest =cupsGetNamedDest(CUPS_HTTP_DEFAULT, current->text(0).toUtf8().constData(), NULL); - - - /* * Check printer properties (auth, color, duplex, copies) * */ - // get printer capabilities - - - const char *type = cupsGetOption("printer-type", dest->num_options, dest->options); - int res = 0; - if (type != NULL) { - res = ::atoi(type); - } - - const char *auth = cupsGetOption("auth-info-required", dest->num_options, dest->options); - if (auth != NULL && (strstr(auth, "username") != NULL || strstr(auth, "password") != NULL)) { - res |= CUPS_PRINTER_AUTHENTICATED; - } - - // Check authentication - if (res & CUPS_PRINTER_AUTHENTICATED) { - ui->labelUser->setEnabled(true); - ui->labelPass->setEnabled(true); - ui->lineEditUser->setEnabled(true); - ui->lineEditPass->setEnabled(true); - this->authRequired = true; - } else { - ui->labelUser->setEnabled(false); - ui->labelPass->setEnabled(false); - ui->lineEditUser->setEnabled(false); - ui->lineEditPass->setEnabled(false); - this->authRequired = false; - } - - // Check color capabilities - if (res & CUPS_PRINTER_COLOR) { - ui->comboBoxColor->setEnabled(true); - ui->comboBoxColor->setCurrentIndex(1); - } else { - ui->comboBoxColor->setEnabled(false); - ui->comboBoxColor->setCurrentIndex(0); - } - - // Check duplex capabilities - if (res & CUPS_PRINTER_DUPLEX) { - ui->comboBoxSides->setEnabled(true); - } else { - ui->comboBoxSides->setEnabled(false); - ui->comboBoxSides->setCurrentIndex(0); - } - - // Check copy capabilities - if (res & CUPS_PRINTER_COPIES) { - ui->lineEditCopies->setEnabled(true); - ui->labelCopies->setEnabled(true); - } else { - ui->lineEditCopies->setEnabled(false); - ui->lineEditCopies->setText("1"); - ui->labelCopies->setEnabled(false); - } - - // Check availability - if (res & CUPS_PRINTER_REJECTING) { - ui->buttonPrint->setEnabled(false); - } else { - ui->buttonPrint->setEnabled(true); - } -} - -// ____________________________________________________________________________ -void MainWindow::on_buttonCancel_clicked() { - // Quit with code 1 - QCoreApplication::instance()->exit(1); -} - -// ____________________________________________________________________________ -void MainWindow::on_buttonPrint_clicked() { - QString cmd; - - // Wenn Farbe möglich ist. Aber trotzdem Graustufen gewählt - // Schieb file durch ghostscript - if (ui->comboBoxColor->isEnabled() && ui->comboBoxColor->currentIndex() == 0) { - // Run ghostscript to make file grayscale - cmd = QString("gs -sDEVICE=psgray -dNOPAUSE -dBATCH -dQUIET -dSAFER -sOutputFile=\"%22\" \"%1\"").arg( - file, - file); - if (system(cmd.toUtf8().constData())) - return; // TODO WARN ABOUT MISSED GS JOB - - } - - /* * Print via cups lib * */ - - // Destination / Queue - cups_dest_t *dest = cupsGetDest( - ui->printerList->currentItem()->text(0).toUtf8().constData(), - NULL, - num_dests, - dests); - - // Duplex - if (ui->comboBoxSides->isEnabled()) { - switch (ui->comboBoxSides->currentIndex()) { - case 0: - dest->num_options = cupsAddOption ("Duplex", - "None", - dest->num_options, - &(dest->options)); - break; - case 1: - dest->num_options = cupsAddOption ("Duplex", - "DuplexNoTumble", - dest->num_options, - &(dest->options)); - break; - case 2: - dest->num_options = cupsAddOption ("Duplex", - "DuplexTumble", - dest->num_options, - &(dest->options)); - break; - } - } - - // Kopien - if (ui->lineEditCopies->isEnabled()) { - dest->num_options = cupsAddOption ("copies", - ui->lineEditCopies->text().toUtf8().constData(), - dest->num_options, - &(dest->options)); - } - - if (!this->authRequired) { - // Only Username - cupsSetUser(this->user); - } else { - // Username + Password - snprintf(_username, FIELDLEN, "%s", ui->lineEditUser->text().toUtf8().constData()); - snprintf(_password, FIELDLEN, "%s", ui->lineEditPass->text().toUtf8().constData()); - cupsSetPasswordCB(&cups_password_cb); - } - - // Drucken - if( 0 == cupsPrintFile(dest->name, - file, - NULL, - dest->num_options, - dest->options)) { - QMessageBox msgBox; - msgBox.setText(cupsLastErrorString()); - msgBox.exec(); - } else { // Quit with code 0 - QCoreApplication::instance()->quit(); - } - -} - - -/////////////////////////////// CODE PAPIERKORB ///////////////////////////// - -/* * Print via sysctem command * */ -// // Username, part of whoami source -// register uid_t uid = geteuid(); -// const char *username = getpwuid(uid)->pw_name; -// cmd = QString("lp -U %1").arg(username); -// // Duplex -// if (ui->comboBoxSides->isEnabled()) -// { -// switch (ui->comboBoxSides->currentIndex()){ -// case 0: -// cmd.append(" -o sides=one-sided"); -// break; -// case 1: -// cmd.append(" -o sides=two-sided-long-edge"); -// break; -// case 2: -// cmd.append(" -o sides=two-sided-long-edge"); -// break; -// } -// } -// // Kopien -// if (ui->lineEditCopies->isEnabled()) -// cmd.append(QString(" -n %1").arg(ui->lineEditCopies->text())); -// // Queue -// cmd.append(QString(" -d %1").arg(ui->printerList->currentItem()->text(0))); -// // File -// cmd.append(QString(" -- \"%1\"").arg(file)); -// // Print results to stdout -// QTextStream (stdout, QIODevice::WriteOnly) << cmd; -// // Execute the command -// system(cmd.toUtf8().constData()); diff --git a/src/mainwindow.h b/src/mainwindow.h deleted file mode 100644 index ec0e4a8..0000000 --- a/src/mainwindow.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef MAINWINDOW_H -#define MAINWINDOW_H - -#include -#include -#include -#include -#include "cups/cups.h" - -namespace Ui { -class MainWindow; -} - -class MainWindow : public QMainWindow -{ - Q_OBJECT - -public: - explicit MainWindow(char *argv[], QWidget *parent = 0); - ~MainWindow(); - -private slots: - void on_printerList_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous); - void on_buttonCancel_clicked(); - void on_buttonPrint_clicked(); - -private: - Ui::MainWindow *ui; - void initializeUI(); - cups_dest_t *dests; - int num_dests; - const char * const user; - const char * const file; - bool authRequired; -}; - -#endif // MAINWINDOW_H diff --git a/src/mainwindow.ui b/src/mainwindow.ui deleted file mode 100644 index 9533e94..0000000 --- a/src/mainwindow.ui +++ /dev/null @@ -1,230 +0,0 @@ - - - MainWindow - - - - 0 - 0 - 574 - 286 - - - - Printjob - - - - - - - - - false - - - true - - - - 1 - - - - - - - - - - - - false - - - User: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - false - - - - 0 - 0 - - - - - - - - - - false - - - - Graustufen - - - - - Farbe - - - - - - - - false - - - - Simplex - - - - - Duplex, Long Edge - - - - - Duplex, Short Edge - - - - - - - - - - false - - - Password: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - false - - - - 0 - 0 - - - - - - - - - - - - - 0 - 0 - - - - false - - - Abbrechen - - - - - - - false - - - - 0 - 0 - - - - Drucken - - - - - - - - - - - false - - - Anzahl Kopien: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - false - - - - 0 - 0 - - - - - 40 - 16777215 - - - - 00; - - - 1 - - - 2 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - - - - diff --git a/src/printergui.pro b/src/printergui.pro deleted file mode 100644 index 5b6da93..0000000 --- a/src/printergui.pro +++ /dev/null @@ -1,22 +0,0 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2013-09-26T00:51:08 -# -#------------------------------------------------- - -QT += core gui - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -TARGET = printergui -TEMPLATE = app - - -SOURCES += main.cpp\ - mainwindow.cpp - -HEADERS += mainwindow.h - -FORMS += mainwindow.ui - -LIBS += -L/usr/lib/x86_64-linux-gnu -lcups diff --git a/src/pwgui/config.h b/src/pwgui/config.h new file mode 100644 index 0000000..a06d9db --- /dev/null +++ b/src/pwgui/config.h @@ -0,0 +1,5 @@ +// This is where pwgui will look for backends. +// Works exactly like /usr/lib/cups/backend, but don't +// use that as it would cause pwgui invoking itself again... +#define BACKEND_PATH "/opt/openslx/cups/backend" + diff --git a/src/pwgui/main.cpp b/src/pwgui/main.cpp new file mode 100644 index 0000000..d75f280 --- /dev/null +++ b/src/pwgui/main.cpp @@ -0,0 +1,135 @@ +#include "pwgui.h" +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NAMELEN 400 +#define BUFLEN 1000 + +static int run_backend(char *backend, char *uri, char *jobid, char *user, char *title, char *copies, char *options, char *file, char *password); + +int main(int argc, char *argv[]) +{ + char tmpfile[NAMELEN]; + char device[NAMELEN]; + char backend[NAMELEN]; + int spoolres; + + // Pretty much what smbspool does, but in a generalized way + if (argc > 2 && strstr(argv[0], ":/") == NULL && strstr(argv[1], ":/") != NULL) { + argv++; + argc--; + } + + // First check parameter count + if (argc != 6 && argc != 7) { + fputs("ERROR: Invalid number of arguments passed.\n", stderr); + return CUPS_BACKEND_FAILED; + } + + if (argc == 6) { + // Data comes from stdin, save... + snprintf(tmpfile, NAMELEN, "/tmp/print-%s-%d-%s-%d", argv[1], (int)time(NULL), argv[2], (int)getpid()); + int fh = open(tmpfile, O_CREAT | O_WRONLY | O_TRUNC, 0600); + if (fh < 0) { + fprintf(stderr, "ERROR: Could not open %s for writing..\n", tmpfile); + return CUPS_BACKEND_FAILED; + } + char buffer[BUFLEN]; + size_t bytes, ret; + while (!feof(stdin)) { + bytes = fread(buffer, BUFLEN, 1, stdin); + if (bytes == 0) break; + if ((ret = write(fh, buffer, bytes)) != bytes) { + fprintf(stderr, "ERROR: Could not write %d bytes to %s (wrote %d)\n", (int)bytes, tmpfile, (int)ret); + remove(tmpfile); + return CUPS_BACKEND_FAILED; + } + } + close(fh); + // + } else { + // File given, check if file exists + snprintf(tmpfile, NAMELEN, "%s", argv[6]); + int fh = open(tmpfile, O_RDONLY); + if (fh < 0) { + fprintf(stderr, "ERROR: Could not open %s for reading..\n", tmpfile); + return CUPS_BACKEND_FAILED; + } + close(fh); + // + } + + // Determine device uri + char *env = getenv("DEVICE_URI"); + if (env != NULL && strchr(env, ':') != NULL) { + snprintf(device, NAMELEN, "%s", env); + } else if (strstr(argv[0], ":/") != NULL) { + snprintf(device, NAMELEN, "%s", argv[0]); + } else { + fputs("ERROR: No device URI given.\n", stderr); + return CUPS_BACKEND_FAILED; + } + + // Get backend from uri + char *colon = strchr(device, ':'); + *colon = '\0'; + snprintf(backend, NAMELEN, "%s/%s", BACKEND_PATH, device); + *colon = ':'; + // Is valid? + if (access(backend, X_OK | R_OK) != 0) { + fprintf(stderr, "ERROR: Backend %s is not executable.\n", backend); + return CUPS_BACKEND_FAILED; + } + + // Try right away with what we got + spoolres = run_backend(backend, device, argv[1], argv[2], argv[3], argv[4], argv[5], tmpfile, NULL); + if (spoolres == CUPS_BACKEND_OK) return spoolres; // Yay + + // Dialog - TODO: Drop privileges here! + QApplication a(argc, argv); + PwGui w(NULL); + w.show(); + return a.exec(); + // TODO ..... +} + +static int run_backend(char *backend, char *uri, char *jobid, char *user, char *title, char *copies, char *options, char *file, char *password) +{ + pid_t pid = fork(); + if (pid == 0) { + // Child + if (user != NULL) setenv("AUTH_USERNAME", user, 1); + if (password != NULL) setenv("AUTH_PASSWORD", password, 1); + char *args[8]; + args[0] = uri; + args[1] = jobid; + args[2] = user; + args[3] = title; + args[4] = copies; + args[5] = options; + args[6] = file; + args[7] = NULL; + execv(backend, args); + exit(127); + return 127; + } + + // Main - wait for it... + int status; + waitpid(pid, &status, 0); + if (!WIFEXITED(status)) { + fprintf(stderr, "ERROR: Running backend %s failed!\n", backend); + return CUPS_BACKEND_FAILED; + } + return WEXITSTATUS(status); +} + diff --git a/src/pwgui/pwgui.cpp b/src/pwgui/pwgui.cpp new file mode 100644 index 0000000..31dd822 --- /dev/null +++ b/src/pwgui/pwgui.cpp @@ -0,0 +1,59 @@ +#include "pwgui.h" +#include "ui_pwgui.h" +#include +#include +#include + +// ____________________________________________________________________________ +PwGui::PwGui(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::PwGui) { + // Initialize UI + initializeUI(); +} + +// ____________________________________________________________________________ +PwGui::~PwGui() { + delete ui; +} + +// ____________________________________________________________________________ +void PwGui::initializeUI() { + ui->setupUi(this); + + /* + // Prefill username + if (this->user != NULL) { + ui->lineEditUser->setText(QString::fromUtf8(user)); + } + */ + + // Protect password from being seen + ui->lineEditPass->setEchoMode(QLineEdit::Password); + ui->lineEditPass->setInputMethodHints(ui->lineEditPass->inputMethodHints() | Qt::ImhNoAutoUppercase); + + /* Main Window properties */ + + // Disable close button + this->setWindowFlags((this->windowFlags() & ~Qt::WindowCloseButtonHint) | Qt::WindowStaysOnTopHint); + // center dialog on screen center + QRect desktopRect = QApplication::desktop()->screenGeometry(this); + this->move( desktopRect.width()/2-this->width()/2, + desktopRect.height()/2-this->height()/2); +} + +/* +void PwGui::on_buttonCancel_clicked() { + // Quit with code 1 + QCoreApplication::instance()->exit(1); +} +*/ + +// ____________________________________________________________________________ +void PwGui::on_checkStatusTimer() { + static int retries = 0; + if (++retries > 20) { + QCoreApplication::instance()->quit(); + } +} + diff --git a/src/pwgui/pwgui.h b/src/pwgui/pwgui.h new file mode 100644 index 0000000..3e56ec8 --- /dev/null +++ b/src/pwgui/pwgui.h @@ -0,0 +1,31 @@ +#ifndef AUTHENTICATION_H +#define AUTHENTICATION_H + +#include +#include +#include + +namespace Ui { +class PwGui; +} + +class QTimer; + +class PwGui : public QMainWindow +{ + Q_OBJECT + +public: + explicit PwGui(QWidget *parent = 0); + ~PwGui(); + +private slots: + void on_checkStatusTimer(); + +private: + Ui::PwGui *ui; + void initializeUI(); + QTimer* checkStatusTimer; +}; + +#endif // AUTHENTICATION_H diff --git a/src/pwgui/pwgui.ui b/src/pwgui/pwgui.ui new file mode 100644 index 0000000..236df30 --- /dev/null +++ b/src/pwgui/pwgui.ui @@ -0,0 +1,145 @@ + + + PwGui + + + + 0 + 0 + 310 + 160 + + + + + 0 + 0 + + + + Drucken - Authentifizierung + + + + + 9 + 9 + 291 + 141 + + + + + + + + + Benutzername + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + + + + + + + + Passwort + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + + + + + + Qt::LeftToRight + + + QFrame::Panel + + + QFrame::Sunken + + + Bitte Anmelden + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + + -- cgit v1.2.3-55-g7522