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

IJHack / QtPass / 24849229813

23 Apr 2026 05:28PM UTC coverage: 27.11% (-0.2%) from 27.334%
24849229813

Pull #1141

github

web-flow
Merge 6d772020a into c2eb59a14
Pull Request #1141: feat: multi-template support via .templates files

0 of 52 new or added lines in 2 files covered. (0.0%)

1 existing line in 1 file now uncovered.

1632 of 6020 relevant lines covered (27.11%)

29.46 hits per line

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

51.69
/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

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

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

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

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

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

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

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

55
  ui->setupUi(this);
×
56

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

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

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

74
/**
75
 * @brief PasswordDialog::~PasswordDialog basic destructor.
76
 */
77
PasswordDialog::~PasswordDialog() { delete ui; }
24✔
78

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

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

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

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

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

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

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

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

146
  QWidget *previous = ui->checkBoxShow;
8✔
147
  // first set templated values
148
  NamedValues namedValues = fileContent.getNamedValues();
8✔
149
  for (QLineEdit *line : AS_CONST(templateLines)) {
9✔
150
    line->setText(namedValues.takeValue(line->objectName()));
2✔
151
    previous = line;
152
  }
153
  // show remaining values (if there are)
154
  otherLines.clear();
8✔
155
  for (const NamedValue &nv : AS_CONST(namedValues)) {
11✔
156
    auto *line = new QLineEdit();
3✔
157
    line->setObjectName(nv.name);
3✔
158
    line->setText(nv.value);
3✔
159
    ui->formLayout->addRow(new QLabel(nv.name), line);
3✔
160
    setTabOrder(previous, line);
3✔
161
    otherLines.append(line);
3✔
162
    previous = line;
163
  }
164

165
  ui->plainTextEdit->insertPlainText(fileContent.getRemainingData());
16✔
166
}
8✔
167

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

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

197
  if (m_templating) {
7✔
198
    QWidget *previous = ui->checkBoxShow;
1✔
199
    for (const QString &field : std::as_const(m_fields)) {
2✔
200
      if (field.isEmpty()) {
1✔
201
        continue;
×
202
      }
203
      auto *line = new QLineEdit();
1✔
204
      line->setObjectName(field);
1✔
205
      ui->formLayout->addRow(new QLabel(field), line);
1✔
206
      setTabOrder(previous, line);
1✔
207
      templateLines.append(line);
1✔
208
      previous = line;
209
    }
210
  }
211
}
7✔
212

213
/**
214
 * @brief PasswordDialog::setLength
215
 * PasswordDialog::setLength password length.
216
 * @param length
217
 */
218
void PasswordDialog::setLength(int length) {
8✔
219
  ui->spinBox_pwdLength->setValue(length);
8✔
220
}
8✔
221

222
/**
223
 * @brief PasswordDialog::setPasswordCharTemplate
224
 * PasswordDialog::setPasswordCharTemplate chose the template style.
225
 * @param templateIndex
226
 */
227
void PasswordDialog::setPasswordCharTemplate(int templateIndex) {
8✔
228
  ui->passwordTemplateSwitch->setCurrentIndex(templateIndex);
8✔
229
}
8✔
230

231
/**
232
 * @brief PasswordDialog::usePwgen
233
 * PasswordDialog::usePwgen don't use own password generator.
234
 * @param usePwgen
235
 */
236
void PasswordDialog::usePwgen(bool usePwgen) {
×
237
  ui->passwordTemplateSwitch->setDisabled(usePwgen);
×
238
  ui->label_characterset->setDisabled(usePwgen);
×
239
}
×
240

241
/**
242
 * @brief Set available templates from .templates file and apply default.
243
 * @param templates Hash of template name to field list.
244
 * @param defaultTemplate Name of default template to select.
245
 */
NEW
246
void PasswordDialog::setAvailableTemplates(
×
247
    const QHash<QString, QStringList> &templates,
248
    const QString &defaultTemplate) {
NEW
249
  QStringList templateNames = templates.keys();
×
NEW
250
  if (templateNames.isEmpty()) {
×
251
    return;
252
  }
253
  QString selected = defaultTemplate;
NEW
254
  if (!templateNames.contains(selected)) {
×
NEW
255
    selected = templateNames.first();
×
256
  }
NEW
257
  auto it = templates.constFind(selected);
×
258
  if (it != templates.constEnd()) {
NEW
259
    QString fields = it.value().join("\n");
×
NEW
260
    setTemplate(fields, true);
×
261
  }
262
}
263

264
/**
265
 * @brief Sets the password from pass show output.
266
 * @param output Output from pass show command
267
 */
268
void PasswordDialog::setPass(const QString &output) {
8✔
269
  setPassword(output);
8✔
270
  // UI is enabled by default when password is set - no additional action needed
271
}
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