File indexing completed on 2024-06-23 05:13:50

0001 /* -*- mode: c++; c-basic-offset:4 -*-
0002     crypto/gui/resultpage.cpp
0003 
0004     This file is part of Kleopatra, the KDE keymanager
0005     SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 
0010 #include <config-kleopatra.h>
0011 
0012 #include "newresultpage.h"
0013 
0014 #include "resultitemwidget.h"
0015 #include "resultlistwidget.h"
0016 
0017 #include <crypto/taskcollection.h>
0018 
0019 #include <Libkleo/Stl_Util>
0020 
0021 #include <KLocalizedString>
0022 
0023 #include <QCheckBox>
0024 #include <QHash>
0025 #include <QLabel>
0026 #include <QProgressBar>
0027 #include <QTimer>
0028 #include <QVBoxLayout>
0029 
0030 static const int ProgressBarHideDelay = 2000; // 2 secs
0031 
0032 using namespace Kleo;
0033 using namespace Kleo::Crypto;
0034 using namespace Kleo::Crypto::Gui;
0035 
0036 class NewResultPage::Private
0037 {
0038     NewResultPage *const q;
0039 
0040 public:
0041     explicit Private(NewResultPage *qq);
0042 
0043     void progress(int progress, int total);
0044     void result(const std::shared_ptr<const Task::Result> &result);
0045     void started(const std::shared_ptr<Task> &result);
0046     void allDone();
0047     QLabel *labelForTag(const QString &tag);
0048 
0049     std::vector<std::shared_ptr<TaskCollection>> m_collections;
0050     QTimer m_hideProgressTimer;
0051     QProgressBar *m_progressBar;
0052     QHash<QString, QLabel *> m_progressLabelByTag;
0053     QVBoxLayout *m_progressLabelLayout;
0054     int m_lastErrorItemIndex;
0055     ResultListWidget *m_resultList;
0056 };
0057 
0058 NewResultPage::Private::Private(NewResultPage *qq)
0059     : q(qq)
0060     , m_lastErrorItemIndex(0)
0061 {
0062     m_hideProgressTimer.setInterval(ProgressBarHideDelay);
0063     m_hideProgressTimer.setSingleShot(true);
0064 
0065     QBoxLayout *const layout = new QVBoxLayout(q);
0066     auto const labels = new QWidget;
0067     m_progressLabelLayout = new QVBoxLayout(labels);
0068     layout->addWidget(labels);
0069     m_progressBar = new QProgressBar;
0070     layout->addWidget(m_progressBar);
0071     m_resultList = new ResultListWidget;
0072     connect(m_resultList, &ResultListWidget::linkActivated, q, &NewResultPage::linkActivated);
0073     layout->addWidget(m_resultList, 1);
0074 
0075     connect(&m_hideProgressTimer, &QTimer::timeout, m_progressBar, &QProgressBar::hide);
0076 }
0077 
0078 void NewResultPage::Private::progress(int progress, int total)
0079 {
0080     Q_ASSERT(progress >= 0);
0081     Q_ASSERT(total >= 0);
0082     m_progressBar->setRange(0, total);
0083     m_progressBar->setValue(progress);
0084 }
0085 
0086 void NewResultPage::Private::allDone()
0087 {
0088     Q_ASSERT(!m_collections.empty());
0089     if (!m_resultList->isComplete()) {
0090         return;
0091     }
0092     m_progressBar->setRange(0, 100);
0093     m_progressBar->setValue(100);
0094     m_collections.clear();
0095     const auto progressLabelByTagKeys{m_progressLabelByTag.keys()};
0096     for (const QString &i : progressLabelByTagKeys) {
0097         if (!i.isEmpty()) {
0098             m_progressLabelByTag.value(i)->setText(i18n("%1: All operations completed.", i));
0099         } else {
0100             m_progressLabelByTag.value(i)->setText(i18n("All operations completed."));
0101         }
0102     }
0103     if (QAbstractButton *cancel = q->wizard()->button(QWizard::CancelButton)) {
0104         cancel->setEnabled(false);
0105     }
0106     Q_EMIT q->completeChanged();
0107     m_hideProgressTimer.start();
0108 }
0109 
0110 void NewResultPage::Private::result(const std::shared_ptr<const Task::Result> &)
0111 {
0112 }
0113 
0114 void NewResultPage::Private::started(const std::shared_ptr<Task> &task)
0115 {
0116     Q_ASSERT(task);
0117     const QString tag = task->tag();
0118     QLabel *const label = labelForTag(tag);
0119     Q_ASSERT(label);
0120     if (tag.isEmpty()) {
0121         label->setText(i18nc("number, operation description", "Operation %1: %2", m_resultList->numberOfCompletedTasks() + 1, task->label()));
0122     } else {
0123         label->setText(i18nc(R"(tag( "OpenPGP" or "CMS"),  operation description)", "%1: %2", tag, task->label()));
0124     }
0125 }
0126 
0127 NewResultPage::NewResultPage(QWidget *parent)
0128     : QWizardPage(parent)
0129     , d(new Private(this))
0130 {
0131     setTitle(i18n("<b>Results</b>"));
0132 }
0133 
0134 NewResultPage::~NewResultPage()
0135 {
0136 }
0137 
0138 void NewResultPage::setTaskCollection(const std::shared_ptr<TaskCollection> &coll)
0139 {
0140     // clear(); ### PENDING(marc) implement
0141     addTaskCollection(coll);
0142 }
0143 
0144 void NewResultPage::addTaskCollection(const std::shared_ptr<TaskCollection> &coll)
0145 {
0146     Q_ASSERT(coll);
0147     if (std::find(d->m_collections.cbegin(), d->m_collections.cend(), coll) != d->m_collections.cend()) {
0148         return;
0149     }
0150     d->m_hideProgressTimer.stop();
0151     d->m_progressBar->show();
0152     d->m_collections.push_back(coll);
0153     d->m_resultList->addTaskCollection(coll);
0154     connect(coll.get(), &TaskCollection::progress, this, [this](int current, int total) {
0155         d->progress(current, total);
0156     });
0157     connect(coll.get(), SIGNAL(done()), this, SLOT(allDone()));
0158     connect(coll.get(),
0159             SIGNAL(result(std::shared_ptr<const Kleo::Crypto::Task::Result>)),
0160             this,
0161             SLOT(result(std::shared_ptr<const Kleo::Crypto::Task::Result>)));
0162     connect(coll.get(), SIGNAL(started(std::shared_ptr<Kleo::Crypto::Task>)), this, SLOT(started(std::shared_ptr<Kleo::Crypto::Task>)));
0163 
0164     for (const std::shared_ptr<Task> &i : coll->tasks()) { // create labels for all tags in collection
0165         Q_ASSERT(i);
0166         QLabel *l = d->labelForTag(i->tag());
0167         Q_ASSERT(l);
0168         (void)l;
0169     }
0170     Q_EMIT completeChanged();
0171 }
0172 
0173 QLabel *NewResultPage::Private::labelForTag(const QString &tag)
0174 {
0175     if (QLabel *const label = m_progressLabelByTag.value(tag)) {
0176         return label;
0177     }
0178     auto label = new QLabel;
0179     label->setTextFormat(Qt::RichText);
0180     label->setWordWrap(true);
0181     m_progressLabelLayout->addWidget(label);
0182     m_progressLabelByTag.insert(tag, label);
0183     return label;
0184 }
0185 
0186 bool NewResultPage::isComplete() const
0187 {
0188     return d->m_resultList->isComplete();
0189 }
0190 
0191 #include "moc_newresultpage.cpp"