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

IJHack / QtPass / 27692393037

17 Jun 2026 01:26PM UTC coverage: 57.221% (-0.2%) from 57.47%
27692393037

Pull #1553

github

web-flow
Merge 9051e6041 into 311601814
Pull Request #1553: refactor(#1511): inject Pass*/AppSettings into dialog layer

11 of 31 new or added lines in 5 files covered. (35.48%)

19 existing lines in 4 files now uncovered.

3966 of 6931 relevant lines covered (57.22%)

23.3 hits per line

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

69.63
/src/passworddialog.cpp
1
// SPDX-FileCopyrightText: 2015 Anne Jan Brouwer
2
// SPDX-License-Identifier: GPL-3.0-or-later
3
#include "passworddialog.h"
4
#include "filecontent.h"
5
#include "pass.h"
6
#include "passwordconfiguration.h"
7
#include "qtpasssettings.h"
8
#include "ui_passworddialog.h"
9
#include "util.h"
10
#include <algorithm>
11

12
#include <QHash>
13
#include <QLabel>
14
#include <QLineEdit>
15
#include <QShortcut>
16
#include <utility>
17

18
#ifdef QT_DEBUG
19
#include "debughelper.h"
20
#endif
21

22
/**
23
 * @brief PasswordDialog::PasswordDialog basic constructor.
24
 * @param passConfig configuration constant
25
 * @param parent
26
 */
27
PasswordDialog::PasswordDialog(PasswordConfiguration passConfig,
17✔
28
                               QWidget *parent)
17✔
29
    : QDialog(parent), ui(new Ui::PasswordDialog),
34✔
30
      m_passConfig(std::move(passConfig)), m_pass(QtPassSettings::getPass()) {
17✔
31
  m_templating = false;
32
  m_isNew = false;
33

34
  ui->setupUi(this);
17✔
35
  setLength(m_passConfig.length);
17✔
36
  setPasswordCharTemplate(m_passConfig.selected);
17✔
37

38
  connect(m_pass, &Pass::finishedShow, this, &PasswordDialog::setPass);
17✔
39
}
17✔
40

41
/**
42
 * @brief PasswordDialog::PasswordDialog complete constructor.
43
 * @param file
44
 * @param isNew
45
 * @param parent pointer
46
 */
NEW
47
PasswordDialog::PasswordDialog(Pass *pass, const AppSettings &s, QString file,
×
NEW
48
                               const bool &isNew, QWidget *parent)
×
NEW
49
    : QDialog(parent), ui(new Ui::PasswordDialog), m_pass(pass),
×
NEW
50
      m_file(std::move(file)), m_isNew(isNew) {
×
51

52
  if (!isNew) {
×
NEW
53
    m_pass->Show(m_file);
×
54
  }
55

56
  ui->setupUi(this);
×
57

58
  setWindowTitle(this->windowTitle() + " " + m_file);
×
NEW
59
  m_passConfig = s.passwordConfiguration;
×
NEW
60
  usePwgen(s.usePwgen);
×
NEW
61
  setTemplate(s.passTemplate, s.useTemplate);
×
62

63
  setLength(m_passConfig.length);
×
64
  setPasswordCharTemplate(m_passConfig.selected);
×
65

NEW
66
  connect(m_pass, &Pass::finishedShow, this, &PasswordDialog::setPass);
×
NEW
67
  connect(m_pass, &Pass::processErrorExit, this, &PasswordDialog::close);
×
68
  connect(this, &PasswordDialog::accepted, this, &PasswordDialog::on_accepted);
×
69
  connect(this, &PasswordDialog::rejected, this, &PasswordDialog::on_rejected);
×
70
}
×
71

72
/**
73
 * @brief PasswordDialog::~PasswordDialog basic destructor.
74
 */
75
PasswordDialog::~PasswordDialog() { delete ui; }
68✔
76

77
/**
78
 * @brief PasswordDialog::on_checkBoxShow_stateChanged hide or show passwords.
79
 * @param arg1
80
 */
81
void PasswordDialog::on_checkBoxShow_stateChanged(int arg1) {
2✔
82
  if (arg1) {
2✔
83
    ui->lineEditPassword->setEchoMode(QLineEdit::Normal);
1✔
84
  } else {
85
    ui->lineEditPassword->setEchoMode(QLineEdit::Password);
1✔
86
  }
87
}
2✔
88

89
/**
90
 * @brief PasswordDialog::on_createPasswordButton_clicked generate a random
91
 * password.
92
 */
