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.2.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sun Oct 10 18:55:54 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003