File indexing completed on 2025-03-09 05:06:37

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 "PrintQueueUi.h"
0008 #include "ui_PrintQueueUi.h"
0009 
0010 #include <JobModel.h>
0011 #include <JobSortFilterModel.h>
0012 #include <ProcessRunner.h>
0013 
0014 #include <KCupsPrinter.h>
0015 #include <KCupsRequest.h>
0016 #include <NoSelectionRectDelegate.h>
0017 
0018 #include <QByteArray>
0019 #include <QDebug>
0020 #include <QMenu>
0021 #include <QPointer>
0022 #include <QShortcut>
0023 #include <QToolBar>
0024 
0025 #include <KConfigGroup>
0026 #include <KIO/AuthInfo>
0027 #include <KJob>
0028 #include <KMessageBox>
0029 #include <KPasswdServerClient>
0030 #include <KSharedConfig>
0031 #include <KUserTimestamp>
0032 #include <KWindowConfig>
0033 
0034 static constexpr uint PRINTER_ICON_SIZE = 92;
0035 
0036 PrintQueueUi::PrintQueueUi(const KCupsPrinter &printer, QWidget *parent)
0037     : QDialog(parent)
0038     , ui(new Ui::PrintQueueUi)
0039     , m_destName(printer.name())
0040 {
0041     ui->setupUi(this);
0042 
0043     // since setupUi needs to setup on the mainWidget()
0044     // we need to manually connect the buttons
0045     connect(ui->cancelJobPB, &QPushButton::clicked, this, &PrintQueueUi::cancelJob);
0046     connect(ui->holdJobPB, &QPushButton::clicked, this, &PrintQueueUi::holdJob);
0047     connect(ui->resumeJobPB, &QPushButton::clicked, this, &PrintQueueUi::resumeJob);
0048     connect(ui->reprintPB, &QPushButton::clicked, this, &PrintQueueUi::reprintJob);
0049 
0050     connect(ui->pausePrinterPB, &QPushButton::clicked, this, &PrintQueueUi::pausePrinter);
0051     connect(ui->configurePrinterPB, &QPushButton::clicked, this, &PrintQueueUi::configurePrinter);
0052 
0053     connect(ui->whichJobsCB, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &PrintQueueUi::whichJobsIndexChanged);
0054 
0055     // Needed so we have our dialog size saved
0056     setAttribute(Qt::WA_DeleteOnClose);
0057 
0058     if (printer.info().isEmpty()) {
0059         m_title = printer.name();
0060     } else {
0061         m_title = printer.info();
0062     }
0063     setWindowTitle(m_title);
0064     setSizeGripEnabled(true);
0065     (void)minimumSizeHint(); // Force the dialog to be laid out now
0066     layout()->setContentsMargins(0, 0, 0, 0);
0067 
0068     m_isClass = printer.isClass();
0069 
0070     // setup default options
0071     ui->jobsView->setCornerWidget(new QWidget);
0072 
0073     setupButtons();
0074 
0075     // loads the standard key icon
0076     m_printerIcon = printer.icon().pixmap(PRINTER_ICON_SIZE, PRINTER_ICON_SIZE);
0077     ui->iconL->setPixmap(m_printerIcon);
0078     ui->printerStatusMsgL->setText(QString());
0079 
0080     // setup the jobs model
0081     m_model = new JobModel(this);
0082     m_model->setParentWId(winId());
0083     m_model->init(printer.name());
0084     connect(m_model, &JobModel::dataChanged, this, &PrintQueueUi::updateButtons);
0085     connect(m_model, &JobModel::dataChanged, this, &PrintQueueUi::update);
0086     m_proxyModel = new JobSortFilterModel(this);
0087     m_proxyModel->setSourceModel(m_model);
0088     m_proxyModel->setDynamicSortFilter(true);
0089 
0090     ui->jobsView->setModel(m_proxyModel);
0091     ui->jobsView->setItemDelegate(new NoSelectionRectDelegate(this));
0092     // sort by status column means the jobs will be sorted by the queue order
0093     ui->jobsView->sortByColumn(JobModel::ColStatus, Qt::AscendingOrder);
0094     connect(ui->jobsView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &PrintQueueUi::updateButtons);
0095     connect(ui->jobsView, &QTreeView::customContextMenuRequested, this, &PrintQueueUi::showContextMenu);
0096     ui->jobsView->header()->setContextMenuPolicy(Qt::CustomContextMenu);
0097     connect(ui->jobsView->header(), &QHeaderView::customContextMenuRequested, this, &PrintQueueUi::showHeaderContextMenu);
0098 
0099     QHeaderView *header = ui->jobsView->header();
0100     header->setSectionResizeMode(QHeaderView::Interactive);
0101     header->setStretchLastSection(false);
0102     header->setSectionResizeMode(JobModel::ColStatus, QHeaderView::ResizeToContents);
0103     header->setSectionResizeMode(JobModel::ColName, QHeaderView::Stretch);
0104     header->setSectionResizeMode(JobModel::ColUser, QHeaderView::ResizeToContents);
0105     header->setSectionResizeMode(JobModel::ColCreated, QHeaderView::ResizeToContents);
0106     header->setSectionResizeMode(JobModel::ColCompleted, QHeaderView::ResizeToContents);
0107     header->setSectionResizeMode(JobModel::ColPages, QHeaderView::ResizeToContents);
0108     header->setSectionResizeMode(JobModel::ColProcessed, QHeaderView::ResizeToContents);
0109     header->setSectionResizeMode(JobModel::ColSize, QHeaderView::ResizeToContents);
0110     header->setSectionResizeMode(JobModel::ColStatusMessage, QHeaderView::ResizeToContents);
0111     header->setSectionResizeMode(JobModel::ColPrinter, QHeaderView::ResizeToContents);
0112 
0113     KConfigGroup printQueue(KSharedConfig::openConfig(QLatin1String("print-manager")), QStringLiteral("PrintQueue"));
0114     if (printQueue.hasKey("ColumnState")) {
0115         // restore the header state order
0116         header->restoreState(printQueue.readEntry("ColumnState", QByteArray()));
0117     } else {
0118         // Hide some columns ColPrinter
0119         header->hideSection(JobModel::ColPrinter);
0120         header->hideSection(JobModel::ColUser);
0121         header->hideSection(JobModel::ColCompleted);
0122         header->hideSection(JobModel::ColSize);
0123         header->hideSection(JobModel::ColFromHost);
0124     }
0125 
0126     // This is emitted when a printer is modified
0127     connect(KCupsConnection::global(), &KCupsConnection::printerModified, this, &PrintQueueUi::updatePrinter);
0128 
0129     // This is emitted when a printer has it's state changed
0130     connect(KCupsConnection::global(), &KCupsConnection::printerStateChanged, this, &PrintQueueUi::updatePrinter);
0131 
0132     // This is emitted when a printer is stopped
0133     connect(KCupsConnection::global(), &KCupsConnection::printerStopped, this, &PrintQueueUi::updatePrinter);
0134 
0135     // This is emitted when a printer is restarted
0136     connect(KCupsConnection::global(), &KCupsConnection::printerRestarted, this, &PrintQueueUi::updatePrinter);
0137 
0138     // This is emitted when a printer is shutdown
0139     connect(KCupsConnection::global(), &KCupsConnection::printerShutdown, this, &PrintQueueUi::updatePrinter);
0140 
0141     // This is emitted when a printer is removed
0142     connect(KCupsConnection::global(), &KCupsConnection::printerDeleted, this, &PrintQueueUi::updatePrinter);
0143 
0144     // This is emitted when a printer/queue is changed
0145     // Deprecated stuff that works better than the above
0146     connect(KCupsConnection::global(), &KCupsConnection::rhPrinterAdded, this, &PrintQueueUi::updatePrinterByName);
0147     connect(KCupsConnection::global(), &KCupsConnection::rhPrinterRemoved, this, &PrintQueueUi::updatePrinterByName);
0148     connect(KCupsConnection::global(), &KCupsConnection::rhQueueChanged, this, &PrintQueueUi::updatePrinterByName);
0149 
0150     updatePrinterByName(m_destName);
0151 
0152     // Restore the dialog size
0153     KConfigGroup configGroup(KSharedConfig::openConfig(QLatin1String("print-manager")), QStringLiteral("PrintQueue"));
0154     KWindowConfig::restoreWindowSize(windowHandle(), configGroup);
0155 
0156     auto delJobShortcut = new QShortcut(QKeySequence::Delete, ui->jobsView);
0157     delJobShortcut->setContext(Qt::WidgetShortcut);
0158     connect(delJobShortcut, &QShortcut::activated, this, &PrintQueueUi::cancelJob);
0159 }
0160 
0161 PrintQueueUi::~PrintQueueUi()
0162 {
0163     KConfigGroup configGroup(KSharedConfig::openConfig(QLatin1String("print-manager")), QStringLiteral("PrintQueue"));
0164     // save the header state order
0165     configGroup.writeEntry("ColumnState", ui->jobsView->header()->saveState());
0166 
0167     // Save the dialog size
0168     KWindowConfig::saveWindowSize(windowHandle(), configGroup);
0169 
0170     delete ui;
0171 }
0172 
0173 int PrintQueueUi::columnCount(const QModelIndex &parent) const
0174 {
0175     if (!parent.isValid()) {
0176         return JobModel::LastColumn;
0177     }
0178     return 0;
0179 }
0180 
0181 void PrintQueueUi::setState(int state, const QString &message)
0182 {
0183     qDebug() << state << message;
0184     if (state != m_lastState || ui->printerStatusMsgL->text() != message) {
0185         // save the last state so the ui doesn't need to keep updating
0186         if (ui->printerStatusMsgL->text() != message) {
0187             ui->printerStatusMsgL->setText(message);
0188         }
0189         m_lastState = state;
0190 
0191         m_printerPaused = false;
0192         switch (state) {
0193         case KCupsPrinter::Idle:
0194             ui->statusL->setText(i18n("Printer ready"));
0195             ui->pausePrinterPB->setText(i18n("Pause Printer"));
0196             ui->pausePrinterPB->setIcon(QIcon::fromTheme(QLatin1String("media-playback-pause")));
0197             break;
0198         case KCupsPrinter::Printing:
0199             if (!m_title.isNull()) {
0200                 QString jobTitle = m_model->processingJob();
0201                 if (jobTitle.isEmpty()) {
0202                     ui->statusL->setText(i18n("Printing..."));
0203                 } else {
0204                     ui->statusL->setText(i18n("Printing '%1'", jobTitle));
0205                 }
0206                 ui->pausePrinterPB->setText(i18n("Pause Printer"));
0207                 ui->pausePrinterPB->setIcon(QIcon::fromTheme(QLatin1String("media-playback-pause")));
0208             }
0209             break;
0210         case KCupsPrinter::Stopped:
0211             m_printerPaused = true;
0212             ui->statusL->setText(i18n("Printer paused"));
0213             ui->pausePrinterPB->setText(i18n("Resume Printer"));
0214             ui->pausePrinterPB->setIcon(QIcon::fromTheme(QLatin1String("media-playback-start")));
0215             break;
0216         default:
0217             ui->statusL->setText(i18n("Printer state unknown"));
0218             break;
0219         }
0220     }
0221 }
0222 
0223 void PrintQueueUi::showContextMenu(const QPoint &point)
0224 {
0225     // check if the click was actually over a job
0226     if (!ui->jobsView->indexAt(point).isValid() || m_preparingMenu) {
0227         return;
0228     }
0229 
0230     // we need to map the selection to source to get the real indexes
0231     QItemSelection selection = m_proxyModel->mapSelectionToSource(ui->jobsView->selectionModel()->selection());
0232     // if the selection is empty the user clicked on an empty space
0233     if (selection.indexes().isEmpty()) {
0234         return;
0235     }
0236 
0237     m_preparingMenu = true;
0238 
0239     // context menu
0240     auto menu = new QMenu(this);
0241     menu->setAttribute(Qt::WA_DeleteOnClose);
0242 
0243     bool moveTo = false;
0244     bool authenticate = false;
0245     const QModelIndexList indexes = selection.indexes();
0246     for (const QModelIndex &index : indexes) {
0247         if (index.column() == JobModel::Columns::ColStatus) {
0248             if (index.flags() & Qt::ItemIsDragEnabled) {
0249                 // Found a move to item
0250                 moveTo = true;
0251             }
0252             if (index.data(JobModel::Role::RoleJobAuthenticationRequired).toBool()) {
0253                 // Found an item which requires authentication
0254                 authenticate = true;
0255             }
0256         }
0257     }
0258 
0259     // if we can move a job create the menu
0260     if (moveTo) {
0261         // move to menu
0262         auto moveToMenu = new QMenu(i18n("Move to"), menu);
0263 
0264         // get printers we can move to
0265         QPointer<KCupsRequest> request = new KCupsRequest;
0266         request->getPrinters({KCUPS_PRINTER_NAME, KCUPS_PRINTER_INFO});
0267         request->waitTillFinished();
0268         if (!request) {
0269             return;
0270         }
0271         const KCupsPrinters printers = request->printers();
0272         request->deleteLater();
0273 
0274         for (const KCupsPrinter &printer : printers) {
0275             // If there is a printer and it's not the current one add it
0276             // as a new destination
0277             if (printer.name() != m_destName) {
0278                 QAction *action = moveToMenu->addAction(printer.info());
0279                 action->setData(printer.name());
0280                 connect(action, &QAction::triggered, this, [=]() {
0281                     this->modifyJob(JobModel::Move, action->data().toString());
0282                 });
0283             }
0284         }
0285 
0286         if (!moveToMenu->isEmpty()) {
0287             menu->addMenu(moveToMenu);
0288         }
0289     }
0290 
0291     // Authenticate
0292     if (authenticate) {
0293         QAction *action = menu->addAction(i18n("Authenticate"));
0294         connect(action, &QAction::triggered, this, &PrintQueueUi::authenticateJob);
0295     }
0296 
0297     if (menu->isEmpty()) {
0298         delete menu;
0299     } else {
0300         // show the menu on the right point
0301         menu->popup(ui->jobsView->mapToGlobal(point));
0302     }
0303 
0304     m_preparingMenu = false;
0305 }
0306 
0307 void PrintQueueUi::showHeaderContextMenu(const QPoint &point)
0308 {
0309     // Displays a menu containing the header name, and
0310     // a check box to indicate if it's being shown
0311     auto menu = new QMenu(this);
0312     for (int i = 0; i < m_proxyModel->columnCount(); i++) {
0313         auto name = m_proxyModel->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString();
0314         QAction *action = menu->addAction(name);
0315         action->setCheckable(true);
0316         action->setChecked(!ui->jobsView->header()->isSectionHidden(i));
0317         action->setData(i);
0318     }
0319 
0320     QAction *action = menu->exec(ui->jobsView->header()->mapToGlobal(point));
0321     if (action) {
0322         int section = action->data().toInt();
0323         if (action->isChecked()) {
0324             ui->jobsView->header()->showSection(section);
0325         } else {
0326             ui->jobsView->header()->hideSection(section);
0327         }
0328     }
0329 }
0330 
0331 void PrintQueueUi::updatePrinterByName(const QString &printer)
0332 {
0333     qDebug() << printer << m_destName;
0334     if (printer != m_destName) {
0335         // It was another printer that changed
0336         return;
0337     }
0338 
0339     const QStringList attr({
0340         KCUPS_PRINTER_INFO,
0341         KCUPS_PRINTER_TYPE,
0342         KCUPS_PRINTER_STATE,
0343         KCUPS_PRINTER_STATE_MESSAGE,
0344     });
0345 
0346     auto request = new KCupsRequest;
0347     connect(request, &KCupsRequest::finished, this, &PrintQueueUi::getAttributesFinished);
0348     request->getPrinterAttributes(printer, m_isClass, attr);
0349 }
0350 
0351 void PrintQueueUi::updatePrinter(const QString &text,
0352                                  const QString &printerUri,
0353                                  const QString &printerName,
0354                                  uint printerState,
0355                                  const QString &printerStateReasons,
0356                                  bool printerIsAcceptingJobs)
0357 {
0358     // REALLY? all these parameters just to say foo was added??
0359     Q_UNUSED(text)
0360     Q_UNUSED(printerUri)
0361     Q_UNUSED(printerState)
0362     Q_UNUSED(printerStateReasons)
0363     Q_UNUSED(printerIsAcceptingJobs)
0364     qDebug() << printerName << printerStateReasons;
0365 
0366     updatePrinterByName(printerName);
0367 }
0368 
0369 void PrintQueueUi::getAttributesFinished(KCupsRequest *request)
0370 {
0371     qDebug() << request->hasError() << request->printers().isEmpty();
0372 
0373     if (request->hasError() || request->printers().isEmpty()) {
0374         // if cups stops we disable our queue
0375         setEnabled(false);
0376         request->deleteLater(); // DO not delete before using as the request is in another thread
0377         return;
0378     } else if (isEnabled() == false) {
0379         // if cups starts again we enable our queue
0380         setEnabled(true);
0381     }
0382 
0383     KCupsPrinter printer = request->printers().first();
0384 
0385     // get printer-info
0386     if (printer.info().isEmpty()) {
0387         m_title = printer.name();
0388     } else {
0389         m_title = printer.info();
0390     }
0391 
0392     // get printer-state
0393     setState(printer.state(), printer.stateMsg());
0394 
0395     // store if the printer is a class
0396     m_isClass = printer.isClass();
0397 
0398     request->deleteLater();
0399 
0400     update();
0401 }
0402 
0403 void PrintQueueUi::update()
0404 {
0405     // Set window title
0406     if (m_model->rowCount()) {
0407         if (m_destName.isNull()) {
0408             setWindowTitle(i18np("All Printers (%1 Job)", "All Printers (%1 Jobs)", m_model->rowCount()));
0409         } else {
0410             setWindowTitle(i18np("%2 (%1 Job)", "%2 (%1 Jobs)", m_model->rowCount(), m_title));
0411         }
0412     } else {
0413         setWindowTitle(m_destName.isNull() ? i18n("All Printers") : m_title);
0414     }
0415 }
0416 
0417 void PrintQueueUi::updateButtons()
0418 {
0419     bool cancel, hold, release, reprint;
0420     // Set all options to false
0421     cancel = hold = release = reprint = false;
0422 
0423     QItemSelection selection;
0424     // we need to map the selection to source to get the real indexes
0425     selection = m_proxyModel->mapSelectionToSource(ui->jobsView->selectionModel()->selection());
0426     // enable or disable the job action buttons if something is selected
0427     if (!selection.indexes().isEmpty()) {
0428         const QModelIndexList indexes = selection.indexes();
0429         for (const QModelIndex &index : indexes) {
0430             if (index.column() == 0) {
0431                 switch (static_cast<ipp_jstate_t>(index.data(JobModel::RoleJobState).toInt())) {
0432                 case IPP_JOB_CANCELED:
0433                 case IPP_JOB_COMPLETED:
0434                 case IPP_JOB_ABORTED:
0435                     break;
0436                 case IPP_JOB_HELD:
0437                 case IPP_JOB_STOPPED:
0438                     release = true;
0439                     cancel = true;
0440                     break;
0441                 default:
0442                     cancel = hold = true;
0443                     break;
0444                 }
0445                 if (index.data(JobModel::RoleJobRestartEnabled).toBool()) {
0446                     reprint = true;
0447                 }
0448             }
0449         }
0450     }
0451 
0452     ui->cancelJobPB->setEnabled(cancel);
0453     ui->holdJobPB->setVisible(hold);
0454     ui->resumeJobPB->setVisible(release);
0455     ui->reprintPB->setEnabled(reprint);
0456 }
0457 
0458 void PrintQueueUi::modifyJob(int action, const QString &destName)
0459 {
0460     // get all selected indexes
0461     QItemSelection selection;
0462     // we need to map the selection to source to get the real indexes
0463     selection = m_proxyModel->mapSelectionToSource(ui->jobsView->selectionModel()->selection());
0464     const QModelIndexList indexes = selection.indexes();
0465     for (const QModelIndex &index : indexes) {
0466         if (index.column() == 0) {
0467             KCupsRequest *request;
0468             request = m_model->modifyJob(index.row(), static_cast<JobModel::JobAction>(action), destName);
0469             if (!request) {
0470                 // probably the job already has this state
0471                 // or this is an unknown action
0472                 continue;
0473             }
0474             request->waitTillFinished();
0475             if (request->hasError()) {
0476                 QString msg, jobName;
0477                 jobName = m_model->item(index.row(), static_cast<int>(JobModel::ColName))->text();
0478                 switch (action) {
0479                 case JobModel::Cancel:
0480                     msg = i18n("Failed to cancel '%1'", jobName);
0481                     break;
0482                 case JobModel::Hold:
0483                     msg = i18n("Failed to hold '%1'", jobName);
0484                     break;
0485                 case JobModel::Release:
0486                     msg = i18n("Failed to release '%1'", jobName);
0487                     break;
0488                 case JobModel::Reprint:
0489                     msg = i18n("Failed to reprint '%1'", jobName);
0490                     break;
0491                 case JobModel::Move:
0492                     msg = i18n("Failed to move '%1' to '%2'", jobName, destName);
0493                     break;
0494                 }
0495                 KMessageBox::detailedError(this, msg, request->errorMsg(), i18n("Failed"));
0496             }
0497             request->deleteLater();
0498         }
0499     }
0500 }
0501 
0502 void PrintQueueUi::pausePrinter()
0503 {
0504     // STOP and RESUME printer
0505     QPointer<KCupsRequest> request = new KCupsRequest;
0506     if (m_printerPaused) {
0507         qDebug() << m_destName << "m_printerPaused";
0508         request->resumePrinter(m_destName);
0509     } else {
0510         qDebug() << m_destName << "NOT m_printerPaused";
0511         request->pausePrinter(m_destName);
0512     }
0513     request->waitTillFinished();
0514     if (request) {
0515         request->deleteLater();
0516     }
0517 }
0518 
0519 void PrintQueueUi::configurePrinter()
0520 {
0521     ProcessRunner::configurePrinter(m_destName);
0522 }
0523 
0524 void PrintQueueUi::cancelJob()
0525 {
0526     // CANCEL a job
0527     modifyJob(JobModel::Cancel);
0528 }
0529 
0530 void PrintQueueUi::holdJob()
0531 {
0532     // HOLD a job
0533     modifyJob(JobModel::Hold);
0534 }
0535 
0536 void PrintQueueUi::resumeJob()
0537 {
0538     // RESUME a job
0539     modifyJob(JobModel::Release);
0540 }
0541 
0542 void PrintQueueUi::reprintJob()
0543 {
0544     modifyJob(JobModel::Reprint);
0545 }
0546 
0547 void PrintQueueUi::authenticateJob()
0548 {
0549     QScopedPointer<KCupsRequest> request(new KCupsRequest);
0550     request->getPrinterAttributes(m_destName, m_isClass, {KCUPS_PRINTER_URI_SUPPORTED, KCUPS_AUTH_INFO_REQUIRED});
0551     request->waitTillFinished();
0552     if (request->hasError() || request->printers().size() != 1) {
0553         qWarning() << "Ignoring request, printer not found or error" << m_destName << request->errorMsg();
0554     }
0555 
0556     const KCupsPrinter printer = request->printers().first();
0557 
0558     KIO::AuthInfo info;
0559     info.keepPassword = true;
0560     info.prompt = i18n("Enter credentials to print from <b>%1</b>", m_destName);
0561     info.url = QUrl(printer.uriSupported());
0562     if (printer.authInfoRequired().contains(QStringLiteral("domain"))) {
0563         info.setExtraField(QStringLiteral("domain"), QStringLiteral(""));
0564     }
0565 
0566     QScopedPointer<KPasswdServerClient> passwdServerClient(new KPasswdServerClient());
0567 
0568     auto winId = static_cast<qlonglong>(this->winId());
0569     auto usertime = static_cast<qlonglong>(KUserTimestamp::userTimestamp());
0570     if (passwdServerClient->checkAuthInfo(&info, winId, usertime)) {
0571         // at this stage we don't know if stored credentials are correct
0572         // trying blindly is risky, it may block this user's account
0573         passwdServerClient->removeAuthInfo(info.url.host(), info.url.scheme(), info.username);
0574     }
0575     const int passwordDialogErrorCode = passwdServerClient->queryAuthInfo(&info, QString(), winId, usertime);
0576     if (passwordDialogErrorCode != KJob::NoError) {
0577         // user cancelled or kiod_kpasswdserver not running
0578         qDebug() << "queryAuthInfo error code" << passwordDialogErrorCode;
0579         return;
0580     }
0581 
0582     QStringList authInfo;
0583     for (QString &authInfoRequired : printer.authInfoRequired()) {
0584         if (authInfoRequired == QStringLiteral("domain")) {
0585             authInfo << info.getExtraField(QStringLiteral("domain")).toString();
0586         } else if (authInfoRequired == QStringLiteral("username")) {
0587             authInfo << info.username;
0588         } else if (authInfoRequired == QStringLiteral("password")) {
0589             authInfo << info.password;
0590         } else {
0591             qWarning() << "No auth info for: " << authInfoRequired;
0592             authInfo << QString();
0593         }
0594     }
0595 
0596     // we need to map the selection to source to get the real indexes
0597     QItemSelection selection = m_proxyModel->mapSelectionToSource(ui->jobsView->selectionModel()->selection());
0598     const QModelIndexList indexes = selection.indexes();
0599     for (const QModelIndex &index : indexes) {
0600         if (index.column() == JobModel::Columns::ColStatus) {
0601             QScopedPointer<KCupsRequest> authRequest(new KCupsRequest);
0602             authRequest->authenticateJob(m_destName, authInfo, index.data(JobModel::Role::RoleJobId).toInt());
0603             authRequest->waitTillFinished();
0604             if (authRequest->hasError()) {
0605                 qWarning() << "Error authenticating jobs" << authRequest->error() << authRequest->errorMsg();
0606                 // remove cache on fail
0607                 passwdServerClient->removeAuthInfo(info.url.host(), info.url.scheme(), info.username);
0608                 return;
0609             }
0610         }
0611     }
0612 }
0613 
0614 void PrintQueueUi::whichJobsIndexChanged(int index)
0615 {
0616     switch (index) {
0617     case 1:
0618         m_model->setWhichJobs(JobModel::WhichCompleted);
0619         break;
0620     case 2:
0621         m_model->setWhichJobs(JobModel::WhichAll);
0622         break;
0623     default:
0624         m_model->setWhichJobs(JobModel::WhichActive);
0625         break;
0626     }
0627 }
0628 
0629 void PrintQueueUi::setupButtons()
0630 {
0631     // setup jobs buttons
0632 
0633     // cancel action
0634     ui->cancelJobPB->setIcon(QIcon::fromTheme(QLatin1String("dialog-cancel")));
0635 
0636     // hold job action
0637     ui->holdJobPB->setIcon(QIcon::fromTheme(QLatin1String("document-open-recent")));
0638 
0639     // resume job action
0640     // TODO we need a new icon
0641     ui->resumeJobPB->setIcon(QIcon::fromTheme(QLatin1String("media-playback-start")));
0642 
0643     ui->reprintPB->setIcon(QIcon::fromTheme(QLatin1String("view-refresh")));
0644 
0645     const QIcon viewFilterIcon = QIcon::fromTheme(QLatin1String("view-filter"));
0646     ui->whichJobsCB->setItemIcon(0, viewFilterIcon);
0647     ui->whichJobsCB->setItemIcon(1, viewFilterIcon);
0648     ui->whichJobsCB->setItemIcon(2, viewFilterIcon);
0649 
0650     // stop start printer
0651     ui->pausePrinterPB->setIcon(QIcon::fromTheme(QLatin1String("media-playback-pause")));
0652 
0653     // configure printer
0654     ui->configurePrinterPB->setIcon(QIcon::fromTheme(QLatin1String("configure")));
0655 }
0656 
0657 void PrintQueueUi::closeEvent(QCloseEvent *event)
0658 {
0659     // emits finished signal to be removed the cache
0660     Q_EMIT finished();
0661     QWidget::closeEvent(event);
0662 }
0663 
0664 #include "moc_PrintQueueUi.cpp"