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

IJHack / QtPass / 23798624303

31 Mar 2026 01:00PM UTC coverage: 18.508%. Remained the same
23798624303

push

github

web-flow
docs: add comprehensive docstrings to C++ source files (#866)

* docs: add docstrings to remaining cpp files

Added docstrings to:
- pass.cpp: executeWrapper, init, boundedRandom, generateRandomPassword
- util.cpp: endsWithGpg, protocolRegex, newLinesRegex
- usersdialog.cpp: passesFilter, isUserExpired, buildUserText, applyUserStyling
- passworddialog.cpp: setPass

* docs: add docstrings to qtpass.cpp and improve existing docstrings

* fix: use trailing return type for isUserExpired per clang-tidy

0 of 1 new or added line in 1 file covered. (0.0%)

7 existing lines in 4 files now uncovered.

933 of 5041 relevant lines covered (18.51%)

7.68 hits per line

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

0.0
/src/usersdialog.cpp
1
// SPDX-FileCopyrightText: 2016 Anne Jan Brouwer
2
// SPDX-License-Identifier: GPL-3.0-or-later
3
#include "usersdialog.h"
4
#include "qtpasssettings.h"
5
#include "ui_usersdialog.h"
6
#include <QApplication>
7
#include <QCloseEvent>
8
#include <QKeyEvent>
9
#include <QMessageBox>
10
#include <QRegularExpression>
11
#include <QSet>
12
#include <QWidget>
13
#include <utility>
14

15
#ifdef QT_DEBUG
16
#include "debughelper.h"
17
#endif
18
/**
19
 * @brief UsersDialog::UsersDialog basic constructor
20
 * @param parent
21
 */
22
UsersDialog::UsersDialog(QString dir, QWidget *parent)
×
23
    : QDialog(parent), ui(new Ui::UsersDialog), m_dir(std::move(dir)) {
×
24

25
  ui->setupUi(this);
×
26

27
  QList<UserInfo> users = QtPassSettings::getPass()->listKeys();
×
28
  if (users.isEmpty()) {
×
29
    QMessageBox::critical(parent, tr("Keylist missing"),
×
30
                          tr("Could not fetch list of available GPG keys"));
×
31
    reject();
×
32
    return;
33
  }
34

35
  QList<UserInfo> secret_keys = QtPassSettings::getPass()->listKeys("", true);
×
36
  QSet<QString> secretKeyIds;
37
  for (const UserInfo &sec : secret_keys) {
×
38
    secretKeyIds.insert(sec.key_id);
×
39
  }
40
  for (auto &user : users) {
×
41
    if (secretKeyIds.contains(user.key_id)) {
×
42
      user.have_secret = true;
×
43
    }
44
  }
45

46
  QList<UserInfo> selected_users;
×
47
  int count = 0;
×
48

49
  QStringList recipients = QtPassSettings::getPass()->getRecipientString(
×
50
      m_dir.isEmpty() ? "" : m_dir, " ", &count);
×
51
  if (!recipients.isEmpty()) {
×
52
    selected_users = QtPassSettings::getPass()->listKeys(recipients);
×
53
  }
54
  QSet<QString> selectedKeyIds;
55
  for (const UserInfo &sel : selected_users) {
×
56
    selectedKeyIds.insert(sel.key_id);
×
57
  }
58
  for (auto &user : users) {
×
59
    if (selectedKeyIds.contains(user.key_id)) {
×
60
      user.enabled = true;
×
61
    }
62
  }
63

64
  if (count > selected_users.size()) {
×
65
    // Some keys seem missing from keyring, add them separately
66
    QStringList allRecipients = QtPassSettings::getPass()->getRecipientList(
×
67
        m_dir.isEmpty() ? "" : m_dir);
×
68
    QSet<QString> missingKeyRecipients;
69
    for (const QString &recipient : allRecipients) {
×
70
      if (missingKeyRecipients.contains(recipient) ||
×
71
          QtPassSettings::getPass()->listKeys(recipient).empty()) {
×
72
        missingKeyRecipients.insert(recipient);
×
73
        UserInfo i;
×
74
        i.enabled = true;
×
75
        i.key_id = recipient;
×
76
        i.name = " ?? " + tr("Key not found in keyring");
×
77
        users.append(i);
78
      }
×
79
    }
80
  }
81

82
  m_userList = users;
83
  populateList();
×
84

85
  connect(ui->buttonBox, &QDialogButtonBox::accepted, this,
×
86
          &UsersDialog::accept);
×
87
  connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
×
88
  connect(ui->listWidget, &QListWidget::itemChanged, this,
×
89
          &UsersDialog::itemChange);
×
90

91
  ui->lineEdit->setClearButtonEnabled(true);
×
92
}
×
93

94
/**
95
 * @brief UsersDialog::~UsersDialog basic destructor.
96
 */
97
UsersDialog::~UsersDialog() { delete ui; }
×
98

99
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
100
Q_DECLARE_METATYPE(UserInfo *)
101
Q_DECLARE_METATYPE(const UserInfo *)
102
#endif
103

104
/**
105
 * @brief UsersDialog::accept
106
 */
107
void UsersDialog::accept() {
×
108
  QtPassSettings::getPass()->Init(m_dir, m_userList);
×
109

110
  QDialog::accept();
×
111
}
×
112

113
/**
114
 * @brief UsersDialog::closeEvent might have to store size and location if that
115
 * is wanted.
116
 * @param event
117
 */
118
void UsersDialog::closeEvent(QCloseEvent *event) {
×
119
  // TODO(annejan): save window size or something
120
  event->accept();
121
}
×
122

123
/**
124
 * @brief UsersDialog::keyPressEvent clear the lineEdit when escape is pressed.
125
 * No action for Enter currently.
126
 * @param event
127
 */
128
void UsersDialog::keyPressEvent(QKeyEvent *event) {
×
129
  switch (event->key()) {
×
130
  case Qt::Key_Escape:
×
131
    ui->lineEdit->clear();
×
132
    break;
×
133
  default:
134
    break;
135
  }
136
}
×
137

138
/**
139
 * @brief UsersDialog::itemChange update the item information.
140
 * @param item
141
 */
142
void UsersDialog::itemChange(QListWidgetItem *item) {
×
143
  if (!item) {
×
144
    return;
×
145
  }
146
  bool ok = false;
×
147
  const int index = item->data(Qt::UserRole).toInt(&ok);
×
148
  if (!ok) {
×
149
#ifdef QT_DEBUG
150
    qWarning() << "UsersDialog::itemChange: invalid user index data for item";
151
#endif
152
    return;
153
  }
154
  if (index < 0 || index >= m_userList.size()) {
×
155
#ifdef QT_DEBUG
156
    qWarning() << "UsersDialog::itemChange: user index out of range:" << index
157
               << "valid range is [0," << (m_userList.size() - 1) << "]";
158
#endif
159
    return;
160
  }
161
  m_userList[index].enabled = item->checkState() == Qt::Checked;
×
162
}
163

164
/**
165
 * @brief UsersDialog::populateList update the view based on filter options
166
 * (such as searching).
167
 * @param filter
168
 */
169
void UsersDialog::populateList(const QString &filter) {
×
170
  static QString lastFilter;
×
171
  static QRegularExpression cachedNameFilter;
×
172
  if (filter != lastFilter) {
×
173
    lastFilter = filter;
×
174
    cachedNameFilter = QRegularExpression(
×
175
        QRegularExpression::wildcardToRegularExpression("*" + filter + "*"),
×
176
        QRegularExpression::CaseInsensitiveOption);
177
  }
178
  const QRegularExpression &nameFilter = cachedNameFilter;
179
  ui->listWidget->clear();
×
180

181
  for (int i = 0; i < m_userList.size(); ++i) {
×
182
    const auto &user = m_userList.at(i);
183
    if (!passesFilter(user, filter, nameFilter)) {
×
184
      continue;
×
185
    }
186

187
    auto *item = new QListWidgetItem(buildUserText(user), ui->listWidget);
×
188
    applyUserStyling(item, user);
×
189
    item->setCheckState(user.enabled ? Qt::Checked : Qt::Unchecked);
×
190
    item->setData(Qt::UserRole, QVariant::fromValue(i));
×
191
    ui->listWidget->addItem(item);
×
192
  }
193
}
×
194

195
/**
196
 * @brief Checks if a user passes the filter criteria.
197
 * @param user User to check
198
 * @param filter Filter string
199
 * @param nameFilter Compiled name filter regex
200
 * @return true if user passes filter
201
 */
UNCOV
202
bool UsersDialog::passesFilter(const UserInfo &user, const QString &filter,
×
203
                               const QRegularExpression &nameFilter) const {
204
  if (!filter.isEmpty() && !nameFilter.match(user.name).hasMatch()) {
×
205
    return false;
206
  }
207
  if (!user.isValid() && !ui->checkBox->isChecked()) {
×
208
    return false;
209
  }
210
  const bool expired = isUserExpired(user);
×
211
  return !(expired && !ui->checkBox->isChecked());
×
212
}
213

214
/**
215
 * @brief Checks if a user's key has expired.
216
 * @param user User to check
217
 * @return true if user's key is expired
218
 */
NEW
219
auto UsersDialog::isUserExpired(const UserInfo &user) const -> bool {
×
220
  return user.expiry.toSecsSinceEpoch() > 0 &&
×
221
         QDateTime::currentDateTime() > user.expiry;
×
222
}
223

224
/**
225
 * @brief Builds display text for a user.
226
 * @param user User to format
227
 * @return Formatted user text
228
 */
229
QString UsersDialog::buildUserText(const UserInfo &user) const {
×
230
  QString text = user.name + "\n" + user.key_id;
×
231
  if (user.created.toSecsSinceEpoch() > 0) {
×
232
    text += " " + tr("created") + " " +
×
233
            QLocale::system().toString(user.created, QLocale::ShortFormat);
×
234
  }
235
  if (user.expiry.toSecsSinceEpoch() > 0) {
×
236
    text += " " + tr("expires") + " " +
×
237
            QLocale::system().toString(user.expiry, QLocale::ShortFormat);
×
238
  }
239
  return text;
×
240
}
241

242
/**
243
 * @brief Applies visual styling to a user list item based on key status.
244
 * @param item List widget item to style
245
 * @param user User whose status determines styling
246
 */
UNCOV
247
void UsersDialog::applyUserStyling(QListWidgetItem *item,
×
248
                                   const UserInfo &user) const {
249
  const QString originalText = item->text();
×
250
  if (user.have_secret) {
×
251
    const QPalette palette = QApplication::palette();
×
252
    item->setForeground(palette.color(QPalette::Link));
×
253
    QFont font = item->font();
×
254
    font.setBold(true);
255
    item->setFont(font);
×
256
  } else if (!user.isValid()) {
×
257
    item->setBackground(Qt::darkRed);
×
258
    item->setForeground(Qt::white);
×
259
    item->setText(tr("[INVALID] ") + originalText);
×
260
  } else if (isUserExpired(user)) {
×
261
    item->setForeground(Qt::darkRed);
×
262
    item->setText(tr("[EXPIRED] ") + originalText);
×
263
  } else if (!user.fullyValid()) {
×
264
    item->setBackground(Qt::darkYellow);
×
265
    item->setForeground(Qt::white);
×
266
    item->setText(tr("[PARTIAL] ") + originalText);
×
267
  } else {
268
    item->setText(originalText);
×
269
  }
270
}
×
271

272
/**
273
 * @brief UsersDialog::on_lineEdit_textChanged typing in the searchbox.
274
 * @param filter
275
 */
276
void UsersDialog::on_lineEdit_textChanged(const QString &filter) {
×
277
  populateList(filter);
×
278
}
×
279

280
/**
281
 * @brief UsersDialog::on_checkBox_clicked filtering.
282
 */
283
void UsersDialog::on_checkBox_clicked() { populateList(ui->lineEdit->text()); }
×
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