#include "printergui.h"
#include "ui_printergui.h"
#include <QMessageBox>
#include <unistd.h>
#include <QTimer>
#include <QStatusBar>
#include <pwd.h>
#include <cups/ppd.h>
static QStringList knownColorOptions = QStringList() << "ColorModel" << "XRXColor";
static QStringList knownDuplexOptions = QStringList() << "Duplex";
static QStringList knownPageSizeOptions = QStringList() << "PageSize";
// ____________________________________________________________________________
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
// Do not use getlogin[_r] as it doesn't fucking work!
struct passwd *pw = getpwuid(getuid());
if (pw != NULL && pw->pw_name != NULL && pw->pw_name[0] != '\0') {
// Detect real name
this->user = strdup(pw->pw_name);
} 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);
connect(bgTimer, SIGNAL(timeout()), this, SLOT(bgTimer_timeout()));
this->bgTimer->start(1000);
}
// ____________________________________________________________________________
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);
ui->comboBoxColor->setEnabled(false);
ui->comboBoxSides->setEnabled(false);
ui->label_color->setEnabled(false);
ui->label_duplex->setEnabled(false);
/* 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::fromUtf8(dest->name));
wi->setText(1, QString::fromUtf8(cupsGetOption("printer-info", dest->num_options, dest->options)));
wi->setText(2, QString::fromUtf8(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);
this->setWindowTitle(QString::fromUtf8("Drucken - %1").arg(this->user));
this->show();
this->showNormal();
this->raise();
this->activateWindow();
}
static void enableOptionSelection(ppd_file_t *ppd, QStringList &nameList, QComboBox *combo, QLabel *label)
{
// Check for each option if it matches an
QString matchedProperty;
for (ppd_option_t *o = ppdFirstOption(ppd); o != NULL; o = ppdNextOption(ppd)) {
QString option(o->keyword);
for (QStringList::iterator it = nameList.begin(); it != nameList.end(); ++it) {
if(!option.contains(*it))
continue;
// Matches, update combo
matchedProperty = option;
combo->setUpdatesEnabled(false);
combo->clear();
for (int i = 0; i < o->num_choices; ++i) {
if (o->choices[i].choice == NULL)
continue;
if (o->choices[i].text == NULL) {
combo->addItem(QString::fromUtf8(o->choices[i].choice), QString::fromLatin1(o->choices[i].choice));
} else {
combo->addItem(QString::fromUtf8(o->choices[i].text), QString::fromLatin1(o->choices[i].choice));
}
if (o->defchoice != NULL && strcmp(o->choices[i].choice, o->defchoice) == 0) {
combo->setCurrentIndex(i);
}
}
combo->setUpdatesEnabled(true);
combo->adjustSize();
break;
}
}
combo->setProperty("key", matchedProperty);
combo->setEnabled(!matchedProperty.isEmpty());
label->setEnabled(!matchedProperty.isEmpty());
}
// ____________________________________________________________________________
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);
}
ppd_file_t *ppd = ppdOpenFile(cupsGetPPD2(CUPS_HTTP_DEFAULT, dest->name));
if (ppd != NULL) {
// Check color capabilities
//if (res & CUPS_PRINTER_COLOR) // No needed? Should just get disabled either way
enableOptionSelection(ppd, knownColorOptions, ui->comboBoxColor, ui->label_color);
enableOptionSelection(ppd, knownDuplexOptions, ui->comboBoxSides, ui->label_duplex);
enableOptionSelection(ppd, knownPageSizeOptions, ui->cboPaperSize, ui->lblPaperSize);
ppdClose(ppd);
} else {
qDebug() << "ppd is null"<< dest->name << cupsLastErrorString();
}
// 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);
statusBar()->showMessage("Dieser Drucker nimmt zur Zeit keine Aufträge an");
} else {
ui->buttonPrint->setEnabled(true);
statusBar()->clearMessage();
}
}
// ____________________________________________________________________________
void PrinterGui::on_buttonCancel_clicked()
{
QCoreApplication::instance()->exit(0);
}
// ____________________________________________________________________________
void PrinterGui::on_buttonPrint_clicked()
{
QString cmd;
/* * Print via cups lib * */
// Destination / Queue
cups_dest_t *dest = cupsGetDest(
ui->printerList->currentItem()->text(0).toUtf8().constData(),
NULL,
num_dests,
dests);
// Color
QString colorKey = ui->comboBoxColor->property("key").toString();
if (!colorKey.isEmpty()) {
dest->num_options = cupsAddOption(colorKey.toUtf8().constData(),
ui->comboBoxColor->itemData(ui->comboBoxColor->currentIndex()).toString().toUtf8().constData(),
dest->num_options,
&(dest->options));
}
// Duplex
QString duplexKey = ui->comboBoxSides->property("key").toString();
if (!duplexKey.isEmpty()) {
dest->num_options = cupsAddOption(duplexKey.toUtf8().constData(),
ui->comboBoxSides->itemData(ui->comboBoxSides->currentIndex()).toString().toUtf8().constData(),
dest->num_options,
&(dest->options));
}
// Paper size
QString paperKey = ui->cboPaperSize->property("key").toString();
if (!paperKey.isEmpty()) {
dest->num_options = cupsAddOption(paperKey.toUtf8().constData(),
ui->cboPaperSize->itemData(ui->cboPaperSize->currentIndex()).toString().toUtf8().constData(),
dest->num_options,
&(dest->options));
}
// Kopien
if (ui->lineEditCopies->isEnabled()) {
dest->num_options = cupsAddOption("copies",
ui->lineEditCopies->text().toUtf8().constData(),
dest->num_options,
&(dest->options));
}
cupsSetUser(this->user);
char jobtitle[100];
snprintf(jobtitle, 100, "gui-%d-%s", (int)getpid(), this->user);
// Drucken
if( 0 == cupsPrintFile(dest->name,
file,
jobtitle,
dest->num_options,
dest->options)) {
QMessageBox::critical(this, "CUPS Fehler", cupsLastErrorString());
} else {
this->bgTimeout = 0;
statusBar()->showMessage("Druckauftrag wird verarbeitet...");
ui->buttonCancel->setEnabled(false);
ui->buttonPrint->setEnabled(false);
ui->cboPaperSize->setEnabled(false);
ui->comboBoxColor->setEnabled(false);
ui->comboBoxSides->setEnabled(false);
ui->lineEditCopies->setEnabled(false);
ui->printerList->setEnabled(false);
}
}
void PrinterGui::bgTimer_timeout()
{
if (this->bgTimeout == -1) {
// Could do something here every second....
return;
}
if (++this->bgTimeout > 120) {
// Job was sent, GUI is invisible, quit after a few seconds
QCoreApplication::instance()->exit(0);
}
}