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

IJHack / QtPass / 25579973242

08 May 2026 09:16PM UTC coverage: 28.036% (+0.005%) from 28.031%
25579973242

push

github

web-flow
refactor: enable bugprone-* in clang-tidy + fix narrowing conversions (#1435)

After clearing the modernize-* / performance-* findings in #1432,
extended the .clang-tidy check set to include bugprone-* with two
exclusions for noise that doesn't fit the project's idioms:

- bugprone-throwing-static-initialization (67 findings): every
  static QString / QRegularExpression in the codebase. Standard Qt
  pattern; these constructors don't throw in practice. Disabling
  matches the convention in most Qt projects.

- bugprone-easily-swappable-parameters (22 findings): adjacent
  same-typed parameters. Stylistic; would require API-breaking
  signature changes that Qt's slot wiring expects.

That left 10 real bugprone-narrowing-conversions findings, all
qsizetype → int truncations (Qt 6 returns 64-bit qsizetype from
indexOf/size/count, but a lot of the codebase uses int).

Pattern: prefer qsizetype where the value stays internal; cast at
Qt-API boundaries that take int.

- configdialog.cpp setRowCount: static_cast<int> (Qt API)
- executor.cpp var.indexOf: int → qsizetype
- filecontent.cpp line.indexOf: int → qsizetype
- mainwindow.cpp tr count: static_cast<int> (Qt API)
- pass.cpp lastIndexOf: int → qsizetype
- pass.cpp *count = recipients.size(): static_cast<int> (out-param)
- passworddialog.cpp template indices: int → qsizetype
- qtpass.cpp prompt index: int → qsizetype

Validation:
- clang-tidy with new config: 0 findings in QtPass-owned code.
- tst_util: 106/106 pass.
- Full build clean.

cert-* yields no unique findings beyond bugprone aliases (the only
one was cert-err58-cpp = bugprone-throwing-static-initialization),
so not separately enabled.

4 of 7 new or added lines in 6 files covered. (57.14%)

1 existing line in 1 file now uncovered.

1854 of 6613 relevant lines covered (28.04%)

27.12 hits per line

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

47.1
/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 "helpers.h"
6
#include "pass.h"
7
#include "passwordconfiguration.h"
8
#include "qtpasssettings.h"
9
#include "ui_passworddialog.h"
10
#include "util.h"
11
#include <algorithm>
12

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

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

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

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

39
  connect(QtPassSettings::getPass(), &Pass::finishedShow, this,
8✔
40
          &PasswordDialog::setPass);
8✔
41
}
8✔
42

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

53
  if (!isNew) {
×
54
    QtPassSettings::getPass()->Show(m_file);
×
55
  }
56

57
  ui->setupUi(this);
×
58

59
  setWindowTitle(this->windowTitle() + " " + m_file);
×
60
  m_passConfig = QtPassSettings::getPasswordConfiguration();
×
61
  usePwgen(QtPassSettings::isUsePwgen());
×
62
  setTemplate(QtPassSettings::getPassTemplate(),
×
63
              QtPassSettings::isUseTemplate());
×
64

65
  setLength(m_passConfig.length);
×
66
  setPasswordCharTemplate(m_passConfig.selected);
×
67

68
  connect(QtPassSettings::getPass(), &Pass::finishedShow, this,
×
69
          &PasswordDialog::setPass);
×
70
  connect(QtPassSettings::getPass(), &Pass::processErrorExit, this,
×
71
          &PasswordDialog::close);
×
72
  connect(this, &PasswordDialog::accepted, this, &PasswordDialog::on_accepted);
×
73
  connect(this, &PasswordDialog::rejected, this, &PasswordDialog::on_rejected);
×
74
}
×
75

76
/**
77
 * @brief PasswordDialog::~PasswordDialog basic destructor.
78
 */
79
PasswordDialog::~PasswordDialog() { delete ui; }
32✔
80

81
/**
82
 * @brief PasswordDialog::on_checkBoxShow_stateChanged hide or show passwords.
83
 * @param arg1
84
 */
