diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1a1a100..7b3637e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,49 +1,48 @@ # let's put most of the "meat" in a static library this way, we can also unit # test parts of it add_library(gpgpass_internal STATIC) target_sources( gpgpass_internal PRIVATE clipboardhelper.h configdialog.h deselectabletreeview.h filecontent.h firsttimedialog.h gpgmehelpers.h mainwindow.h pass.h passwordconfiguration.h passworddialog.h qpushbuttonfactory.h settings.h storemodel.h userinfo.h usersdialog.h util.h clipboardhelper.cpp configdialog.cpp filecontent.cpp firsttimedialog.cpp mainwindow.cpp pass.cpp passworddialog.cpp settings.cpp storemodel.cpp usersdialog.cpp util.cpp ../resources.qrc ) ki18n_wrap_ui(gpgpass_internal mainwindow.ui configdialog.ui usersdialog.ui keygenwidget.ui passworddialog.ui userswidget.ui - selectpasswordstore.ui ) target_link_libraries(gpgpass_internal Qt6::Widgets KF6::Prison KF6::IconThemes KF6::I18n KF6::WidgetsAddons QGpgmeQt6) diff --git a/src/firsttimedialog.cpp b/src/firsttimedialog.cpp index 9850730..f515513 100644 --- a/src/firsttimedialog.cpp +++ b/src/firsttimedialog.cpp @@ -1,205 +1,202 @@ /* SPDX-FileCopyrightText: 2023 g10 Code GmbH SPDX-FileContributor: Sune Stolborg Vuorela SPDX-License-Identifier: GPL-3.0-or-later */ #include "firsttimedialog.h" #include "qdebug.h" #include #include #include #include #include #include #include "gpgmehelpers.h" #include "settings.h" #include "ui_keygenwidget.h" -#include "ui_selectpasswordstore.h" -#include "ui_userswidget.h" -#include "util.h" #include #include #include #include DialogState::DialogState(Pass &p) : pass(p) { } QList DialogState::privateKeys() const { auto job = protocol->keyListJob(); std::vector keys; auto result = job->exec(QStringList(), true, keys); if (!isSuccess(result.error())) { return {}; } QList users; for (const auto &key : keys) { UserInfo ui; ui.created = QDateTime::fromSecsSinceEpoch(key.subkey(0).creationTime()); ui.key_id = fromGpgmeCharStar(key.keyID()); ui.name = createCombinedNameString(key.userID(0)); ui.validity = key.userID(0).validityAsString(); ui.expiry = QDateTime::fromSecsSinceEpoch(key.subkey(0).expirationTime()); ui.have_secret = key.hasSecret(); users.append(ui); } return users; } FirstTimeDialog::FirstTimeDialog(QWidget *mainWindow, Pass &pass) : m_mainWindow(mainWindow) , m_state(pass) { setWindowTitle(i18n("GnuPG Password Manager setup")); setPage(Intro, new IntroPage(m_state)); setPage(KeyGen, new KeyGenPage(m_state)); setPage(Done, new DonePage()); QTransform rotate; rotate.rotate(-90); setPixmap(QWizard::WatermarkPixmap, QPixmap(QLatin1String(":/artwork/gnupg-logo-320x100tr.png")).transformed(rotate)); setPixmap(QWizard::LogoPixmap, QPixmap(QLatin1String(":/artwork/64-gpgpass.png"))); setStartId(Intro); } void FirstTimeDialog::done(int i) { if (i == QDialog::DialogCode::Accepted) { QSettings s; s.setValue(QStringLiteral("setup"), true); if (Settings::getAutoclearSeconds() < 5) Settings::setAutoclearSeconds(10); if (Settings::getAutoclearPanelSeconds() < 5) Settings::setAutoclearPanelSeconds(10); Settings::setPassTemplate(QStringLiteral("login\nurl")); m_mainWindow->show(); } QWizard::done(i); } bool FirstTimeDialog::wouldDoSomething() const { return m_state.privateKeys().isEmpty(); } int FirstTimeDialog::nextId() const { switch (currentId()) { case Intro: if (m_state.privateKeys().isEmpty()) { return KeyGen; } else { return Done; } case KeyGen: return Done; default: return -1; } return -1; }; IntroPage::IntroPage(DialogState &s) : m_state(s) { QVBoxLayout *lay = new QVBoxLayout(); lay->addWidget(new QLabel(i18n("Welcome to GnuPG Password manager"))); setTitle(i18n("Welcome")); setSubTitle(i18n("Setting up")); setLayout(lay); } KeyGenPage::KeyGenPage(DialogState &s) : m_state(s) { setTitle(i18n("Generate keys")); setSubTitle(i18n("Generate keys")); m_ui = std::make_unique(); m_ui->setupUi(this); m_ui->spinner->hide(); m_ui->generateButton->setEnabled(false); m_ui->message->hide(); m_ui->email->setValidator( new QRegularExpressionValidator(QRegularExpression(QRegularExpression::anchoredPattern(QStringLiteral(R"(\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b)")), QRegularExpression::CaseInsensitiveOption))); connect(m_ui->generateButton, &QPushButton::clicked, this, &KeyGenPage::startKeyGen); connect(m_ui->email, &QLineEdit::textChanged, this, &KeyGenPage::checkEntries); connect(m_ui->name, &QLineEdit::textChanged, this, &KeyGenPage::checkEntries); } void KeyGenPage::startKeyGen() { m_ui->email->setEnabled(false); m_ui->name->setEnabled(false); m_ui->generateButton->setEnabled(false); m_ui->includeComment->setEnabled(false); m_ui->spinner->show(); auto job = m_state.protocol->quickJob(); connect(job, &QGpgME::QuickJob::result, this, [this](auto &&result, const QString &log, auto &&logResult) { if (isSuccess(result)) { Q_EMIT this->completeChanged(); this->m_ui->spinner->hide(); this->m_ui->message->show(); this->m_ui->message->setText(i18n("Key generated")); } else { this->m_ui->message->setText(fromGpgmeCharStar(result.asString())); this->m_ui->message->show(); } Q_UNUSED(log); Q_UNUSED(logResult); }); QString uid; if (m_ui->includeComment->isChecked()) { uid = QStringLiteral("%1 (PasswordManager) <%2>"); } else { uid = QStringLiteral("%1 <%2>"); } job->startCreate(uid.arg(m_ui->name->text(), m_ui->email->text()), "future-default"); } void KeyGenPage::checkEntries() { auto emailValidator = m_ui->email->validator(); bool enable = false; if (emailValidator) { auto email = m_ui->email->text(); int i = 0; if (emailValidator->validate(email, i) == QValidator::Acceptable) { qDebug() << "email valid"; enable = m_ui->name->text().size() > 4; } else { qDebug() << "email invalid"; } } else { qDebug() << "no email validator"; // TODO_REMOV enable = true; } m_ui->generateButton->setEnabled(enable); } KeyGenPage::~KeyGenPage() = default; bool KeyGenPage::isComplete() const { return !m_state.privateKeys().isEmpty(); } DonePage::DonePage() { setTitle(i18n("Setup done")); setSubTitle(i18n("Thanks")); setFinalPage(true); } diff --git a/src/firsttimedialog.h b/src/firsttimedialog.h index 3aa6c1c..a5d59a3 100644 --- a/src/firsttimedialog.h +++ b/src/firsttimedialog.h @@ -1,78 +1,75 @@ /* SPDX-FileCopyrightText: 2023 g10 Code GmbH SPDX-FileContributor: Sune Stolborg Vuorela SPDX-License-Identifier: GPL-3.0-or-later */ #ifndef FIRSTTIMEDIALOG_H #define FIRSTTIMEDIALOG_H #include "usersdialog.h" #include #include #include class Ui_KeyGenWidget; -class Ui_UsersWidget; -class Ui_KeyGenWidget; -class Ui_SelectPasswordStore; class DialogState : public QObject { Q_OBJECT public: explicit DialogState(Pass &p); QList privateKeys() const; QGpgME::Protocol *protocol = QGpgME::openpgp(); QString storePath; Pass &pass; }; class FirstTimeDialog : public QWizard { enum Pages { Intro, KeyGen, Done }; Q_OBJECT public: FirstTimeDialog(QWidget *mainWindow, Pass &pass); int nextId() const override; void done(int i) override; bool wouldDoSomething() const; private: QWidget *m_mainWindow; DialogState m_state; }; class IntroPage : public QWizardPage { Q_OBJECT public: explicit IntroPage(DialogState &s); private: DialogState &m_state; }; class KeyGenPage : public QWizardPage { Q_OBJECT public: explicit KeyGenPage(DialogState &s); bool isComplete() const override; ~KeyGenPage(); private Q_SLOTS: void startKeyGen(); void checkEntries(); private: DialogState &m_state; std::unique_ptr m_ui; }; class DonePage : public QWizardPage { public: DonePage(); }; #endif // FIRSTTIMEDIALOG_H