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> 43 #include <tdeprocess.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" void setErrorMessage(const TQString &msg)
Sets the last error message.
PageOrder pageOrder() const
See TQPrinter::pageOrder().
bool outputToFile() const
See TQPrinter::outputToFile().
TQString outputFileName() const
See TQPrinter::outputFileName().
This class is the main interface to access the TDE print framework.
void setRealPageSize(TQSize p)
DO NOT USE, WILL BE REMOVED.
static PageSelectionType pageSelection()
Returns the page selection mode of the current application.
const TQMap< TQString, TQString > & options() const
Returns the complete set of print options from the KPrinter object.
TQString errorMessage() const
Returns the last error message issued by the print system.
PageSize pageSize() const
See TQPrinter::pageSize().
PageSetType pageSet() const
Returns the page set of the current KPrinter object.
const TQString & option(const TQString &key) const
Starts the add printer wizard.
TQString docName() const
See TQPrinter::docName().
PageSize
Defines the paper size to use.
TQString printerName() const
See TQPrinter::printerName().
void setOption(const TQString &key, const TQString &value)
Adds or modifies an option in the KPrinter object.