00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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 <tdelocale.h>
00036 #include <kdebug.h>
00037 #include <kurl.h>
00038
00039 #include "config.h"
00040
00041 KMCupsJobManager::KMCupsJobManager(TQObject *parent, const char *name, const TQStringList & )
00042 : KMJobManager(parent,name)
00043 {
00044 }
00045
00046 KMCupsJobManager::~KMCupsJobManager()
00047 {
00048 }
00049
00050 int KMCupsJobManager::actions()
00051 {
00052 return KMJob::All;
00053 }
00054
00055 bool KMCupsJobManager::sendCommandSystemJob(const TQPtrList<KMJob>& jobs, int action, const TQString& argstr)
00056 {
00057 IppRequest req;
00058 TQString uri;
00059 bool value(true);
00060
00061 TQPtrListIterator<KMJob> it(jobs);
00062 for (;it.current() && value;++it)
00063 {
00064
00065
00066
00067 req.addURI(IPP_TAG_OPERATION,"job-uri",it.current()->uri());
00068 req.addName(IPP_TAG_OPERATION,"requesting-user-name",CupsInfos::self()->login());
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 switch (action)
00081 {
00082 case KMJob::Remove:
00083 req.setOperation(IPP_CANCEL_JOB);
00084 break;
00085 case KMJob::Hold:
00086 req.setOperation(IPP_HOLD_JOB);
00087 break;
00088 case KMJob::Resume:
00089 req.setOperation(IPP_RELEASE_JOB);
00090 break;
00091 case KMJob::Restart:
00092 req.setOperation(IPP_RESTART_JOB);
00093 break;
00094 case KMJob::Move:
00095 if (argstr.isEmpty()) return false;
00096 req.setOperation(CUPS_MOVE_JOB);
00097 uri =
00098 TQString::fromLatin1("ipp://%1/printers/%2").arg(CupsInfos::self()->hostaddr(),
00099 argstr);
00100 req.addURI(IPP_TAG_OPERATION, "job-printer-uri", uri);
00101 break;
00102 default:
00103 return false;
00104 }
00105
00106 if (!(value = req.doRequest("/jobs/")))
00107 KMManager::self()->setErrorMsg(req.statusMessage());
00108 }
00109
00110 return value;
00111 }
00112
00113 bool KMCupsJobManager::listJobs(const TQString& prname, KMJobManager::JobType type, int limit)
00114 {
00115 IppRequest req;
00116 TQStringList keys;
00117 CupsInfos *infos = CupsInfos::self();
00118
00119
00120 keys.append("job-id");
00121 keys.append("job-uri");
00122 keys.append("job-name");
00123 keys.append("job-state");
00124 keys.append("job-printer-uri");
00125 keys.append("job-k-octets");
00126 keys.append("job-originating-user-name");
00127 keys.append("job-k-octets-completed");
00128 keys.append("job-media-sheets");
00129 keys.append("job-media-sheets-completed");
00130 keys.append("job-priority");
00131 keys.append("job-billing");
00132
00133 req.setOperation(IPP_GET_JOBS);
00134
00135
00136 KMPrinter *mp = KMManager::self()->findPrinter(prname);
00137 if (!mp)
00138 return false;
00139
00140 if (!mp->uri().isEmpty())
00141 {
00142 req.addURI(IPP_TAG_OPERATION, "printer-uri", mp->uri().prettyURL());
00143
00144
00145
00146
00147 }
00148 else
00149 req.addURI(IPP_TAG_OPERATION, "printer-uri", TQString("ipp://%1/%2/%3").arg(infos->hostaddr(),
00150 (mp&&mp->isClass())?"classes":"printers", prname));
00151
00152
00153 req.addKeyword(IPP_TAG_OPERATION, "requested-attributes", keys);
00154 if (type == KMJobManager::CompletedJobs)
00155 req.addKeyword(IPP_TAG_OPERATION,"which-jobs",TQString::fromLatin1("completed"));
00156 if (limit > 0)
00157 req.addInteger(IPP_TAG_OPERATION,"limit",limit);
00158
00159
00160 if (req.doRequest("/"))
00161 parseListAnswer(req, mp);
00162 else
00163 return false;
00164
00165 return true;
00166 }
00167
00168 void KMCupsJobManager::parseListAnswer(IppRequest& req, KMPrinter *pr)
00169 {
00170 ipp_attribute_t *attr = req.first();
00171 ipp_attribute_t *nextAttr;
00172 KMJob *job = new KMJob();
00173 TQString uri;
00174 while (attr)
00175 {
00176 #ifdef HAVE_CUPS_1_6
00177 TQString name(ippGetName(attr));
00178 if (name == "job-id") job->setId(ippGetInteger(attr, 0));
00179 else if (name == "job-uri") job->setUri(TQString::fromLocal8Bit(ippGetString(attr, 0, NULL)));
00180 else if (name == "job-name") job->setName(TQString::fromLocal8Bit(ippGetString(attr, 0, NULL)));
00181 else if (name == "job-state")
00182 {
00183 switch (ippGetInteger(attr, 0))
00184 {
00185 case IPP_JOB_PENDING:
00186 job->setState(KMJob::Queued);
00187 break;
00188 case IPP_JOB_HELD:
00189 job->setState(KMJob::Held);
00190 break;
00191 case IPP_JOB_PROCESSING:
00192 job->setState(KMJob::Printing);
00193 break;
00194 case IPP_JOB_STOPPED:
00195 job->setState(KMJob::Error);
00196 break;
00197 case IPP_JOB_CANCELLED:
00198 job->setState(KMJob::Cancelled);
00199 break;
00200 case IPP_JOB_ABORTED:
00201 job->setState(KMJob::Aborted);
00202 break;
00203 case IPP_JOB_COMPLETED:
00204 job->setState(KMJob::Completed);
00205 break;
00206 default:
00207 job->setState(KMJob::Unknown);
00208 break;
00209 }
00210 }
00211 else if (name == "job-k-octets") job->setSize(ippGetInteger(attr, 0));
00212 else if (name == "job-originating-user-name") job->setOwner(TQString::fromLocal8Bit(ippGetString(attr, 0, NULL)));
00213 else if (name == "job-k-octets-completed") job->setProcessedSize(ippGetInteger(attr, 0));
00214 else if (name == "job-media-sheets") job->setPages(ippGetInteger(attr, 0));
00215 else if (name == "job-media-sheets-completed") job->setProcessedPages(ippGetInteger(attr, 0));
00216 else if (name == "job-printer-uri" && !pr->isRemote())
00217 {
00218 TQString str(ippGetString(attr, 0, NULL));
00219 int p = str.findRev('/');
00220 if (p != -1)
00221 job->setPrinter(str.mid(p+1));
00222 }
00223 else if (name == "job-priority")
00224 {
00225 job->setAttribute(0, TQString::fromLatin1("%1").arg(ippGetInteger(attr, 0), 3));
00226 }
00227 else if (name == "job-billing")
00228 {
00229 job->setAttributeCount(2);
00230 job->setAttribute(1, TQString::fromLocal8Bit(ippGetString(attr, 0, NULL)));
00231 }
00232
00233 nextAttr = ippNextAttribute(req.request());
00234 if (name.isEmpty() || (!nextAttr))
00235 {
00236 if (job->printer().isEmpty())
00237 job->setPrinter(pr->printerName());
00238 job->setRemote(pr->isRemote());
00239 addJob(job);
00240 job = new KMJob();
00241 }
00242 attr = nextAttr;
00243 #else // HAVE_CUPS_1_6
00244 TQString name(attr->name);
00245 if (name == "job-id") job->setId(attr->values[0].integer);
00246 else if (name == "job-uri") job->setUri(TQString::fromLocal8Bit(attr->values[0].string.text));
00247 else if (name == "job-name") job->setName(TQString::fromLocal8Bit(attr->values[0].string.text));
00248 else if (name == "job-state")
00249 {
00250 switch (attr->values[0].integer)
00251 {
00252 case IPP_JOB_PENDING:
00253 job->setState(KMJob::Queued);
00254 break;
00255 case IPP_JOB_HELD:
00256 job->setState(KMJob::Held);
00257 break;
00258 case IPP_JOB_PROCESSING:
00259 job->setState(KMJob::Printing);
00260 break;
00261 case IPP_JOB_STOPPED:
00262 job->setState(KMJob::Error);
00263 break;
00264 case IPP_JOB_CANCELLED:
00265 job->setState(KMJob::Cancelled);
00266 break;
00267 case IPP_JOB_ABORTED:
00268 job->setState(KMJob::Aborted);
00269 break;
00270 case IPP_JOB_COMPLETED:
00271 job->setState(KMJob::Completed);
00272 break;
00273 default:
00274 job->setState(KMJob::Unknown);
00275 break;
00276 }
00277 }
00278 else if (name == "job-k-octets") job->setSize(attr->values[0].integer);
00279 else if (name == "job-originating-user-name") job->setOwner(TQString::fromLocal8Bit(attr->values[0].string.text));
00280 else if (name == "job-k-octets-completed") job->setProcessedSize(attr->values[0].integer);
00281 else if (name == "job-media-sheets") job->setPages(attr->values[0].integer);
00282 else if (name == "job-media-sheets-completed") job->setProcessedPages(attr->values[0].integer);
00283 else if (name == "job-printer-uri" && !pr->isRemote())
00284 {
00285 TQString str(attr->values[0].string.text);
00286 int p = str.findRev('/');
00287 if (p != -1)
00288 job->setPrinter(str.mid(p+1));
00289 }
00290 else if (name == "job-priority")
00291 {
00292 job->setAttribute(0, TQString::fromLatin1("%1").arg(attr->values[0].integer, 3));
00293 }
00294 else if (name == "job-billing")
00295 {
00296 job->setAttributeCount(2);
00297 job->setAttribute(1, TQString::fromLocal8Bit(attr->values[0].string.text));
00298 }
00299
00300 if (name.isEmpty() || attr == req.last())
00301 {
00302 if (job->printer().isEmpty())
00303 job->setPrinter(pr->printerName());
00304 job->setRemote(pr->isRemote());
00305 addJob(job);
00306 job = new KMJob();
00307 }
00308
00309 attr = attr->next;
00310 #endif // HAVE_CUPS_1_6
00311 }
00312 delete job;
00313 }
00314
00315 bool KMCupsJobManager::doPluginAction(int ID, const TQPtrList<KMJob>& jobs)
00316 {
00317 switch (ID)
00318 {
00319 case 0:
00320 if (jobs.count() == 1)
00321 return jobIppReport(jobs.getFirst());
00322 break;
00323 case 1:
00324 return changePriority(jobs, true);
00325 case 2:
00326 return changePriority(jobs, false);
00327 case 3:
00328 return editJobAttributes(jobs.getFirst());
00329 }
00330 return false;
00331 }
00332
00333 bool KMCupsJobManager::jobIppReport(KMJob *j)
00334 {
00335 IppRequest req;
00336
00337 req.setOperation(IPP_GET_JOB_ATTRIBUTES);
00338 req.addURI(IPP_TAG_OPERATION, "job-uri", j->uri());
00339 bool result(true);
00340
00341
00342
00343
00344
00345
00346
00347
00348 if ((result=req.doRequest("/")))
00349 static_cast<KMCupsManager*>(KMManager::self())->ippReport(req, IPP_TAG_JOB, i18n("Job Report"));
00350 else
00351 KMManager::self()->setErrorMsg(i18n("Unable to retrieve job information: ")+req.statusMessage());
00352 return result;
00353 }
00354
00355 TQValueList<TDEAction*> KMCupsJobManager::createPluginActions(TDEActionCollection *coll)
00356 {
00357 TQValueList<TDEAction*> list;
00358 TDEAction *act(0);
00359
00360 list << (act = new PluginAction(0, i18n("&Job IPP Report"), "tdeprint_report", 0, coll, "plugin_ipp"));
00361 act->setGroup("plugin");
00362 list << (act = new PluginAction(1, i18n("&Increase Priority"), "go-up", 0, coll, "plugin_prioup"));
00363 act->setGroup("plugin");
00364 list << (act = new PluginAction(2, i18n("&Decrease Priority"), "go-down", 0, coll, "plugin_priodown"));
00365 act->setGroup("plugin");
00366 list << (act = new PluginAction(3, i18n("&Edit Attributes..."), "edit", 0, coll, "plugin_editjob"));
00367 act->setGroup("plugin");
00368
00369 return list;
00370 }
00371
00372 void KMCupsJobManager::validatePluginActions(TDEActionCollection *coll, const TQPtrList<KMJob>& joblist)
00373 {
00374 TQPtrListIterator<KMJob> it(joblist);
00375 bool flag(true);
00376 for (; it.current(); ++it)
00377 {
00378 flag = (flag && it.current()->type() == KMJob::System
00379 && (it.current()->state() == KMJob::Queued || it.current()->state() == KMJob::Held)
00380 );
00381 }
00382 flag = (flag && joblist.count() > 0);
00383 TDEAction *a;
00384 if ( ( a = coll->action( "plugin_ipp" ) ) )
00385 a->setEnabled( joblist.count() == 1 );
00386 if ( ( a = coll->action( "plugin_prioup" ) ) )
00387 a->setEnabled( flag );
00388 if ( ( a = coll->action( "plugin_priodown" ) ) )
00389 a->setEnabled( flag );
00390 if ( ( a = coll->action( "plugin_editjob" ) ) )
00391 a->setEnabled( flag && ( joblist.count() == 1 ) );
00392 }
00393
00394 bool KMCupsJobManager::changePriority(const TQPtrList<KMJob>& jobs, bool up)
00395 {
00396 TQPtrListIterator<KMJob> it(jobs);
00397 bool result(true);
00398 for (; it.current() && result; ++it)
00399 {
00400 int value = it.current()->attribute(0).toInt();
00401 if (up) value = TQMIN(value+10, 100);
00402 else value = TQMAX(value-10, 1);
00403
00404 IppRequest req;
00405
00406
00407
00408
00409
00410
00411
00412
00413 req.setOperation(IPP_SET_JOB_ATTRIBUTES);
00414 req.addURI(IPP_TAG_OPERATION, "job-uri", it.current()->uri());
00415 req.addName(IPP_TAG_OPERATION, "requesting-user-name", CupsInfos::self()->login());
00416 req.addInteger(IPP_TAG_JOB, "job-priority", value);
00417
00418 if (!(result = req.doRequest("/jobs/")))
00419 KMManager::self()->setErrorMsg(i18n("Unable to change job priority: ")+req.statusMessage());
00420 }
00421 return result;
00422 }
00423
00424 static TQString processRange(const TQString& range)
00425 {
00426 TQStringList l = TQStringList::split(',', range, false);
00427 TQString s;
00428 for (TQStringList::ConstIterator it=l.begin(); it!=l.end(); ++it)
00429 {
00430 s.append(*it);
00431 if ((*it).find('-') == -1)
00432 s.append("-").append(*it);
00433 s.append(",");
00434 }
00435 if (!s.isEmpty())
00436 s.truncate(s.length()-1);
00437 return s;
00438 }
00439
00440 bool KMCupsJobManager::editJobAttributes(KMJob *j)
00441 {
00442 IppRequest req;
00443
00444 req.setOperation(IPP_GET_JOB_ATTRIBUTES);
00445 req.addURI(IPP_TAG_OPERATION, "job-uri", j->uri());
00446
00447
00448
00449
00450
00451
00452
00453
00454 if (!req.doRequest("/"))
00455 {
00456 KMManager::self()->setErrorMsg(i18n("Unable to retrieve job information: ")+req.statusMessage());
00457 return false;
00458 }
00459
00460 TQMap<TQString,TQString> opts = req.toMap(IPP_TAG_JOB);
00461
00462 if (opts.contains("copies"))
00463 opts["kde-copies"] = opts["copies"];
00464 if (opts.contains("page-set"))
00465 opts["kde-pageset"] = (opts["page-set"] == "even" ? "2" : (opts["page-set"] == "odd" ? "1" : "0"));
00466 if (opts.contains("OutputOrder"))
00467 opts["kde-pageorder"] = opts["OutputOrder"];
00468 if (opts.contains("multiple-document-handling"))
00469 opts["kde-collate"] = (opts["multiple-document-handling"] == "separate-documents-collated-copies" ? "Collate" : "Uncollate");
00470 if (opts.contains("page-ranges"))
00471 opts["kde-range"] = opts["page-ranges"];
00472
00473
00474 KMPrinter *prt = KMManager::self()->findPrinter(j->printer());
00475 if (!prt)
00476 {
00477 KMManager::self()->setErrorMsg(i18n("Unable to find printer %1.").arg(j->printer()));
00478 return false;
00479 }
00480 KMManager::self()->completePrinterShort(prt);
00481 KPrinter::ApplicationType oldAppType = KPrinter::applicationType();
00482 KPrinter::setApplicationType(KPrinter::StandAlone);
00483 KPrinterPropertyDialog dlg(prt);
00484 dlg.setDriver(KMManager::self()->loadPrinterDriver(prt));
00485 KMFactory::self()->uiManager()->setupPrinterPropertyDialog(&dlg);
00486 KPrinter::setApplicationType( oldAppType );
00487 if (dlg.driver())
00488 dlg.addPage(new KPDriverPage(prt, dlg.driver(), &dlg));
00489 dlg.addPage(new KPCopiesPage(0, &dlg));
00490 dlg.addPage(new KPSchedulePage(&dlg));
00491 dlg.addPage(new KPTagsPage(true, &dlg));
00492 dlg.setOptions(opts);
00493 dlg.enableSaveButton(false);
00494 dlg.setCaption(i18n("Attributes of Job %1@%2 (%3)").arg(j->id()).arg(j->printer()).arg(j->name()));
00495 if (dlg.exec())
00496 {
00497 opts.clear();
00498
00499 dlg.getOptions(opts, true);
00500
00501 opts["copies"] = opts["kde-copies"];
00502 opts["OutputOrder"] = opts["kde-pageorder"];
00503 opts["multiple-document-handling"] = (opts["kde-collate"] == "Collate" ? "separate-documents-collated-copies" : "separate-documents-uncollated-copies");
00504 opts["page-set"] = (opts["kde-pageset"] == "1" ? "odd" : (opts["kde-pageset"] == "2" ? "even" : "all"));
00505
00506 opts["page-ranges"] = processRange(opts["kde-range"]);
00507
00508 req.init();
00509 req.setOperation(IPP_SET_JOB_ATTRIBUTES);
00510 req.addURI(IPP_TAG_OPERATION, "job-uri", j->uri());
00511 req.addName(IPP_TAG_OPERATION, "requesting-user-name", CupsInfos::self()->login());
00512 req.setMap(opts);
00513
00514 if (!req.doRequest("/jobs/"))
00515 {
00516 KMManager::self()->setErrorMsg(i18n("Unable to set job attributes: ")+req.statusMessage());
00517 return false;
00518 }
00519 }
00520
00521 return true;
00522 }
00523
00524 #include "kmcupsjobmanager.moc"