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 <klocale.h>
00036 #include <kdebug.h>
00037 #include <kurl.h>
00038
00039 KMCupsJobManager::KMCupsJobManager(QObject *parent, const char *name, const QStringList & )
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
00063
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
00069
00070
00071
00072
00073
00074
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 =
00096 QString::fromLatin1("ipp://%1/printers/%2").arg(CupsInfos::self()->hostaddr(),
00097 argstr);
00098 req.addURI(IPP_TAG_OPERATION, "job-printer-uri", uri);
00099 break;
00100 default:
00101 return false;
00102 }
00103
00104 if (!(value = req.doRequest("/jobs/")))
00105 KMManager::self()->setErrorMsg(req.statusMessage());
00106 }
00107
00108 return value;
00109 }
00110
00111 bool KMCupsJobManager::listJobs(const QString& prname, KMJobManager::JobType type, int limit)
00112 {
00113 IppRequest req;
00114 QStringList keys;
00115 CupsInfos *infos = CupsInfos::self();
00116
00117
00118 keys.append("job-id");
00119 keys.append("job-uri");
00120 keys.append("job-name");
00121 keys.append("job-state");
00122 keys.append("job-printer-uri");
00123 keys.append("job-k-octets");
00124 keys.append("job-originating-user-name");
00125 keys.append("job-k-octets-completed");
00126 keys.append("job-media-sheets");
00127 keys.append("job-media-sheets-completed");
00128 keys.append("job-priority");
00129 keys.append("job-billing");
00130
00131 req.setOperation(IPP_GET_JOBS);
00132
00133
00134 KMPrinter *mp = KMManager::self()->findPrinter(prname);
00135 if (!mp)
00136 return false;
00137
00138 if (!mp->uri().isEmpty())
00139 {
00140 req.addURI(IPP_TAG_OPERATION, "printer-uri", mp->uri().prettyURL());
00141
00142
00143
00144
00145 }
00146 else
00147 req.addURI(IPP_TAG_OPERATION, "printer-uri", QString("ipp://%1/%2/%3").arg(infos->hostaddr(),
00148 (mp&&mp->isClass())?"classes":"printers", prname));
00149
00150
00151 req.addKeyword(IPP_TAG_OPERATION, "requested-attributes", keys);
00152 if (type == KMJobManager::CompletedJobs)
00153 req.addKeyword(IPP_TAG_OPERATION,"which-jobs",QString::fromLatin1("completed"));
00154 if (limit > 0)
00155 req.addInteger(IPP_TAG_OPERATION,"limit",limit);
00156
00157
00158 if (req.doRequest("/"))
00159 parseListAnswer(req, mp);
00160 else
00161 return false;
00162
00163 return true;
00164 }
00165
00166 void KMCupsJobManager::parseListAnswer(IppRequest& req, KMPrinter *pr)
00167 {
00168 ipp_attribute_t *attr = req.first();
00169 KMJob *job = new KMJob();
00170 QString uri;
00171 while (attr)
00172 {
00173 QString name(attr->name);
00174 if (name == "job-id") job->setId(attr->values[0].integer);
00175 else if (name == "job-uri") job->setUri(QString::fromLocal8Bit(attr->values[0].string.text));
00176 else if (name == "job-name") job->setName(QString::fromLocal8Bit(attr->values[0].string.text));
00177 else if (name == "job-state")
00178 {
00179 switch (attr->values[0].integer)
00180 {
00181 case IPP_JOB_PENDING:
00182 job->setState(KMJob::Queued);
00183 break;
00184 case IPP_JOB_HELD:
00185 job->setState(KMJob::Held);
00186 break;
00187 case IPP_JOB_PROCESSING:
00188 job->setState(KMJob::Printing);
00189 break;
00190 case IPP_JOB_STOPPED:
00191 job->setState(KMJob::Error);
00192 break;
00193 case IPP_JOB_CANCELLED:
00194 job->setState(KMJob::Cancelled);
00195 break;
00196 case IPP_JOB_ABORTED:
00197 job->setState(KMJob::Aborted);
00198 break;
00199 case IPP_JOB_COMPLETED:
00200 job->setState(KMJob::Completed);
00201 break;
00202 default:
00203 job->setState(KMJob::Unknown);
00204 break;
00205 }
00206 }
00207 else if (name == "job-k-octets") job->setSize(attr->values[0].integer);
00208 else if (name == "job-originating-user-name") job->setOwner(QString::fromLocal8Bit(attr->values[0].string.text));
00209 else if (name == "job-k-octets-completed") job->setProcessedSize(attr->values[0].integer);
00210 else if (name == "job-media-sheets") job->setPages(attr->values[0].integer);
00211 else if (name == "job-media-sheets-completed") job->setProcessedPages(attr->values[0].integer);
00212 else if (name == "job-printer-uri" && !pr->isRemote())
00213 {
00214 QString str(attr->values[0].string.text);
00215 int p = str.findRev('/');
00216 if (p != -1)
00217 job->setPrinter(str.mid(p+1));
00218 }
00219 else if (name == "job-priority")
00220 {
00221 job->setAttribute(0, QString::fromLatin1("%1").arg(attr->values[0].integer, 3));
00222 }
00223 else if (name == "job-billing")
00224 {
00225 job->setAttributeCount(2);
00226 job->setAttribute(1, QString::fromLocal8Bit(attr->values[0].string.text));
00227 }
00228
00229 if (name.isEmpty() || attr == req.last())
00230 {
00231 if (job->printer().isEmpty())
00232 job->setPrinter(pr->printerName());
00233 job->setRemote(pr->isRemote());
00234 addJob(job);
00235 job = new KMJob();
00236 }
00237
00238 attr = attr->next;
00239 }
00240 delete job;
00241 }
00242
00243 bool KMCupsJobManager::doPluginAction(int ID, const QPtrList<KMJob>& jobs)
00244 {
00245 switch (ID)
00246 {
00247 case 0:
00248 if (jobs.count() == 1)
00249 return jobIppReport(jobs.getFirst());
00250 break;
00251 case 1:
00252 return changePriority(jobs, true);
00253 case 2:
00254 return changePriority(jobs, false);
00255 case 3:
00256 return editJobAttributes(jobs.getFirst());
00257 }
00258 return false;
00259 }
00260
00261 bool KMCupsJobManager::jobIppReport(KMJob *j)
00262 {
00263 IppRequest req;
00264
00265 req.setOperation(IPP_GET_JOB_ATTRIBUTES);
00266 req.addURI(IPP_TAG_OPERATION, "job-uri", j->uri());
00267 bool result(true);
00268
00269
00270
00271
00272
00273
00274
00275
00276 if ((result=req.doRequest("/")))
00277 static_cast<KMCupsManager*>(KMManager::self())->ippReport(req, IPP_TAG_JOB, i18n("Job Report"));
00278 else
00279 KMManager::self()->setErrorMsg(i18n("Unable to retrieve job information: ")+req.statusMessage());
00280 return result;
00281 }
00282
00283 QValueList<KAction*> KMCupsJobManager::createPluginActions(KActionCollection *coll)
00284 {
00285 QValueList<KAction*> list;
00286 KAction *act(0);
00287
00288 list << (act = new PluginAction(0, i18n("&Job IPP Report"), "kdeprint_report", 0, coll, "plugin_ipp"));
00289 act->setGroup("plugin");
00290 list << (act = new PluginAction(1, i18n("&Increase Priority"), "up", 0, coll, "plugin_prioup"));
00291 act->setGroup("plugin");
00292 list << (act = new PluginAction(2, i18n("&Decrease Priority"), "down", 0, coll, "plugin_priodown"));
00293 act->setGroup("plugin");
00294 list << (act = new PluginAction(3, i18n("&Edit Attributes..."), "edit", 0, coll, "plugin_editjob"));
00295 act->setGroup("plugin");
00296
00297 return list;
00298 }
00299
00300 void KMCupsJobManager::validatePluginActions(KActionCollection *coll, const QPtrList<KMJob>& joblist)
00301 {
00302 QPtrListIterator<KMJob> it(joblist);
00303 bool flag(true);
00304 for (; it.current(); ++it)
00305 {
00306 flag = (flag && it.current()->type() == KMJob::System
00307 && (it.current()->state() == KMJob::Queued || it.current()->state() == KMJob::Held)
00308 );
00309 }
00310 flag = (flag && joblist.count() > 0);
00311 KAction *a;
00312 if ( ( a = coll->action( "plugin_ipp" ) ) )
00313 a->setEnabled( joblist.count() == 1 );
00314 if ( ( a = coll->action( "plugin_prioup" ) ) )
00315 a->setEnabled( flag );
00316 if ( ( a = coll->action( "plugin_priodown" ) ) )
00317 a->setEnabled( flag );
00318 if ( ( a = coll->action( "plugin_editjob" ) ) )
00319 a->setEnabled( flag && ( joblist.count() == 1 ) );
00320 }
00321
00322 bool KMCupsJobManager::changePriority(const QPtrList<KMJob>& jobs, bool up)
00323 {
00324 QPtrListIterator<KMJob> it(jobs);
00325 bool result(true);
00326 for (; it.current() && result; ++it)
00327 {
00328 int value = it.current()->attribute(0).toInt();
00329 if (up) value = QMIN(value+10, 100);
00330 else value = QMAX(value-10, 1);
00331
00332 IppRequest req;
00333
00334
00335
00336
00337
00338
00339
00340
00341 req.setOperation(IPP_SET_JOB_ATTRIBUTES);
00342 req.addURI(IPP_TAG_OPERATION, "job-uri", it.current()->uri());
00343 req.addName(IPP_TAG_OPERATION, "requesting-user-name", CupsInfos::self()->login());
00344 req.addInteger(IPP_TAG_JOB, "job-priority", value);
00345
00346 if (!(result = req.doRequest("/jobs/")))
00347 KMManager::self()->setErrorMsg(i18n("Unable to change job priority: ")+req.statusMessage());
00348 }
00349 return result;
00350 }
00351
00352 static QString processRange(const QString& range)
00353 {
00354 QStringList l = QStringList::split(',', range, false);
00355 QString s;
00356 for (QStringList::ConstIterator it=l.begin(); it!=l.end(); ++it)
00357 {
00358 s.append(*it);
00359 if ((*it).find('-') == -1)
00360 s.append("-").append(*it);
00361 s.append(",");
00362 }
00363 if (!s.isEmpty())
00364 s.truncate(s.length()-1);
00365 return s;
00366 }
00367
00368 bool KMCupsJobManager::editJobAttributes(KMJob *j)
00369 {
00370 IppRequest req;
00371
00372 req.setOperation(IPP_GET_JOB_ATTRIBUTES);
00373 req.addURI(IPP_TAG_OPERATION, "job-uri", j->uri());
00374
00375
00376
00377
00378
00379
00380
00381
00382 if (!req.doRequest("/"))
00383 {
00384 KMManager::self()->setErrorMsg(i18n("Unable to retrieve job information: ")+req.statusMessage());
00385 return false;
00386 }
00387
00388 QMap<QString,QString> opts = req.toMap(IPP_TAG_JOB);
00389
00390 if (opts.contains("copies"))
00391 opts["kde-copies"] = opts["copies"];
00392 if (opts.contains("page-set"))
00393 opts["kde-pageset"] = (opts["page-set"] == "even" ? "2" : (opts["page-set"] == "odd" ? "1" : "0"));
00394 if (opts.contains("OutputOrder"))
00395 opts["kde-pageorder"] = opts["OutputOrder"];
00396 if (opts.contains("multiple-document-handling"))
00397 opts["kde-collate"] = (opts["multiple-document-handling"] == "separate-documents-collated-copies" ? "Collate" : "Uncollate");
00398 if (opts.contains("page-ranges"))
00399 opts["kde-range"] = opts["page-ranges"];
00400
00401
00402 KMPrinter *prt = KMManager::self()->findPrinter(j->printer());
00403 if (!prt)
00404 {
00405 KMManager::self()->setErrorMsg(i18n("Unable to find printer %1.").arg(j->printer()));
00406 return false;
00407 }
00408 KMManager::self()->completePrinterShort(prt);
00409 KPrinter::ApplicationType oldAppType = KPrinter::applicationType();
00410 KPrinter::setApplicationType(KPrinter::StandAlone);
00411 KPrinterPropertyDialog dlg(prt);
00412 dlg.setDriver(KMManager::self()->loadPrinterDriver(prt));
00413 KMFactory::self()->uiManager()->setupPrinterPropertyDialog(&dlg);
00414 KPrinter::setApplicationType( oldAppType );
00415 if (dlg.driver())
00416 dlg.addPage(new KPDriverPage(prt, dlg.driver(), &dlg));
00417 dlg.addPage(new KPCopiesPage(0, &dlg));
00418 dlg.addPage(new KPSchedulePage(&dlg));
00419 dlg.addPage(new KPTagsPage(true, &dlg));
00420 dlg.setOptions(opts);
00421 dlg.enableSaveButton(false);
00422 dlg.setCaption(i18n("Attributes of Job %1@%2 (%3)").arg(j->id()).arg(j->printer()).arg(j->name()));
00423 if (dlg.exec())
00424 {
00425 opts.clear();
00426
00427 dlg.getOptions(opts, true);
00428
00429 opts["copies"] = opts["kde-copies"];
00430 opts["OutputOrder"] = opts["kde-pageorder"];
00431 opts["multiple-document-handling"] = (opts["kde-collate"] == "Collate" ? "separate-documents-collated-copies" : "separate-documents-uncollated-copies");
00432 opts["page-set"] = (opts["kde-pageset"] == "1" ? "odd" : (opts["kde-pageset"] == "2" ? "even" : "all"));
00433
00434 opts["page-ranges"] = processRange(opts["kde-range"]);
00435
00436 req.init();
00437 req.setOperation(IPP_SET_JOB_ATTRIBUTES);
00438 req.addURI(IPP_TAG_OPERATION, "job-uri", j->uri());
00439 req.addName(IPP_TAG_OPERATION, "requesting-user-name", CupsInfos::self()->login());
00440 req.setMap(opts);
00441
00442 if (!req.doRequest("/jobs/"))
00443 {
00444 KMManager::self()->setErrorMsg(i18n("Unable to set job attributes: ")+req.statusMessage());
00445 return false;
00446 }
00447 }
00448
00449 return true;
00450 }
00451
00452 #include "kmcupsjobmanager.moc"