/**
* 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.
*
* Foobar 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 Foobar. If not, see .
*
* The initial version of the source code is inherited from gpg4usb-team.
* Their source code version also complies with GNU General Public License.
*
* The source code version of this software was modified and released
* by Saturneric starting on May 12, 2021.
*
*/
#include "ui/keypair_details/KeyPairSubkeyTab.h"
KeyPairSubkeyTab::KeyPairSubkeyTab(GpgME::GpgContext *ctx, const GpgKey &key, QWidget *parent) : mCtx(ctx), mKey(key), QWidget(parent) {
createSubkeyList();
createSubkeyOperaMenu();
listBox = new QGroupBox("Subkey List");
detailBox = new QGroupBox("Detail of Selected Subkey");
auto uidButtonsLayout = new QGridLayout();
auto addSubkeyButton = new QPushButton(tr("Generate A New Subkey"));
if(!mKey.is_private_key || !mKey.has_master_key) {
addSubkeyButton->setDisabled(true);
setHidden(addSubkeyButton);
}
uidButtonsLayout->addWidget(addSubkeyButton, 0, 1);
auto *baseLayout = new QVBoxLayout();
auto subkeyListLayout = new QGridLayout();
subkeyListLayout->addWidget(subkeyList, 0, 0);
subkeyListLayout->addLayout(uidButtonsLayout, 1, 0);
auto *subkeyDetailLayout = new QGridLayout();
subkeyDetailLayout->addWidget(new QLabel(tr("Key ID: ")), 0, 0);
subkeyDetailLayout->addWidget(new QLabel(tr("Algorithm: ")), 1, 0);
subkeyDetailLayout->addWidget(new QLabel(tr("Key Size:")), 2, 0);
subkeyDetailLayout->addWidget(new QLabel(tr("Usage: ")), 3, 0);
subkeyDetailLayout->addWidget(new QLabel(tr("Expires On ")), 4, 0);
subkeyDetailLayout->addWidget(new QLabel(tr("Last Update: ")), 5, 0);
subkeyDetailLayout->addWidget(new QLabel(tr("Existence: ")), 6, 0);
subkeyDetailLayout->addWidget(new QLabel(tr("Fingerprint: ")), 7, 0);
keyidVarLabel = new QLabel();
keySizeVarLabel = new QLabel();
expireVarLabel = new QLabel();
algorithmVarLabel = new QLabel();
createdVarLabel = new QLabel();
usageVarLabel = new QLabel();
masterKeyExistVarLabel = new QLabel();
fingerPrintVarLabel = new QLabel();
subkeyDetailLayout->addWidget(keyidVarLabel, 0, 1);
subkeyDetailLayout->addWidget(keySizeVarLabel, 2, 1);
subkeyDetailLayout->addWidget(expireVarLabel, 4, 1);
subkeyDetailLayout->addWidget(algorithmVarLabel, 1, 1);
subkeyDetailLayout->addWidget(createdVarLabel, 5, 1);
subkeyDetailLayout->addWidget(usageVarLabel, 3, 1);
subkeyDetailLayout->addWidget(masterKeyExistVarLabel, 6, 1);
subkeyDetailLayout->addWidget(fingerPrintVarLabel, 7, 1);
listBox->setLayout(subkeyListLayout);
detailBox->setLayout(subkeyDetailLayout);
baseLayout->addWidget(listBox);
baseLayout->addWidget(detailBox);
baseLayout->addStretch();
connect(addSubkeyButton, SIGNAL(clicked(bool)), this, SLOT(slotAddSubkey()));
connect(mCtx, SIGNAL(signalKeyInfoChanged()), this, SLOT(slotRefreshSubkeyList()));
connect(subkeyList, SIGNAL(itemSelectionChanged()), this, SLOT(slotRefreshSubkeyDetail()));
setLayout(baseLayout);
setAttribute(Qt::WA_DeleteOnClose, true);
slotRefreshSubkeyList();
}
void KeyPairSubkeyTab::createSubkeyList() {
subkeyList = new QTableWidget(this);
subkeyList->setColumnCount(5);
subkeyList->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
subkeyList->verticalHeader()->hide();
subkeyList->setShowGrid(false);
subkeyList->setSelectionBehavior(QAbstractItemView::SelectRows);
// tableitems not editable
subkeyList->setEditTriggers(QAbstractItemView::NoEditTriggers);
// no focus (rectangle around tableitems)
// may be it should focus on whole row
subkeyList->setFocusPolicy(Qt::NoFocus);
subkeyList->setAlternatingRowColors(true);
QStringList labels;
labels << tr("Subkey ID") << tr("Key Size") << tr("Algo") << tr("Create Date") << tr("Expire Date");
subkeyList->setHorizontalHeaderLabels(labels);
subkeyList->horizontalHeader()->setStretchLastSection(false);
}
void KeyPairSubkeyTab::slotRefreshSubkeyList() {
int row = 0;
subkeyList->setSelectionMode(QAbstractItemView::SingleSelection);
this->buffered_subkeys.clear();
for(const auto &subkeys : mKey.subKeys) {
if(subkeys.disabled || subkeys.revoked) {
continue;
}
this->buffered_subkeys.push_back(&subkeys);
}
subkeyList->setRowCount(buffered_subkeys.size());
for(const auto& subkeys : buffered_subkeys) {
auto *tmp0 = new QTableWidgetItem(subkeys->id);
tmp0->setTextAlignment(Qt::AlignCenter);
subkeyList->setItem(row, 0, tmp0);
auto *tmp1 = new QTableWidgetItem(QString::number(subkeys->length));
tmp1->setTextAlignment(Qt::AlignCenter);
subkeyList->setItem(row, 1, tmp1);
auto *tmp2 = new QTableWidgetItem(subkeys->pubkey_algo);
tmp2->setTextAlignment(Qt::AlignCenter);
subkeyList->setItem(row, 2, tmp2);
auto *tmp3= new QTableWidgetItem(subkeys->timestamp.toString());
tmp3->setTextAlignment(Qt::AlignCenter);
subkeyList->setItem(row, 3, tmp3);
auto *tmp4= new QTableWidgetItem(subkeys->expires.toTime_t() == 0 ? tr("Never Expire") : subkeys->expires.toString());
tmp4->setTextAlignment(Qt::AlignCenter);
subkeyList->setItem(row, 4, tmp4);
row++;
}
if(subkeyList->rowCount() > 0) {
subkeyList->selectRow(0);
}
}
void KeyPairSubkeyTab::slotAddSubkey() {
auto dialog = new SubkeyGenerateDialog(mCtx, mKey, this);
dialog->show();
}
void KeyPairSubkeyTab::slotRefreshSubkeyDetail() {
auto key = getSelectedSubkey();
keyidVarLabel->setText(key->id);
keySizeVarLabel->setText(QString::number(key->length));
expireVarLabel->setText(key->expires.toTime_t() == 0 ? tr("Never Expires") : key->expires.toString());
if(key->expires.toTime_t() != 0 && key->expires < QDateTime::currentDateTime()) {
auto paletteExpired = expireVarLabel->palette();
paletteExpired.setColor(expireVarLabel->foregroundRole(), Qt::red);
expireVarLabel->setPalette(paletteExpired);
} else {
auto paletteValid = expireVarLabel->palette();
paletteValid.setColor(expireVarLabel->foregroundRole(), Qt::darkGreen);
expireVarLabel->setPalette(paletteValid);
}
algorithmVarLabel->setText(key->pubkey_algo);
createdVarLabel->setText(key->timestamp.toString());
QString usage;
QTextStream usage_steam(&usage);
if(key->can_certify)
usage_steam << "Cert ";
if(key->can_encrypt)
usage_steam << "Encr ";
if(key->can_sign)
usage_steam << "Sign ";
if(key->can_authenticate)
usage_steam << "Auth ";
usageVarLabel->setText(usage);
// Show the situation that master key not exists.
masterKeyExistVarLabel->setText(key->secret ? "Exists" : "Not Exists");
if(!key->secret){
auto paletteExpired = masterKeyExistVarLabel->palette();
paletteExpired.setColor(masterKeyExistVarLabel->foregroundRole(), Qt::red);
masterKeyExistVarLabel->setPalette(paletteExpired);
} else {
auto paletteValid = masterKeyExistVarLabel->palette();
paletteValid.setColor(masterKeyExistVarLabel->foregroundRole(), Qt::darkGreen);
masterKeyExistVarLabel->setPalette(paletteValid);
}
fingerPrintVarLabel->setText(key->fpr);
}
void KeyPairSubkeyTab::createSubkeyOperaMenu() {
subkeyOperaMenu = new QMenu(this);
// auto *revokeSubkeyAct = new QAction(tr("Revoke Subkey"));
auto *editSubkeyAct = new QAction(tr("Edit Expire Date"));
connect(editSubkeyAct, SIGNAL(triggered(bool)), this, SLOT(slotEditSubkey()));
// subkeyOperaMenu->addAction(revokeSubkeyAct);
subkeyOperaMenu->addAction(editSubkeyAct);
}
void KeyPairSubkeyTab::slotEditSubkey() {
qDebug() << "Slot Edit Subkry";
auto *subkey = getSelectedSubkey();
if(subkey == buffered_subkeys[0]) {
subkey = nullptr;
}
auto dialog = new KeySetExpireDateDialog(mCtx, mKey, subkey, this);
dialog->show();
}
void KeyPairSubkeyTab::slotRevokeSubkey() {
}
void KeyPairSubkeyTab::contextMenuEvent(QContextMenuEvent *event) {
if (!subkeyList->selectedItems().isEmpty()) {
subkeyOperaMenu->exec(event->globalPos());
}
}
const GpgSubKey *KeyPairSubkeyTab::getSelectedSubkey() {
int row = 0;
for(int i = 0 ; i < subkeyList->rowCount(); i++) {
if(subkeyList->item(row, 0)->isSelected()) break;
row++;
}
return buffered_subkeys[row];
}