File indexing completed on 2022-09-27 16:37:19

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 
0013 #include <KCupsRequest.h>
0014 #include <KCupsPrinter.h>
0015 #include <NoSelectionRectDelegate.h>
0016 
0017 #include <QToolBar>
0018 #include <QMenu>
0019 #include <QByteArray>
0020 #include <QProcess>
0021 #include <QDebug>
0022 #include <QPointer>
0023 #include <QShortcut>
0024 
0025 #include <KMessageBox>
0026 #include <KSharedConfig>
0027 #include <KConfigGroup>
0028 #include <KWindowConfig>
0029 #include <KIO/AuthInfo>
0030 #include <KIO/Job>
0031 #include <KUserTimestamp>
0032 #include <KPasswdServerClient>
0033 
0034 #define 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.name() % QLatin1String(" - ") % 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")), "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")), "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")), "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 ||
0185         ui->printerStatusMsgL->text() != message) {
0186         // save the last state so the ui doesn't need to keep updating
0187         if (ui->printerStatusMsgL->text() != message) {
0188             ui->printerStatusMsgL->setText(message);
0189         }
0190         m_lastState = state;
0191 
0192         m_printerPaused = false;
0193         switch (state) {
0194         case KCupsPrinter::Idle:
0195             ui->statusL->setText(i18n("Printer ready"));
0196             ui->pausePrinterPB->setText(i18n("Pause Printer"));
0197             ui->pausePrinterPB->setIcon(QIcon::fromTheme(QLatin1String("media-playback-pause")));
0198             break;
0199         case KCupsPrinter::Printing:
0200             if (!m_title.isNull()) {
0201                 QString jobTitle = m_model->processingJob();
0202                 if (jobTitle.isEmpty()) {
0203                     ui->statusL->setText(i18n("Printing..."));
0204                 } else {
0205                     ui->statusL->setText(i18n("Printing '%1'", jobTitle));
0206                 }
0207                 ui->pausePrinterPB->setText(i18n("Pause Printer"));
0208                 ui->pausePrinterPB->setIcon(QIcon::fromTheme(QLatin1String("media-playback-pause")));
0209             }
0210             break;
0211         case KCupsPrinter::Stopped:
0212             m_printerPaused = true;
0213             ui->statusL->setText(i18n("Printer paused"));
0214             ui->pausePrinterPB->setText(i18n("Resume Printer"));
0215             ui->pausePrinterPB->setIcon(QIcon::fromTheme(QLatin1String("media-playback-start")));
0216             break;
0217         default :
0218             ui->statusL->setText(i18n("Printer state unknown"));
0219             break;
0220         }
0221     }
0222 }
0223 
0224 void PrintQueueUi::showContextMenu(const QPoint &point)
0225 {
0226     // check if the click was actually over a job
0227     if (!ui->jobsView->indexAt(point).isValid() || m_preparingMenu) {
0228         return;
0229     }
0230 
0231     // we need to map the selection to source to get the real indexes
0232     QItemSelection selection = m_proxyModel->mapSelectionToSource(ui->jobsView->selectionModel()->selection());
0233     // if the selection is empty the user clicked on an empty space
0234     if (selection.indexes().isEmpty()) {
0235         return;
0236     }
0237 
0238     m_preparingMenu = true;
0239 
0240     // context menu
0241     auto menu = new QMenu(this);
0242     menu->setAttribute(Qt::WA_DeleteOnClose);
0243 
0244     bool moveTo = false;
0245     bool authenticate = false;
0246     const QModelIndexList indexes = selection.indexes();
0247     for (const QModelIndex &index : indexes) {
0248         if (index.column() == JobModel::Columns::ColStatus) {
0249             if (index.flags() & Qt::ItemIsDragEnabled) {
0250                 // Found a move to item
0251                 moveTo = true;
0252             }
0253             if (index.data(JobModel::Role::RoleJobAuthenticationRequired).toBool()) {
0254                 // Found an item which requires authentication
0255                 authenticate = true;
0256             }
0257         }
0258     }
0259 
0260     // if we can move a job create the menu
0261     if (moveTo) {
0262         // move to menu
0263         auto moveToMenu = new QMenu(i18n("Move to"), menu);
0264 
0265         // get printers we can move to
0266         QPointer<KCupsRequest> request = new KCupsRequest;
0267         request->getPrinters({ KCUPS_PRINTER_NAME, KCUPS_PRINTER_INFO });
0268         request->waitTillFinished();
0269         if (!request) {
0270             return;
0271         }
0272         const KCupsPrinters printers = request->printers();
0273         request->deleteLater();
0274 
0275         for (const KCupsPrinter &printer : printers) {
0276             // If there is a printer and it's not the current one add it
0277             // as a new destination
0278             if (printer.name() != m_destName) {
0279                 QAction *action = moveToMenu->addAction(printer.info());
0280                 action->setData(printer.name());
0281                 connect(action, &QAction::triggered, this, [=] () {
0282                     this->modifyJob(JobModel::Move, action->data().toString());
0283                 });
0284             }
0285         }
0286 
0287         if (!moveToMenu->isEmpty()) {
0288             menu->addMenu(moveToMenu);
0289         }
0290     }
0291 
0292     // Authenticate
0293     if (authenticate) {
0294         QAction *action = menu->addAction(i18n("Authenticate"));
0295         connect(action, &QAction::triggered, this, &PrintQueueUi::authenticateJob);
0296     }
0297 
0298     if (menu->isEmpty()) {
0299         delete menu;
0300     } else {
0301         // show the menu on the right point
0302         menu->popup(ui->jobsView->mapToGlobal(point));
0303     }
0304 
0305     m_preparingMenu = false;
0306 }
0307 
0308 void PrintQueueUi::showHeaderContextMenu(const QPoint &point)
0309 {
0310     // Displays a menu containing the header name, and
0311     // a check box to indicate if it's being shown
0312     auto menu = new QMenu(this);
0313     for (int i = 0; i < m_proxyModel->columnCount(); i++) {
0314         auto name = m_proxyModel->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString();
0315         QAction *action = menu->addAction(name);
0316         action->setCheckable(true);
0317         action->setChecked(!ui->jobsView->header()->isSectionHidden(i));
0318         action->setData(i);
0319     }
0320 
0321     QAction *action = menu->exec(ui->jobsView->header()->mapToGlobal(point));
0322     if (action) {
0323         int section = action->data().toInt();
0324         if (action->isChecked()) {
0325             ui->jobsView->header()->showSection(section);
0326         } else {
0327             ui->jobsView->header()->hideSection(section);
0328         }
0329     }
0330 }
0331 
0332 void PrintQueueUi::updatePrinterByName(const QString &printer)
0333 {
0334     qDebug() << printer << m_destName;
0335     if (printer != m_destName) {
0336         // It was another printer that changed
0337         return;
0338     }
0339 
0340     const QStringList attr({
0341                                KCUPS_PRINTER_INFO,
0342                                KCUPS_PRINTER_TYPE,
0343                                KCUPS_PRINTER_STATE,
0344                                KCUPS_PRINTER_STATE_MESSAGE,
0345                            });
0346 
0347     auto request = new KCupsRequest;
0348     connect(request, &KCupsRequest::finished, this, &PrintQueueUi::getAttributesFinished);
0349     request->getPrinterAttributes(printer, m_isClass, attr);
0350 }
0351 
0352 void PrintQueueUi::updatePrinter(const QString &text, const QString &printerUri, const QString &printerName, uint printerState, const QString &printerStateReasons, bool printerIsAcceptingJobs)
0353 {
0354     // REALLY? all these parameters just to say foo was added??
0355     Q_UNUSED(text)
0356     Q_UNUSED(printerUri)
0357     Q_UNUSED(printerState)
0358     Q_UNUSED(printerStateReasons)
0359     Q_UNUSED(printerIsAcceptingJobs)
0360     qDebug() << printerName << printerStateReasons;
0361 
0362     updatePrinterByName(printerName);
0363 }
0364 
0365 void PrintQueueUi::getAttributesFinished(KCupsRequest *request)
0366 {
0367     qDebug() << request->hasError() << request->printers().isEmpty();
0368 
0369     if (request->hasError() || request->printers().isEmpty()) {
0370         // if cups stops we disable our queue
0371         setEnabled(false);
0372         request->deleteLater(); // DO not delete before using as the request is in another thread
0373         return;
0374     } else if (isEnabled() == false) {
0375         // if cups starts again we enable our queue
0376         setEnabled(true);
0377     }
0378 
0379     KCupsPrinter printer = request->printers().first();
0380 
0381     // get printer-info
0382     if (printer.info().isEmpty()) {
0383         m_title = printer.name();
0384     } else {
0385         m_title = printer.name() + QLatin1String(" - ") + printer.info();
0386     }
0387 
0388     // get printer-state
0389     setState(printer.state(), printer.stateMsg());
0390 
0391     // store if the printer is a class
0392     m_isClass = printer.isClass();
0393 
0394     request->deleteLater();
0395 
0396     update();
0397 }
0398 
0399 void PrintQueueUi::update()
0400 {
0401     // Set window title
0402     if (m_model->rowCount()) {
0403         if (m_destName.isNull()) {
0404             setWindowTitle(i18np("All Printers (%1 Job)", "All Printers (%1 Jobs)", m_model->rowCount()));
0405         } else {
0406             setWindowTitle(i18np("%2 (%1 Job)", "%2 (%1 Jobs)", m_model->rowCount(), m_title));
0407         }
0408     } else {
0409         setWindowTitle(m_destName.isNull() ? i18n("All Printers") : m_title);
0410     }
0411 }
0412 
0413 void PrintQueueUi::updateButtons()
0414 {
0415     bool cancel, hold, release, reprint;
0416     // Set all options to false
0417     cancel = hold = release = reprint = false;
0418 
0419     QItemSelection selection;
0420     // we need to map the selection to source to get the real indexes
0421     selection = m_proxyModel->mapSelectionToSource(ui->jobsView->selectionModel()->selection());
0422     // enable or disable the job action buttons if something is selected
0423     if (!selection.indexes().isEmpty()) {
0424         const QModelIndexList indexes = selection.indexes();
0425         for (const QModelIndex &index : indexes) {
0426             if (index.column() == 0) {
0427                 switch (static_cast<ipp_jstate_t>(index.data(JobModel::RoleJobState).toInt())) {
0428                     case IPP_JOB_CANCELED :
0429                     case IPP_JOB_COMPLETED :
0430                     case IPP_JOB_ABORTED :
0431                         break;
0432                     case IPP_JOB_HELD :
0433                     case IPP_JOB_STOPPED :
0434                         release = true;
0435                         cancel = true;
0436                         break;
0437                     default:
0438                         cancel = hold = true;
0439                         break;
0440                 }
0441                 if (index.data(JobModel::RoleJobRestartEnabled).toBool()) {
0442                     reprint = true;
0443                 }
0444             }
0445         }
0446     }
0447 
0448     ui->cancelJobPB->setEnabled(cancel);
0449     ui->holdJobPB->setVisible(hold);
0450     ui->resumeJobPB->setVisible(release);
0451     ui->reprintPB->setEnabled(reprint);
0452 }
0453 
0454 void PrintQueueUi::modifyJob(int action, const QString &destName)
0455 {
0456     // get all selected indexes
0457     QItemSelection selection;
0458     // we need to map the selection to source to get the real indexes
0459     selection = m_proxyModel->mapSelectionToSource(ui->jobsView->selectionModel()->selection());
0460     const QModelIndexList indexes = selection.indexes();
0461     for (const QModelIndex &index : indexes) {
0462         if (index.column() == 0) {
0463             KCupsRequest *request;
0464             request = m_model->modifyJob(index.row(),
0465                                          static_cast<JobModel::JobAction>(action),
0466                                          destName);
0467             if (!request) {
0468                 // probably the job already has this state
0469                 // or this is an unknown action
0470                 continue;
0471             }
0472             request->waitTillFinished();
0473             if (request->hasError()) {
0474                 QString msg, jobName;
0475                 jobName = m_model->item(index.row(), static_cast<int>(JobModel::ColName))->text();
0476                 switch (action) {
0477                 case JobModel::Cancel:
0478                     msg = i18n("Failed to cancel '%1'", jobName);
0479                     break;
0480                 case JobModel::Hold:
0481                     msg = i18n("Failed to hold '%1'", jobName);
0482                     break;
0483                 case JobModel::Release:
0484                     msg = i18n("Failed to release '%1'", jobName);
0485                     break;
0486                 case JobModel::Reprint:
0487                     msg = i18n("Failed to reprint '%1'", jobName);
0488                     break;
0489                 case JobModel::Move:
0490                     msg = i18n("Failed to move '%1' to '%2'", jobName, destName);
0491                     break;
0492                 }
0493                 KMessageBox::detailedSorry(this,
0494                                            msg,
0495                                            request->errorMsg(),
0496                                            i18n("Failed"));
0497             }
0498             request->deleteLater();
0499         }
0500     }
0501 }
0502 
0503 void PrintQueueUi::pausePrinter()
0504 {
0505     // STOP and RESUME printer
0506     QPointer<KCupsRequest> request = new KCupsRequest;
0507     if (m_printerPaused) {
0508         qDebug() << m_destName << "m_printerPaused";
0509         request->resumePrinter(m_destName);
0510     } else {
0511         qDebug() << m_destName << "NOT m_printerPaused";
0512         request->pausePrinter(m_destName);
0513     }
0514     request->waitTillFinished();
0515     if (request) {
0516         request->deleteLater();
0517     }
0518 }
0519 
0520 void PrintQueueUi::configurePrinter()
0521 {
0522     QProcess::startDetached(QLatin1String("configure-printer"), {m_destName});
0523 }
0524 
0525 void PrintQueueUi::cancelJob()
0526 {
0527     // CANCEL a job
0528     modifyJob(JobModel::Cancel);
0529 }
0530 
0531 void PrintQueueUi::holdJob()
0532 {
0533     // HOLD a job
0534     modifyJob(JobModel::Hold);
0535 }
0536 
0537 void PrintQueueUi::resumeJob()
0538 {
0539     // RESUME a job
0540     modifyJob(JobModel::Release);
0541 }
0542 
0543 void PrintQueueUi::reprintJob()
0544 {
0545     modifyJob(JobModel::Reprint);
0546 }
0547 
0548 void PrintQueueUi::authenticateJob()
0549 {
0550     QScopedPointer<KCupsRequest> request(new KCupsRequest);
0551     request->getPrinterAttributes(m_destName, m_isClass, { KCUPS_PRINTER_URI_SUPPORTED, KCUPS_AUTH_INFO_REQUIRED });
0552     request->waitTillFinished();
0553     if (request->hasError() || request->printers().size() != 1) {
0554         qWarning() << "Ignoring request, printer not found or error" << m_destName << request->errorMsg();
0555     }
0556 
0557     const KCupsPrinter printer = request->printers().first();
0558 
0559     KIO::AuthInfo info;
0560     info.keepPassword = true;
0561     info.prompt = i18n("Enter credentials to print from <b>%1</b>", m_destName);
0562     info.url = QUrl(printer.uriSupported());
0563     if (printer.authInfoRequired().contains(QStringLiteral("domain"))) {
0564         info.setExtraField(QStringLiteral("domain"), QStringLiteral(""));
0565     }
0566 
0567     QScopedPointer<KPasswdServerClient> passwdServerClient(new KPasswdServerClient());
0568 
0569     auto winId = static_cast<qlonglong>(this->winId());
0570     auto usertime = static_cast<qlonglong>(KUserTimestamp::userTimestamp());
0571     if (passwdServerClient->checkAuthInfo(&info, winId, usertime)) {
0572         // at this stage we don't know if stored credentials are correct
0573         // trying blindly is risky, it may block this user's account
0574         passwdServerClient->removeAuthInfo(info.url.host(), info.url.scheme(), info.username);
0575     }
0576     const int passwordDialogErrorCode = passwdServerClient->queryAuthInfo(&info, QString(), winId, usertime);
0577     if (passwordDialogErrorCode != KJob::NoError) {
0578         // user cancelled or kiod_kpasswdserver not running
0579         qDebug() << "queryAuthInfo error code" << passwordDialogErrorCode;
0580         return;
0581     }
0582 
0583     QStringList authInfo;
0584     for (QString &authInfoRequired : printer.authInfoRequired()) {
0585         if (authInfoRequired == QStringLiteral("domain")) {
0586             authInfo << info.getExtraField(QStringLiteral("domain")).toString();
0587         } else if (authInfoRequired == QStringLiteral("username")) {
0588             authInfo << info.username;
0589         } else if (authInfoRequired == QStringLiteral("password")) {
0590             authInfo << info.password;
0591         } else {
0592             qWarning() << "No auth info for: " << authInfoRequired;
0593             authInfo << QString();
0594         }
0595     }
0596 
0597     // we need to map the selection to source to get the real indexes
0598     QItemSelection selection = m_proxyModel->mapSelectionToSource(ui->jobsView->selectionModel()->selection());
0599     const QModelIndexList indexes = selection.indexes();
0600     for (const QModelIndex &index : indexes) {
0601         if (index.column() == JobModel::Columns::ColStatus) {
0602             QScopedPointer<KCupsRequest> authRequest(new KCupsRequest);
0603             authRequest->authenticateJob(m_destName, authInfo, index.data(JobModel::Role::RoleJobId).toInt());
0604             authRequest->waitTillFinished();
0605             if (authRequest->hasError()) {
0606                 qWarning() << "Error authenticating jobs" << authRequest->error() << authRequest->errorMsg();
0607                 // remove cache on fail
0608                 passwdServerClient->removeAuthInfo(info.url.host(), info.url.scheme(), info.username);
0609                 return;
0610             }
0611         }
0612     }
0613 
0614 }
0615 
0616 void PrintQueueUi::whichJobsIndexChanged(int index)
0617 {
0618     switch (index) {
0619     case 1:
0620         m_model->setWhichJobs(JobModel::WhichCompleted);
0621         break;
0622     case 2:
0623         m_model->setWhichJobs(JobModel::WhichAll);
0624         break;
0625     default:
0626         m_model->setWhichJobs(JobModel::WhichActive);
0627         break;
0628     }
0629 
0630 }
0631 
0632 void PrintQueueUi::setupButtons()
0633 {
0634     // setup jobs buttons
0635 
0636     // cancel action
0637     ui->cancelJobPB->setIcon(QIcon::fromTheme(QLatin1String("dialog-cancel")));
0638 
0639     // hold job action
0640     ui->holdJobPB->setIcon(QIcon::fromTheme(QLatin1String("document-open-recent")));
0641 
0642     // resume job action
0643     // TODO we need a new icon
0644     ui->resumeJobPB->setIcon(QIcon::fromTheme(QLatin1String("media-playback-start")));
0645 
0646     ui->reprintPB->setIcon(QIcon::fromTheme(QLatin1String("view-refresh")));
0647 
0648     const QIcon viewFilterIcon = QIcon::fromTheme(QLatin1String("view-filter"));
0649     ui->whichJobsCB->setItemIcon(0, viewFilterIcon);
0650     ui->whichJobsCB->setItemIcon(1, viewFilterIcon);
0651     ui->whichJobsCB->setItemIcon(2, viewFilterIcon);
0652 
0653     // stop start printer
0654     ui->pausePrinterPB->setIcon(QIcon::fromTheme(QLatin1String("media-playback-pause")));
0655 
0656     // configure printer
0657     ui->configurePrinterPB->setIcon(QIcon::fromTheme(QLatin1String("configure")));
0658 }
0659 
0660 void PrintQueueUi::closeEvent(QCloseEvent *event)
0661 {
0662     // emits finished signal to be removed the cache
0663     Q_EMIT finished();
0664     QWidget::closeEvent(event);
0665 }
0666 
0667 #include "moc_PrintQueueUi.cpp"