• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

IJHack / QtPass / 24939003443

25 Apr 2026 07:38PM UTC coverage: 26.843% (-0.8%) from 27.609%
24939003443

Pull #1170

github

web-flow
Merge 661dce8eb into 9048d2bb3
Pull Request #1170: feat: add Import key dialog to UsersDialog for issue #1167

0 of 92 new or added lines in 3 files covered. (0.0%)

19 existing lines in 1 file now uncovered.

1722 of 6415 relevant lines covered (26.84%)

27.63 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/importkeydialog.cpp
1
// SPDX-FileCopyrightText: 2026 Anne Jan Brouwer
2
// SPDX-License-Identifier: GPL-3.0-or-later
3
#include "importkeydialog.h"
4

5
#include "executor.h"
6
#include "qtpasssettings.h"
7
#include "ui_importkeydialog.h"
8

9
#include <QApplication>
10
#include <QClipboard>
11
#include <QFile>
12
#include <QFileDialog>
13
#include <QMessageBox>
14
#include <QPlainTextEdit>
15
#include <QPushButton>
16
#include <QRegularExpression>
17
#include <QTextStream>
18

NEW
19
ImportKeyDialog::ImportKeyDialog(QWidget *parent)
×
NEW
20
    : QDialog(parent), ui(new Ui::ImportKeyDialog) {
×
NEW
21
  ui->setupUi(this);
×
22

NEW
23
  ui->inputTextEdit->setPlaceholderText(
×
NEW
24
      tr("Paste an ASCII-armored GPG key here..."));
×
25

NEW
26
  ui->importButton->setEnabled(false);
×
NEW
27
  ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
×
28

NEW
29
  connect(ui->inputTextEdit, &QPlainTextEdit::textChanged, this,
×
NEW
30
         &ImportKeyDialog::on_inputTextEdit_textChanged);
×
NEW
31
}
×
32

NEW
33
ImportKeyDialog::~ImportKeyDialog() = default;
×
34

NEW
35
QString ImportKeyDialog::importedKeyFingerprint() const {
×
NEW
36
  return m_importedFingerprint;
×
37
}
38

NEW
39
void ImportKeyDialog::on_fileButton_clicked() {
×
40
  const QString fileName = QFileDialog::getOpenFileName(
NEW
41
      this, tr("Import GPG Key"), QString(),
×
NEW
42
      tr("GPG Key Files") + " (*.asc *.gpg *.key);;;" + tr("All Files") + " (*)");
×
43

NEW
44
  if (fileName.isEmpty()) {
×
45
    return;
46
  }
47

NEW
48
  QFile file(fileName);
×
NEW
49
  if (!file.open(QIODevice::ReadOnly)) {
×
NEW
50
    QMessageBox::warning(this, tr("Import Key"),
×
NEW
51
                        tr("Could not open file: %1").arg(fileName));
×
52
    return;
53
  }
54

NEW
55
  QTextStream in(&file);
×
NEW
56
  QString content = in.readAll();
×
NEW
57
  file.close();
×
58

NEW
59
  ui->inputTextEdit->setPlainText(content);
×
NEW
60
}
×
61

NEW
62
void ImportKeyDialog::on_pasteButton_clicked() {
×
NEW
63
  QClipboard *clipboard = QApplication::clipboard();
×
NEW
64
  const QString text = clipboard->text();
×
65

NEW
66
  ui->inputTextEdit->setPlainText(text);
×
NEW
67
}
×
68

NEW
69
void ImportKeyDialog::on_importButton_clicked() {
×
NEW
70
  const QString input = ui->inputTextEdit->toPlainText().trimmed();
×
NEW
71
  if (input.isEmpty()) {
×
72
    return;
73
  }
74

NEW
75
  if (importFromString(input)) {
×
NEW
76
    accept();
×
77
  }
78
}
79

NEW
80
void ImportKeyDialog::on_inputTextEdit_textChanged() {
×
NEW
81
  const bool hasInput = !ui->inputTextEdit->toPlainText().trimmed().isEmpty();
×
NEW
82
  ui->importButton->setEnabled(hasInput);
×
NEW
83
  ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(hasInput);
×
NEW
84
}
×
85

NEW
86
bool ImportKeyDialog::importFromString(const QString &input) {
×
NEW
87
  QString gpgExe = QtPassSettings::getGpgExecutable();
×
NEW
88
  QStringList args = {"--import", "--batch", "--yes"};
×
89

NEW
90
  QString stdOut;
×
NEW
91
  QString stdErr;
×
92

93
  int result =
NEW
94
      Executor::executeBlocking(gpgExe, args, input, &stdOut, &stdErr);
×
95

NEW
96
  if (result != 0) {
×
NEW
97
    showError(tr("GPG import failed:\n%1").arg(stdErr));
×
NEW
98
    return false;
×
99
  }
100

NEW
101
  QString fingerprint = parseGpgImportOutput(stdOut);
×
NEW
102
  if (fingerprint.isEmpty()) {
×
NEW
103
    fingerprint = parseGpgImportOutput(stdErr);
×
104
  }
105

NEW
106
  if (fingerprint.isEmpty()) {
×
NEW
107
    showError(tr("Could not parse imported key fingerprint from GPG output."));
×
NEW
108
    return false;
×
109
  }
110

NEW
111
  m_importedFingerprint = fingerprint;
×
NEW
112
  showSuccess(fingerprint);
×
113
  return true;
NEW
114
}
×
115

NEW
116
QString ImportKeyDialog::parseGpgImportOutput(const QString &output) {
×
117
  QRegularExpression re(
NEW
118
      QStringLiteral(R"(gpg: key (\w+): imported)"));
×
NEW
119
  QRegularExpressionMatch match = re.match(output);
×
NEW
120
  if (match.hasMatch()) {
×
NEW
121
    return match.captured(1);
×
122
  }
123

NEW
124
  re.setPattern(QStringLiteral(R"(gpg: key (\w+):.*imported)"));
×
NEW
125
  match = re.match(output);
×
NEW
126
  if (match.hasMatch()) {
×
NEW
127
    return match.captured(1);
×
128
  }
129

130
  return QString();
NEW
131
}
×
132

NEW
133
void ImportKeyDialog::showError(const QString &message) {
×
NEW
134
  QMessageBox::warning(this, tr("Import Key"), message);
×
NEW
135
}
×
136

NEW
137
void ImportKeyDialog::showSuccess(const QString &fingerprint) {
×
NEW
138
  QMessageBox::information(this, tr("Import Key"),
×
NEW
139
                          tr("Successfully imported key: %1")
×
NEW
140
                              .arg(fingerprint));
×
NEW
141
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc