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 = 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
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
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
00142
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
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
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);
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
00268
00269
00270
00271
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 );
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
00333
00334
00335
00336
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
00374
00375
00376
00377
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
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
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
00425 dlg.getOptions(opts, true);
00426
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
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
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"