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"