85
void PasswordDialog::on_checkBoxShow_stateChanged(int arg1) {
×
86
  if (arg1) {
×
87
    ui->lineEditPassword->setEchoMode(QLineEdit::Normal);
×
88
  } else {
89
    ui->lineEditPassword->setEchoMode(QLineEdit::Password);
×
90
  }
91
}
×
92

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

106
  QString newPass = QtPassSettings::getPass()->generatePassword(
×
107
      static_cast<unsigned int>(ui->spinBox_pwdLength->value()),
×
108
      m_passConfig.Characters[static_cast<PasswordConfiguration::characterSet>(
109
          currentIndex)]);
×
110
  if (!newPass.isEmpty()) {
×
111
    ui->lineEditPassword->setText(newPass);
×
112
  }
113
  ui->widget->setEnabled(true);
×
114
}
115

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

125
  if (newValue.right(1) != "\n") {
×
126
    newValue += "\n";
×
127
  }
128

129
  QtPassSettings::getPass()->Insert(m_file, newValue, !m_isNew);
×
130
}
131

132
/**
133
 * @brief PasswordDialog::on_rejected handle Cancel click for QDialog
134
 */
135
void PasswordDialog::on_rejected() { setPassword(QString()); }
×
136

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

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

171
  ui->plainTextEdit->insertPlainText(fileContent.getRemainingData());
16✔
172
}
8✔
173

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

194
/**
195
 * @brief PasswordDialog::setTemplate set the template and create the fields.
196
 * @param rawFields
197
 */
198
void PasswordDialog::setTemplate(const QString &rawFields, bool useTemplate) {
7✔
199
  m_fields = rawFields.split('\n');
7✔
200
  m_templating = useTemplate;
7✔
201

202
  for (QLineEdit *line : std::as_const(m_templateLines)) {
7✔
203
    ui->formLayout->removeRow(line);
×
204
  }
205
  m_templateLines.clear();
7✔
206

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

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

231
/**
232
 * @brief PasswordDialog::setLength
233
 * PasswordDialog::setLength password length.
234
 * @param length
235
 */
236
void PasswordDialog::setLength(int length) {
8✔
237
  ui->spinBox_pwdLength->setValue(length);
8✔
238
}
8✔
239

240
/**
241
 * @brief PasswordDialog::setPasswordCharTemplate
242
 * PasswordDialog::setPasswordCharTemplate chose the template style.
243
 * @param templateIndex
244
 */
245
void PasswordDialog::setPasswordCharTemplate(int templateIndex) {
8✔
246
  ui->passwordTemplateSwitch->setCurrentIndex(templateIndex);
8✔
247
}
8✔
248

249
/**
250
 * @brief PasswordDialog::usePwgen
251
 * PasswordDialog::usePwgen don't use own password generator.
252
 * @param usePwgen
253
 */
254
void PasswordDialog::usePwgen(bool usePwgen) {
×
255
  ui->passwordTemplateSwitch->setDisabled(usePwgen);
×
256
  ui->label_characterset->setDisabled(usePwgen);
×
257
}
×
258

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

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

293
/**
294
 * @brief Cycle to next template (Ctrl+T).
295
 */
296
void PasswordDialog::cycleTemplate() {
×
297
  if (m_availableTemplates.isEmpty()) {
298
    return;
×
299
  }
300
  QStringList names = m_availableTemplates.keys();
×
301
  std::sort(names.begin(), names.end());
×
302

303
  qsizetype currentIdx = names.indexOf(m_currentTemplateName);
304
  qsizetype nextIdx;
UNCOV
305
  if (currentIdx < 0) {
×
306
    nextIdx = 0;
307
  } else {
308
    nextIdx = (currentIdx + 1) % names.size();
×
309
  }
310
  applyTemplate(names.at(nextIdx));
×
311
}
312

313
/**
314
 * @brief Sets the password from pass show output.
315
 * @param output Output from pass show command
316
 */
317
void PasswordDialog::setPass(const QString &output) {
8✔
318
  setPassword(output);
8✔
319
  // UI is enabled by default when password is set - no additional action needed
320
}
8✔
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