kdeprint Library API Documentation

kmcupsjobmanager.cpp

00001 /*
00002  *  This file is part of the KDE libraries
00003  *  Copyright (c) 2001 Michael Goffioul <kdeprint@swing.be>
00004  *
00005  *  This library is free software; you can redistribute it and/or
00006  *  modify it under the terms of the GNU Library General Public
00007  *  License version 2 as published by the Free Software Foundation.
00008  *
00009  *  This library is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  *  Library General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU Library General Public License
00015  *  along with this library; see the file COPYING.LIB.  If not, write to
00016  *  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00017  *  Boston, MA 02111-1307, USA.
00018  **/
00019 
00020 #include "kmcupsjobmanager.h"
00021 #include "kmcupsmanager.h"
00022 #include "kmjob.h"
00023 #include "cupsinfos.h"
00024 #include "ipprequest.h"
00025 #include "pluginaction.h"
00026 #include "kprinter.h"
00027 #include "kprinterpropertydialog.h"
00028 #include "kmuimanager.h"
00029 #include "kmfactory.h"
00030 #include "kpdriverpage.h"
00031 #include "kpschedulepage.h"
00032 #include "kpcopiespage.h"
00033 #include "kptagspage.h"
00034 
00035 #include <klocale.h>
00036 #include <kdebug.h>
00037 #include <kurl.h>
00038 
00039 KMCupsJobManager::KMCupsJobManager(QObject *parent, const char *name, const QStringList & /*args*/)
00040 : KMJobManager(parent,name)
00041 {
00042 }
00043 
00044 KMCupsJobManager::~KMCupsJobManager()
00045 {
00046 }
00047 
00048 int KMCupsJobManager::actions()
00049 {
00050     return KMJob::All;
00051 }
00052 
00053 bool KMCupsJobManager::sendCommandSystemJob(const QPtrList<KMJob>& jobs, int action, const QString& argstr)
00054 {
00055     IppRequest  req;
00056     QString     uri;
00057     bool        value(true);
00058 
00059     QPtrListIterator<KMJob> it(jobs);
00060     for (;it.current() && value;++it)
00061     {
00062         // hypothesis: job operation are always done on local jobs. The only operation
00063         // allowed on remote jobs is listing (done elsewhere).
00064 
00065         req.addURI(IPP_TAG_OPERATION,"job-uri",it.current()->uri());
00066         req.addName(IPP_TAG_OPERATION,"requesting-user-name",CupsInfos::self()->login());
00067         /*
00068         QString jobHost;
00069         if (!it.current()->uri().isEmpty())
00070         {
00071             KURL    url(it.current()->uri());
00072             req.setHost(url.host());
00073             req.setPort(url.port());
00074             jobHost = url.host();
00075         }
00076         */
00077 
00078         switch (action)
00079         {
00080             case KMJob::Remove:
00081                 req.setOperation(IPP_CANCEL_JOB);
00082                 break;
00083             case KMJob::Hold:
00084                 req.setOperation(IPP_HOLD_JOB);
00085                 break;
00086             case KMJob::Resume:
00087                 req.setOperation(IPP_RELEASE_JOB);
00088                 break;
00089             case KMJob::Restart:
00090                 req.setOperation(IPP_RESTART_JOB);
00091                 break;
00092             case KMJob::Move:
00093                 if (argstr.isEmpty()) return false;
00094                 req.setOperation(CUPS_MOVE_JOB);
00095                 uri = QString::fromLatin1("ipp://%1:%2/printers/%3").arg(CupsInfos::self()->host()).arg(CupsInfos::self()->port()).arg(argstr);
00096                 req.addURI(IPP_TAG_OPERATION, "job-printer-uri", uri);
00097                 break;
00098             default:
00099                 return false;
00100         }
00101 
00102         if (!(value = req.doRequest("/jobs/")))
00103             KMManager::self()->setErrorMsg(req.statusMessage());
00104     }
00105 
00106     return value;
00107 }
00108 
00109 bool KMCupsJobManager::listJobs(const QString& prname, KMJobManager::JobType type, int limit)
00110 {
00111     IppRequest  req;
00112     QString     uri("ipp://%1:%2/%3/%4");
00113     QStringList keys;
00114     CupsInfos   *infos = CupsInfos::self();
00115 
00116     // wanted attributes
00117     keys.append("job-id");
00118     keys.append("job-uri");
00119     keys.append("job-name");
00120     keys.append("job-state");
00121     keys.append("job-printer-uri");
00122     keys.append("job-k-octets");
00123     keys.append("job-originating-user-name");
00124     keys.append("job-k-octets-completed");
00125     keys.append("job-media-sheets");
00126     keys.append("job-media-sheets-completed");
00127     keys.append("job-priority");
00128     keys.append("job-billing");
00129 
00130     req.setOperation(IPP_GET_JOBS);
00131 
00132     // add printer-uri
00133     KMPrinter *mp = KMManager::self()->findPrinter(prname);
00134     if (!mp)
00135         return false;
00136 
00137     if (!mp->uri().isEmpty())
00138     {
00139         req.addURI(IPP_TAG_OPERATION, "printer-uri", mp->uri().prettyURL());
00140         /*
00141         req.setHost(mp->uri().host());
00142         req.setPort(mp->uri().port());
00143         */
00144     }
00145     else
00146         req.addURI(IPP_TAG_OPERATION, "printer-uri", uri.arg(infos->host()).arg(infos->port()).arg(((mp&&mp->isClass())?"classes":"printers")).arg(prname));
00147 
00148     // other attributes
00149     req.addKeyword(IPP_TAG_OPERATION, "requested-attributes", keys);
00150     if (type == KMJobManager::CompletedJobs)
00151         req.addKeyword(IPP_TAG_OPERATION,"which-jobs",QString::fromLatin1("completed"));
00152     if (limit > 0)
00153         req.addInteger(IPP_TAG_OPERATION,"limit",limit);
00154 
00155     // send request
00156     if (req.doRequest("/"))
00157         parseListAnswer(req, mp);
00158     else
00159         return false;
00160 
00161     return true;
00162 }
00163 
00164 void KMCupsJobManager::parseListAnswer(IppRequest& req, KMPrinter *pr)
00165 {
00166     ipp_attribute_t *attr = req.first();
00167     KMJob       *job = new KMJob();
00168     QString     uri;
00169     while (attr)
00170     {
00171         QString name(attr->name);
00172         if (name == "job-id") job->setId(attr->values[0].integer);
00173         else if (name == "job-uri") job->setUri(QString::fromLocal8Bit(attr->values[0].string.text));
00174         else if (name == "job-name") job->setName(QString::fromLocal8Bit(attr->values[0].string.text));
00175         else if (name == "job-state")
00176         {
00177             switch (attr->values[0].integer)
00178             {
00179                 case IPP_JOB_PENDING:
00180                     job->setState(KMJob::Queued);
00181                     break;
00182                 case IPP_JOB_HELD:
00183                     job->setState(KMJob::Held);
00184                     break;
00185                 case IPP_JOB_PROCESSING:
00186                     job->setState(KMJob::Printing);
00187                     break;
00188                 case IPP_JOB_STOPPED:
00189                     job->setState(KMJob::Error);
00190                     break;
00191                 case IPP_JOB_CANCELLED:
00192                     job->setState(KMJob::Cancelled);
00193                     break;
00194                 case IPP_JOB_ABORTED:
00195                     job->setState(KMJob::Aborted);
00196                     break;
00197                 case IPP_JOB_COMPLETED:
00198                     job->setState(KMJob::Completed);
00199                     break;
00200                 default:
00201                     job->setState(KMJob::Unknown);
00202                     break;
00203             }
00204         }
00205         else if (name == "job-k-octets") job->setSize(attr->values[0].integer);
00206         else if (name == "job-originating-user-name") job->setOwner(QString::fromLocal8Bit(attr->values[0].string.text));
00207         else if (name == "job-k-octets-completed") job->setProcessedSize(attr->values[0].integer);
00208         else if (name == "job-media-sheets") job->setPages(attr->values[0].integer);
00209         else if (name == "job-media-sheets-completed") job->setProcessedPages(attr->values[0].integer);
00210         else if (name == "job-printer-uri" && !pr->isRemote())
00211         {
00212             QString str(attr->values[0].string.text);
00213             int p = str.findRev('/');
00214             if (p != -1)
00215                 job->setPrinter(str.mid(p+1));
00216         }
00217         else if (name == "job-priority")
00218         {
00219             job->setAttribute(0, QString::fromLatin1("%1").arg(attr->values[0].integer, 3));
00220         }
00221         else if (name == "job-billing")
00222         {
00223             job->setAttributeCount(2);
00224             job->setAttribute(1, QString::fromLocal8Bit(attr->values[0].string.text));
00225         }
00226 
00227         if (name.isEmpty() || attr == req.last())
00228         {
00229             if (job->printer().isEmpty())
00230                 job->setPrinter(pr->printerName());
00231             job->setRemote(pr->isRemote());
00232             addJob(job);    // don't use job after this call !!!
00233             job = new KMJob();
00234         }
00235 
00236         attr = attr->next;
00237     }
00238     delete job;
00239 }
00240 
00241 bool KMCupsJobManager::doPluginAction(int ID, const QPtrList<KMJob>& jobs)
00242 {
00243     switch (ID)
00244     {
00245         case 0:
00246             if (jobs.count() == 1)
00247                 return jobIppReport(jobs.getFirst());
00248             break;
00249         case 1:
00250             return changePriority(jobs, true);
00251         case 2:
00252             return changePriority(jobs, false);
00253         case 3:
00254             return editJobAttributes(jobs.getFirst());
00255     }
00256     return false;
00257 }
00258 
00259 bool KMCupsJobManager::jobIppReport(KMJob *j)
00260 {
00261     IppRequest  req;
00262 
00263     req.setOperation(IPP_GET_JOB_ATTRIBUTES);
00264     req.addURI(IPP_TAG_OPERATION, "job-uri", j->uri());
00265     bool    result(true);
00266     /*
00267     if (!j->uri().isEmpty())
00268     {
00269         KURL    url(j->uri());
00270         req.setHost(url.host());
00271         req.setPort(url.port());
00272     }
00273     */
00274     if ((result=req.doRequest("/")))
00275         static_cast<KMCupsManager*>(KMManager::self())->ippReport(req, IPP_TAG_JOB, i18n("Job Report"));
00276     else
00277         KMManager::self()->setErrorMsg(i18n("Unable to retrieve job information: ")+req.statusMessage());
00278     return result;
00279 }
00280 
00281 QValueList<KAction*> KMCupsJobManager::createPluginActions(KActionCollection *coll)
00282 {
00283     QValueList<KAction*>    list;
00284     KAction *act(0);
00285 
00286     list <<  (act = new PluginAction(0, i18n("&Job IPP Report"), "kdeprint_report", 0, coll, "plugin_ipp"));
00287     act->setGroup("plugin");
00288     list << (act = new PluginAction(1, i18n("&Increase Priority"), "up", 0, coll, "plugin_prioup"));
00289     act->setGroup("plugin");
00290     list << (act = new PluginAction(2, i18n("&Decrease Priority"), "down", 0, coll, "plugin_priodown"));
00291     act->setGroup("plugin");
00292     list << (act = new PluginAction(3, i18n("&Edit Attributes..."), "edit", 0, coll, "plugin_editjob"));
00293     act->setGroup("plugin");
00294 
00295     return list;
00296 }
00297 
00298 void KMCupsJobManager::validatePluginActions(KActionCollection *coll, const QPtrList<KMJob>& joblist)
00299 {
00300     QPtrListIterator<KMJob> it(joblist);
00301     bool    flag(true);
00302     for (; it.current(); ++it)
00303     {
00304         flag = (flag && it.current()->type() == KMJob::System
00305                 && (it.current()->state() == KMJob::Queued || it.current()->state() == KMJob::Held)
00306             /*&& !it.current()->isRemote()*/);
00307     }
00308     flag = (flag && joblist.count() > 0);
00309     KAction *a;
00310     if ( ( a = coll->action( "plugin_ipp" ) ) )
00311         a->setEnabled( joblist.count() == 1 );
00312     if ( ( a = coll->action( "plugin_prioup" ) ) )
00313         a->setEnabled( flag );
00314     if ( ( a = coll->action( "plugin_priodown" ) ) )
00315         a->setEnabled( flag );
00316     if ( ( a = coll->action( "plugin_editjob" ) ) )
00317         a->setEnabled( flag && ( joblist.count() == 1 ) );
00318 }
00319 
00320 bool KMCupsJobManager::changePriority(const QPtrList<KMJob>& jobs, bool up)
00321 {
00322     QPtrListIterator<KMJob> it(jobs);
00323     bool    result(true);
00324     for (; it.current() && result; ++it)
00325     {
00326         int value = it.current()->attribute(0).toInt();
00327         if (up) value = QMIN(value+10, 100);
00328         else value = QMAX(value-10, 1);
00329 
00330         IppRequest  req;
00331         /*
00332         if (!it.current()->uri().isEmpty())
00333         {
00334             KURL    url(it.current()->uri());
00335             req.setHost(url.host());
00336             req.setPort(url.port());
00337         }
00338         */
00339         req.setOperation(IPP_SET_JOB_ATTRIBUTES);
00340         req.addURI(IPP_TAG_OPERATION, "job-uri", it.current()->uri());
00341         req.addName(IPP_TAG_OPERATION, "requesting-user-name", CupsInfos::self()->login());
00342         req.addInteger(IPP_TAG_JOB, "job-priority", value);
00343 
00344         if (!(result = req.doRequest("/jobs/")))
00345             KMManager::self()->setErrorMsg(i18n("Unable to change job priority: ")+req.statusMessage());
00346     }
00347     return result;
00348 }
00349 
00350 static QString processRange(const QString& range)
00351 {
00352     QStringList l = QStringList::split(',', range, false);
00353     QString s;
00354     for (QStringList::ConstIterator it=l.begin(); it!=l.end(); ++it)
00355     {
00356         s.append(*it);
00357         if ((*it).find('-') == -1)
00358             s.append("-").append(*it);
00359         s.append(",");
00360     }
00361     if (!s.isEmpty())
00362         s.truncate(s.length()-1);
00363     return s;
00364 }
00365 
00366 bool KMCupsJobManager::editJobAttributes(KMJob *j)
00367 {
00368     IppRequest  req;
00369 
00370     req.setOperation(IPP_GET_JOB_ATTRIBUTES);
00371     req.addURI(IPP_TAG_OPERATION, "job-uri", j->uri());
00372     /*
00373     if (!j->uri().isEmpty())
00374     {
00375         KURL    url(j->uri());
00376         req.setHost(url.host());
00377         req.setPort(url.port());
00378     }
00379     */
00380     if (!req.doRequest("/"))
00381     {
00382         KMManager::self()->setErrorMsg(i18n("Unable to retrieve job information: ")+req.statusMessage());
00383         return false;
00384     }
00385 
00386     QMap<QString,QString>   opts = req.toMap(IPP_TAG_JOB);
00387     // translate the "Copies" option to non-CUPS syntax
00388     if (opts.contains("copies"))
00389         opts["kde-copies"] = opts["copies"];
00390     if (opts.contains("page-set"))
00391         opts["kde-pageset"] = (opts["page-set"] == "even" ? "2" : (opts["page-set"] == "odd" ? "1" : "0"));
00392     if (opts.contains("OutputOrder"))
00393         opts["kde-pageorder"] = opts["OutputOrder"];
00394     if (opts.contains("multiple-document-handling"))
00395         opts["kde-collate"] = (opts["multiple-document-handling"] == "separate-documents-collated-copies" ? "Collate" : "Uncollate");
00396     if (opts.contains("page-ranges"))
00397         opts["kde-range"] = opts["page-ranges"];
00398 
00399     // find printer and construct dialog
00400     KMPrinter   *prt = KMManager::self()->findPrinter(j->printer());
00401     if (!prt)
00402     {
00403         KMManager::self()->setErrorMsg(i18n("Unable to find printer %1.").arg(j->printer()));
00404         return false;
00405     }
00406     KMManager::self()->completePrinterShort(prt);
00407     KPrinter::ApplicationType oldAppType = KPrinter::applicationType();
00408     KPrinter::setApplicationType(KPrinter::StandAlone);
00409     KPrinterPropertyDialog  dlg(prt);
00410     dlg.setDriver(KMManager::self()->loadPrinterDriver(prt));
00411     KMFactory::self()->uiManager()->setupPrinterPropertyDialog(&dlg);
00412     KPrinter::setApplicationType( oldAppType );
00413     if (dlg.driver())
00414         dlg.addPage(new KPDriverPage(prt, dlg.driver(), &dlg));
00415     dlg.addPage(new KPCopiesPage(0, &dlg));
00416     dlg.addPage(new KPSchedulePage(&dlg));
00417     dlg.addPage(new KPTagsPage(true, &dlg));
00418     dlg.setOptions(opts);
00419     dlg.enableSaveButton(false);
00420     dlg.setCaption(i18n("Attributes of Job %1@%2 (%3)").arg(j->id()).arg(j->printer()).arg(j->name()));
00421     if (dlg.exec())
00422     {
00423         opts.clear();
00424         // include default values to override non-default values
00425         dlg.getOptions(opts, true);
00426         // translate the "Copies" options from non-CUPS syntax
00427         opts["copies"] = opts["kde-copies"];
00428         opts["OutputOrder"] = opts["kde-pageorder"];
00429         opts["multiple-document-handling"] = (opts["kde-collate"] == "Collate" ? "separate-documents-collated-copies" : "separate-documents-uncollated-copies");
00430         opts["page-set"] = (opts["kde-pageset"] == "1" ? "odd" : (opts["kde-pageset"] == "2" ? "even" : "all"));
00431         // it seems CUPS is buggy. Disable page-ranges modification, otherwise nothing gets printed
00432         opts["page-ranges"] = processRange(opts["kde-range"]);
00433 
00434         req.init();
00435         req.setOperation(IPP_SET_JOB_ATTRIBUTES);
00436         req.addURI(IPP_TAG_OPERATION, "job-uri", j->uri());
00437         req.addName(IPP_TAG_OPERATION, "requesting-user-name", CupsInfos::self()->login());
00438         req.setMap(opts);
00439         //req.dump(1);
00440         if (!req.doRequest("/jobs/"))
00441         {
00442             KMManager::self()->setErrorMsg(i18n("Unable to set job attributes: ")+req.statusMessage());
00443             return false;
00444         }
00445     }
00446 
00447     return true;
00448 }
00449 
00450 #include "kmcupsjobmanager.moc"
KDE Logo
This file is part of the documentation for kdeprint Library Version 3.4.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Sep 15 10:58:22 2005 by doxygen 1.4.4 written by Dimitri van Heesch, © 1997-2003