93
void PasswordDialog::on_createPasswordButton_clicked() {
×
94
  ui->widget->setEnabled(false);
×
95
  const int currentIndex = ui->passwordTemplateSwitch->currentIndex();
×
96
  if (currentIndex < 0 ||
×
97
      currentIndex >= static_cast<int>(PasswordConfiguration::CHARSETS_COUNT)) {
98
    ui->widget->setEnabled(true);
×
99
    return;
×
100
  }
101

NEW
102
  QString newPass = m_pass->generatePassword(
×
103
      static_cast<unsigned int>(ui->spinBox_pwdLength->value()),
×
104
      m_passConfig.Characters[static_cast<PasswordConfiguration::characterSet>(
105
          currentIndex)]);
×
106
  if (!newPass.isEmpty()) {
×
107
    ui->lineEditPassword->setText(newPass);
×
108
  }
109
  ui->widget->setEnabled(true);
×
110
}
111

112
/**
113
 * @brief PasswordDialog::on_accepted handle Ok click for QDialog
114
 */
115
void PasswordDialog::on_accepted() {
×
116
  QString newValue = getPassword();
×
117
  if (newValue.isEmpty()) {
×
118
    return;
119
  }
120

121
  if (newValue.right(1) != "\n") {
×
122
    newValue += "\n";
×
123
  }
124

NEW
125
  m_pass->Insert(m_file, newValue, !m_isNew);
×
126
}
127

128
/**
129
 * @brief PasswordDialog::on_rejected handle Cancel click for QDialog
130
 */
131
void PasswordDialog::on_rejected() { setPassword(QString()); }
×
132

133
/**
134
 * @brief PasswordDialog::setPassword populate the (templated) fields.
135
 * @param password
136
 */
137
void PasswordDialog::setPassword(const QString &password) {
9✔
138
  // Always parse all fields as editable so users can edit any field in the
139
  // password file. This fixes issue #132 where users couldn't edit
140
  // fields without toggling the "Show all fields templated" setting.
141
  FileContent fileContent = FileContent::parse(password, m_fields, true);
9✔
142
  ui->lineEditPassword->setText(fileContent.getPassword());
9✔
143

144
  QWidget *previous = ui->checkBoxShow;
9✔
145
  // first set templated values
146
  NamedValues namedValues = fileContent.getNamedValues();
9✔
147
  for (QLineEdit *line : std::as_const(m_templateLines)) {
10✔
148
    line->setText(namedValues.takeValue(line->objectName()));
2✔
149
    previous = line;
150
  }
151
  // show remaining values (if there are)
152
  // Remove previously created dynamic widgets to prevent duplicates and leaks
153
  for (QLineEdit *line : std::as_const(m_otherLines)) {
9✔
154
    ui->formLayout->removeRow(line);
×
155
  }
156
  m_otherLines.clear();
9✔
157
  for (const NamedValue &nv : std::as_const(namedValues)) {
12✔
158
    auto *line = new QLineEdit();
3✔
159
    line->setObjectName(nv.name);
3✔
160
    line->setText(nv.value);
3✔
161
    ui->formLayout->addRow(new QLabel(nv.name), line);
3✔
162
    setTabOrder(previous, line);
3✔
163
    m_otherLines.append(line);
3✔
164
    previous = line;
165
  }
166

167
  ui->plainTextEdit->insertPlainText(fileContent.getRemainingData());
18✔
168
}
9✔
169

170
/**
171
 * @brief PasswordDialog::getPassword  join the (templated) fields to a QString
172
 * for writing back.
173
 * @return collapsed password.
174
 */
175
auto PasswordDialog::getPassword() -> QString {
9✔
176
  QString passFile = ui->lineEditPassword->text() + "\n";
18✔
177
  QList<QLineEdit *> allLines(m_templateLines);
178
  allLines.append(m_otherLines);
9✔
179
  for (QLineEdit *line : std::as_const(allLines)) {
13✔
180
    QString text = line->text();
4✔
181
    if (text.isEmpty()) {
4✔
182
      continue;
183
    }
184
    passFile += line->objectName() + ": " + text + "\n";
8✔
185
  }
186
  passFile += ui->plainTextEdit->toPlainText();
18✔
187
  return passFile;
9✔
188
}
189

190
/**
191
 * @brief PasswordDialog::setTemplate set the template and create the fields.
192
 * @param rawFields
193
 */
