21#include "kprinterimpl.h" 
   25#include "kmuimanager.h" 
   26#include "kxmlcommand.h" 
   27#include "kmspecialmanager.h" 
   28#include "kmthreadjob.h" 
   34#include <kinputdialog.h> 
   36#include <dcopclient.h> 
   37#include <tdeapplication.h> 
   38#include <tdestandarddirs.h> 
   39#include <kdatastream.h> 
   41#include <kmimemagic.h> 
   42#include <tdemessagebox.h> 
   43#include <tdeprocess.h> 
   48void dumpOptions(
const TQMap<TQString,TQString>&);
 
   49void initEditPrinter(KMPrinter *p)
 
   53        p->setEditedOptions(p->defaultOptions());
 
   60KPrinterImpl::KPrinterImpl(TQObject *parent, 
const char *name)
 
   61: TQObject(parent,name)
 
   66KPrinterImpl::~KPrinterImpl()
 
   70void 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 );
 
  135bool KPrinterImpl::setupCommand(TQString&, 
KPrinter*)
 
  140bool 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);
 
  180void 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);
 
  195int KPrinterImpl::dcopPrint(
const TQString& cmd, 
const TQStringList& files, 
bool removeflag)
 
  197    kdDebug(500) << 
"tdeprint: print command: " << cmd << endl;
 
  200    DCOPClient  *dclient = tdeApp->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;
 
  223void 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 = tdeApp->dcopClient();
 
  236    if (!dclient || (!dclient->isAttached() && !dclient->attach()))
 
  242    TQDataStream arg( data, IO_WriteOnly );
 
  244    arg << (int)getpid();
 
  245    arg << tdeApp->caption();
 
  246    dclient->send( 
"kded", 
"tdeprintd", 
"statusMessage(TQString,int,TQString)", data );
 
  249bool 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."));
 
  295TQString KPrinterImpl::tempFile()
 
  299    do f = locateLocal(
"tmp",
"tdeprint_") + TDEApplication::randomString(8); 
while (TQFile::exists(f));
 
  303int 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);
 
  342int 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);
 
  454int 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)
 
  556bool 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);
 
  575TQString KPrinterImpl::quote(
const TQString& s)
 
  576{ 
return TDEProcess::quote(s); }
 
  578void KPrinterImpl::saveOptions(
const TQMap<TQString,TQString>& opts)
 
  584void 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];
 
  594void 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.