From 5e0b45ab474c4f3037d443cd3b62c65cb4bf9998 Mon Sep 17 00:00:00 2001 From: Raul Metsma Date: Wed, 13 Nov 2024 16:31:44 +0200 Subject: [PATCH 1/2] Update ContainerWidget to new UI guidlines IB-7969 Signed-off-by: Raul Metsma --- client/MainWindow.cpp | 69 ++---- client/MainWindow.h | 6 +- client/images/icon_Edit.svg | 17 +- client/images/icon_Edit_hover.svg | 16 -- client/images/icon_Edit_pressed.svg | 16 -- client/images/icon_arrow_left.svg | 3 + client/images/images.qrc | 3 +- client/translations/en.ts | 51 +--- client/translations/et.ts | 51 +--- client/translations/ru.ts | 51 +--- client/widgets/ContainerPage.cpp | 179 ++++++-------- client/widgets/ContainerPage.h | 11 +- client/widgets/ContainerPage.ui | 347 +++++++++------------------- client/widgets/LabelButton.cpp | 72 +----- client/widgets/LabelButton.h | 9 - 15 files changed, 226 insertions(+), 675 deletions(-) delete mode 100644 client/images/icon_Edit_hover.svg delete mode 100644 client/images/icon_Edit_pressed.svg create mode 100644 client/images/icon_arrow_left.svg diff --git a/client/MainWindow.cpp b/client/MainWindow.cpp index 2fbb8d71b..885b56de1 100644 --- a/client/MainWindow.cpp +++ b/client/MainWindow.cpp @@ -108,7 +108,7 @@ MainWindow::MainWindow( QWidget *parent ) separator->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); separator->setStyleSheet(QStringLiteral("background-color: #D9D9D9;")); separator->resize(8000, 1); - separator->move(110, 0); + separator->move(mapToGlobal(ui->topBar->pos())); separator->show(); #endif @@ -124,8 +124,6 @@ MainWindow::MainWindow( QWidget *parent ) updateSelectorData(token); updateMyEID(token); ui->cryptoContainerPage->cardChanged(token.cert()); - if(cryptoDoc) - ui->cryptoContainerPage->update(cryptoDoc, token.cert()); }); QPCSC::instance().start(); @@ -151,8 +149,6 @@ MainWindow::MainWindow( QWidget *parent ) connect(ui->cryptoContainerPage, &ContainerPage::action, this, &MainWindow::onCryptoAction); connect(ui->cryptoContainerPage, &ContainerPage::addFiles, this, [this](const QStringList &files) { openFiles(files, true); } ); connect(ui->cryptoContainerPage, &ContainerPage::fileRemoved, this, &MainWindow::removeCryptoFile); - connect(ui->cryptoContainerPage, &ContainerPage::keysSelected, this, &MainWindow::updateKeys); - connect(ui->cryptoContainerPage, &ContainerPage::removed, this, &MainWindow::removeAddress); connect(ui->cryptoContainerPage, &ContainerPage::warning, this, [this](WarningText warningText) { ui->warnings->showWarning(warningText); ui->crypto->warningIcon(true); @@ -339,19 +335,15 @@ void MainWindow::navigateToPage( Pages page, const QStringList &files, bool crea if(!filename.isNull()) { signatureContainer->create(filename); - bool filesAdded = false; for(const auto &file: files) { if(signatureContainer->documentModel()->addFile(file)) - filesAdded = true; + navigate = true; } - navigate = filesAdded; } } - else if(signatureContainer->open(files[0])) - { - navigate = true; - } + else + navigate = signatureContainer->open(files[0]); if(navigate) { resetDigiDoc(signatureContainer.release()); @@ -361,7 +353,7 @@ void MainWindow::navigateToPage( Pages page, const QStringList &files, bool crea else if(page == CryptoDetails) { navigate = false; - std::unique_ptr cryptoContainer(new CryptoDoc(this)); + auto cryptoContainer = std::make_unique(this); if(create) { @@ -369,23 +361,19 @@ void MainWindow::navigateToPage( Pages page, const QStringList &files, bool crea if(!filename.isNull()) { cryptoContainer->clear(filename); - bool filesAdded = false; for(const auto &file: files) { if(cryptoContainer->documentModel()->addFile(file)) - filesAdded = true; + navigate = true; } - navigate = filesAdded; } } - else if(cryptoContainer->open(files[0])) - { - navigate = true; - } + else + navigate = cryptoContainer->open(files[0]); if(navigate) { - resetCryptoDoc(cryptoContainer.release()); - ui->cryptoContainerPage->transition(cryptoDoc, qApp->signer()->tokenauth().cert()); + resetCryptoDoc(std::move(cryptoContainer)); + ui->cryptoContainerPage->transition(cryptoDoc.get(), qApp->signer()->tokenauth().cert()); } } @@ -469,7 +457,7 @@ void MainWindow::convertToCDoc() if(filename.isNull()) return; - std::unique_ptr cryptoContainer(new CryptoDoc(this)); + auto cryptoContainer = std::make_unique(this); cryptoContainer->clear(filename); // If signed, add whole signed document to cryptocontainer; otherwise content only @@ -482,9 +470,9 @@ void MainWindow::convertToCDoc() if(!cardData.cert().isNull()) cryptoContainer->addKey(CKey(cardData.cert())); - resetCryptoDoc(cryptoContainer.release()); + resetCryptoDoc(std::move(cryptoContainer)); resetDigiDoc(nullptr, false); - ui->cryptoContainerPage->transition(cryptoDoc, qApp->signer()->tokenauth().cert()); + ui->cryptoContainerPage->transition(cryptoDoc.get(), qApp->signer()->tokenauth().cert()); selectPage(CryptoDetails); FadeInNotification::success(ui->topBar, tr("Converted to crypto container!")); @@ -520,14 +508,14 @@ void MainWindow::onCryptoAction(int action, const QString &/*id*/, const QString case DecryptToken: if(decrypt()) { - ui->cryptoContainerPage->transition(cryptoDoc, qApp->signer()->tokenauth().cert()); + ui->cryptoContainerPage->transition(cryptoDoc.get(), qApp->signer()->tokenauth().cert()); FadeInNotification::success(ui->topBar, tr("Decryption succeeded!")); } break; case EncryptContainer: if(encrypt()) { - ui->cryptoContainerPage->transition(cryptoDoc, qApp->signer()->tokenauth().cert()); + ui->cryptoContainerPage->transition(cryptoDoc.get(), qApp->signer()->tokenauth().cert()); FadeInNotification::success(ui->topBar, tr("Encryption succeeded!")); } break; @@ -688,12 +676,10 @@ void MainWindow::openContainer(bool signature) openFiles(files); } -void MainWindow::resetCryptoDoc(CryptoDoc *doc) +void MainWindow::resetCryptoDoc(std::unique_ptr &&doc) { ui->crypto->warningIcon(false); - ui->cryptoContainerPage->clear(); - delete cryptoDoc; - cryptoDoc = doc; + cryptoDoc = std::move(doc); } void MainWindow::resetDigiDoc(DigiDoc *doc, bool warnOnChange) @@ -886,15 +872,6 @@ void MainWindow::sign(F &&sign) adjustDrops(); } -void MainWindow::removeAddress(int index) -{ - if(cryptoDoc) - { - cryptoDoc->removeKey(index); - ui->cryptoContainerPage->update(cryptoDoc, qApp->signer()->tokenauth().cert()); - } -} - void MainWindow::removeCryptoFile(int index) { if(!cryptoDoc) @@ -1077,18 +1054,6 @@ void MainWindow::updateSelectorData(TokenData data) showCardMenu(false); } -void MainWindow::updateKeys(const QList &keys) -{ - if(!cryptoDoc) - return; - - for(auto i = cryptoDoc->keys().size() - 1; i >= 0; i--) - cryptoDoc->removeKey(i); - for(const auto &key: keys) - cryptoDoc->addKey(key); - ui->cryptoContainerPage->update(cryptoDoc, qApp->signer()->tokenauth().cert()); -} - void MainWindow::containerSummary() { #ifdef Q_OS_WIN diff --git a/client/MainWindow.h b/client/MainWindow.h index e00de6995..b63e9fe90 100644 --- a/client/MainWindow.h +++ b/client/MainWindow.h @@ -83,9 +83,8 @@ private Q_SLOTS: void openFiles(const QStringList &files, bool addFile = false, bool forceCreate = false); void pinUnblock(QSmartCardData::PinType type, bool isForgotPin); void pinPukChange( QSmartCardData::PinType type ); - void resetCryptoDoc(CryptoDoc *doc = nullptr); + void resetCryptoDoc(std::unique_ptr &&doc = {}); void resetDigiDoc(DigiDoc *doc = nullptr, bool warnOnChange = true); - void removeAddress(int index); void removeCryptoFile(int index); bool removeFile(DocumentModel *model, int index); void removeSignature(int index); @@ -102,7 +101,6 @@ private Q_SLOTS: void showPinBlockedWarning(const QSmartCardData& t); void updateSelector(); void updateSelectorData(TokenData data); - void updateKeys(const QList &keys); void updateMyEID(const TokenData &t); void updateMyEid(const QSmartCardData &data); bool wrap(const QString& wrappedFile, bool enclose); @@ -113,7 +111,7 @@ private Q_SLOTS: static void containerToEmail(const QString &fileName); static QStringList dropEventFiles(QDropEvent *event); - CryptoDoc* cryptoDoc = nullptr; + std::unique_ptr cryptoDoc; DigiDoc* digiDoc = nullptr; Ui::MainWindow *ui; }; diff --git a/client/images/icon_Edit.svg b/client/images/icon_Edit.svg index 5c6390248..0be93d601 100644 --- a/client/images/icon_Edit.svg +++ b/client/images/icon_Edit.svg @@ -1,16 +1,3 @@ - - - - Icon_Edit - - - - - - - - - - - + + \ No newline at end of file diff --git a/client/images/icon_Edit_hover.svg b/client/images/icon_Edit_hover.svg deleted file mode 100644 index a789a3adb..000000000 --- a/client/images/icon_Edit_hover.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - Icon_Edit hover - - - - - - - - - - - - \ No newline at end of file diff --git a/client/images/icon_Edit_pressed.svg b/client/images/icon_Edit_pressed.svg deleted file mode 100644 index 9b387b2f8..000000000 --- a/client/images/icon_Edit_pressed.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - Icon_Edit - - - - - - - - - - - - \ No newline at end of file diff --git a/client/images/icon_arrow_left.svg b/client/images/icon_arrow_left.svg new file mode 100644 index 000000000..e09a5b32c --- /dev/null +++ b/client/images/icon_arrow_left.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/client/images/images.qrc b/client/images/images.qrc index 8355e5942..52c5c9d00 100644 --- a/client/images/images.qrc +++ b/client/images/images.qrc @@ -19,6 +19,7 @@ icon_Allkiri_hover.svg icon_Allkiri_small.svg icon_Allkiri.svg + icon_arrow_left.svg icon_check.svg icon_checkbox.svg icon_checkbox_active.svg @@ -30,8 +31,6 @@ icon_checkbox_check_hover.svg icon_digitempel.svg icon_download.svg - icon_Edit_hover.svg - icon_Edit_pressed.svg icon_Edit.svg icon_help.svg icon_IDkaart_disabled.svg diff --git a/client/translations/en.ts b/client/translations/en.ts index 277107699..1c274da27 100644 --- a/client/translations/en.ts +++ b/client/translations/en.ts @@ -500,42 +500,6 @@ Container: Container: - - CHANGE - CHANGE - - - CANCEL - ← CANCEL - - - SEND WITH E-MAIL - SEND WITH E-MAIL - - - PRINT SUMMARY - PRINT SUMMARY - - - ENCRYPT - ENCRYPT - - - SIGN - SIGN - - - SAVE AS - SAVE AS - - - SAVE WITHOUT SIGNING - SAVE WITHOUT SIGNING - - - STARTING - ← START - The document has already been signed by you. The document has already been signed by you. @@ -550,39 +514,40 @@ Change - accessible Change Cancel - accessible Cancel Encrypt - accessible Encrypt Save as - accessible Save as Send with e-mail - accessible Send with e-mail Print summary - accessible Print summary Save without signing - accessible Save without signing + + Start + Start + + + Sign + Sign + CryptoDoc diff --git a/client/translations/et.ts b/client/translations/et.ts index 6bdb232f1..933394f3d 100644 --- a/client/translations/et.ts +++ b/client/translations/et.ts @@ -500,42 +500,6 @@ Container: Ümbrik: - - CHANGE - MUUDA - - - CANCEL - ← KATKESTA - - - SEND WITH E-MAIL - EDASTA E-POSTIGA - - - PRINT SUMMARY - TRÜKI KINNITUSLEHT - - - ENCRYPT - KRÜPTEERI - - - SIGN - ALLKIRJASTA - - - SAVE AS - SALVESTA - - - SAVE WITHOUT SIGNING - SALVESTA ALLKIRJASTAMATA - - - STARTING - ← ALGUSESSE - The document has already been signed by you. Dokument on Sinu poolt juba allkirjastatud. @@ -550,39 +514,40 @@ Change - accessible Muuda Cancel - accessible Katkesta Encrypt - accessible Krüpteeri Save as - accessible Salvesta Send with e-mail - accessible Edasta e-postiga Print summary - accessible Trüki kinnitusleht Save without signing - accessible Salvesta allkirjastamata + + Start + Algusesse + + + Sign + Allkirjasta + CryptoDoc diff --git a/client/translations/ru.ts b/client/translations/ru.ts index 8022b67b3..2881c4e49 100644 --- a/client/translations/ru.ts +++ b/client/translations/ru.ts @@ -500,42 +500,6 @@ Container: Kонтейнер: - - CHANGE - ПОМЕНЯТЬ - - - CANCEL - ← ОТМЕНА - - - SEND WITH E-MAIL - ОТПРАВИТЬ С Е-ПOЧТOЙ - - - PRINT SUMMARY - ПОДТВЕРЖДАЮЩИЙ ЛИСТ - - - ENCRYPT - ШИФРОВАТЬ - - - SIGN - ПОДПИСАТЬ - - - SAVE AS - CОХРАНИТЬ - - - SAVE WITHOUT SIGNING - СОХРАНИТЬ БЕЗ ПОДПИСИ - - - STARTING - ← В НАЧАЛО - The document has already been signed by you. Вы уже подписали этот документ. @@ -550,39 +514,40 @@ Change - accessible Поменять Cancel - accessible Отмена Encrypt - accessible Зашифровать Save as - accessible Cохранить Send with e-mail - accessible Отправить с е-пoчтoй Print summary - accessible Подтверждающий лист Save without signing - accessible Сохранить без подписи + + Start + В начало + + + Sign + Подписать + CryptoDoc diff --git a/client/widgets/ContainerPage.cpp b/client/widgets/ContainerPage.cpp index f5a41b8f8..47cebc6e2 100644 --- a/client/widgets/ContainerPage.cpp +++ b/client/widgets/ContainerPage.cpp @@ -23,7 +23,6 @@ #include "CryptoDoc.h" #include "DigiDoc.h" #include "Settings.h" -#include "Styles.h" #include "SslCertificate.h" #include "dialogs/AddRecipients.h" #include "dialogs/FileDialog.h" @@ -46,25 +45,13 @@ ContainerPage::ContainerPage(QWidget *parent) { ui->setupUi( this ); ui->leftPane->init(fileName); - - ui->container->setFont(Styles::font(Styles::Regular, 14)); - ui->containerFile->setFont(Styles::font(Styles::Regular, 14)); - - ui->changeLocation->setIcons(QStringLiteral("/images/icon_Edit.svg"), - QStringLiteral("/images/icon_Edit_hover.svg"), QStringLiteral("/images/icon_Edit_pressed.svg"), 18, 18); - ui->changeLocation->init(LabelButton::BoxedDeepCeruleanWithCuriousBlue, tr("CHANGE")); ui->containerFile->installEventFilter(this); - ui->cancel->init(LabelButton::BoxedMojo, tr("CANCEL")); - ui->convert->init(LabelButton::BoxedDeepCerulean, tr("ENCRYPT")); - ui->saveAs->init(LabelButton::BoxedDeepCerulean, tr("SAVE AS")); - ui->email->init(LabelButton::BoxedDeepCerulean, tr("SEND WITH E-MAIL")); - ui->summary->init(LabelButton::BoxedDeepCerulean, tr("PRINT SUMMARY")); - ui->save->init(LabelButton::BoxedDeepCerulean, tr("SAVE WITHOUT SIGNING")); + ui->summary->hide(); mobileCode = Settings::MOBILEID_CODE; - auto connectCode = [this](QToolButton *btn, int code) { - connect(btn, &QToolButton::clicked, this, [this,code] { emit forward(code); }); + auto connectCode = [this](QAbstractButton *btn, int code) { + connect(btn, &QAbstractButton::clicked, this, [this,code] { emit forward(code); }); }; connect(this, &ContainerPage::moved,this, &ContainerPage::setHeader); @@ -79,12 +66,9 @@ ContainerPage::ContainerPage(QWidget *parent) connect(ui->leftPane, &ItemList::removed, this, &ContainerPage::fileRemoved); connect(ui->leftPane, &ItemList::addItem, this, &ContainerPage::forward); connect(ui->rightPane, &ItemList::addItem, this, &ContainerPage::forward); - connect(ui->rightPane, &ItemList::addressSearch, this, &ContainerPage::addressSearch); connect(ui->rightPane, &ItemList::removed, this, &ContainerPage::removed); connect(ui->containerFile, &QLabel::linkActivated, this, [this](const QString &link) { emit action(Actions::ContainerNavigate, link); }); - - ui->summary->setVisible(Settings::SHOW_PRINT_SUMMARY); } ContainerPage::~ContainerPage() @@ -92,29 +76,14 @@ ContainerPage::~ContainerPage() delete ui; } -void ContainerPage::addressSearch() -{ - AddRecipients dlg(ui->rightPane, this); - if(dlg.exec() && dlg.isUpdated()) - emit keysSelected(dlg.keys()); -} - void ContainerPage::cardChanged(const SslCertificate &cert, bool isBlocked) { emit ui->rightPane->idChanged(cert); isSeal = cert.type() & SslCertificate::TempelType; isExpired = !cert.isValid(); this->isBlocked = isBlocked; - cardChanged(cert.personalCode()); -} - -void ContainerPage::cardChanged(const QString &idCode) -{ - cardInReader = idCode; - if(ui->leftPane->getState() & SignatureContainers) - showSigningButton(); - else if(ui->leftPane->getState() & EncryptedContainer) - updateDecryptionButton(); + cardInReader = cert.personalCode(); + emit certChanged(cert); } bool ContainerPage::checkAction(int code, const QString& selectedCard, const QString& selectedMobile) @@ -157,7 +126,7 @@ void ContainerPage::clearPopups() void ContainerPage::elideFileName() { - ui->containerFile->setText(QStringLiteral("%1") + ui->containerFile->setText(QStringLiteral("%1") .arg(ui->containerFile->fontMetrics().elidedText(FileDialog::normalized(fileName).toHtmlEscaped(), Qt::ElideMiddle, ui->containerFile->width()))); } @@ -190,7 +159,7 @@ void ContainerPage::forward(int code) if(QString newCode = Settings::MOBILEID_CODE; newCode != mobileCode) { mobileCode = std::move(newCode); - cardChanged(cardInReader); + showSigningButton(); } break; } @@ -205,7 +174,7 @@ void ContainerPage::forward(int code) if(QString newCode = Settings::SMARTID_CODE; newCode != mobileCode) { mobileCode = std::move(newCode); - cardChanged(cardInReader); + showSigningButton(); } break; } @@ -221,11 +190,6 @@ void ContainerPage::forward(int code) } } -void ContainerPage::hideRightPane() -{ - ui->rightPane->hide(); -} - void ContainerPage::changeEvent(QEvent* event) { if (event->type() == QEvent::LanguageChange) @@ -245,12 +209,6 @@ void ContainerPage::setHeader(const QString &file) elideFileName(); } -void ContainerPage::showRightPane(ItemType itemType, const char *header) -{ - ui->rightPane->init(itemType, header); - ui->rightPane->show(); -} - void ContainerPage::showMainAction(const QList &actions) { if(!mainAction) @@ -262,9 +220,9 @@ void ContainerPage::showMainAction(const QList &actions) bool isSignCard = actions.contains(SignatureAdd) || actions.contains(SignatureToken); bool isSignMobile = !isSignCard && (actions.contains(SignatureMobile) || actions.contains(SignatureSmartID)); bool isEncrypt = actions.contains(EncryptContainer) && !ui->rightPane->findChildren().isEmpty(); - bool isDecrypt = actions.contains(DecryptContainer) || actions.contains(DecryptToken); + bool isDecrypt = !isBlocked && (actions.contains(DecryptContainer) || actions.contains(DecryptToken)); mainAction->setButtonEnabled(isSupported && !hasEmptyFile && - (isEncrypt || isSignMobile || (!isBlocked && ((isSignCard && !isExpired) || isDecrypt)))); + (isEncrypt || isDecrypt || isSignMobile || (isSignCard && !isBlocked && !isExpired))); ui->mainActionSpacer->changeSize(198, 20, QSizePolicy::Fixed); ui->navigationArea->layout()->invalidate(); } @@ -288,12 +246,41 @@ void ContainerPage::showSigningButton() void ContainerPage::transition(CryptoDoc *container, const QSslCertificate &cert) { + disconnect(ui->rightPane, &ItemList::addressSearch, container, nullptr); + connect(ui->rightPane, &ItemList::addressSearch, container, [this, container] { + AddRecipients dlg(ui->rightPane, this); + if(!dlg.exec() || !dlg.isUpdated()) + return; + for(auto i = container->keys().size() - 1; i >= 0; i--) + container->removeKey(i); + ui->rightPane->clear(); + for(const auto &key: dlg.keys()) + { + container->addKey(key); + ui->rightPane->addWidget(new AddressItem(key, ui->rightPane, true)); + } + showMainAction({ EncryptContainer }); + }); + disconnect(this, &ContainerPage::removed, container, nullptr); + connect(this, &ContainerPage::removed, container, [this, container](int index) { + container->removeKey(index); + ui->rightPane->removeItem(index); + showMainAction({ EncryptContainer }); + }); + disconnect(this, &ContainerPage::certChanged, container, nullptr); + connect(this, &ContainerPage::certChanged, container, [this, container](const SslCertificate &cert) { + isSupported = container->state() & UnencryptedContainer || container->canDecrypt(cert); + if(ui->leftPane->getState() & EncryptedContainer) + updateDecryptionButton(); + }); + disconnect(container, &CryptoDoc::destroyed, this, &ContainerPage::clear); + connect(container, &CryptoDoc::destroyed, this, &ContainerPage::clear); + clear(); emit action(ClearCryptoWarning); isSupported = container->state() & UnencryptedContainer || container->canDecrypt(cert); setHeader(container->fileName()); bool hasUnsupported = false; - ui->rightPane->clear(); for(const CKey &key: container->keys()) { hasUnsupported = std::max(hasUnsupported, key.unsupported); @@ -309,12 +296,8 @@ void ContainerPage::transition(DigiDoc* container) { clear(); emit action(ClearSignatureWarning); - QMap errors; + std::map errors; setHeader(container->fileName()); - auto addError = [&errors](const SignatureItem* item) { - int counter = errors.value(item->getError()); - errors[item->getError()] = ++counter; - }; if(!container->timestamps().isEmpty()) { @@ -324,7 +307,7 @@ void ContainerPage::transition(DigiDoc* container) { auto *item = new SignatureItem(c, container->state(), ui->rightPane); if(c.isInvalid()) - addError(item); + ++errors[item->getError()]; ui->rightPane->addHeaderWidget(item); } } @@ -333,12 +316,12 @@ void ContainerPage::transition(DigiDoc* container) { auto *item = new SignatureItem(c, container->state(), ui->rightPane); if(c.isInvalid()) - addError(item); + ++errors[item->getError()]; ui->rightPane->addWidget(item); } - for(auto i = errors.constBegin(); i != errors.constEnd(); ++i) - emit warning({i.key(), i.value()}); + for(const auto &[key, value]: errors) + emit warning({key, value}); if(container->fileName().endsWith(QStringLiteral("ddoc"), Qt::CaseInsensitive)) emit warning({UnsupportedDDocWarning}); if(container->isAsicS()) @@ -363,25 +346,6 @@ void ContainerPage::transition(DigiDoc* container) updatePanes(container->state()); } -void ContainerPage::update(CryptoDoc* container, const QSslCertificate &cert) -{ - isSupported = container->canDecrypt(cert) || container->state() & UnencryptedContainer; - hasEmptyFile = false; - bool hasUnsupported = false; - ui->rightPane->clear(); - for(const CKey &key: container->keys()) - { - hasUnsupported = std::max(hasUnsupported, key.unsupported); - ui->rightPane->addWidget(new AddressItem(key, ui->rightPane, true)); - } - if(hasUnsupported) - emit warning({UnsupportedCDocWarning}); - if(container->state() & EncryptedContainer) - updateDecryptionButton(); - if(container->state() & UnencryptedContainer) - showMainAction({ EncryptContainer }); -} - void ContainerPage::updateDecryptionButton() { showMainAction({ isSeal ? DecryptToken : DecryptContainer }); @@ -391,7 +355,8 @@ void ContainerPage::updatePanes(ContainerState state) { ui->leftPane->stateChange(state); ui->rightPane->stateChange(state); - bool showPrintSummary = Settings::SHOW_PRINT_SUMMARY; + ui->save->setVisible(state == UnsignedContainer); + ui->rightPane->setHidden(state == UnsignedContainer); auto setButtonsVisible = [](const QVector &buttons, bool visible) { for(QWidget *button: buttons) button->setVisible(visible); }; @@ -399,61 +364,51 @@ void ContainerPage::updatePanes(ContainerState state) switch( state ) { case UnsignedContainer: - cancelText = QT_TR_NOOP("CANCEL"); + cancelText = QT_TR_NOOP("Cancel"); ui->changeLocation->show(); ui->rightPane->clear(); - hideRightPane(); ui->leftPane->init(fileName, QT_TRANSLATE_NOOP("ItemList", "Container files")); showSigningButton(); - setButtonsVisible({ ui->cancel, ui->convert, ui->save }, true); setButtonsVisible({ ui->saveAs, ui->email, ui->summary }, false); break; case UnsignedSavedContainer: - cancelText = QT_TR_NOOP("STARTING"); + cancelText = QT_TR_NOOP("Start"); ui->changeLocation->show(); ui->leftPane->init(fileName, QT_TRANSLATE_NOOP("ItemList", "Container files")); - if( showPrintSummary ) - setButtonsVisible({ ui->cancel, ui->convert, ui->saveAs, ui->email, ui->summary }, true); - else - setButtonsVisible({ ui->cancel, ui->convert, ui->saveAs, ui->email }, true); - setButtonsVisible({ ui->save }, false); - showRightPane( ItemSignature, QT_TRANSLATE_NOOP("ItemList", "Container is not signed")); + ui->rightPane->init(ItemSignature, QT_TRANSLATE_NOOP("ItemList", "Container is not signed")); + ui->summary->setVisible(Settings::SHOW_PRINT_SUMMARY); + setButtonsVisible({ ui->saveAs, ui->email }, true); break; case SignedContainer: - cancelText = QT_TR_NOOP("STARTING"); + cancelText = QT_TR_NOOP("Start"); ui->changeLocation->hide(); ui->leftPane->init(fileName, QT_TRANSLATE_NOOP("ItemList", "Container files")); - showRightPane(ItemSignature, QT_TRANSLATE_NOOP("ItemList", "Container signatures")); - if( showPrintSummary ) - setButtonsVisible({ ui->cancel, ui->convert, ui->saveAs, ui->email, ui->summary }, true); - else - setButtonsVisible({ ui->cancel, ui->convert, ui->saveAs, ui->email }, true); - setButtonsVisible({ ui->save }, false); + ui->rightPane->init(ItemSignature, QT_TRANSLATE_NOOP("ItemList", "Container signatures")); + ui->summary->setVisible(Settings::SHOW_PRINT_SUMMARY); + setButtonsVisible({ ui->saveAs, ui->email }, true); break; case UnencryptedContainer: - cancelText = QT_TR_NOOP("STARTING"); - convertText = QT_TR_NOOP("SIGN"); + cancelText = QT_TR_NOOP("Start"); + convertText = QT_TR_NOOP("Sign"); ui->changeLocation->show(); - ui->leftPane->init(fileName); - showRightPane(ItemAddress, QT_TRANSLATE_NOOP("ItemList", "Recipients")); + ui->leftPane->init(fileName, QT_TRANSLATE_NOOP("ItemList", "Encrypted files")); + ui->rightPane->init(ItemAddress, QT_TRANSLATE_NOOP("ItemList", "Recipients")); showMainAction({ EncryptContainer }); - setButtonsVisible({ ui->cancel, ui->convert }, true); - setButtonsVisible({ ui->save, ui->saveAs, ui->email, ui->summary }, false); + setButtonsVisible({ ui->saveAs, ui->email }, false); break; case EncryptedContainer: - cancelText = QT_TR_NOOP("STARTING"); - convertText = QT_TR_NOOP("SIGN"); + cancelText = QT_TR_NOOP("Start"); + convertText = QT_TR_NOOP("Sign"); ui->changeLocation->hide(); ui->leftPane->init(fileName, QT_TRANSLATE_NOOP("ItemList", "Encrypted files")); - showRightPane(ItemAddress, QT_TRANSLATE_NOOP("ItemList", "Recipients")); + ui->rightPane->init(ItemAddress, QT_TRANSLATE_NOOP("ItemList", "Recipients")); updateDecryptionButton(); - setButtonsVisible({ ui->save, ui->summary }, false); - setButtonsVisible({ ui->cancel, ui->convert, ui->saveAs, ui->email }, true); + setButtonsVisible({ ui->saveAs, ui->email }, true); break; default: // Uninitialized cannot be shown on container page @@ -470,10 +425,6 @@ void ContainerPage::togglePrinting(bool enable) void ContainerPage::translateLabels() { - ui->changeLocation->setText(tr("CHANGE")); - ui->changeLocation->setAccessibleName(ui->changeLocation->text().toLower()); ui->cancel->setText(tr(cancelText)); - ui->cancel->setAccessibleName(tr(cancelText).toLower()); ui->convert->setText(tr(convertText)); - ui->convert->setAccessibleName(tr(convertText).toLower()); } diff --git a/client/widgets/ContainerPage.h b/client/widgets/ContainerPage.h index c9370fc47..47ba67afc 100644 --- a/client/widgets/ContainerPage.h +++ b/client/widgets/ContainerPage.h @@ -45,34 +45,29 @@ class ContainerPage final : public QWidget ~ContainerPage() final; void cardChanged(const SslCertificate &cert, bool isBlocked = false); - void cardChanged(const QString &idCode); void clear(); void clearPopups(); void setHeader(const QString &file); void togglePrinting(bool enable); void transition(CryptoDoc *container, const QSslCertificate &cert); void transition(DigiDoc* container); - void update(CryptoDoc *container, const QSslCertificate &cert); signals: void action(int code, const QString &info1 = {}, const QString &info2 = {}); void addFiles(const QStringList &files); + void certChanged(const SslCertificate &cert); void fileRemoved(int row); - void keysSelected(const QList &keys); void moved(const QString &to); void removed(int row); void warning(const WarningText &warningText); private: - void addressSearch(); void changeEvent(QEvent* event) final; bool checkAction(int code, const QString& selectedCard, const QString& selectedMobile); void elideFileName(); bool eventFilter(QObject *o, QEvent *e) final; void forward(int code); - void hideRightPane(); void showMainAction(const QList &actions); - void showRightPane(ria::qdigidoc4::ItemType itemType, const char *header); void showSigningButton(); void updateDecryptionButton(); void updatePanes(ria::qdigidoc4::ContainerState state); @@ -84,8 +79,8 @@ class ContainerPage final : public QWidget QString fileName; QString mobileCode; - const char *cancelText = QT_TR_NOOP("CANCEL"); - const char *convertText = QT_TR_NOOP("ENCRYPT"); + const char *cancelText = QT_TR_NOOP("Cancel"); + const char *convertText = QT_TR_NOOP("Encrypt"); bool isSupported = false; bool hasEmptyFile = false; bool isSeal = false; diff --git a/client/widgets/ContainerPage.ui b/client/widgets/ContainerPage.ui index a1832cc11..4cef223a1 100644 --- a/client/widgets/ContainerPage.ui +++ b/client/widgets/ContainerPage.ui @@ -10,29 +10,20 @@ 491 - - - 914 - 334 - - #leftPane, #rightPane { background-color: #ffffff; } #leftPane { -border: solid #D9D9D8; +border: solid #F3F5F7; border-width: 0px 1px 0px 0px; } #containerHeader { -border: solid #c8c8c8; -border-width: 0px 0px 1px 0px; -background-color: #F4F5F6; +background-color: #F3F5F7; } #navigationArea { -background-color: #F4F5F6; -border: solid #DEE4E9; -border-width: 1px 0px 0px 0px; +background-color: #F3F5F7; +border-top: 1px solid #E7EAEF; } @@ -56,45 +47,61 @@ border-width: 1px 0px 0px 0px; 914 - 36 + 40 16777215 - 36 + 40 + + QWidget { +font-family: Roboto, Helvetica; +font-size: 14px; +} +#container { +color: #415982; +} +#containerFile { +color: #215081; +text-decoration: underline solid; +} +QPushButton { +padding: 9px 12px; +border-radius: 4px; +color: #2F70B6; +font-weight: 700; +} +QPushButton:hover { +background-color: #EAF1F8; +} +QPushButton:pressed { +background-color: #BFD3E8; +} + - 5 + 4 - 8 + 12 - 3 + 0 - 14 + 12 - 7 + 0 - - - 14 - - Qt::TabFocus - - color: #727679; -background-color: #F4F5F6; - Container: @@ -102,23 +109,12 @@ background-color: #F4F5F6; - - - 14 - true - - Qt::TabFocus Qt::NoContextMenu - - color: #353739; -text-decoration: underline solid; -background-color: #F4F5F6; - C:\Downloads\Leping.bdoc @@ -128,28 +124,22 @@ background-color: #F4F5F6; - - - - Roboto Condensed - 12 - true - - + PointingHandCursor - - Change - - - border: none; - - CHANGE + Change - - Qt::ToolButtonTextBesideIcon + + + :/images/icon_Edit.svg:/images/icon_Edit.svg + + + + 16 + 16 + @@ -183,53 +173,67 @@ background-color: #F4F5F6; 40 + + QPushButton { +padding: 9px 12px; +border-radius: 4px; +color: #2F70B6; +font-family: Roboto, Helvetica; +font-size: 12px; +font-weight: 700; +} +QPushButton:hover { +background-color: #EAF1F8; +} +QPushButton:pressed { +background-color: #BFD3E8; +} +QPushButton:default { +color: #AD2A45; +} +QPushButton:default:hover { +background-color: #F5EBED; +} +QPushButton:default:pressed { +background-color: #E1C1C6; +} + + + 16 + - 6 + 24 0 - 7 + 32 0 - - - - 85 - 25 - - - - - 85 - 25 - - - - - Roboto Condensed - 12 - - + PointingHandCursor - - Cancel + + Cancel - - border: none; -border-radius: 3px; -color: #c53e3e; -text-decoration: none solid rgb(197, 62, 62); + + + :/images/icon_arrow_left.svg:/images/icon_arrow_left.svg - - CANCEL + + + 14 + 14 + + + + true @@ -247,190 +251,52 @@ text-decoration: none solid rgb(197, 62, 62); - - - - 90 - 25 - - - - - 90 - 25 - - - - - Roboto Condensed - 12 - false - false - - + PointingHandCursor - - Encrypt - - - border-radius: 3px; -color: #006eb5; -text-decoration: none solid rgb(0, 110, 181); -border: none; - - ENCRYPT + Encrypt - - - - 160 - 25 - - - - - 160 - 25 - - - - - Roboto Condensed - 12 - - + PointingHandCursor - - Save as - - - border-radius: 3px; -color: #006eb5; -text-decoration: none solid rgb(0, 110, 181); -border: none; - - SAVE AS + Save as - - - - 150 - 25 - - - - - 150 - 25 - - - - - Roboto Condensed - 12 - - + PointingHandCursor - - Send with e-mail - - - border-radius: 3px; -color: #006eb5; -text-decoration: none solid rgb(0, 110, 181); -border: none; - - SEND WITH E-MAIL + Send with e-mail - - - - 150 - 25 - - - - - 150 - 25 - - - - - 12 - - + PointingHandCursor - - Print summary - - - border-radius: 3px; -color: #006eb5; -text-decoration: none solid rgb(0, 110, 181); -text-align: center; -border: none; - - PRINT SUMMARY + Print summary - - - - 182 - 25 - - - - - 182 - 25 - - - - - Roboto Condensed - 12 - - + PointingHandCursor - - Save without signing - - - border-radius: 3px; -color: #006eb5; -text-decoration: none solid rgb(0, 110, 181); -text-align: center; -border: none; - - SAVE WITHOUT SIGNING + Save without signing @@ -444,7 +310,7 @@ border: none; - 198 + 200 20 @@ -456,11 +322,6 @@ border: none; - - LabelButton - QToolButton -
widgets/LabelButton.h
-
ItemList QScrollArea @@ -474,6 +335,8 @@ border: none; 1
- + + + diff --git a/client/widgets/LabelButton.cpp b/client/widgets/LabelButton.cpp index 2a72cde7f..57607622a 100644 --- a/client/widgets/LabelButton.cpp +++ b/client/widgets/LabelButton.cpp @@ -20,8 +20,6 @@ #include "LabelButton.h" #include "Styles.h" -#include - LabelButton::LabelButton( QWidget *parent ): QToolButton(parent) {} @@ -35,83 +33,21 @@ void LabelButton::init(Style style, const QString &label) // Blues static const QString CURIOUS_BLUE = QStringLiteral("#31A3D9"); static const QString DEEP_CERULEAN = QStringLiteral("#006EB5"); - // Reds - static const QString MOJO = QStringLiteral("#981E32"); // Whites - static const QString PORCELAIN = QStringLiteral("#f4f5f6"); static const QString WHITE = QStringLiteral("#ffffff"); - static const QString borderRadius = QStringLiteral(" border-radius: 2px;"); - static const QString none = QStringLiteral("none"); - static const QString solid = QStringLiteral("1px solid %1"); - static const QString styleTemplate = QStringLiteral("background-color: %1; color: %2;%4 border: %3; text-decoration: none solid;"); + static const QString styleTemplate = QStringLiteral("background-color: %1; color: %2; border: none; text-decoration: none solid;"); auto setStyle = [this](const QString &normal, const QString &hover, const QString &pressed) { setStyleSheet(QStringLiteral("QToolButton { %1 }\nQToolButton:hover { %2 }\nQToolButton:pressed { %3 }").arg(normal, hover, pressed)); }; switch( style ) { - case BoxedDeepCerulean: - setStyle( - styleTemplate.arg(PORCELAIN, DEEP_CERULEAN, none, borderRadius), - styleTemplate.arg(PORCELAIN, DEEP_CERULEAN, solid.arg(DEEP_CERULEAN), borderRadius), - styleTemplate.arg(DEEP_CERULEAN, PORCELAIN, none, borderRadius)); - break; - case BoxedMojo: - setStyle( - styleTemplate.arg(PORCELAIN, MOJO, none, borderRadius), - styleTemplate.arg(PORCELAIN, MOJO, solid.arg(MOJO), borderRadius), - styleTemplate.arg(MOJO, PORCELAIN, none, borderRadius)); - break; - case BoxedDeepCeruleanWithCuriousBlue: // Edit - setStyle( - styleTemplate.arg(PORCELAIN, DEEP_CERULEAN, solid.arg(PORCELAIN), borderRadius), - styleTemplate.arg(PORCELAIN, CURIOUS_BLUE, solid.arg(CURIOUS_BLUE), borderRadius), - styleTemplate.arg(CURIOUS_BLUE, PORCELAIN, solid.arg(CURIOUS_BLUE), borderRadius)); - break; case DeepCeruleanWithLochmara: // Add files setStyle( - styleTemplate.arg(WHITE, DEEP_CERULEAN, none, QString()), - styleTemplate.arg(DEEP_CERULEAN, WHITE, none, QString()), - styleTemplate.arg(CURIOUS_BLUE, WHITE, none, QString())); - break; - default: break; - } -} - -void LabelButton::setIcons(const QString &normalIcon, const QString &hoverIcon, const QString &pressedIcon, int w, int h) -{ - setIconSize(QSize(w, h)); - normal = ":" + normalIcon; - hover = ":" + hoverIcon; - pressed = ":" + pressedIcon; - QIcon ico; - ico.addFile(normal, iconSize()); - setIcon(ico); -} - -bool LabelButton::event(QEvent *e) -{ - if(icon().isNull()) - return QToolButton::event(e); - auto set = [this](const QString &icon) { - if(icon.isEmpty()) - return; - QIcon ico; - ico.addFile(icon, iconSize()); - setIcon(ico); - }; - switch(e->type()) - { - case QEvent::HoverEnter: - set(hover); - break; - case QEvent::HoverLeave: - set(normal); - break; - case QEvent::MouseButtonPress: - set(pressed); + styleTemplate.arg(WHITE, DEEP_CERULEAN), + styleTemplate.arg(DEEP_CERULEAN, WHITE), + styleTemplate.arg(CURIOUS_BLUE, WHITE)); break; default: break; } - return QToolButton::event(e); } diff --git a/client/widgets/LabelButton.h b/client/widgets/LabelButton.h index ea6ea3068..34e8c7179 100644 --- a/client/widgets/LabelButton.h +++ b/client/widgets/LabelButton.h @@ -29,19 +29,10 @@ class LabelButton : public QToolButton public: enum Style { - BoxedDeepCerulean, - BoxedMojo, - BoxedDeepCeruleanWithCuriousBlue, // Edit DeepCeruleanWithLochmara, // Add files }; explicit LabelButton(QWidget *parent = nullptr); void init(Style style, const QString &label = {}); - void setIcons(const QString &normalIcon, const QString &hoverIcon, const QString &pressedIcon, int w, int h); - -private: - bool event(QEvent *e) override; - - QString normal, hover, pressed; }; From f810c5fd57c337df09106c2760967bb9d0eb76a4 Mon Sep 17 00:00:00 2001 From: Raul Metsma Date: Fri, 6 Dec 2024 16:42:19 +0200 Subject: [PATCH 2/2] Extend signature to LTA Signed-off-by: Raul Metsma --- client/DigiDoc.cpp | 125 ++++++++++++++++++++--------- client/DigiDoc.h | 6 +- client/MainWindow.cpp | 10 +++ client/common_enums.h | 3 +- client/dialogs/SignatureDialog.cpp | 7 +- client/translations/en.ts | 12 +++ client/translations/et.ts | 12 +++ client/translations/ru.ts | 12 +++ client/widgets/ContainerPage.cpp | 6 +- client/widgets/ContainerPage.ui | 7 ++ 10 files changed, 157 insertions(+), 43 deletions(-) diff --git a/client/DigiDoc.cpp b/client/DigiDoc.cpp index 9b12e0d39..69a797475 100644 --- a/client/DigiDoc.cpp +++ b/client/DigiDoc.cpp @@ -242,14 +242,12 @@ QDateTime DigiDocSignature::tsTime() const return toTime(s->TimeStampTime()); } -QSslCertificate DigiDocSignature::tsaCert() const +QList> DigiDocSignature::archiveTimeStamps() const { - return toCertificate(s->ArchiveTimeStampCertificate()); -} - -QDateTime DigiDocSignature::tsaTime() const -{ - return toTime(s->ArchiveTimeStampTime()); + QList> result; + for(const TSAInfo &i: s->ArchiveTimeStamps()) + result.append({toCertificate(i.cert), toTime(i.time)});; + return result; } DigiDocSignature::SignatureStatus DigiDocSignature::validate(bool qscd) @@ -448,6 +446,56 @@ DocumentModel* DigiDoc::documentModel() const return m_documentModel.get(); } +bool DigiDoc::extend() +{ + try { + auto *signer = qApp->signer(); + signer->setUserAgent(QStringLiteral("%1/%2 (%3) Devices: %4").arg( + QCoreApplication::applicationName(), + QCoreApplication::applicationVersion(), + Common::applicationOs(), + Common::drivers().join(',')).toUtf8().constData()); + qApp->waitForTSL(fileName()); + QWidget *parent = qobject_cast(QObject::parent()); + if(parent == nullptr) + parent = Application::activeWindow(); + ServiceConfirmation cb(parent); + QString current = m_fileName; + if(waitFor([&] { + if(auto container = Container::extendContainerValidity(*b, signer)) + { + load(std::move(container), cb); + return true; + } + return false; + })) + { + const QString asics = QCoreApplication::translate("MainWindow", "Documents (%1)").arg(QLatin1String("*.asics *.scs")); + QFileInfo f(current); + QString name = f.absolutePath() + '/' + f.completeBaseName() + QStringLiteral(".asics"); + return save(FileDialog::getSaveFileName(Application::mainWindow(), QCoreApplication::translate("MainWindow", "Save file"), name, asics)); + } + else + save(); + } + catch(const Exception &e) + { + Exception::ExceptionCode code = Exception::General; + QStringList causes = parseException(e, code); + switch(code) + { + case Exception::NetworkError: + case Exception::HostNotFound: + WarningDialog::show(tr("Failed to sign container. Please check the access to signing services and network settings."), causes.join('\n')); break; + case Exception::InvalidUrl: + WarningDialog::show(tr("Failed to sign container. Signing service URL is incorrect."), causes.join('\n')); break; + default: + setLastError(tr("Failed to sign container."), e); break; + } + } + return false; +} + QString DigiDoc::fileName() const { return m_fileName; } bool DigiDoc::isError(bool failure, const QString &msg) const @@ -485,6 +533,39 @@ bool DigiDoc::isSupported() const return b && b->mediaType() == "application/vnd.etsi.asic-e+zip" && !isCades(); } +void DigiDoc::load(std::unique_ptr &&doc, ServiceConfirmation &cb) +{ + clear(); + b = std::move(doc); + if(b && b->mediaType() == "application/vnd.etsi.asic-s+zip" && + b->dataFiles().size() == 1 && + b->signatures().size() == 1) + { + const DataFile *f = b->dataFiles().at(0); + if(from(f->fileName()).endsWith(QStringLiteral(".ddoc"), Qt::CaseInsensitive)) + { + const QString tmppath = FileDialog::tempPath(FileDialog::safeName(from(f->fileName()))); + f->saveAs(to(tmppath)); + if(QFileInfo::exists(tmppath)) + { + m_tempFiles.append(tmppath); + try { + parentContainer = std::exchange(b, Container::openPtr(to(tmppath), &cb)); + } catch(const Exception &) {} + } + } + } + bool isTimeStamped = parentContainer && parentContainer->signatures().at(0)->trustedSigningTime().compare("2018-07-01T00:00:00Z") < 0; + for(const Signature *signature: b->signatures()) + m_signatures.append(DigiDocSignature(signature, this, isTimeStamped)); + if(parentContainer) + { + for(const Signature *signature: parentContainer->signatures()) + m_timestamps.append(DigiDocSignature(signature, this)); + } + containerState = signatures().isEmpty() ? ContainerState::UnsignedSavedContainer : ContainerState::SignedContainer; +} + QString DigiDoc::mediaType() const { return b ? from( b->mediaType() ) : QString(); } @@ -513,40 +594,12 @@ bool DigiDoc::open( const QString &file ) parent = Application::activeWindow(); ServiceConfirmation cb(parent); qApp->waitForTSL( file ); - clear(); try { WaitDialogHolder waitDialog(parent, tr("Opening"), false); return waitFor([&] { - b = Container::openPtr(to(file), &cb); - if(b && b->mediaType() == "application/vnd.etsi.asic-s+zip" && - b->dataFiles().size() == 1 && - b->signatures().size() == 1) - { - const DataFile *f = b->dataFiles().at(0); - if(from(f->fileName()).endsWith(QStringLiteral(".ddoc"), Qt::CaseInsensitive)) - { - const QString tmppath = FileDialog::tempPath(FileDialog::safeName(from(f->fileName()))); - f->saveAs(to(tmppath)); - if(QFileInfo::exists(tmppath)) - { - m_tempFiles.append(tmppath); - try { - parentContainer = std::exchange(b, Container::openPtr(to(tmppath), &cb)); - } catch(const Exception &) {} - } - } - } - bool isTimeStamped = parentContainer && parentContainer->signatures().at(0)->trustedSigningTime().compare("2018-07-01T00:00:00Z") < 0; - for(const Signature *signature: b->signatures()) - m_signatures.append(DigiDocSignature(signature, this, isTimeStamped)); - if(parentContainer) - { - for(const Signature *signature: parentContainer->signatures()) - m_timestamps.append(DigiDocSignature(signature, this)); - } + load(Container::openPtr(to(file), &cb), cb); Application::addRecent(file); m_fileName = file; - containerState = signatures().isEmpty() ? ContainerState::UnsignedSavedContainer : ContainerState::SignedContainer; return true; }); } catch(const Exception &e) { diff --git a/client/DigiDoc.h b/client/DigiDoc.h index 92941c825..d03b31835 100644 --- a/client/DigiDoc.h +++ b/client/DigiDoc.h @@ -68,8 +68,7 @@ class DigiDocSignature QDateTime trustedTime() const; QSslCertificate tsCert() const; QDateTime tsTime() const; - QSslCertificate tsaCert() const; - QDateTime tsaTime() const; + QList> archiveTimeStamps() const; int warning() const; private: @@ -110,6 +109,7 @@ class SDocumentModel final: public DocumentModel friend class DigiDoc; }; +struct ServiceConfirmation; class DigiDoc: public QObject { @@ -122,6 +122,7 @@ class DigiDoc: public QObject void create( const QString &file ); void clear(); DocumentModel *documentModel() const; + bool extend(); QString fileName() const; bool isAsicS() const; bool isCades() const; @@ -149,6 +150,7 @@ class DigiDoc: public QObject private: bool isError(bool failure, const QString &msg = {}) const; + void load(std::unique_ptr &&doc, ServiceConfirmation &cb); static void setLastError( const QString &msg, const digidoc::Exception &e ); std::unique_ptr b; diff --git a/client/MainWindow.cpp b/client/MainWindow.cpp index 885b56de1..c0c30d45b 100644 --- a/client/MainWindow.cpp +++ b/client/MainWindow.cpp @@ -405,6 +405,16 @@ void MainWindow::onSignAction(int action, const QString &info1, const QString &i digiDoc->sign(city, state, zip, country, role, &s); }); break; + case SignatureExtend: + { + if(!digiDoc) + break; + WarningDialog *d = new WarningDialog(tr("All signatures are extended in container."), this); + d->addButton(tr("Extend"), QMessageBox::Yes); + if(d->exec() == QMessageBox::Yes && digiDoc->extend()) + ui->signContainerPage->transition(digiDoc); + break; + } case ClearSignatureWarning: ui->signature->warningIcon(false); ui->warnings->closeWarnings(SignDetails); diff --git a/client/common_enums.h b/client/common_enums.h index c9529e7cf..7f68c7440 100644 --- a/client/common_enums.h +++ b/client/common_enums.h @@ -49,13 +49,14 @@ enum Actions { EncryptContainer, DecryptContainer, DecryptToken, + ClearCryptoWarning, SignatureAdd, SignatureMobile, SignatureSmartID, SignatureToken, + SignatureExtend, ClearSignatureWarning, - ClearCryptoWarning, }; enum ItemType { diff --git a/client/dialogs/SignatureDialog.cpp b/client/dialogs/SignatureDialog.cpp index 69642bab5..3ab242aa7 100644 --- a/client/dialogs/SignatureDialog.cpp +++ b/client/dialogs/SignatureDialog.cpp @@ -186,8 +186,6 @@ SignatureDialog::SignatureDialog(const DigiDocSignature &signature, QWidget *par } addItem(t, tr("Signed file count"), QString::number(s.container()->documentModel()->rowCount())); addItem(t, QStringLiteral("SPUri"), QUrl(s.spuri())); - addTime(t, tr("Archive Timestamp"), s.tsaTime()); - addCert(t, tr("Archive TS Certificate"), tr("Archive TS Certificate issuer"), s.tsaCert()); addTime(t, tr("Signature Timestamp"), s.tsTime()); addCert(t, tr("TS Certificate"), tr("TS Certificate issuer"), s.tsCert()); addItem(t, tr("Hash value of signature"), SslCertificate::toHex(s.messageImprint())); @@ -195,6 +193,11 @@ SignatureDialog::SignatureDialog(const DigiDocSignature &signature, QWidget *par addTime(t, tr("OCSP time"), s.ocspTime()); addItem(t, tr("Signing time (UTC)"), s.trustedTime()); addItem(t, tr("Claimed signing time (UTC)"), s.claimedTime()); + for(const auto &[cert, time]: s.archiveTimeStamps()) + { + addTime(t, tr("Archive Timestamp"), time); + addCert(t, tr("Archive TS Certificate"), tr("Archive TS Certificate issuer"), cert); + } #ifdef Q_OS_MAC t->setFont(Styles::font(Styles::Regular, 13)); diff --git a/client/translations/en.ts b/client/translations/en.ts index 1c274da27..be9bb986f 100644 --- a/client/translations/en.ts +++ b/client/translations/en.ts @@ -548,6 +548,10 @@ Sign Sign + + Extend signature(s) + +
CryptoDoc @@ -1621,6 +1625,14 @@ ID-CARD Crypto Crypto + + All signatures are extended in container. + + + + Extend + + MobileDialog diff --git a/client/translations/et.ts b/client/translations/et.ts index 933394f3d..537218171 100644 --- a/client/translations/et.ts +++ b/client/translations/et.ts @@ -548,6 +548,10 @@ Sign Allkirjasta + + Extend signature(s) + + CryptoDoc @@ -1621,6 +1625,14 @@ ID-KAARDIGA Crypto Krüpto + + All signatures are extended in container. + + + + Extend + + MobileDialog diff --git a/client/translations/ru.ts b/client/translations/ru.ts index 2881c4e49..59105d409 100644 --- a/client/translations/ru.ts +++ b/client/translations/ru.ts @@ -548,6 +548,10 @@ Sign Подписать + + Extend signature(s) + + CryptoDoc @@ -1622,6 +1626,14 @@ ID-КАРТОЙ Crypto Крипто + + All signatures are extended in container. + + + + Extend + + MobileDialog diff --git a/client/widgets/ContainerPage.cpp b/client/widgets/ContainerPage.cpp index 47cebc6e2..3dc3c00a4 100644 --- a/client/widgets/ContainerPage.cpp +++ b/client/widgets/ContainerPage.cpp @@ -47,6 +47,7 @@ ContainerPage::ContainerPage(QWidget *parent) ui->leftPane->init(fileName); ui->containerFile->installEventFilter(this); ui->summary->hide(); + ui->extend->hide(); mobileCode = Settings::MOBILEID_CODE; @@ -62,6 +63,7 @@ ContainerPage::ContainerPage(QWidget *parent) connectCode(ui->email, Actions::ContainerEmail); connectCode(ui->summary, Actions::ContainerSummary); connectCode(ui->save, Actions::ContainerSave); + connectCode(ui->extend, Actions::SignatureExtend); connect(ui->leftPane, &FileList::addFiles, this, &ContainerPage::addFiles); connect(ui->leftPane, &ItemList::removed, this, &ContainerPage::fileRemoved); connect(ui->leftPane, &ItemList::addItem, this, &ContainerPage::forward); @@ -370,7 +372,7 @@ void ContainerPage::updatePanes(ContainerState state) ui->rightPane->clear(); ui->leftPane->init(fileName, QT_TRANSLATE_NOOP("ItemList", "Container files")); showSigningButton(); - setButtonsVisible({ ui->saveAs, ui->email, ui->summary }, false); + setButtonsVisible({ ui->saveAs, ui->email, ui->summary, ui->extend }, false); break; case UnsignedSavedContainer: cancelText = QT_TR_NOOP("Start"); @@ -388,7 +390,7 @@ void ContainerPage::updatePanes(ContainerState state) ui->leftPane->init(fileName, QT_TRANSLATE_NOOP("ItemList", "Container files")); ui->rightPane->init(ItemSignature, QT_TRANSLATE_NOOP("ItemList", "Container signatures")); ui->summary->setVisible(Settings::SHOW_PRINT_SUMMARY); - setButtonsVisible({ ui->saveAs, ui->email }, true); + setButtonsVisible({ ui->saveAs, ui->email, ui->extend }, true); break; case UnencryptedContainer: cancelText = QT_TR_NOOP("Start"); diff --git a/client/widgets/ContainerPage.ui b/client/widgets/ContainerPage.ui index 4cef223a1..7a682d8c5 100644 --- a/client/widgets/ContainerPage.ui +++ b/client/widgets/ContainerPage.ui @@ -300,6 +300,13 @@ background-color: #E1C1C6; + + + + Extend signature(s) + + +