File indexing completed on 2025-01-05 05:09:29
0001 /* 0002 SPDX-FileCopyrightText: 2010-2018 Daniel Nicoletti <dantti12@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "JobModel.h" 0008 0009 #include "kcupslib_log.h" 0010 0011 #include <KCupsJob.h> 0012 #include <KCupsPrinter.h> 0013 #include <KCupsRequest.h> 0014 0015 #include <QDateTime> 0016 #include <QIODevice> 0017 #include <QMimeData> 0018 #include <QPointer> 0019 0020 #include <KFormat> 0021 #include <KLocalizedString> 0022 #include <KMessageBox> 0023 #include <KUser> 0024 0025 JobModel::JobModel(QObject *parent) 0026 : QStandardItemModel(parent) 0027 { 0028 setHorizontalHeaderItem(ColStatus, new QStandardItem(i18n("Status"))); 0029 setHorizontalHeaderItem(ColName, new QStandardItem(i18n("Name"))); 0030 setHorizontalHeaderItem(ColUser, new QStandardItem(i18n("User"))); 0031 setHorizontalHeaderItem(ColCreated, new QStandardItem(i18n("Created"))); 0032 setHorizontalHeaderItem(ColCompleted, new QStandardItem(i18n("Completed"))); 0033 setHorizontalHeaderItem(ColPages, new QStandardItem(i18n("Pages"))); 0034 setHorizontalHeaderItem(ColProcessed, new QStandardItem(i18n("Processed"))); 0035 setHorizontalHeaderItem(ColSize, new QStandardItem(i18n("Size"))); 0036 setHorizontalHeaderItem(ColStatusMessage, new QStandardItem(i18n("Status Message"))); 0037 setHorizontalHeaderItem(ColPrinter, new QStandardItem(i18n("Printer"))); 0038 setHorizontalHeaderItem(ColFromHost, new QStandardItem(i18n("From Hostname"))); 0039 0040 m_roles = QStandardItemModel::roleNames(); 0041 m_roles[RoleJobId] = "jobId"; 0042 m_roles[RoleJobState] = "jobState"; 0043 m_roles[RoleJobName] = "jobName"; 0044 m_roles[RoleJobPages] = "jobPages"; 0045 m_roles[RoleJobSize] = "jobSize"; 0046 m_roles[RoleJobOwner] = "jobOwner"; 0047 m_roles[RoleJobCreatedAt] = "jobCreatedAt"; 0048 m_roles[RoleJobIconName] = "jobIconName"; 0049 m_roles[RoleJobCancelEnabled] = "jobCancelEnabled"; 0050 m_roles[RoleJobHoldEnabled] = "jobHoldEnabled"; 0051 m_roles[RoleJobReleaseEnabled] = "jobReleaseEnabled"; 0052 m_roles[RoleJobRestartEnabled] = "jobRestartEnabled"; 0053 m_roles[RoleJobPrinter] = "jobPrinter"; 0054 m_roles[RoleJobOriginatingHostName] = "jobFrom"; 0055 0056 // This is emitted when a job change it's state 0057 connect(KCupsConnection::global(), &KCupsConnection::jobState, this, &JobModel::insertUpdateJob); 0058 0059 // This is emitted when a job is created 0060 connect(KCupsConnection::global(), &KCupsConnection::jobCreated, this, &JobModel::insertUpdateJob); 0061 0062 // This is emitted when a job is stopped 0063 connect(KCupsConnection::global(), &KCupsConnection::jobStopped, this, &JobModel::insertUpdateJob); 0064 0065 // This is emitted when a job has it's config changed 0066 connect(KCupsConnection::global(), &KCupsConnection::jobConfigChanged, this, &JobModel::insertUpdateJob); 0067 0068 // This is emitted when a job change it's progress 0069 connect(KCupsConnection::global(), &KCupsConnection::jobProgress, this, &JobModel::insertUpdateJob); 0070 0071 // This is emitted when a printer is removed 0072 connect(KCupsConnection::global(), &KCupsConnection::jobCompleted, this, &JobModel::jobCompleted); 0073 0074 connect(KCupsConnection::global(), &KCupsConnection::serverAudit, this, &JobModel::getJobs); 0075 connect(KCupsConnection::global(), &KCupsConnection::serverStarted, this, &JobModel::getJobs); 0076 connect(KCupsConnection::global(), &KCupsConnection::serverStopped, this, &JobModel::getJobs); 0077 connect(KCupsConnection::global(), &KCupsConnection::serverRestarted, this, &JobModel::getJobs); 0078 } 0079 0080 void JobModel::setParentWId(WId parentId) 0081 { 0082 m_parentId = parentId; 0083 } 0084 0085 void JobModel::init(const QString &destName) 0086 { 0087 m_destName = destName; 0088 0089 // Get all jobs 0090 getJobs(); 0091 } 0092 0093 void JobModel::hold(const QString &printerName, int jobId) 0094 { 0095 QPointer<KCupsRequest> request = new KCupsRequest; 0096 request->holdJob(printerName, jobId); 0097 request->waitTillFinished(); 0098 if (request) { 0099 request->deleteLater(); 0100 } 0101 } 0102 0103 void JobModel::release(const QString &printerName, int jobId) 0104 { 0105 QPointer<KCupsRequest> request = new KCupsRequest; 0106 request->releaseJob(printerName, jobId); 0107 request->waitTillFinished(); 0108 if (request) { 0109 request->deleteLater(); 0110 } 0111 } 0112 0113 void JobModel::cancel(const QString &printerName, int jobId) 0114 { 0115 QPointer<KCupsRequest> request = new KCupsRequest; 0116 request->cancelJob(printerName, jobId); 0117 request->waitTillFinished(); 0118 if (request) { 0119 request->deleteLater(); 0120 } 0121 } 0122 0123 void JobModel::move(const QString &printerName, int jobId, const QString &toPrinterName) 0124 { 0125 QPointer<KCupsRequest> request = new KCupsRequest; 0126 request->moveJob(printerName, jobId, toPrinterName); 0127 request->waitTillFinished(); 0128 if (request) { 0129 request->deleteLater(); 0130 } 0131 } 0132 0133 void JobModel::getJobs() 0134 { 0135 if (m_jobRequest) { 0136 return; 0137 } 0138 0139 m_jobRequest = new KCupsRequest; 0140 connect(m_jobRequest, &KCupsRequest::finished, this, &JobModel::getJobFinished); 0141 0142 const static QStringList attrs({KCUPS_JOB_ID, 0143 KCUPS_JOB_NAME, 0144 KCUPS_JOB_K_OCTETS, 0145 KCUPS_JOB_K_OCTETS_PROCESSED, 0146 KCUPS_JOB_STATE, 0147 KCUPS_JOB_STATE_REASONS, 0148 KCUPS_JOB_HOLD_UNTIL, 0149 KCUPS_TIME_AT_COMPLETED, 0150 KCUPS_TIME_AT_CREATION, 0151 KCUPS_TIME_AT_PROCESSING, 0152 KCUPS_JOB_PRINTER_URI, 0153 KCUPS_JOB_ORIGINATING_USER_NAME, 0154 KCUPS_JOB_ORIGINATING_HOST_NAME, 0155 KCUPS_JOB_MEDIA_PROGRESS, 0156 KCUPS_JOB_MEDIA_SHEETS, 0157 KCUPS_JOB_MEDIA_SHEETS_COMPLETED, 0158 KCUPS_JOB_PRINTER_STATE_MESSAGE, 0159 KCUPS_JOB_PRESERVED}); 0160 m_jobRequest->getJobs(m_destName, false, m_whichjobs, attrs); 0161 0162 m_processingJob.clear(); 0163 } 0164 0165 static KCupsJobs sanitizeJobs(KCupsJobs jobs) 0166 { 0167 // For some reason sometimes cups has broken job queues with jobs with duplicated id 0168 // our model doesn't like that at all so sanitize the job list before processing it 0169 QVector<int> seenIds; 0170 int i = 0; 0171 while (i < jobs.count()) { 0172 const int jobId = jobs.at(i).id(); 0173 if (seenIds.contains(jobId)) { 0174 qCWarning(LIBKCUPS) << "Found job with duplicated id" << jobId; 0175 jobs.removeAt(i); 0176 } else { 0177 seenIds << jobId; 0178 ++i; 0179 } 0180 } 0181 return jobs; 0182 } 0183 0184 void JobModel::getJobFinished(KCupsRequest *request) 0185 { 0186 if (request) { 0187 if (request->hasError()) { 0188 // clear the model after so that the proper widget can be shown 0189 clear(); 0190 } else { 0191 const KCupsJobs jobs = sanitizeJobs(request->jobs()); 0192 qCDebug(LIBKCUPS) << jobs.size(); 0193 for (int i = 0; i < jobs.size(); ++i) { 0194 const KCupsJob job = jobs.at(i); 0195 if (job.state() == IPP_JOB_PROCESSING) { 0196 m_processingJob = job.name(); 0197 } 0198 0199 // try to find the job row 0200 const int job_row = jobRow(job.id()); 0201 if (job_row == -1) { 0202 // not found, insert new one 0203 insertJob(i, job); 0204 } else { 0205 // update the job 0206 updateJob(job_row, job); 0207 0208 if (job_row != i) { 0209 // found at wrong position 0210 // take it and insert on the right position 0211 const QList<QStandardItem *> row = takeRow(job_row); 0212 insertRow(i, row); 0213 } 0214 } 0215 } 0216 0217 // remove old jobs 0218 // The above code starts from 0 and make sure 0219 // dest == modelIndex(x) and if it's not the 0220 // case it either inserts or moves it. 0221 // so any item > num_jobs can be safely deleted 0222 while (rowCount() > jobs.size()) { 0223 removeRow(rowCount() - 1); 0224 } 0225 } 0226 request->deleteLater(); 0227 } else { 0228 qCWarning(LIBKCUPS) << "Should not be called from a non KCupsRequest class" << sender(); 0229 } 0230 m_jobRequest = nullptr; 0231 } 0232 0233 void JobModel::jobCompleted(const QString &text, 0234 const QString &printerUri, 0235 const QString &printerName, 0236 uint printerState, 0237 const QString &printerStateReasons, 0238 bool printerIsAcceptingJobs, 0239 uint jobId, 0240 uint jobState, 0241 const QString &jobStateReasons, 0242 const QString &jobName, 0243 uint jobImpressionsCompleted) 0244 { 0245 // REALLY? all these parameters just to say foo was deleted?? 0246 Q_UNUSED(text) 0247 Q_UNUSED(printerUri) 0248 Q_UNUSED(printerName) 0249 Q_UNUSED(printerState) 0250 Q_UNUSED(printerStateReasons) 0251 Q_UNUSED(printerIsAcceptingJobs) 0252 Q_UNUSED(jobId) 0253 Q_UNUSED(jobState) 0254 Q_UNUSED(jobStateReasons) 0255 Q_UNUSED(jobName) 0256 Q_UNUSED(jobImpressionsCompleted) 0257 0258 // We grab all jobs again 0259 getJobs(); 0260 } 0261 0262 void JobModel::insertUpdateJob(const QString &text, 0263 const QString &printerUri, 0264 const QString &printerName, 0265 uint printerState, 0266 const QString &printerStateReasons, 0267 bool printerIsAcceptingJobs, 0268 uint jobId, 0269 uint jobState, 0270 const QString &jobStateReasons, 0271 const QString &jobName, 0272 uint jobImpressionsCompleted) 0273 { 0274 // REALLY? all these parameters just to say foo was created?? 0275 Q_UNUSED(text) 0276 Q_UNUSED(printerUri) 0277 Q_UNUSED(printerName) 0278 Q_UNUSED(printerState) 0279 Q_UNUSED(printerStateReasons) 0280 Q_UNUSED(printerIsAcceptingJobs) 0281 Q_UNUSED(jobId) 0282 Q_UNUSED(jobState) 0283 Q_UNUSED(jobStateReasons) 0284 Q_UNUSED(jobName) 0285 Q_UNUSED(jobImpressionsCompleted) 0286 0287 // We grab all jobs again 0288 getJobs(); 0289 } 0290 0291 void JobModel::insertJob(int pos, const KCupsJob &job) 0292 { 0293 // insert the first column which has the job state and id 0294 QList<QStandardItem *> row; 0295 ipp_jstate_e jobState = job.state(); 0296 auto statusItem = new QStandardItem(jobStatus(jobState)); 0297 statusItem->setData(jobState, RoleJobState); 0298 statusItem->setData(job.id(), RoleJobId); 0299 statusItem->setData(job.name(), RoleJobName); 0300 statusItem->setData(job.originatingUserName(), RoleJobOwner); 0301 statusItem->setData(job.originatingHostName(), RoleJobOriginatingHostName); 0302 QString size = KFormat().formatByteSize(job.size()); 0303 statusItem->setData(size, RoleJobSize); 0304 QString createdAt = QLocale().toString(job.createdAt()); 0305 statusItem->setData(createdAt, RoleJobCreatedAt); 0306 0307 // TODO move the update code before the insert and reuse some code... 0308 statusItem->setData(KCupsJob::iconName(jobState), RoleJobIconName); 0309 statusItem->setData(KCupsJob::cancelEnabled(jobState), RoleJobCancelEnabled); 0310 statusItem->setData(KCupsJob::holdEnabled(jobState), RoleJobHoldEnabled); 0311 statusItem->setData(KCupsJob::releaseEnabled(jobState), RoleJobReleaseEnabled); 0312 statusItem->setData(job.reprintEnabled(), RoleJobRestartEnabled); 0313 0314 QString pages = QString::number(job.pages()); 0315 if (job.processedPages()) { 0316 pages = QString::number(job.processedPages()) + QLatin1Char('/') + QString::number(job.processedPages()); 0317 } 0318 if (statusItem->data(RoleJobPages) != pages) { 0319 statusItem->setData(pages, RoleJobPages); 0320 } 0321 0322 row << statusItem; 0323 for (int i = ColName; i < LastColumn; i++) { 0324 // adds all Items to the model 0325 row << new QStandardItem; 0326 } 0327 0328 // insert the whole row 0329 insertRow(pos, row); 0330 0331 // update the items 0332 updateJob(pos, job); 0333 } 0334 0335 void JobModel::updateJob(int pos, const KCupsJob &job) 0336 { 0337 // Job Status & internal dataipp_jstate_e 0338 ipp_jstate_e jobState = job.state(); 0339 QStandardItem *colStatus = item(pos, ColStatus); 0340 if (colStatus->data(RoleJobState).toInt() != jobState) { 0341 colStatus->setText(jobStatus(jobState)); 0342 colStatus->setData(static_cast<int>(jobState), RoleJobState); 0343 0344 colStatus->setData(KCupsJob::iconName(jobState), RoleJobIconName); 0345 colStatus->setData(KCupsJob::cancelEnabled(jobState), RoleJobCancelEnabled); 0346 colStatus->setData(KCupsJob::holdEnabled(jobState), RoleJobHoldEnabled); 0347 colStatus->setData(KCupsJob::releaseEnabled(jobState), RoleJobReleaseEnabled); 0348 colStatus->setData(job.reprintEnabled(), RoleJobRestartEnabled); 0349 } 0350 0351 const QString pages = 0352 job.processedPages() ? QString::number(job.processedPages()) + QLatin1Char('/') + QString::number(job.processedPages()) : QString::number(job.pages()); 0353 if (colStatus->data(RoleJobPages) != pages) { 0354 colStatus->setData(pages, RoleJobPages); 0355 } 0356 0357 colStatus->setData(job.authenticationRequired(), RoleJobAuthenticationRequired); 0358 0359 // internal dest name & column 0360 const QString destName = job.printer(); 0361 if (colStatus->data(RoleJobPrinter).toString() != destName) { 0362 colStatus->setData(destName, RoleJobPrinter); 0363 // Column job printer Name 0364 item(pos, ColPrinter)->setText(destName); 0365 } 0366 0367 // job name 0368 const QString jobName = job.name(); 0369 if (item(pos, ColName)->text() != jobName) { 0370 colStatus->setData(jobName, RoleJobName); 0371 item(pos, ColName)->setText(jobName); 0372 } 0373 0374 // owner of the job 0375 // try to get the full user name 0376 QString userString = job.originatingUserName(); 0377 const KUser user(userString); 0378 if (user.isValid() && !user.property(KUser::FullName).toString().isEmpty()) { 0379 userString = user.property(KUser::FullName).toString(); 0380 } 0381 0382 // user name 0383 QStandardItem *colUser = item(pos, ColUser); 0384 if (colUser->text() != userString) { 0385 colUser->setText(userString); 0386 } 0387 0388 // when it was created 0389 const QDateTime timeAtCreation = job.createdAt(); 0390 QStandardItem *colCreated = item(pos, ColCreated); 0391 if (colCreated->data(Qt::DisplayRole).toDateTime() != timeAtCreation) { 0392 colCreated->setData(timeAtCreation, Qt::DisplayRole); 0393 } 0394 0395 // when it was completed 0396 const QDateTime completedAt = job.completedAt(); 0397 QStandardItem *colCompleted = item(pos, ColCompleted); 0398 if (colCompleted->data(Qt::DisplayRole).toDateTime() != completedAt) { 0399 if (!completedAt.isNull()) { 0400 colCompleted->setData(completedAt, Qt::DisplayRole); 0401 } else { 0402 // Clean the data might happen when the job is restarted 0403 colCompleted->setText(QString()); 0404 } 0405 } 0406 0407 // job pages 0408 const int completedPages = job.processedPages(); 0409 QStandardItem *colPages = item(pos, ColPages); 0410 if (colPages->data(Qt::UserRole) != completedPages) { 0411 colPages->setData(completedPages, Qt::UserRole); 0412 colPages->setText(QString::number(completedPages)); 0413 } 0414 0415 // when it was processed 0416 const QDateTime timeAtProcessing = job.processedAt(); 0417 QStandardItem *colProcessed = item(pos, ColProcessed); 0418 if (colProcessed->data(Qt::DisplayRole).toDateTime() != timeAtProcessing) { 0419 if (!timeAtProcessing.isNull()) { 0420 colProcessed->setData(timeAtProcessing, Qt::DisplayRole); 0421 } else { 0422 // Clean the data might happen when the job is restarted 0423 colCompleted->setText(QString()); 0424 } 0425 } 0426 0427 int jobSize = job.size(); 0428 QStandardItem *colSize = item(pos, ColSize); 0429 if (colSize->data(Qt::UserRole) != jobSize) { 0430 colSize->setData(jobSize, Qt::UserRole); 0431 colSize->setText(KFormat().formatByteSize(jobSize)); 0432 } 0433 0434 // job printer state message 0435 const QString stateMessage = job.stateMsg(); 0436 QStandardItem *colStatusMessage = item(pos, ColStatusMessage); 0437 if (colStatusMessage->text() != stateMessage) { 0438 colStatusMessage->setText(stateMessage); 0439 } 0440 0441 // owner of the job 0442 // try to get the full user name 0443 const QString originatingHostName = job.originatingHostName(); 0444 QStandardItem *colFromHost = item(pos, ColFromHost); 0445 if (colFromHost->text() != originatingHostName) { 0446 colFromHost->setText(originatingHostName); 0447 } 0448 } 0449 0450 QStringList JobModel::mimeTypes() const 0451 { 0452 return {QStringLiteral("application/x-cupsjobs")}; 0453 } 0454 0455 Qt::DropActions JobModel::supportedDropActions() const 0456 { 0457 return Qt::MoveAction; 0458 } 0459 0460 QMimeData *JobModel::mimeData(const QModelIndexList &indexes) const 0461 { 0462 auto mimeData = new QMimeData(); 0463 QByteArray encodedData; 0464 0465 QDataStream stream(&encodedData, QIODevice::WriteOnly); 0466 0467 for (const QModelIndex &index : indexes) { 0468 if (index.isValid() && index.column() == 0) { 0469 // serialize the jobId and fromDestName 0470 stream << data(index, RoleJobId).toInt() << data(index, RoleJobPrinter).toString() << item(index.row(), ColName)->text(); 0471 } 0472 } 0473 0474 mimeData->setData(QLatin1String("application/x-cupsjobs"), encodedData); 0475 return mimeData; 0476 } 0477 0478 bool JobModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) 0479 { 0480 Q_UNUSED(row) 0481 Q_UNUSED(column) 0482 Q_UNUSED(parent) 0483 if (action == Qt::IgnoreAction) { 0484 return true; 0485 } 0486 0487 if (!data->hasFormat(QLatin1String("application/x-cupsjobs"))) { 0488 return false; 0489 } 0490 0491 QByteArray encodedData = data->data(QLatin1String("application/x-cupsjobs")); 0492 QDataStream stream(&encodedData, QIODevice::ReadOnly); 0493 0494 bool ret = false; 0495 while (!stream.atEnd()) { 0496 QString fromDestName, displayName; 0497 int jobId; 0498 // get the jobid and the from dest name 0499 stream >> jobId >> fromDestName >> displayName; 0500 if (fromDestName == m_destName) { 0501 continue; 0502 } 0503 0504 QPointer<KCupsRequest> request = new KCupsRequest; 0505 request->moveJob(fromDestName, jobId, m_destName); 0506 request->waitTillFinished(); 0507 if (request) { 0508 if (request->hasError()) { 0509 // failed to move one job 0510 // we return here to avoid more password tries 0511 KMessageBox::detailedErrorWId(m_parentId, i18n("Failed to move '%1' to '%2'", displayName, m_destName), request->errorMsg(), i18n("Failed")); 0512 } 0513 request->deleteLater(); 0514 ret = !request->hasError(); 0515 } 0516 } 0517 return ret; 0518 } 0519 0520 QHash<int, QByteArray> JobModel::roleNames() const 0521 { 0522 return m_roles; 0523 } 0524 0525 KCupsRequest *JobModel::modifyJob(int row, JobAction action, const QString &newDestName, const QModelIndex &parent) 0526 { 0527 Q_UNUSED(parent) 0528 0529 if (row < 0 || row >= rowCount()) { 0530 qCWarning(LIBKCUPS) << "Row number is invalid:" << row; 0531 return nullptr; 0532 } 0533 0534 QStandardItem *job = item(row, ColStatus); 0535 int jobId = job->data(RoleJobId).toInt(); 0536 QString destName = job->data(RoleJobPrinter).toString(); 0537 0538 // ignore some jobs 0539 ipp_jstate_t state = static_cast<ipp_jstate_t>(job->data(RoleJobState).toInt()); 0540 if ((state == IPP_JOB_HELD && action == Hold) || (state == IPP_JOB_CANCELED && action == Cancel) || (state != IPP_JOB_HELD && action == Release)) { 0541 return nullptr; 0542 } 0543 0544 auto request = new KCupsRequest; 0545 switch (action) { 0546 case Cancel: 0547 request->cancelJob(destName, jobId); 0548 break; 0549 case Hold: 0550 request->holdJob(destName, jobId); 0551 break; 0552 case Release: 0553 request->releaseJob(destName, jobId); 0554 break; 0555 case Reprint: 0556 request->restartJob(destName, jobId); 0557 break; 0558 case Move: 0559 request->moveJob(destName, jobId, newDestName); 0560 break; 0561 default: 0562 qCWarning(LIBKCUPS) << "Unknown ACTION called!!!" << action; 0563 return nullptr; 0564 } 0565 0566 return request; 0567 } 0568 0569 int JobModel::jobRow(int jobId) 0570 { 0571 // find the position of the jobId inside the model 0572 for (int i = 0; i < rowCount(); i++) { 0573 if (jobId == item(i)->data(RoleJobId).toInt()) { 0574 return i; 0575 } 0576 } 0577 // -1 if not found 0578 return -1; 0579 } 0580 0581 QString JobModel::jobStatus(ipp_jstate_e job_state) 0582 { 0583 switch (job_state) { 0584 case IPP_JOB_PENDING: 0585 return i18n("Pending"); 0586 case IPP_JOB_HELD: 0587 return i18n("On hold"); 0588 case IPP_JOB_PROCESSING: 0589 return QLatin1String("-"); 0590 case IPP_JOB_STOPPED: 0591 return i18n("Stopped"); 0592 case IPP_JOB_CANCELED: 0593 return i18n("Canceled"); 0594 case IPP_JOB_ABORTED: 0595 return i18n("Aborted"); 0596 case IPP_JOB_COMPLETED: 0597 return i18n("Completed"); 0598 } 0599 return QLatin1String("-"); 0600 } 0601 0602 void JobModel::clear() 0603 { 0604 removeRows(0, rowCount()); 0605 } 0606 0607 void JobModel::setWhichJobs(WhichJobs whichjobs) 0608 { 0609 switch (whichjobs) { 0610 case WhichActive: 0611 m_whichjobs = CUPS_WHICHJOBS_ACTIVE; 0612 break; 0613 case WhichCompleted: 0614 m_whichjobs = CUPS_WHICHJOBS_COMPLETED; 0615 break; 0616 case WhichAll: 0617 m_whichjobs = CUPS_WHICHJOBS_ALL; 0618 break; 0619 } 0620 0621 getJobs(); 0622 } 0623 0624 Qt::ItemFlags JobModel::flags(const QModelIndex &index) const 0625 { 0626 if (index.isValid()) { 0627 ipp_jstate_t state = static_cast<ipp_jstate_t>(item(index.row(), ColStatus)->data(RoleJobState).toInt()); 0628 if (state == IPP_JOB_PENDING || state == IPP_JOB_PROCESSING) { 0629 return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; 0630 } 0631 } 0632 return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDropEnabled; 0633 } 0634 0635 QString JobModel::processingJob() const 0636 { 0637 return m_processingJob; 0638 } 0639 0640 #include "moc_JobModel.cpp"