1 /**************************************************************************
2 *   Copyright (C) 2005-2020 by Oleksandr Shneyder                         *
3 *                              <o.shneyder@phoca-gmbh.de>                 *
4 *                                                                         *
5 *   This program is free software; you can redistribute it and/or modify  *
6 *   it under the terms of the GNU General Public License as published by  *
7 *   the Free Software Foundation; either version 2 of the License, or     *
8 *   (at your option) any later version.                                   *
9 *   This program is distributed in the hope that it will be useful,       *
10 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
11 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
12 *   GNU General Public License for more details.                          *
13 *                                                                         *
14 *   You should have received a copy of the GNU General Public License     *
15 *   along with this program.  If not, see <https://www.gnu.org/licenses/>. *
16 ***************************************************************************/
17 
18 #include "x2goclientconfig.h"
19 #include "printprocess.h"
20 #include "x2gologdebug.h"
21 #include <QFile>
22 #include "x2gosettings.h"
23 #include <QDir>
24 #include "printdialog.h"
25 #if (!defined Q_OS_WIN) && (!defined Q_WS_HILDON)
26 #include "cupsprint.h"
27 #else
28 #include "printwidget.h"
29 #endif
30 #include <QProcess>
31 #include <QMessageBox>
32 #include <QFileDialog>
33 #include "x2gologdebug.h"
34 #ifdef Q_OS_WIN
35 #include "wapi.h"
36 #endif
37 #include <QTimer>
PrintProcess(QString pdf,QString title,QObject * parent)38 PrintProcess::PrintProcess ( QString pdf, QString title, QObject *parent ) :
39 		QObject ( parent )
40 {
41 	x2goDebug<<"Starting print process.";
42 	pdfFile=pdf;
43 	pdfTitle=title;
44 	parentWidg= ( QWidget* ) parent;
45 	if ( !loadSettings() )
46 	{
47 		QFile::remove ( pdfFile );
48 		return;
49 	}
50 	if ( viewPdf )
51 	{
52 		x2goDebug<<"Opening PDF file: "<<pdfFile<<"; title: "<<pdfTitle;
53 		QTimer::singleShot ( 100, this, SLOT ( openPdf() ) );
54 	}
55 	else
56 	{
57 		x2goDebug<<"Printing PDF file: "<<pdfFile<<"; title: "<<pdfTitle;
58 		QTimer::singleShot ( 100, this, SLOT ( print() ) );
59 	}
60 }
61 
62 
~PrintProcess()63 PrintProcess::~PrintProcess()
64 {
65 	x2goDebug<<"Closing print process.";
66 }
67 
68 
slot_processFinished(int exitCode,QProcess::ExitStatus exitStatus)69 void PrintProcess::slot_processFinished ( int exitCode,
70         QProcess::ExitStatus exitStatus )
71 {
72 	disconnect ( this,SIGNAL ( finished ( int , QProcess::ExitStatus ) ),
73 	             this,SLOT ( slot_processFinished (
74 	                             int,QProcess::ExitStatus ) ) );
75 	QFile::remove ( pdfFile );
76 	if ( exitCode==0 && exitStatus==QProcess::NormalExit )
77 	{
78 		if ( !printStdIn )
79 		{
80 			if ( !QProcess::startDetached (
81 			            printCmd+" \""+psFile+"\"" ) )
82 				slot_error ( QProcess::FailedToStart );
83 		}
84 		else
85 		{
86 			QProcess* proc=new QProcess;
87 			proc->setStandardInputFile ( psFile );
88 			connect ( proc,SIGNAL (
89 			              error ( QProcess::ProcessError ) ),
90 			          this,SLOT (
91 			              slot_error (
92 			                  QProcess::ProcessError ) ) );
93 			proc->start ( printCmd );
94 		}
95 	}
96 	else
97 		slot_pdf2psError ( QProcess::Crashed );
98 }
99 
100 
loadSettings()101 bool PrintProcess::loadSettings()
102 {
103 	X2goSettings st ( "printing" );
104 
105 	if ( st.setting()->value ( "showdialog",true ).toBool() )
106 	{
107 		PrintDialog dlg;
108 		if ( dlg.exec() ==QDialog::Rejected )
109 			return false;
110 	}
111 
112 	viewPdf=st.setting()->value ( "pdfview",false ).toBool();
113 	customPrintCmd=st.setting()->value ( "print/startcmd",false ).toBool();
114 	printCmd=st.setting()->value ( "print/command","lpr" ).toString();
115 	printStdIn= st.setting()->value ( "print/stdin",false ).toBool();
116 	printPs=st.setting()->value ( "print/ps",false ).toBool();
117 
118 	pdfOpen= st.setting()->value ( "view/open",true ).toBool();
119 
120 #ifndef Q_OS_WIN
121 	pdfOpenCmd=st.setting()->value ( "view/command","xpdf" ).toString();
122 #else
123 	winX2goPrinter=
124 	    st.setting()->value ( "print/defaultprinter",
125 	               wapiGetDefaultPrinter() ).toString();
126 #endif
127 #ifdef Q_WS_HILDON
128 	pdfOpenCmd="run-standalone.sh dbus-send --print-reply"
129 	           " --dest=com.nokia.osso_pdfviewer "
130 	           "/com/nokia/osso_pdfviewer "
131 	           "com.nokia.osso_pdfviewer.mime_open string:file://";
132 	viewPdf=true;
133 #endif
134 	return true;
135 
136 }
137 
138 
openPdf()139 void PrintProcess::openPdf()
140 {
141 	x2goDebug<<"Opening/saving PDF ...";
142 	if ( pdfOpen )
143 	{
144 #ifndef Q_OS_WIN
145 #ifndef Q_WS_HILDON
146 		QString cmd=pdfOpenCmd+" \""+pdfFile+"\"";
147 #else
148 		QString cmd=pdfOpenCmd+"\""+pdfFile+"\"";
149 #endif
150 		x2goDebug<<"Using PDF viewer command: "<<cmd;
151 		if ( ! QProcess::startDetached ( cmd ) )
152 			slot_error ( QProcess::FailedToStart );
153 
154 #else
155 		wapiShellExecute ( "open",
156 		                   wapiShortFileName ( pdfFile ),
157 		                   QString::null,
158 		                   wapiShortFileName ( QDir::homePath() ) );
159 #endif
160 	}
161 	else
162 	{
163 		QString homePath=QDir::homePath();
164 #ifndef Q_OS_WIN
165 		homePath +="/"+pdfTitle+".pdf";
166 #else
167 		homePath +="\\x2goprint.pdf";
168 #endif
169 		QString fileName = QFileDialog::getSaveFileName ( 0,
170 		                   tr ( "Save File" ),
171 		                   homePath,
172 		                   tr ( "PDF Document (*.pdf)" ) );
173 		if ( fileName.length() >0 )
174 			QFile::rename ( pdfFile,fileName );
175 
176 	}
177 }
178 
print()179 void PrintProcess::print()
180 {
181 #ifndef Q_WS_HILDON
182 	if ( !customPrintCmd )
183 	{
184 #ifndef Q_OS_WIN
185 		CUPSPrint prn;
186 		prn.setCurrentPrinter ( prn.getDefaultUserPrinter() );
187 		prn.print ( pdfFile, pdfTitle );
188 #else
189 		x2goDebug<<"Printing to "<<winX2goPrinter;
190 		wapiShellExecute ( "printto",
191 		                   wapiShortFileName ( pdfFile ),
192 		                   winX2goPrinter,
193 		                   wapiShortFileName ( QDir::homePath() ) );
194 #endif
195 	}
196 	else
197 #endif //Q_WS_HILDON
198 	{
199 		if ( !printPs )
200 		{
201 			if ( !printStdIn )
202 			{
203 				if ( !QProcess::startDetached (
204 				            printCmd+
205 				            " \""+pdfFile+"\"" ) )
206 					slot_error ( QProcess::FailedToStart );
207 
208 			}
209 			else
210 			{
211 				QProcess* proc=new QProcess;
212 				proc->setStandardInputFile ( pdfFile );
213 				connect ( proc,SIGNAL (
214 				              error (
215 				                  QProcess::ProcessError ) ),
216 				          this,SLOT (
217 				              slot_error (
218 				                  QProcess::ProcessError ) ) );
219 				proc->start ( printCmd );
220 			}
221 		}
222 		else
223 		{
224 			QStringList args;
225 			psFile=pdfFile;
226 			psFile.replace ( "pdf","ps" );
227 			args<<pdfFile<<psFile;
228 			QProcess* proc=new QProcess;
229 			connect ( proc,SIGNAL (
230 			              finished ( int ,
231 			                         QProcess::ExitStatus ) ),
232 			          this,SLOT (
233 			              slot_processFinished (
234 			                  int,
235 			                  QProcess::ExitStatus ) ) );
236 			connect ( proc,SIGNAL (
237 			              error ( QProcess::ProcessError ) ),
238 			          this,SLOT (
239 			              slot_pdf2psError (
240 			                  QProcess::ProcessError ) ) );
241 #ifndef Q_OS_WIN
242 			proc->start ( "pdf2ps",args );
243 #else
244 			QString pdf2ps,ver;
245 			PrintWidget::gsInfo ( ver,pdf2ps );
246 			QString wdir=pdf2ps;
247 			wdir.replace ( "pdf2ps.bat","" );
248 			proc->setWorkingDirectory ( wdir );
249 			QStringList env=QProcess::systemEnvironment();
250 			env.replaceInStrings ( QRegExp ( "^PATH=(.*)",
251 			                                 Qt::CaseInsensitive ),
252 			                       "PATH=\\1;"+wdir );
253 			wdir.replace ( "\\lib\\","\\bin\\" );
254 			env.replaceInStrings ( QRegExp ( "^PATH=(.*)",
255 			                                 Qt::CaseInsensitive ),
256 			                       "PATH=\\1;"+wdir );
257 			proc->setEnvironment ( env );
258 			proc->start ( pdf2ps,args );
259 #endif
260 		}
261 	}
262 }
263 
slot_error(QProcess::ProcessError)264 void PrintProcess::slot_error ( QProcess::ProcessError )
265 {
266 	QString message=tr ( "Failed to execute command:\n" );
267 	if ( viewPdf )
268 		message+=" "+pdfOpenCmd+ " " +pdfFile;
269 	else
270 	{
271 		message+=printCmd;
272 		if ( !printStdIn )
273 		{
274 			message+=" ";
275 			if ( printPs )
276 				message+=psFile;
277 			else
278 				message+=pdfFile;
279 		}
280 	}
281 	QMessageBox::critical ( 0l, tr ( "Printing error." ),
282 	                        message );
283 
284 }
285 
slot_pdf2psError(QProcess::ProcessError)286 void PrintProcess::slot_pdf2psError ( QProcess::ProcessError )
287 {
288 	QMessageBox::critical ( 0l, tr ( "Printing error." ),
289 	                        tr ( "Failed to execute command:\n" ) +
290 	                        "pdf2ps "+pdfFile+" "+psFile );
291 }
292