diff options
author | Saturneric <[email protected]> | 2022-07-22 17:46:34 +0000 |
---|---|---|
committer | Saturneric <[email protected]> | 2022-07-22 17:46:34 +0000 |
commit | a6d22ea199b62d433c595ed5b9f51398fc8b7f5a (patch) | |
tree | a09fb7383a655a18a79c72f54c57352ddba7a4b3 /src/ui/dialog/keypair_details/KeyPairSubkeyTab.cpp | |
parent | style(src): reformat code (diff) | |
download | GpgFrontend-a6d22ea199b62d433c595ed5b9f51398fc8b7f5a.tar.gz GpgFrontend-a6d22ea199b62d433c595ed5b9f51398fc8b7f5a.zip |
refactor(ui): adjust file structure
Diffstat (limited to 'src/ui/dialog/keypair_details/KeyPairSubkeyTab.cpp')
-rw-r--r-- | src/ui/dialog/keypair_details/KeyPairSubkeyTab.cpp | 338 |
1 files changed, 338 insertions, 0 deletions
diff --git a/src/ui/dialog/keypair_details/KeyPairSubkeyTab.cpp b/src/ui/dialog/keypair_details/KeyPairSubkeyTab.cpp new file mode 100644 index 00000000..fe1d0798 --- /dev/null +++ b/src/ui/dialog/keypair_details/KeyPairSubkeyTab.cpp @@ -0,0 +1,338 @@ +/** + * Copyright (C) 2021 Saturneric + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric<[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#include "KeyPairSubkeyTab.h" + +#include "core/function/gpg/GpgKeyGetter.h" +#include "ui/SignalStation.h" + +namespace GpgFrontend::UI { + +KeyPairSubkeyTab::KeyPairSubkeyTab(const std::string& key_id, QWidget* parent) + : QWidget(parent), key_(GpgKeyGetter::GetInstance().GetKey(key_id)) { + LOG(INFO) << key_.GetEmail() << key_.IsPrivateKey() << key_.IsHasMasterKey() + << key_.GetSubKeys()->front().IsPrivateKey(); + + create_subkey_list(); + create_subkey_opera_menu(); + + list_box_ = new QGroupBox(_("Subkey List")); + detail_box_ = new QGroupBox(_("Detail of Selected Subkey")); + + auto uidButtonsLayout = new QGridLayout(); + + auto addSubkeyButton = new QPushButton(_("Generate A New Subkey")); + if (!key_.IsPrivateKey() || !key_.IsHasMasterKey()) { + addSubkeyButton->setDisabled(true); + setHidden(addSubkeyButton); + } + + uidButtonsLayout->addWidget(addSubkeyButton, 0, 1); + + auto* baseLayout = new QVBoxLayout(); + + auto subkeyListLayout = new QGridLayout(); + subkeyListLayout->addWidget(subkey_list_, 0, 0); + subkeyListLayout->addLayout(uidButtonsLayout, 1, 0); + subkeyListLayout->setContentsMargins(0, 10, 0, 0); + + auto* subkeyDetailLayout = new QGridLayout(); + + subkeyDetailLayout->addWidget(new QLabel(QString(_("Key ID")) + ": "), 0, 0); + subkeyDetailLayout->addWidget(new QLabel(QString(_("Algorithm")) + ": "), 1, + 0); + subkeyDetailLayout->addWidget(new QLabel(QString(_("Key Size")) + ": "), 2, + 0); + subkeyDetailLayout->addWidget(new QLabel(QString(_("Usage")) + ": "), 3, 0); + subkeyDetailLayout->addWidget( + new QLabel(QString(_("Expires On (Local Time)")) + ": "), 4, 0); + subkeyDetailLayout->addWidget( + new QLabel(QString(_("Create Date (Local Time)")) + ": "), 5, 0); + subkeyDetailLayout->addWidget(new QLabel(QString(_("Existence")) + ": "), 6, + 0); + subkeyDetailLayout->addWidget( + new QLabel(QString(_("Key in Smart Card")) + ": "), 7, 0); + subkeyDetailLayout->addWidget(new QLabel(QString(_("Fingerprint")) + ": "), 8, + 0); + + key_id_var_label_ = new QLabel(this); + key_size_var_label_ = new QLabel(this); + expire_var_label_ = new QLabel(this); + algorithm_var_label_ = new QLabel(this); + created_var_label_ = new QLabel(this); + usage_var_label_ = new QLabel(this); + master_key_exist_var_label_ = new QLabel(this); + fingerprint_var_label_ = new QLabel(this); + card_key_label_ = new QLabel(this); + + subkeyDetailLayout->addWidget(key_id_var_label_, 0, 1, 1, 1); + subkeyDetailLayout->addWidget(key_size_var_label_, 2, 1, 1, 2); + subkeyDetailLayout->addWidget(expire_var_label_, 4, 1, 1, 2); + subkeyDetailLayout->addWidget(algorithm_var_label_, 1, 1, 1, 2); + subkeyDetailLayout->addWidget(created_var_label_, 5, 1, 1, 2); + subkeyDetailLayout->addWidget(usage_var_label_, 3, 1, 1, 2); + subkeyDetailLayout->addWidget(master_key_exist_var_label_, 6, 1, 1, 2); + subkeyDetailLayout->addWidget(card_key_label_, 7, 1, 1, 2); + subkeyDetailLayout->addWidget(fingerprint_var_label_, 8, 1, 1, 2); + + auto* copyKeyIdButton = new QPushButton(_("Copy")); + copyKeyIdButton->setFlat(true); + subkeyDetailLayout->addWidget(copyKeyIdButton, 0, 2); + connect(copyKeyIdButton, &QPushButton::clicked, this, [=]() { + QString fpr = key_id_var_label_->text().trimmed(); + QClipboard* cb = QApplication::clipboard(); + cb->setText(fpr); + }); + + list_box_->setLayout(subkeyListLayout); + list_box_->setContentsMargins(0, 12, 0, 0); + detail_box_->setLayout(subkeyDetailLayout); + + baseLayout->addWidget(list_box_); + baseLayout->addWidget(detail_box_); + baseLayout->addStretch(); + + connect(addSubkeyButton, &QPushButton::clicked, this, + &KeyPairSubkeyTab::slot_add_subkey); + connect(subkey_list_, &QTableWidget::itemSelectionChanged, this, + &KeyPairSubkeyTab::slot_refresh_subkey_detail); + + // key database refresh signal + connect(SignalStation::GetInstance(), + &SignalStation::SignalKeyDatabaseRefreshDone, this, + &KeyPairSubkeyTab::slot_refresh_key_info); + connect(SignalStation::GetInstance(), + &SignalStation::SignalKeyDatabaseRefreshDone, this, + &KeyPairSubkeyTab::slot_refresh_subkey_list); + + baseLayout->setContentsMargins(0, 0, 0, 0); + + setLayout(baseLayout); + setAttribute(Qt::WA_DeleteOnClose, true); + + slot_refresh_subkey_list(); +} + +void KeyPairSubkeyTab::create_subkey_list() { + subkey_list_ = new QTableWidget(this); + + subkey_list_->setColumnCount(5); + subkey_list_->horizontalHeader()->setSectionResizeMode( + QHeaderView::ResizeToContents); + subkey_list_->verticalHeader()->hide(); + subkey_list_->setShowGrid(false); + subkey_list_->setSelectionBehavior(QAbstractItemView::SelectRows); + + // tableitems not editable + subkey_list_->setEditTriggers(QAbstractItemView::NoEditTriggers); + + // no focus (rectangle around tableitems) + // may be it should focus on whole row + subkey_list_->setFocusPolicy(Qt::NoFocus); + subkey_list_->setAlternatingRowColors(true); + + QStringList labels; + labels << _("Subkey ID") << _("Key Size") << _("Algo") + << _("Create Date (UTC)") << _("Expire Date (UTC)"); + + subkey_list_->setHorizontalHeaderLabels(labels); + subkey_list_->horizontalHeader()->setStretchLastSection(false); +} + +void KeyPairSubkeyTab::slot_refresh_subkey_list() { + LOG(INFO) << "Called"; + int row = 0; + + subkey_list_->setSelectionMode(QAbstractItemView::SingleSelection); + + this->buffered_subkeys_.clear(); + auto sub_keys = key_.GetSubKeys(); + for (auto& sub_key : *sub_keys) { + if (sub_key.IsDisabled() || sub_key.IsRevoked()) continue; + this->buffered_subkeys_.push_back(std::move(sub_key)); + } + + subkey_list_->setRowCount(buffered_subkeys_.size()); + + for (const auto& subkeys : buffered_subkeys_) { + auto* tmp0 = new QTableWidgetItem(QString::fromStdString(subkeys.GetID())); + tmp0->setTextAlignment(Qt::AlignCenter); + subkey_list_->setItem(row, 0, tmp0); + + auto* tmp1 = new QTableWidgetItem(QString::number(subkeys.GetKeyLength())); + tmp1->setTextAlignment(Qt::AlignCenter); + subkey_list_->setItem(row, 1, tmp1); + + auto* tmp2 = + new QTableWidgetItem(QString::fromStdString(subkeys.GetPubkeyAlgo())); + tmp2->setTextAlignment(Qt::AlignCenter); + subkey_list_->setItem(row, 2, tmp2); + + auto* tmp3 = new QTableWidgetItem( + QString::fromStdString(to_iso_string(subkeys.GetCreateTime()))); + tmp3->setTextAlignment(Qt::AlignCenter); + subkey_list_->setItem(row, 3, tmp3); + + auto* tmp4 = new QTableWidgetItem( + boost::posix_time::to_time_t( + boost::posix_time::ptime(subkeys.GetExpireTime())) == 0 + ? _("Never Expire") + : QString::fromStdString(to_iso_string(subkeys.GetExpireTime()))); + tmp4->setTextAlignment(Qt::AlignCenter); + subkey_list_->setItem(row, 4, tmp4); + + if (!row) { + for (auto i = 0; i < subkey_list_->columnCount(); i++) { + subkey_list_->item(row, i)->setForeground(QColor(65, 105, 255)); + } + } + + row++; + } + + if (subkey_list_->rowCount() > 0) { + subkey_list_->selectRow(0); + } +} + +void KeyPairSubkeyTab::slot_add_subkey() { + auto dialog = new SubkeyGenerateDialog(key_.GetId(), this); + dialog->show(); +} + +void KeyPairSubkeyTab::slot_refresh_subkey_detail() { + auto& subkey = get_selected_subkey(); + + key_id_var_label_->setText(QString::fromStdString(subkey.GetID())); + key_size_var_label_->setText(QString::number(subkey.GetKeyLength())); + + time_t subkey_time_t = boost::posix_time::to_time_t( + boost::posix_time::ptime(subkey.GetExpireTime())); + + expire_var_label_->setText( + subkey_time_t == 0 ? _("Never Expires") + : QLocale::system().toString(QDateTime::fromTime_t( + to_time_t(subkey.GetExpireTime())))); + if (subkey_time_t != 0 && + subkey.GetExpireTime() < boost::posix_time::second_clock::local_time()) { + auto paletteExpired = expire_var_label_->palette(); + paletteExpired.setColor(expire_var_label_->foregroundRole(), Qt::red); + expire_var_label_->setPalette(paletteExpired); + } else { + auto paletteValid = expire_var_label_->palette(); + paletteValid.setColor(expire_var_label_->foregroundRole(), Qt::darkGreen); + expire_var_label_->setPalette(paletteValid); + } + + algorithm_var_label_->setText(QString::fromStdString(subkey.GetPubkeyAlgo())); + created_var_label_->setText(QLocale::system().toString( + QDateTime::fromTime_t(to_time_t(subkey.GetCreateTime())))); + + std::stringstream usage_steam; + + if (subkey.IsHasCertificationCapability()) + usage_steam << _("Certificate") << " "; + if (subkey.IsHasEncryptionCapability()) usage_steam << _("Encrypt") << " "; + if (subkey.IsHasSigningCapability()) usage_steam << _("Sign") << " "; + if (subkey.IsHasAuthenticationCapability()) usage_steam << _("Auth") << " "; + + usage_var_label_->setText(usage_steam.str().c_str()); + + // Show the situation that secret key not exists. + master_key_exist_var_label_->setText(subkey.IsSecretKey() ? _("Exists") + : _("Not Exists")); + + // Show the situation if key in a smart card. + card_key_label_->setText(subkey.IsCardKey() ? _("Yes") : _("No")); + + if (!subkey.IsSecretKey()) { + auto palette_expired = master_key_exist_var_label_->palette(); + palette_expired.setColor(master_key_exist_var_label_->foregroundRole(), + Qt::red); + master_key_exist_var_label_->setPalette(palette_expired); + } else { + auto palette_valid = master_key_exist_var_label_->palette(); + palette_valid.setColor(master_key_exist_var_label_->foregroundRole(), + Qt::darkGreen); + master_key_exist_var_label_->setPalette(palette_valid); + } + + if (!subkey.IsCardKey()) { + auto palette_expired = card_key_label_->palette(); + palette_expired.setColor(card_key_label_->foregroundRole(), Qt::red); + card_key_label_->setPalette(palette_expired); + } else { + auto palette_valid = card_key_label_->palette(); + palette_valid.setColor(card_key_label_->foregroundRole(), Qt::darkGreen); + card_key_label_->setPalette(palette_valid); + } + + fingerprint_var_label_->setText( + QString::fromStdString(subkey.GetFingerprint())); +} + +void KeyPairSubkeyTab::create_subkey_opera_menu() { + subkey_opera_menu_ = new QMenu(this); + auto* editSubkeyAct = new QAction(_("Edit Expire Date")); + connect(editSubkeyAct, &QAction::triggered, this, + &KeyPairSubkeyTab::slot_edit_subkey); + + subkey_opera_menu_->addAction(editSubkeyAct); +} + +void KeyPairSubkeyTab::slot_edit_subkey() { + LOG(INFO) << "Fpr" << get_selected_subkey().GetFingerprint(); + + auto dialog = new KeySetExpireDateDialog( + key_.GetId(), get_selected_subkey().GetFingerprint(), this); + dialog->show(); +} + +void KeyPairSubkeyTab::slot_revoke_subkey() {} + +void KeyPairSubkeyTab::contextMenuEvent(QContextMenuEvent* event) { + if (!subkey_list_->selectedItems().isEmpty()) { + subkey_opera_menu_->exec(event->globalPos()); + } +} + +const GpgSubKey& KeyPairSubkeyTab::get_selected_subkey() { + int row = 0; + + for (int i = 0; i < subkey_list_->rowCount(); i++) { + if (subkey_list_->item(row, 0)->isSelected()) break; + row++; + } + + return buffered_subkeys_[row]; +} +void KeyPairSubkeyTab::slot_refresh_key_info() { + key_ = GpgKeyGetter::GetInstance().GetKey(key_.GetId()); +} + +} // namespace GpgFrontend::UI |