21 #include "kprinterimpl.h"
23 #include "kmfactory.h"
24 #include "kmmanager.h"
25 #include "kmuimanager.h"
26 #include "kxmlcommand.h"
27 #include "kmspecialmanager.h"
28 #include "kmthreadjob.h"
29 #include "kmprinter.h"
34 #include <kinputdialog.h>
35 #include <tdelocale.h>
36 #include <dcopclient.h>
37 #include <tdeapplication.h>
38 #include <kstandarddirs.h>
39 #include <kdatastream.h>
41 #include <kmimemagic.h>
42 #include <tdemessagebox.h>
44 #include <tdeconfig.h>
48 void dumpOptions(
const TQMap<TQString,TQString>&);
49 void initEditPrinter(KMPrinter *p)
53 p->setEditedOptions(p->defaultOptions());
60 KPrinterImpl::KPrinterImpl(TQObject *parent,
const char *name)
61 : TQObject(parent,name)
66 KPrinterImpl::~KPrinterImpl()
70 void KPrinterImpl::preparePrinting(
KPrinter *printer)
75 KMManager *mgr = KMFactory::self()->manager();
76 DrMain *driver = mgr->loadPrinterDriver(mgr->findPrinter(printer->
printerName()),
false);
82 TQString psname = printer->
option(
"PageSize");
85 DrListOption *opt = (DrListOption*)driver->findOption(
"PageSize");
86 if (opt) psname = opt->get(
"default");
88 if (!psname.isEmpty())
90 printer->
setOption(
"kde-pagesize",TQString::number((
int)pageNameToPageSize(psname)));
91 DrPageSize *ps = driver->findPageSize(psname);
104 TQString res = printer->
option(
"Resolution" );
107 DrBase *opt = driver->findOption(
"Resolution" );
109 res = opt->get(
"default" );
111 res = driver->get(
"resolution" );
113 if ( !res.isEmpty() )
115 TQRegExp re(
"(\\d+)(?:x(\\d+))?dpi" );
116 if ( re.search( res ) != -1 )
118 if ( !re.cap( 2 ).isEmpty() )
119 printer->
setOption(
"kde-resolution", re.cap( 2 ) );
121 printer->
setOption(
"kde-resolution", re.cap( 1 ) );
126 TQString fonts = driver->get(
"fonts" );
127 if ( !fonts.isEmpty() )
128 printer->
setOption(
"kde-fonts", fonts );
135 bool KPrinterImpl::setupCommand(TQString&,
KPrinter*)
140 bool KPrinterImpl::printFiles(
KPrinter *p,
const TQStringList& f,
bool flag)
143 if (p->
option(
"kde-isspecial") ==
"1")
148 if ( !url.isLocalFile() )
150 cmd = ( flag ?
"mv" :
"cp" ) + (
" %in $out{" + p->
outputFileName() +
"}" );
163 if (!proc.start(TDEProcess::Block) || !proc.normalExit() || proc.exitStatus() != 0)
172 else if (!setupSpecialCommand(cmd,p,f))
175 else if (!setupCommand(cmd,p))
177 return startPrinting(cmd,p,f,flag);
180 void KPrinterImpl::broadcastOption(
const TQString& key,
const TQString& value)
183 TQPtrList<KMPrinter> *printers = KMFactory::self()->manager()->printerListComplete(
false);
186 TQPtrListIterator<KMPrinter> it(*printers);
187 for (;it.current();++it)
189 initEditPrinter(it.current());
190 it.current()->setEditedOption(key,value);
195 int KPrinterImpl::dcopPrint(
const TQString& cmd,
const TQStringList& files,
bool removeflag)
197 kdDebug(500) <<
"tdeprint: print command: " << cmd << endl;
200 DCOPClient *dclient = kapp->dcopClient();
201 if (!dclient || (!dclient->isAttached() && !dclient->attach()))
206 TQByteArray data, replyData;
208 TQDataStream arg( data, IO_WriteOnly );
212 if (dclient->call(
"kded",
"tdeprintd",
"print(TQString,TQStringList,bool)", data, replyType, replyData ))
214 if (replyType ==
"int")
216 TQDataStream _reply_stream( replyData, IO_ReadOnly );
217 _reply_stream >> result;
223 void KPrinterImpl::statusMessage(
const TQString& msg,
KPrinter *printer)
225 kdDebug(500) <<
"tdeprint: status message: " << msg << endl;
226 TDEConfig *conf = KMFactory::self()->printConfig();
227 conf->setGroup(
"General");
228 if (!conf->readBoolEntry(
"ShowStatusMsg",
true))
231 TQString message(msg);
232 if (printer && !msg.isEmpty())
233 message.prepend(i18n(
"Printing document: %1").arg(printer->
docName())+
"\n");
235 DCOPClient *dclient = kapp->dcopClient();
236 if (!dclient || (!dclient->isAttached() && !dclient->attach()))
242 TQDataStream arg( data, IO_WriteOnly );
244 arg << (int)getpid();
245 arg << kapp->caption();
246 dclient->send(
"kded",
"tdeprintd",
"statusMessage(TQString,int,TQString)", data );
249 bool KPrinterImpl::startPrinting(
const TQString& cmd,
KPrinter *printer,
const TQStringList& files,
bool flag)
251 statusMessage(i18n(
"Sending print data to printer: %1").arg(printer->
printerName()), printer);
253 TQString command(cmd), filestr;
254 TQStringList printfiles;
255 if (command.find(
"%in") == -1) command.append(
" %in");
257 for (TQStringList::ConstIterator it=files.begin(); it!=files.end(); ++it)
258 if (TQFile::exists(*it))
261 filestr.append(quote(*it)).append(
" ");
262 printfiles.append(*it);
265 kdDebug(500) <<
"File not found: " << (*it) << endl;
267 if (printfiles.count() > 0)
269 command.replace(
"%in",filestr);
270 int pid = dcopPrint(command,files,flag);
274 KMThreadJob::createJob(pid,printer->
printerName(),printer->
docName(),getenv(
"USER"),0);
279 TQString msg = i18n(
"Unable to start child print process. ");
281 msg += i18n(
"The TDE print server (<b>tdeprintd</b>) could not be contacted. Check that this server is running.");
283 msg += i18n(
"1 is the command that <files> is given to",
"Check the command syntax:\n%1 <files>").arg(cmd);
290 printer->
setErrorMessage(i18n(
"No valid file was found for printing. Operation aborted."));
295 TQString KPrinterImpl::tempFile()
299 do f = locateLocal(
"tmp",
"tdeprint_") + TDEApplication::randomString(8);
while (TQFile::exists(f));
303 int KPrinterImpl::filterFiles(
KPrinter *printer, TQStringList& files,
bool flag)
305 TQStringList flist = TQStringList::split(
',',printer->
option(
"_kde-filters"),
false);
306 TQMap<TQString,TQString> opts = printer->
options();
315 (printer->
option(
"kde-isspecial") ==
"1" || !(KMFactory::self()->uiManager()->pluginPageCap() & KMUiManager::PSSelect)) &&
316 (printer->
pageOrder() == KPrinter::LastPageFirst ||
317 !printer->
option(
"kde-range").isEmpty() ||
318 printer->
pageSet() != KPrinter::AllPages))
320 if (flist.findIndex(
"psselect") == -1)
322 int index = KXmlCommandManager::self()->insertCommand(flist,
"psselect",
false);
323 if (index == -1 || !KXmlCommandManager::self()->checkCommand(
"psselect"))
325 printer->
setErrorMessage(i18n(
"<p>Unable to perform the requested page selection. The filter <b>psselect</b> "
326 "cannot be inserted in the current filter chain. See <b>Filter</b> tab in the "
327 "printer properties dialog for further information.</p>"));
331 if (printer->
pageOrder() == KPrinter::LastPageFirst)
332 opts[
"_kde-psselect-order"] =
"r";
333 if (!printer->
option(
"kde-range").isEmpty())
334 opts[
"_kde-psselect-range"] = printer->
option(
"kde-range");
335 if (printer->
pageSet() != KPrinter::AllPages)
336 opts[
"_kde-psselect-set"] = (printer->
pageSet() == KPrinter::OddPages ?
"-o" :
"-e");
339 return doFilterFiles(printer, files, flist, opts, flag);
342 int KPrinterImpl::doFilterFiles(
KPrinter *printer, TQStringList& files,
const TQStringList& flist,
const TQMap<TQString,TQString>& opts,
bool flag)
345 if (flist.count() == 0)
349 TQStringList inputMimeTypes;
350 for (uint i=0;i<flist.count();i++)
352 KXmlCommand *filter = KXmlCommandManager::self()->loadCommand(flist[i]);
355 printer->
setErrorMessage(i18n(
"<p>Could not load filter description for <b>%1</b>.</p>").arg(flist[i]));
359 inputMimeTypes = filter->inputMimeTypes();
361 TQString subcmd = filter->buildCommand(opts,(i>0),(i<(flist.count()-1)));
363 if (!subcmd.isEmpty())
365 filtercmd.append(subcmd);
366 if (i < flist.count()-1)
367 filtercmd.append(
"| ");
371 printer->
setErrorMessage(i18n(
"<p>Error while reading filter description for <b>%1</b>. Empty command line received.</p>").arg(flist[i]));
375 kdDebug(500) <<
"tdeprint: filter command: " << filtercmd << endl;
377 TQString rin(
"%in"), rout(
"%out"), rpsl(
"%psl"), rpsu(
"%psu");
379 for (TQStringList::Iterator it=files.begin(); it!=files.end(); ++it)
381 TQString mime = KMimeMagic::self()->findFileType(*it)->mimeType();
382 if (inputMimeTypes.find(mime) == inputMimeTypes.end())
384 if (KMessageBox::warningContinueCancel(0,
385 "<p>" + i18n(
"The MIME type %1 is not supported as input of the filter chain "
386 "(this may happen with non-CUPS spoolers when performing page selection "
387 "on a non-PostScript file). Do you want TDE to convert the file to a supported "
388 "format?</p>").arg(mime),
389 TQString::null, i18n(
"Convert")) == KMessageBox::Continue)
398 TQString targetMime = KInputDialog::getItem(
399 i18n(
"Select MIME Type"),
400 i18n(
"Select the target format for the conversion:"),
401 inputMimeTypes, 0,
false, &ok);
407 TQStringList filters = KXmlCommandManager::self()->autoConvert(mime, targetMime);
408 if (filters.count() == 0)
410 KMessageBox::error(0, i18n(
"No appropriate filter found. Select another target format."));
414 int result = doFilterFiles(printer, ff, filters, TQMap<TQString,TQString>(), flag);
422 KMessageBox::error(0,
423 i18n(
"<qt>Operation failed with message:<br>%1<br>Select another target format.</qt>").arg(printer->
errorMessage()));
435 TQString tmpfile = tempFile();
436 TQString cmd(filtercmd);
437 cmd.replace(rout,quote(tmpfile));
438 cmd.replace(rpsl,ps.lower());
439 cmd.replace(rpsu,ps);
440 cmd.replace(rin,quote(*it));
441 statusMessage(i18n(
"Filtering print data"), printer);
442 int status = system(TQFile::encodeName(cmd));
443 if (status < 0 || WEXITSTATUS(status) == 127)
445 printer->
setErrorMessage(i18n(
"Error while filtering. Command was: <b>%1</b>.").arg(filtercmd));
448 if (flag) TQFile::remove(*it);
454 int KPrinterImpl::autoConvertFiles(
KPrinter *printer, TQStringList& files,
bool flag)
456 TQString primaryMimeType =
"application/postscript";
457 TQStringList mimeTypes( primaryMimeType );
458 if ( printer->
option(
"kde-isspecial" ) ==
"1" )
460 if ( !printer->
option(
"kde-special-command" ).isEmpty() )
462 KXmlCommand *cmd = KXmlCommandManager::self()->loadCommand( printer->
option(
"kde-special-command" ),
true );
465 mimeTypes = cmd->inputMimeTypes();
468 primaryMimeType = mimeTypes[ 0 ];
474 KMFactory::PluginInfo info = KMFactory::self()->pluginInfo(KMFactory::self()->printSystem());
475 mimeTypes = info.mimeTypes;
476 primaryMimeType = info.primaryMimeType;
478 KMFactory::PluginInfo info = KMFactory::self()->pluginInfo(KMFactory::self()->printSystem());
479 int status(0), result;
480 for (TQStringList::Iterator it=files.begin(); it!=files.end(); )
482 TQString mime = KMimeMagic::self()->findFileType(*it)->mimeType();
483 if ( mime ==
"application/x-zerosize" )
486 KMessageBox::information( NULL,
487 i18n(
"<qt>The print file is empty and will be ignored:<p>%1</p></qt>" ).arg( *it ),
488 TQString::null,
"emptyFileNotPrinted" );
490 TQFile::remove( *it );
491 it = files.remove( it );
494 else if (mimeTypes.findIndex(mime) == -1)
496 if ((result=KMessageBox::warningYesNoCancel(NULL,
497 i18n(
"<qt>The file format <em> %1 </em> is not directly supported by the current print system. You "
498 "now have 3 options: "
500 "<li> TDE can attempt to convert this file automatically to a supported format. "
501 "(Select <em>Convert</em>) </li>"
502 "<li> You can try to send the file to the printer without any conversion. "
503 "(Select <em>Keep</em>) </li>"
504 "<li> You can cancel the printjob. "
505 "(Select <em>Cancel</em>) </li>"
507 "Do you want TDE to attempt and convert this file to %2?</qt>").arg(mime).arg(primaryMimeType),
511 TQString::fromLatin1(
"tdeprintAutoConvert"))) == KMessageBox::Yes)
514 TQStringList flist = KXmlCommandManager::self()->autoConvert(mime, primaryMimeType);
515 if (flist.count() == 0)
517 KMessageBox::error(NULL,
518 i18n(
"<qt>No appropriate filter was found to convert the file format %1 into %2.<br>"
520 "<li>Go to <i>System Options -> Commands</i> to look through the list of "
521 "possible filters. Each filter executes an external program.</li>"
522 "<li> See if the required external program is available.on your "
525 "</qt>").arg(mime).arg(primaryMimeType),
529 it = files.remove(it);
533 switch (doFilterFiles(printer, l, flist, TQMap<TQString,TQString>(), flag))
545 else if (result == KMessageBox::Cancel)
556 bool KPrinterImpl::setupSpecialCommand(TQString& cmd,
KPrinter *p,
const TQStringList&)
558 TQString s(p->
option(
"kde-special-command"));
565 s = KMFactory::self()->specialManager()->setupCommand(s, p->
options());
568 s.replace(
"%psl", ps.lower());
569 s.replace(
"%psu", ps);
575 TQString KPrinterImpl::quote(
const TQString& s)
576 {
return TDEProcess::quote(s); }
578 void KPrinterImpl::saveOptions(
const TQMap<TQString,TQString>& opts)
584 void KPrinterImpl::loadAppOptions()
586 TDEConfig *conf = TDEGlobal::config();
587 conf->setGroup(
"KPrinter Settings");
588 TQStringList opts = conf->readListEntry(
"ApplicationOptions");
589 for (uint i=0; i<opts.count(); i+=2)
590 if (opts[i].startsWith(
"app-"))
591 m_options[opts[i]] = opts[i+1];
594 void KPrinterImpl::saveAppOptions()
596 TQStringList optlist;
597 for (TQMap<TQString,TQString>::ConstIterator it=m_options.begin(); it!=m_options.end(); ++it)
598 if (it.key().startsWith(
"app-"))
599 optlist << it.key() << it.data();
601 TDEConfig *conf = TDEGlobal::config();
602 conf->setGroup(
"KPrinter Settings");
603 conf->writeEntry(
"ApplicationOptions", optlist);
606 #include "kprinterimpl.moc"
This class is the main interface to access the TDE print framework.
TQString docName() const
See TQPrinter::docName().
PageSize
Defines the paper size to use.
const TQString & option(const TQString &key) const
Starts the add printer wizard.
bool outputToFile() const
See TQPrinter::outputToFile().
void setRealPageSize(TQSize p)
DO NOT USE, WILL BE REMOVED.
void setErrorMessage(const TQString &msg)
Sets the last error message.
TQString printerName() const
See TQPrinter::printerName().
TQString outputFileName() const
See TQPrinter::outputFileName().
void setOption(const TQString &key, const TQString &value)
Adds or modifies an option in the KPrinter object.
PageSize pageSize() const
See TQPrinter::pageSize().
const TQMap< TQString, TQString > & options() const
Returns the complete set of print options from the KPrinter object.
PageSetType pageSet() const
Returns the page set of the current KPrinter object.
PageOrder pageOrder() const
See TQPrinter::pageOrder().
static PageSelectionType pageSelection()
Returns the page selection mode of the current application.
TQString errorMessage() const
Returns the last error message issued by the print system.