summaryrefslogblamecommitdiffstats
path: root/src/maingui/printergui.cpp
blob: 21e03f4af4802cd20a8e289bd836096e2ac545ab (plain) (tree)
1
2
3
4
5
6
7
8
9

                          
                      

                   
                     
                      
                
                     
 

                                                                                   
                                                                      
 

                                                                               
                        
                               


                        
 
                                                                           
 

                                                              







                                                                          
 


                                                                                            
 

                                         
 

                        
 



                                                                           

 
                                                                               

                         



                                        

 
                                                                               

                               
                          


                                                                    
                                                                  



                                             
 



                                                                             
































                                                                                                                               




                                                                                
 



                               

 
                                                                                                          










                                                                                               
                                                        

                                                                  







                                                                                                                                           


                                                                  
                                                       







                                                      
 
                                                                               

                                                                                                       
                                    
 
                                                                                                             

 
                                                                        
 





                                                                                           
 
                                                                                  
                          
                                           


                                                                                                    
                                                                                                     
                              
                
                                                                                










                                                      
 


                                                   
                                                                                           

                                                  
                                          
         

 

























                                                                                                           
                                                                               

                                          
                      
 
 
                                                                               

                                         
                    
 
                                    
 





                                                                                           
 
                
                                                                         
                                  
                                                                                
                                                                                                                                                  

                                                                     
         
                 
                                                                          
                                   
                                                                                 








                                                                                                                                                  

                                                                     
         

                                              
                                                           





                                                                                                   









                                                                                                   

                  
                                         


                                                 

                                              

                                                                                  
                                    
                                                                           





                                                      
         
 
 
 










                                                                           
 
#include "printergui.h"
#include "ui_printergui.h"
#include <QMessageBox>
#include <unistd.h>
#include <QTimer>
#include <QStatusBar>
#include <QCloseEvent>
#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) :
	QDialog(parent),
	ui(new Ui::PrinterGui),
	statusBar(NULL),
	bgTimeout(-1),
	jobId(0)
{
	// 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);
	this->setWindowModality(Qt::ApplicationModal);
	// Put always on top
	this->setWindowFlags(Qt::Dialog | Qt::WindowStaysOnTopHint);
	ui->horizontalLayoutButtons->setAlignment(Qt::AlignRight);
	ui->comboBoxColor->setEnabled(false);
	ui->comboBoxSides->setEnabled(false);
	ui->label_color->setEnabled(false);
	ui->label_duplex->setEnabled(false);

	// Create a status bar (qt designer doesn't support this for dialogs)
	statusBar = new QStatusBar(this);
	ui->statusBarLayout->addWidget(statusBar);

	/*  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  */

	// 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::closeEvent(QCloseEvent * e)
{
	if (e->isAccepted()) {
		if (jobId != 0) {
			cupsCancelJob(ui->printerList->currentItem()->text(0).toUtf8().constData(), jobId);
			jobId = 0;
		}
		QCoreApplication::instance()->exit(0);
	}
	QDialog::closeEvent(e);
}

void PrinterGui::keyPressEvent(QKeyEvent * e)
{
	if(e->key() != Qt::Key_Escape) {
		QDialog::keyPressEvent(e);
		return;
	}
	this->close();
}

void PrinterGui::hideEvent(QHideEvent * e)
{
	this->close();
}

// ____________________________________________________________________________
void PrinterGui::on_buttonCancel_clicked()
{
	this->close();
}

// ____________________________________________________________________________
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[200];
	const char *docName;
	docName = getenv("J");
	if (docName == NULL) {
		docName = getenv("N");
	}
	if (docName == NULL) {
		docName = "Untitled";
	}
	snprintf(jobtitle, sizeof(jobtitle), "gui-%d-%s (%s)", (int)getpid(), this->user, docName);

	// Drucken
	jobId = cupsPrintFile(dest->name,
	                       file,
	                       jobtitle,
	                       dest->num_options,
	                       dest->options);
	if (jobId == 0) {
		QMessageBox::critical(this, "CUPS Fehler", cupsLastErrorString());
	} else {
		this->bgTimeout = 0;
		statusBar->showMessage("Druckauftrag wird verarbeitet...");
		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);
	}
}