194
void PasswordDialog::setTemplate(const QString &rawFields, bool useTemplate) {
12✔
195
  m_fields = rawFields.split('\n');
12✔
196
  m_templating = useTemplate;
12✔
197

198
  for (QLineEdit *line : std::as_const(m_templateLines)) {
14✔
199
    ui->formLayout->removeRow(line);
2✔
200
  }
201
  m_templateLines.clear();
12✔
202

203
  // Defensively remove all rows tracked in m_otherLines to prevent accumulation
204
  // when cycling templates or applying new templates after setPassword
205
  for (QLineEdit *line : std::as_const(m_otherLines)) {
12✔
206
    ui->formLayout->removeRow(line);
×
207
  }
208
  m_otherLines.clear();
12✔
209

210
  if (m_templating) {
12✔
211
    QWidget *previous = ui->checkBoxShow;
6✔
212
    for (const QString &field : std::as_const(m_fields)) {
13✔
213
      if (field.isEmpty()) {
7✔
214
        continue;
×
215
      }
216
      auto *line = new QLineEdit();
7✔
217
      auto *label = new QLabel(field);
7✔
218
      line->setObjectName(field);
7✔
219
      ui->formLayout->addRow(label, line);
7✔
220
      setTabOrder(previous, line);
7✔
221
      m_templateLines.append(line);
7✔
222
      previous = line;
223
    }
224
  }
225
}
12✔
226

227
/**
228
 * @brief PasswordDialog::setLength
229
 * PasswordDialog::setLength password length.
230
 * @param length
231
 */
232
void PasswordDialog::setLength(int length) {
19✔
233
  ui->spinBox_pwdLength->setValue(length);
19✔
234
}
19✔
235

236
/**
237
 * @brief PasswordDialog::setPasswordCharTemplate
238
 * PasswordDialog::setPasswordCharTemplate chose the template style.
239
 * @param templateIndex
240
 */
241
void PasswordDialog::setPasswordCharTemplate(int templateIndex) {
19✔
242
  ui->passwordTemplateSwitch->setCurrentIndex(templateIndex);
19✔
243
}
19✔
244

245
/**
246
 * @brief PasswordDialog::usePwgen
247
 * PasswordDialog::usePwgen don't use own password generator.
248
 * @param usePwgen
249
 */
250
void PasswordDialog::usePwgen(bool usePwgen) {
2✔
251
  ui->passwordTemplateSwitch->setDisabled(usePwgen);
2✔
252
  ui->label_characterset->setDisabled(usePwgen);
2✔
253
}
2✔
254

255
/**
256
 * @brief Set available templates from .templates file and apply default.
257
 * @param templates Hash of template name to field list.
258
 * @param defaultTemplate Name of default template to select.
259
 */
260
void PasswordDialog::setAvailableTemplates(
3✔
261
    const QHash<QString, QStringList> &templates,
262
    const QString &defaultTemplate) {
263
  m_availableTemplates = templates;
3✔
264
  QStringList templateNames = templates.keys();
3✔
265
  if (templateNames.isEmpty()) {
3✔
266
    return;
267
  }
268
  std::sort(templateNames.begin(), templateNames.end());
6✔
269
  QString selected = defaultTemplate;
270
  if (!templateNames.contains(selected)) {
3✔
271
    selected = templateNames.first();
×
272
  }
273
  applyTemplate(selected);
3✔
274
}
275

276
/**
277
 * @brief Apply a template by name.
278
 * @param templateName Name of template to apply.
279
 */
280
void PasswordDialog::applyTemplate(const QString &templateName) {
5✔
281
  auto it = m_availableTemplates.constFind(templateName);
5✔
282
  if (it != m_availableTemplates.constEnd()) {
283
    m_currentTemplateName = templateName;
5✔
284
    QString fields = it.value().join("\n");
5✔
285
    setTemplate(fields, true);
5✔
286
  }
287
}
5✔
288

289
/**
290
 * @brief Cycle to next template (Ctrl+T).
291
 */
292
void PasswordDialog::cycleTemplate() {
4✔
293
  if (m_availableTemplates.isEmpty()) {
294
    return;
2✔
295
  }
296
  QStringList names = m_availableTemplates.keys();
2✔
297
  std::sort(names.begin(), names.end());
4✔
298

299
  qsizetype currentIdx = names.indexOf(m_currentTemplateName);
300
  qsizetype nextIdx;
301
  if (currentIdx < 0) {
2✔
302
    nextIdx = 0;
303
  } else {
304
    nextIdx = (currentIdx + 1) % names.size();
2✔
305
  }
306
  applyTemplate(names.at(nextIdx));
2✔
307
}
308

309
/**
310
 * @brief Sets the password from pass show output.
311
 * @param output Output from pass show command
312
 */
313
void PasswordDialog::setPass(const QString &output) {
9✔
314
  setPassword(output);
9✔
315
  // UI is enabled by default when password is set - no additional action needed
316
}
9✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc