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

IJHack / QtPass / 24591428477

17 Apr 2026 11:40PM UTC coverage: 21.908% (-0.2%) from 22.061%
24591428477

push

github

web-flow
fix: improve profile creation experience (#1036)

* fix: improve profile creation experience

- Add default 'New Profile' name with auto-focus
- Add double-click folder browser for path column
- Add tooltips for Name and Path columns
- Initialize pass and git when creating new profile with new folder
- Add ProfileInit helper class for profile initialization

* fix: snapshot existingProfiles before setProfiles in on_accepted

existingProfiles was captured after setProfiles(getProfiles()) had
already run, so it always contained the new profiles — making
initializeNewProfiles unable to detect any profile as new.

Move the snapshot immediately before setProfiles and remove the
redundant second setProfiles call.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: improve profile creation experience

- Add default 'New Profile' name with auto-focus
- Add double-click folder browser for path column
- Add tooltips for Name and Path columns
- Initialize pass and git when creating new profile with new folder
- Add ProfileInit helper class for profile initialization
- Use sorted profile iteration for deterministic order
- Capture existingProfiles before setProfiles to detect new profiles

* fix: apply CodeRabbit auto-fixes

Fixed 1 file(s) based on 1 unresolved review comment.

Co-authored-by: CodeRabbit <noreply@coderabbit.ai>

---------

Co-authored-by: Anne Jan Brouwer <brouwer@annejan.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: CodeRabbit <noreply@coderabbit.ai>

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

27 existing lines in 3 files now uncovered.

1199 of 5473 relevant lines covered (21.91%)

8.58 hits per line

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

0.0
/src/configdialog.cpp
1
// SPDX-FileCopyrightText: 2014 Anne Jan Brouwer
2
// SPDX-License-Identifier: GPL-3.0-or-later
3
#include "configdialog.h"
4
#include "keygendialog.h"
5
#include "mainwindow.h"
6
#include "profileinit.h"
7
#include "qtpasssettings.h"
8
#include "ui_configdialog.h"
9
#include "usersdialog.h"
10
#include "util.h"
11
#include <QClipboard>
12
#include <QDir>
13
#include <QFileDialog>
14
#include <QMessageBox>
15
#include <QPushButton>
16
#include <QSystemTrayIcon>
17
#include <QTableWidgetItem>
18
#include <utility>
19
#ifdef Q_OS_WIN
20
#include <windows.h>
21
#endif
22

23
#ifdef QT_DEBUG
24
#include "debughelper.h"
25
#endif
26

27
/**
28
 * @brief ConfigDialog::ConfigDialog this sets up the configuration screen.
29
 * @param parent
30
 */
31
ConfigDialog::ConfigDialog(MainWindow *parent)
×
32
    : QDialog(parent), ui(new Ui::ConfigDialog) {
×
33
  mainWindow = parent;
×
34
  ui->setupUi(this);
×
35

36
  // Restore dialog state
37
  QByteArray savedGeometry = QtPassSettings::getDialogGeometry("configDialog");
×
38
  bool hasSavedGeometry = !savedGeometry.isEmpty();
39
  if (hasSavedGeometry) {
×
40
    restoreGeometry(savedGeometry);
×
41
  }
42
  if (QtPassSettings::isDialogMaximized("configDialog")) {
×
43
    showMaximized();
×
44
  } else if (!hasSavedGeometry) {
45
    // Let window manager handle positioning for first launch
46
  }
47

48
  ui->passPath->setText(QtPassSettings::getPassExecutable());
×
49
  setGitPath(QtPassSettings::getGitExecutable());
×
50
  ui->gpgPath->setText(QtPassSettings::getGpgExecutable());
×
51
  ui->storePath->setText(QtPassSettings::getPassStore());
×
52

53
  ui->spinBoxAutoclearSeconds->setValue(QtPassSettings::getAutoclearSeconds());
×
54
  ui->spinBoxAutoclearPanelSeconds->setValue(
×
55
      QtPassSettings::getAutoclearPanelSeconds());
×
56
  ui->checkBoxHidePassword->setChecked(QtPassSettings::isHidePassword());
×
57
  ui->checkBoxHideContent->setChecked(QtPassSettings::isHideContent());
×
58
  ui->checkBoxUseMonospace->setChecked(QtPassSettings::isUseMonospace());
×
59
  ui->checkBoxDisplayAsIs->setChecked(QtPassSettings::isDisplayAsIs());
×
60
  ui->checkBoxNoLineWrapping->setChecked(QtPassSettings::isNoLineWrapping());
×
61
  ui->checkBoxAddGPGId->setChecked(QtPassSettings::isAddGPGId(true));
×
62

63
  if (QSystemTrayIcon::isSystemTrayAvailable()) {
×
64
    ui->checkBoxHideOnClose->setChecked(QtPassSettings::isHideOnClose());
×
65
    ui->checkBoxStartMinimized->setChecked(QtPassSettings::isStartMinimized());
×
66
  } else {
67
    ui->checkBoxUseTrayIcon->setEnabled(false);
×
68
    ui->checkBoxUseTrayIcon->setToolTip(tr("System tray is not available"));
×
69
    ui->checkBoxHideOnClose->setEnabled(false);
×
70
    ui->checkBoxStartMinimized->setEnabled(false);
×
71
  }
72

73
  ui->checkBoxAvoidCapitals->setChecked(QtPassSettings::isAvoidCapitals());
×
74
  ui->checkBoxAvoidNumbers->setChecked(QtPassSettings::isAvoidNumbers());
×
75
  ui->checkBoxLessRandom->setChecked(QtPassSettings::isLessRandom());
×
76
  ui->checkBoxUseSymbols->setChecked(QtPassSettings::isUseSymbols());
×
77
  ui->plainTextEditTemplate->setPlainText(QtPassSettings::getPassTemplate());
×
78
  ui->checkBoxTemplateAllFields->setChecked(
×
79
      QtPassSettings::isTemplateAllFields());
×
80
  ui->checkBoxAutoPull->setChecked(QtPassSettings::isAutoPull());
×
81
  ui->checkBoxAutoPush->setChecked(QtPassSettings::isAutoPush());
×
82
  ui->checkBoxAlwaysOnTop->setChecked(QtPassSettings::isAlwaysOnTop());
×
83

84
#if defined(Q_OS_WIN)
85
  ui->checkBoxUseOtp->hide();
86
  ui->checkBoxUseQrencode->hide();
87
  ui->label_10->hide();
88
#endif
89

90
  if (!isPassOtpAvailable()) {
×
91
    ui->checkBoxUseOtp->setEnabled(false);
×
92
    ui->checkBoxUseOtp->setToolTip(
×
93
        tr("Pass OTP extension needs to be installed"));
×
94
  }
95

96
  if (!isQrencodeAvailable()) {
×
97
    ui->checkBoxUseQrencode->setEnabled(false);
×
98
    ui->checkBoxUseQrencode->setToolTip(tr("qrencode needs to be installed"));
×
99
  }
100

101
  setProfiles(QtPassSettings::getProfiles(), QtPassSettings::getProfile());
×
102
  setPwgenPath(QtPassSettings::getPwgenExecutable());
×
103
  setPasswordConfiguration(QtPassSettings::getPasswordConfiguration());
×
104

105
  usePass(QtPassSettings::isUsePass());
×
106
  useAutoclear(QtPassSettings::isUseAutoclear());
×
107
  useAutoclearPanel(QtPassSettings::isUseAutoclearPanel());
×
108
  useTrayIcon(QtPassSettings::isUseTrayIcon());
×
109
  useGit(QtPassSettings::isUseGit());
×
110

111
  useOtp(QtPassSettings::isUseOtp());
×
112
  useQrencode(QtPassSettings::isUseQrencode());
×
113

114
  usePwgen(QtPassSettings::isUsePwgen());
×
115
  useTemplate(QtPassSettings::isUseTemplate());
×
116

117
  ui->profileTable->verticalHeader()->hide();
×
118
  ui->profileTable->horizontalHeader()->setSectionResizeMode(
×
119
      1, QHeaderView::Stretch);
120
  ui->label->setText(ui->label->text() + VERSION);
×
121
  ui->comboBoxClipboard->clear();
×
122

123
  ui->comboBoxClipboard->addItem(tr("No Clipboard"));
×
124
  ui->comboBoxClipboard->addItem(tr("Always copy to clipboard"));
×
125
  ui->comboBoxClipboard->addItem(tr("On-demand copy to clipboard"));
×
126

127
  int currentIndex = QtPassSettings::getClipBoardTypeRaw();
×
128
  ui->comboBoxClipboard->setCurrentIndex(currentIndex);
×
129
  on_comboBoxClipboard_activated(currentIndex);
×
130

131
  QClipboard *clip = QApplication::clipboard();
×
132
  if (!clip->supportsSelection()) {
×
133
    useSelection(false);
×
134
    ui->checkBoxSelection->setVisible(false);
×
135
  } else {
136
    useSelection(QtPassSettings::isUseSelection());
×
137
  }
138

139
  if (!Util::configIsValid()) {
×
140
    // Show Programs tab, which is likely
141
    // what the user needs to fix now.
142
    ui->tabWidget->setCurrentIndex(1);
×
143
  }
144

145
  connect(ui->profileTable, &QTableWidget::itemChanged, this,
×
146
          &ConfigDialog::onProfileTableItemChanged);
×
147
  connect(this, &ConfigDialog::accepted, this, &ConfigDialog::on_accepted);
×
148
}
×
149

150
/**
151
 * @brief ConfigDialog::~ConfigDialog config destructor, makes sure the
152
 * mainWindow knows about git, gpg and pass executables.
153
 */
154
ConfigDialog::~ConfigDialog() {
×
155
  QtPassSettings::setGitExecutable(ui->gitPath->text());
×
156
  QtPassSettings::setGpgExecutable(ui->gpgPath->text());
×
157
  QtPassSettings::setPassExecutable(ui->passPath->text());
×
158
}
×
159

160
/**
161
 * @brief ConfigDialog::setGitPath set the git executable path.
162
 * Make sure the checkBoxUseGit is updated.
163
 * @param path
164
 */
165
void ConfigDialog::setGitPath(const QString &path) {
×
166
  ui->gitPath->setText(path);
×
167
  ui->checkBoxUseGit->setEnabled(!path.isEmpty());
×
168
  if (path.isEmpty()) {
×
169
    useGit(false);
×
170
  }
171
}
×
172

173
/**
174
 * @brief ConfigDialog::usePass set wether or not we want to use pass.
175
 * Update radio buttons accordingly.
176
 * @param usePass
177
 */
178
void ConfigDialog::usePass(bool usePass) {
×
179
  ui->radioButtonNative->setChecked(!usePass);
×
180
  ui->radioButtonPass->setChecked(usePass);
×
181
  setGroupBoxState();
×
182
}
×
183

184
/**
185
 * @brief Validates the configuration table fields and enables or disables the
186
 * OK button accordingly.
187
 * @example
188
 * ConfigDialog dialog;
189
 * QTableWidgetItem *item = dialog.findChild<QTableWidgetItem*>();
190
 * dialog.validate(item);
191
 *
192
 * @param QTableWidgetItem *item - The table item to validate; if null,
193
 * validates all relevant items in the profile table.
194
 * @return void - This function does not return a value.
195
 */
196
void ConfigDialog::validate(QTableWidgetItem *item) {
×
197
  bool status = true;
198

199
  if (item == nullptr) {
×
200
    for (int i = 0; i < ui->profileTable->rowCount(); i++) {
×
201
      for (int j = 0; j < ui->profileTable->columnCount(); j++) {
×
202
        QTableWidgetItem *_item = ui->profileTable->item(i, j);
×
203

204
        if (_item->text().isEmpty() && j != 2) {
×
205
          _item->setBackground(Qt::red);
×
206
          _item->setToolTip(tr("This field is required"));
×
207
          status = false;
208
          break;
209
        } else {
210
          _item->setBackground(QBrush());
×
211
          _item->setToolTip(QString());
×
212
        }
213
      }
214

215
      if (!status) {
216
        break;
217
      }
218
    }
219
  } else {
220
    if (item->text().isEmpty() && item->column() != 2) {
×
221
      item->setBackground(Qt::red);
×
222
      item->setToolTip(tr("This field is required"));
×
223
      status = false;
224
    } else {
225
      item->setBackground(QBrush());
×
226
      item->setToolTip(QString());
×
227
    }
228
  }
229

230
  ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(status);
×
231
}
×
232

233
/**
234
 * @brief Saves the configuration dialog settings to persistent application
235
 * settings.
236
 * @example
237
 * ConfigDialog dialog;
238
 * dialog.on_accepted();
239
 * // Expected output: All UI-selected configuration values are stored via
240
 * QtPassSettings.
241
 *
242
 * @return void - This method does not return a value.
243
 */
244
void ConfigDialog::on_accepted() {
×
245
  QtPassSettings::setPassExecutable(ui->passPath->text());
×
246
  QtPassSettings::setGitExecutable(ui->gitPath->text());
×
247
  QtPassSettings::setGpgExecutable(ui->gpgPath->text());
×
248
  QtPassSettings::setPassStore(
×
249
      Util::normalizeFolderPath(ui->storePath->text()));
×
250
  QtPassSettings::setUsePass(ui->radioButtonPass->isChecked());
×
251
  QtPassSettings::setClipBoardType(ui->comboBoxClipboard->currentIndex());
×
252
  QtPassSettings::setUseSelection(ui->checkBoxSelection->isChecked());
×
253
  QtPassSettings::setUseAutoclear(ui->checkBoxAutoclear->isChecked());
×
254
  QtPassSettings::setAutoclearSeconds(ui->spinBoxAutoclearSeconds->value());
×
255
  QtPassSettings::setUseAutoclearPanel(ui->checkBoxAutoclearPanel->isChecked());
×
256
  QtPassSettings::setAutoclearPanelSeconds(
×
257
      ui->spinBoxAutoclearPanelSeconds->value());
×
258
  QtPassSettings::setHidePassword(ui->checkBoxHidePassword->isChecked());
×
259
  QtPassSettings::setHideContent(ui->checkBoxHideContent->isChecked());
×
260
  QtPassSettings::setUseMonospace(ui->checkBoxUseMonospace->isChecked());
×
261
  QtPassSettings::setDisplayAsIs(ui->checkBoxDisplayAsIs->isChecked());
×
262
  QtPassSettings::setNoLineWrapping(ui->checkBoxNoLineWrapping->isChecked());
×
263
  QtPassSettings::setAddGPGId(ui->checkBoxAddGPGId->isChecked());
×
264
  QtPassSettings::setUseTrayIcon(ui->checkBoxUseTrayIcon->isEnabled() &&
×
265
                                 ui->checkBoxUseTrayIcon->isChecked());
×
266
  QtPassSettings::setHideOnClose(ui->checkBoxHideOnClose->isEnabled() &&
×
267
                                 ui->checkBoxHideOnClose->isChecked());
×
268
  QtPassSettings::setStartMinimized(ui->checkBoxStartMinimized->isEnabled() &&
×
269
                                    ui->checkBoxStartMinimized->isChecked());
×
270
  QHash<QString, QHash<QString, QString>> existingProfiles =
NEW
271
      QtPassSettings::getProfiles();
×
272
  QtPassSettings::setProfiles(getProfiles());
×
273
  QtPassSettings::setUseGit(ui->checkBoxUseGit->isChecked());
×
274
  QtPassSettings::setUseOtp(ui->checkBoxUseOtp->isChecked());
×
275
  QtPassSettings::setUseQrencode(ui->checkBoxUseQrencode->isChecked());
×
276
  QtPassSettings::setPwgenExecutable(ui->pwgenPath->text());
×
277
  QtPassSettings::setUsePwgen(ui->checkBoxUsePwgen->isChecked());
×
278
  QtPassSettings::setAvoidCapitals(ui->checkBoxAvoidCapitals->isChecked());
×
279
  QtPassSettings::setAvoidNumbers(ui->checkBoxAvoidNumbers->isChecked());
×
280
  QtPassSettings::setLessRandom(ui->checkBoxLessRandom->isChecked());
×
281
  QtPassSettings::setUseSymbols(ui->checkBoxUseSymbols->isChecked());
×
282
  QtPassSettings::setPasswordConfiguration(getPasswordConfiguration());
×
283
  QtPassSettings::setUseTemplate(ui->checkBoxUseTemplate->isChecked());
×
284
  QtPassSettings::setPassTemplate(ui->plainTextEditTemplate->toPlainText());
×
285
  QtPassSettings::setTemplateAllFields(
×
286
      ui->checkBoxTemplateAllFields->isChecked());
×
287
  QtPassSettings::setAutoPush(ui->checkBoxAutoPush->isChecked());
×
288
  QtPassSettings::setAutoPull(ui->checkBoxAutoPull->isChecked());
×
289
  QtPassSettings::setAlwaysOnTop(ui->checkBoxAlwaysOnTop->isChecked());
×
290

291
  QtPassSettings::setVersion(VERSION);
×
292

293
  // Initialize new profiles that need pass/git initialization
NEW
294
  initializeNewProfiles(existingProfiles);
×
UNCOV
295
}
×
296

297
/**
298
 * @brief Automatically detects required external binaries in the system PATH
299
 * and updates the dialog fields.
300
 * @example
301
 * ConfigDialog configDialog;
302
 * configDialog.on_autodetectButton_clicked();
303
 *
304
 * @return void - This function does not return a value.
305
 */
306
void ConfigDialog::on_autodetectButton_clicked() {
×
307
  QString pass = Util::findBinaryInPath("pass");
×
308
  if (!pass.isEmpty()) {
×
309
    ui->passPath->setText(pass);
×
310
  }
311
  usePass(!pass.isEmpty());
×
312
  QString gpg = Util::findBinaryInPath("gpg2");
×
313
  if (gpg.isEmpty()) {
×
314
    gpg = Util::findBinaryInPath("gpg");
×
315
  }
316
  if (!gpg.isEmpty()) {
×
317
    ui->gpgPath->setText(gpg);
×
318
  }
319
  QString git = Util::findBinaryInPath("git");
×
320
  if (!git.isEmpty()) {
×
321
    ui->gitPath->setText(git);
×
322
  }
323
  QString pwgen = Util::findBinaryInPath("pwgen");
×
324
  if (!pwgen.isEmpty()) {
×
325
    ui->pwgenPath->setText(pwgen);
×
326
  }
327
}
×
328

329
/**
330
 * @brief ConfigDialog::on_radioButtonNative_clicked wrapper for
331
 * ConfigDialog::setGroupBoxState()
332
 */
333
void ConfigDialog::on_radioButtonNative_clicked() { setGroupBoxState(); }
×
334

335
/**
336
 * @brief ConfigDialog::on_radioButtonPass_clicked wrapper for
337
 * ConfigDialog::setGroupBoxState()
338
 */
339
void ConfigDialog::on_radioButtonPass_clicked() { setGroupBoxState(); }
×
340

341
/**
342
 * @brief ConfigDialog::getSecretKeys get list of secret/private keys
343
 * @return QStringList keys
344
 */
345
auto ConfigDialog::getSecretKeys() -> QStringList {
×
346
  QList<UserInfo> keys = QtPassSettings::getPass()->listKeys("", true);
×
347
  QStringList names;
×
348

349
  if (keys.empty()) {
×
350
    return names;
351
  }
352

353
  foreach (const UserInfo &sec, keys)
×
354
    names << sec.name;
×
355

356
  return names;
×
357
}
358

359
/**
360
 * @brief ConfigDialog::setGroupBoxState update checkboxes.
361
 */
362
void ConfigDialog::setGroupBoxState() {
×
363
  bool state = ui->radioButtonPass->isChecked();
×
364
  ui->groupBoxNative->setEnabled(!state);
×
365
  ui->groupBoxPass->setEnabled(state);
×
366
  if (state) {
×
367
    // pass mode: disable all password generation controls
368
    ui->spinBoxPasswordLength->setEnabled(false);
×
369
    ui->checkBoxUsePwgen->setEnabled(false);
×
370
    ui->checkBoxAvoidCapitals->setEnabled(false);
×
371
    ui->checkBoxUseSymbols->setEnabled(false);
×
372
    ui->checkBoxLessRandom->setEnabled(false);
×
373
    ui->checkBoxAvoidNumbers->setEnabled(false);
×
374
    ui->labelPasswordChars->setEnabled(false);
×
375
    ui->passwordCharTemplateSelector->setEnabled(false);
×
376
    ui->lineEditPasswordChars->setEnabled(false);
×
377
  } else {
378
    // native mode: restore pwgen/charset state from existing handlers
379
    ui->spinBoxPasswordLength->setEnabled(true);
×
380
    ui->checkBoxUsePwgen->setEnabled(!ui->pwgenPath->text().isEmpty());
×
381
    on_checkBoxUsePwgen_clicked();
×
382
  }
383
}
×
384

385
/**
386
 * @brief ConfigDialog::selectExecutable pop-up to choose an executable.
387
 * @return
388
 */
389
auto ConfigDialog::selectExecutable() -> QString {
×
390
  QFileDialog dialog(this);
×
391
  dialog.setFileMode(QFileDialog::ExistingFile);
×
392
  dialog.setOption(QFileDialog::ReadOnly);
×
393
  if (dialog.exec()) {
×
394
    return dialog.selectedFiles().constFirst();
×
395
  }
396

397
  return {};
398
}
×
399

400
/**
401
 * @brief ConfigDialog::selectFolder pop-up to choose a folder.
402
 * @return
403
 */
404
auto ConfigDialog::selectFolder() -> QString {
×
405
  QFileDialog dialog(this);
×
406
  dialog.setFileMode(QFileDialog::Directory);
×
407
  dialog.setFilter(QDir::NoFilter);
×
408
  dialog.setOption(QFileDialog::ShowDirsOnly);
×
409
  if (dialog.exec()) {
×
410
    return dialog.selectedFiles().constFirst();
×
411
  }
412

413
  return {};
414
}
×
415

416
/**
417
 * @brief ConfigDialog::on_toolButtonGit_clicked get git application.
418
 * Enable checkboxes if found.
419
 */
420
void ConfigDialog::on_toolButtonGit_clicked() {
×
421
  QString git = selectExecutable();
×
422
  bool state = !git.isEmpty();
×
423
  if (state) {
×
424
    ui->gitPath->setText(git);
×
425
  } else {
426
    useGit(false);
×
427
  }
428

429
  ui->checkBoxUseGit->setEnabled(state);
×
430
}
×
431

432
/**
433
 * @brief ConfigDialog::on_toolButtonGpg_clicked get gpg application.
434
 */
435
void ConfigDialog::on_toolButtonGpg_clicked() {
×
436
  QString gpg = selectExecutable();
×
437
  if (!gpg.isEmpty()) {
×
438
    ui->gpgPath->setText(gpg);
×
439
  }
440
}
×
441

442
/**
443
 * @brief ConfigDialog::on_pushButtonGenerateKey_clicked open keygen dialog.
444
 */
445
void ConfigDialog::on_pushButtonGenerateKey_clicked() {
×
446
  KeygenDialog d(this);
×
447
  d.exec();
×
448
}
×
449

450
/**
451
 * @brief ConfigDialog::on_toolButtonPass_clicked get pass application.
452
 */
453
void ConfigDialog::on_toolButtonPass_clicked() {
×
454
  QString pass = selectExecutable();
×
455
  if (!pass.isEmpty()) {
×
456
    ui->passPath->setText(pass);
×
457
  }
458
}
×
459

460
/**
461
 * @brief ConfigDialog::on_toolButtonStore_clicked get .password-store
462
 * location.
463
 */
464
void ConfigDialog::on_toolButtonStore_clicked() {
×
465
  QString store = selectFolder();
×
466
  if (!store.isEmpty()) {
×
467
    ui->storePath->setText(store);
×
468
  }
469
}
×
470

471
/**
472
 * @brief ConfigDialog::on_comboBoxClipboard_activated show and hide options.
473
 * @param index of selectbox (0 = no clipboard).
474
 */
475
void ConfigDialog::on_comboBoxClipboard_activated(int index) {
×
476
  bool state = index > 0;
×
477

478
  ui->checkBoxSelection->setEnabled(state);
×
479
  ui->checkBoxAutoclear->setEnabled(state);
×
480
  ui->checkBoxHidePassword->setEnabled(state);
×
481
  ui->checkBoxHideContent->setEnabled(state);
×
482
  if (state) {
×
483
    ui->spinBoxAutoclearSeconds->setEnabled(ui->checkBoxAutoclear->isChecked());
×
484
    ui->labelSeconds->setEnabled(ui->checkBoxAutoclear->isChecked());
×
485
  } else {
486
    ui->spinBoxAutoclearSeconds->setEnabled(false);
×
487
    ui->labelSeconds->setEnabled(false);
×
488
  }
489
}
×
490

491
/**
492
 * @brief ConfigDialog::on_checkBoxAutoclearPanel_clicked enable and disable
493
 * options based on autoclear use.
494
 */
495
void ConfigDialog::on_checkBoxAutoclearPanel_clicked() {
×
496
  bool state = ui->checkBoxAutoclearPanel->isChecked();
×
497
  ui->spinBoxAutoclearPanelSeconds->setEnabled(state);
×
498
  ui->labelPanelSeconds->setEnabled(state);
×
499
}
×
500

501
/**
502
 * @brief ConfigDialog::useSelection set the clipboard type use from
503
 * MainWindow.
504
 * @param useSelection
505
 */
506
void ConfigDialog::useSelection(bool useSelection) {
×
507
  ui->checkBoxSelection->setChecked(useSelection);
×
508
  on_checkBoxSelection_clicked();
×
509
}
×
510

511
/**
512
 * @brief ConfigDialog::useAutoclear set the clipboard autoclear use from
513
 * MainWindow.
514
 * @param useAutoclear
515
 */
516
void ConfigDialog::useAutoclear(bool useAutoclear) {
×
517
  ui->checkBoxAutoclear->setChecked(useAutoclear);
×
518
  on_checkBoxAutoclear_clicked();
×
519
}
×
520

521
/**
522
 * @brief ConfigDialog::useAutoclearPanel set the panel autoclear use from
523
 * MainWindow.
524
 * @param useAutoclearPanel
525
 */
526
void ConfigDialog::useAutoclearPanel(bool useAutoclearPanel) {
×
527
  ui->checkBoxAutoclearPanel->setChecked(useAutoclearPanel);
×
528
  on_checkBoxAutoclearPanel_clicked();
×
529
}
×
530

531
/**
532
 * @brief ConfigDialog::on_checkBoxSelection_clicked checkbox clicked, update
533
 * state via ConfigDialog::on_comboBoxClipboard_activated
534
 */
535
void ConfigDialog::on_checkBoxSelection_clicked() {
×
536
  on_comboBoxClipboard_activated(ui->comboBoxClipboard->currentIndex());
×
537
}
×
538

539
/**
540
 * @brief ConfigDialog::on_checkBoxAutoclear_clicked checkbox clicked, update
541
 * state via ConfigDialog::on_comboBoxClipboard_activated
542
 */
543
void ConfigDialog::on_checkBoxAutoclear_clicked() {
×
544
  on_comboBoxClipboard_activated(ui->comboBoxClipboard->currentIndex());
×
545
}
×
546

547
/**
548
 * @brief ConfigDialog::genKey tunnel function to make MainWindow generate a
549
 * gpg key pair.
550
 * @todo refactor the process to not be entangled so much.
551
 * @param batch
552
 * @param dialog
553
 */
554
void ConfigDialog::genKey(const QString &batch, QDialog *dialog) {
×
555
  mainWindow->generateKeyPair(batch, dialog);
×
556
}
×
557

558
/**
559
 * @brief ConfigDialog::setProfiles set the profiles and chosen profile from
560
 * MainWindow.
561
 * @param profiles
562
 * @param profile
563
 */
564
void ConfigDialog::setProfiles(QHash<QString, QHash<QString, QString>> profiles,
×
565
                               const QString &currentProfile) {
566
  if (profiles.contains("")) {
×
567
    profiles.remove("");
×
568
    // remove weird "" key value pairs
569
  }
570

571
  ui->profileTable->setRowCount(profiles.count());
×
572
  QHashIterator<QString, QHash<QString, QString>> i(profiles);
×
573
  int n = 0;
574
  while (i.hasNext()) {
×
575
    i.next();
576
    if (!i.value().isEmpty() && !i.key().isEmpty()) {
×
577
      ui->profileTable->setItem(n, 0, new QTableWidgetItem(i.key()));
×
578
      ui->profileTable->setItem(n, 1,
×
579
                                new QTableWidgetItem(i.value().value("path")));
×
580
      ui->profileTable->setItem(
×
581
          n, 2, new QTableWidgetItem(i.value().value("signingKey")));
×
582
      if (i.key() == currentProfile) {
×
583
        ui->profileTable->selectRow(n);
×
584
      }
585
    }
586
    ++n;
×
587
  }
588
}
×
589

590
/**
591
 * @brief ConfigDialog::getProfiles return profile list.
592
 * @return
593
 */
594
auto ConfigDialog::getProfiles() -> QHash<QString, QHash<QString, QString>> {
×
595
  QHash<QString, QHash<QString, QString>> profiles;
×
596
  // Check?
597
  for (int i = 0; i < ui->profileTable->rowCount(); ++i) {
×
598
    QHash<QString, QString> profile;
×
599
    QTableWidgetItem *pathItem = ui->profileTable->item(i, 1);
×
600
    if (nullptr != pathItem) {
×
601
      QTableWidgetItem *item = ui->profileTable->item(i, 0);
×
602
      if (item == nullptr) {
×
603
        continue;
604
      }
605
      profile["path"] = pathItem->text();
×
606
      QTableWidgetItem *signingKeyItem = ui->profileTable->item(i, 2);
×
607
      if (nullptr != signingKeyItem) {
×
608
        profile["signingKey"] = signingKeyItem->text();
×
609
      }
610
      profiles.insert(item->text(), profile);
×
611
    }
612
  }
×
613
  return profiles;
×
614
}
×
615

616
/**
617
 * @brief Initialize new profiles that need pass/git initialization.
618
 * @param existingProfiles The profiles that existed before the dialog was
619
 * opened.
620
 */
NEW
621
void ConfigDialog::initializeNewProfiles(
×
622
    const QHash<QString, QHash<QString, QString>> &existingProfiles) {
NEW
623
  QHash<QString, QHash<QString, QString>> newProfiles = getProfiles();
×
624

625
  // Collect keys and sort for deterministic iteration
NEW
626
  QStringList keys = newProfiles.keys();
×
627
  keys.sort();
628

NEW
629
  for (const QString &name : keys) {
×
NEW
630
    const QString &path = newProfiles.value(name).value("path");
×
631

632
    // Skip if already existed before (check by name and path)
NEW
633
    if (existingProfiles.contains(name) &&
×
NEW
634
        existingProfiles.value(name).value("path") == path) {
×
NEW
635
      continue;
×
636
    }
637

638
    // This is a new profile - check if needs initialization
639
    // needsInit returns false for non-existent directories
NEW
640
    if (!ProfileInit::needsInit(path)) {
×
NEW
641
      continue;
×
642
    }
643

644
    // Temporarily switch the active store so pass/git init operate on
645
    // the new profile's directory rather than the currently-saved one.
NEW
646
    const QString prevStore = QtPassSettings::getPassStore();
×
NEW
647
    QtPassSettings::setPassStore(path);
×
648

649
    // Show user selection dialog for GPG recipients
650
    // UsersDialog will run pass init when accepted
NEW
651
    UsersDialog usersDialog(path, this);
×
NEW
652
    usersDialog.setWindowTitle(tr("Select recipients for %1").arg(name));
×
NEW
653
    const int result = usersDialog.exec();
×
654

NEW
655
    if (result == QDialog::Accepted && ui->checkBoxUseGit->isChecked()) {
×
NEW
656
      QtPassSettings::getPass()->GitInit();
×
657
    }
658

659
    // Restore previous store setting
NEW
660
    QtPassSettings::setPassStore(prevStore);
×
NEW
661
  }
×
NEW
662
}
×
663

664
/**
665
 * @brief ConfigDialog::on_addButton_clicked add a profile row.
666
 */
667
void ConfigDialog::on_addButton_clicked() {
×
668
  int n = ui->profileTable->rowCount();
×
669
  ui->profileTable->insertRow(n);
×
NEW
670
  ui->profileTable->setItem(n, 0, new QTableWidgetItem(tr("New Profile")));
×
671
  ui->profileTable->setItem(n, 1, new QTableWidgetItem(ui->storePath->text()));
×
672
  ui->profileTable->setItem(n, 2, new QTableWidgetItem());
×
673
  ui->profileTable->selectRow(n);
×
674
  ui->deleteButton->setEnabled(true);
×
675

NEW
676
  ui->profileTable->editItem(ui->profileTable->item(n, 0));
×
NEW
677
  ui->profileTable->item(n, 0)->setSelected(true);
×
678

679
  validate();
×
680
}
×
681

682
/**
683
 * @brief ConfigDialog::on_profileTable_cellDoubleClicked open folder browser
684
 * for path column (column 1).
685
 */
NEW
686
void ConfigDialog::on_profileTable_cellDoubleClicked(int row, int column) {
×
NEW
687
  if (column == 1) {
×
NEW
688
    QString dir = selectFolder();
×
NEW
689
    if (!dir.isEmpty()) {
×
NEW
690
      ui->profileTable->item(row, 1)->setText(dir);
×
691
    }
692
  }
NEW
693
}
×
694

695
/**
696
 * @brief ConfigDialog::on_deleteButton_clicked remove a profile row.
697
 */
698
void ConfigDialog::on_deleteButton_clicked() {
×
699
  QSet<int> selectedRows; //  we use a set to prevent doubles
700
  QList<QTableWidgetItem *> itemList = ui->profileTable->selectedItems();
×
701
  if (itemList.count() == 0) {
×
702
    QMessageBox::warning(this, tr("No profile selected"),
×
703
                         tr("No profile selected to delete"));
×
704
    return;
705
  }
706
  QTableWidgetItem *item;
707
  foreach (item, itemList)
×
708
    selectedRows.insert(item->row());
×
709
  // get a list, and sort it big to small
710
  QList<int> rows = selectedRows.values();
×
711
  std::sort(rows.begin(), rows.end());
×
712
  // now actually do the removing:
713
  foreach (int row, rows)
×
714
    ui->profileTable->removeRow(row);
×
715
  if (ui->profileTable->rowCount() < 1) {
×
716
    ui->deleteButton->setEnabled(false);
×
717
  }
718

719
  validate();
×
720
}
721

722
/**
723
 * @brief ConfigDialog::criticalMessage wrapper for showing critical messages
724
 * in a popup.
725
 * @param title
726
 * @param text
727
 */
728
void ConfigDialog::criticalMessage(const QString &title, const QString &text) {
×
729
  QMessageBox::critical(this, title, text, QMessageBox::Ok, QMessageBox::Ok);
×
730
}
×
731

732
/**
733
 * @brief Checks whether the qrencode executable is available on the system.
734
 * @example
735
 * bool result = ConfigDialog::isQrencodeAvailable();
736
 * std::cout << result << std::endl; // Expected output: true if qrencode is
737
 * found, otherwise false
738
 *
739
 * @return bool - True if qrencode is available; otherwise false. On Windows,
740
 * always returns false.
741
 */
742
auto ConfigDialog::isQrencodeAvailable() -> bool {
×
743
#ifdef Q_OS_WIN
744
  return false;
745
#else
746
  QProcess which;
×
747
  which.start("which", QStringList() << "qrencode");
×
748
  which.waitForFinished();
×
749
  QtPassSettings::setQrencodeExecutable(
×
750
      which.readAllStandardOutput().trimmed());
×
751
  return which.exitCode() == 0;
×
752
#endif
753
}
×
754

755
auto ConfigDialog::isPassOtpAvailable() -> bool {
×
756
#ifdef Q_OS_WIN
757
  return false;
758
#else
759
  QProcess pass;
×
760
  pass.start(QtPassSettings::getPassExecutable(), QStringList() << "otp"
×
761
                                                                << "--help");
×
762
  pass.waitForFinished(2000);
×
763
  return pass.exitCode() == 0;
×
764
#endif
765
}
×
766

767
/**
768
 * @brief ConfigDialog::wizard first-time use wizard.
769
 * @todo make this thing more reliable.
770
 */
771
void ConfigDialog::wizard() {
×
772
  (void)Util::configIsValid();
×
773
  on_autodetectButton_clicked();
×
774

775
  if (!checkGpgExistence()) {
×
776
    return;
777
  }
778
  if (!checkSecretKeys()) {
×
779
    return;
780
  }
781
  if (!checkPasswordStore()) {
×
782
    return;
783
  }
784
  handleGpgIdFile();
×
785

786
  ui->checkBoxHidePassword->setCheckState(Qt::Checked);
×
787
}
788

789
/**
790
 * @brief Checks whether the configured GnuPG executable exists.
791
 * @example
792
 * bool result = ConfigDialog::checkGpgExistence();
793
 * std::cout << result << std::endl; // Expected output: true if GnuPG is found,
794
 * false otherwise
795
 *
796
 * @return bool - True if the GnuPG path is valid or uses a WSL command prefix;
797
 * false if the executable cannot be found and an error message is shown.
798
 */
799
auto ConfigDialog::checkGpgExistence() -> bool {
×
800
  QString gpg = ui->gpgPath->text();
×
801
  if (!gpg.startsWith("wsl ") && !QFile(gpg).exists()) {
×
802
    criticalMessage(
×
803
        tr("GnuPG not found"),
×
804
#ifdef Q_OS_WIN
805
#ifdef WINSTORE
806
        tr("Please install GnuPG on your system.<br>Install "
807
           "<strong>Ubuntu</strong> from the Microsoft Store to get it.<br>"
808
           "If you already did so, make sure you started it once and<br>"
809
           "click \"Autodetect\" in the next dialog.")
810
#else
811
        tr("Please install GnuPG on your system.<br>Install "
812
           "<strong>Ubuntu</strong> from the Microsoft Store<br>or <a "
813
           "href=\"https://www.gnupg.org/download/#sec-1-2\">download</a> it "
814
           "from GnuPG.org")
815
#endif
816
#else
817
        tr("Please install GnuPG on your system.<br>Install "
×
818
           "<strong>gpg</strong> using your favorite package manager<br>or "
819
           "<a "
820
           "href=\"https://www.gnupg.org/download/#sec-1-2\">download</a> it "
821
           "from GnuPG.org")
822
#endif
823
    );
824
    return false;
×
825
  }
826
  return true;
827
}
828

829
/**
830
 * @brief Checks whether secret keys are available and, if needed, prompts the
831
 * user to generate them.
832
 * @example
833
 * bool result = ConfigDialog.checkSecretKeys();
834
 * std::cout << result << std::endl; // Expected output: true if keys are
835
 * present or key generation dialog is accepted, false otherwise
836
 *
837
 * @return bool - Returns true when secret keys are already available or the key
838
 * generation dialog is accepted; false if the dialog is rejected.
839
 */
840
auto ConfigDialog::checkSecretKeys() -> bool {
×
841
  QString gpg = ui->gpgPath->text();
×
842
  QStringList names = getSecretKeys();
×
843

844
#ifdef QT_DEBUG
845
  dbg() << names;
846
#endif
847

848
  if ((gpg.startsWith("wsl ") || QFile(gpg).exists()) && names.empty()) {
×
849
    KeygenDialog d(this);
×
850
    return d.exec();
×
851
  }
×
852
  return true;
853
}
854

855
/**
856
 * @brief Checks whether the password-store path exists and prompts the user to
857
 * create it if it does not.
858
 * @example
859
 * bool result = ConfigDialog::checkPasswordStore();
860
 * std::cout << std::boolalpha << result << std::endl; // Expected output: true
861
 * if the store exists or is created successfully, false if creation fails
862
 *
863
 * @return bool - True if the password-store exists or is successfully created,
864
 * false if creation fails.
865
 */
866
auto ConfigDialog::checkPasswordStore() -> bool {
×
867
  QString passStore = ui->storePath->text();
×
868

869
  if (!QFile(passStore).exists()) {
×
870
    if (QMessageBox::question(
×
871
            this, tr("Create password-store?"),
×
872
            tr("Would you like to create a password-store at %1?")
×
873
                .arg(passStore),
×
874
            QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
875
      if (!QDir().mkdir(passStore)) {
×
876
        QMessageBox::warning(
×
877
            this, tr("Error"),
×
878
            tr("Failed to create password-store at: %1").arg(passStore));
×
879
        return false;
×
880
      }
881
#ifdef Q_OS_WIN
882
      SetFileAttributes(passStore.toStdWString().c_str(),
883
                        FILE_ATTRIBUTE_HIDDEN);
884
#endif
885
      if (ui->checkBoxUseGit->isChecked()) {
×
886
        emit mainWindow->passGitInitNeeded();
×
887
      }
888
      mainWindow->userDialog(passStore);
×
889
    }
890
  }
891
  return true;
892
}
893

894
/**
895
 * @brief Handles selection and validation of the password store's .gpg-id file.
896
 * @example
897
 * ConfigDialog dialog;
898
 * dialog.handleGpgIdFile();
899
 *
900
 * @return void - This method does not return a value; it updates the UI flow
901
 * and may prompt the user to choose a valid password store.
902
 */
903
void ConfigDialog::handleGpgIdFile() {
×
904
  QString passStore = ui->storePath->text();
×
905
  if (!QFile(QDir(passStore).filePath(".gpg-id")).exists()) {
×
906
#ifdef QT_DEBUG
907
    dbg() << ".gpg-id file does not exist";
908
#endif
909
    criticalMessage(tr("Password store not initialised"),
×
910
                    tr("The folder %1 doesn't seem to be a password store or "
×
911
                       "is not yet initialised.")
912
                        .arg(passStore));
×
913

914
    while (!QFile(passStore).exists()) {
×
915
      on_toolButtonStore_clicked();
×
916
      if (passStore == ui->storePath->text()) {
×
917
        return;
918
      }
919
      passStore = ui->storePath->text();
×
920
    }
921
    if (!QFile(passStore + ".gpg-id").exists()) {
×
922
#ifdef QT_DEBUG
923
      dbg() << ".gpg-id file still does not exist :/";
924
#endif
925
      mainWindow->userDialog(passStore);
×
926
    }
927
  }
928
}
929

930
/**
931
 * @brief ConfigDialog::useTrayIcon set preference for using trayicon.
932
 * Enable or disable related checkboxes accordingly.
933
 * @param useSystray
934
 */
935
void ConfigDialog::useTrayIcon(bool useSystray) {
×
936
  if (QSystemTrayIcon::isSystemTrayAvailable()) {
×
937
    ui->checkBoxUseTrayIcon->setChecked(useSystray);
×
938
    ui->checkBoxHideOnClose->setEnabled(useSystray);
×
939
    ui->checkBoxStartMinimized->setEnabled(useSystray);
×
940

941
    if (!useSystray) {
×
942
      ui->checkBoxHideOnClose->setChecked(false);
×
943
      ui->checkBoxStartMinimized->setChecked(false);
×
944
    }
945
  }
946
}
×
947

948
/**
949
 * @brief ConfigDialog::on_checkBoxUseTrayIcon_clicked enable and disable
950
 * related checkboxes.
951
 */
952
void ConfigDialog::on_checkBoxUseTrayIcon_clicked() {
×
953
  bool state = ui->checkBoxUseTrayIcon->isChecked();
×
954
  ui->checkBoxHideOnClose->setEnabled(state);
×
955
  ui->checkBoxStartMinimized->setEnabled(state);
×
956
}
×
957

958
/**
959
 * @brief ConfigDialog::closeEvent close this window.
960
 * @param event
961
 */
962
void ConfigDialog::closeEvent(QCloseEvent *event) {
×
963
  QtPassSettings::setDialogGeometry("configDialog", saveGeometry());
×
964
  if (!isMaximized()) {
×
965
    QtPassSettings::setDialogPos("configDialog", pos());
×
966
    QtPassSettings::setDialogSize("configDialog", size());
×
967
  }
968
  QtPassSettings::setDialogMaximized("configDialog", isMaximized());
×
969
  event->accept();
970
}
×
971

972
/**
973
 * @brief ConfigDialog::useGit set preference for using git.
974
 * @param useGit
975
 */
976
void ConfigDialog::useGit(bool useGit) {
×
977
  ui->checkBoxUseGit->setChecked(useGit);
×
978
  on_checkBoxUseGit_clicked();
×
979
}
×
980

981
/**
982
 * @brief ConfigDialog::useOtp set preference for using otp plugin.
983
 * @param useOtp
984
 */
985
void ConfigDialog::useOtp(bool useOtp) {
×
986
  ui->checkBoxUseOtp->setChecked(useOtp);
×
987
}
×
988

989
/**
990
 * @brief ConfigDialog::useQrencode set preference for using qrencode plugin.
991
 * @param useQrencode
992
 */
993
void ConfigDialog::useQrencode(bool useQrencode) {
×
994
  ui->checkBoxUseQrencode->setChecked(useQrencode);
×
995
}
×
996

997
/**
998
 * @brief ConfigDialog::on_checkBoxUseGit_clicked enable or disable related
999
 * checkboxes.
1000
 */
1001
void ConfigDialog::on_checkBoxUseGit_clicked() {
×
1002
  ui->checkBoxAddGPGId->setEnabled(ui->checkBoxUseGit->isChecked());
×
1003
  ui->checkBoxAutoPull->setEnabled(ui->checkBoxUseGit->isChecked());
×
1004
  ui->checkBoxAutoPush->setEnabled(ui->checkBoxUseGit->isChecked());
×
1005
}
×
1006

1007
/**
1008
 * @brief ConfigDialog::on_toolButtonPwgen_clicked enable or disable related
1009
 * options in the interface.
1010
 */
1011
void ConfigDialog::on_toolButtonPwgen_clicked() {
×
1012
  QString pwgen = selectExecutable();
×
1013
  if (!pwgen.isEmpty()) {
×
1014
    ui->pwgenPath->setText(pwgen);
×
1015
    ui->checkBoxUsePwgen->setEnabled(true);
×
1016
  } else {
1017
    ui->checkBoxUsePwgen->setEnabled(false);
×
1018
    ui->checkBoxUsePwgen->setChecked(false);
×
1019
  }
1020
}
×
1021

1022
/**
1023
 * @brief ConfigDialog::setPwgenPath set pwgen executable path.
1024
 * Enable or disable related options in the interface.
1025
 * @param pwgen
1026
 */
1027
void ConfigDialog::setPwgenPath(const QString &pwgen) {
×
1028
  ui->pwgenPath->setText(pwgen);
×
1029
  if (pwgen.isEmpty()) {
×
1030
    ui->checkBoxUsePwgen->setChecked(false);
×
1031
    ui->checkBoxUsePwgen->setEnabled(false);
×
1032
  }
1033
  on_checkBoxUsePwgen_clicked();
×
1034
}
×
1035

1036
/**
1037
 * @brief ConfigDialog::on_checkBoxUsePwgen_clicked enable or disable related
1038
 * options in the interface.
1039
 */
1040
void ConfigDialog::on_checkBoxUsePwgen_clicked() {
×
1041
  if (ui->radioButtonPass->isChecked())
×
1042
    return;
1043
  bool usePwgen = ui->checkBoxUsePwgen->isChecked();
×
1044
  ui->checkBoxAvoidCapitals->setEnabled(usePwgen);
×
1045
  ui->checkBoxAvoidNumbers->setEnabled(usePwgen);
×
1046
  ui->checkBoxLessRandom->setEnabled(usePwgen);
×
1047
  ui->checkBoxUseSymbols->setEnabled(usePwgen);
×
1048
  ui->lineEditPasswordChars->setEnabled(!usePwgen);
×
1049
  ui->labelPasswordChars->setEnabled(!usePwgen);
×
1050
  ui->passwordCharTemplateSelector->setEnabled(!usePwgen);
×
1051
}
1052

1053
/**
1054
 * @brief ConfigDialog::usePwgen set preference for using pwgen (can be
1055
 * overruled by empty pwgenPath).
1056
 * enable or disable related options in the interface via
1057
 * ConfigDialog::on_checkBoxUsePwgen_clicked
1058
 * @param usePwgen
1059
 */
1060
void ConfigDialog::usePwgen(bool usePwgen) {
×
1061
  if (ui->pwgenPath->text().isEmpty()) {
×
1062
    usePwgen = false;
1063
  }
1064
  ui->checkBoxUsePwgen->setChecked(usePwgen);
×
1065
  on_checkBoxUsePwgen_clicked();
×
1066
}
×
1067

1068
void ConfigDialog::setPasswordConfiguration(
×
1069
    const PasswordConfiguration &config) {
1070
  ui->spinBoxPasswordLength->setValue(config.length);
×
1071
  ui->passwordCharTemplateSelector->setCurrentIndex(config.selected);
×
1072
  if (config.selected != PasswordConfiguration::CUSTOM) {
×
1073
    ui->lineEditPasswordChars->setEnabled(false);
×
1074
  }
1075
  ui->lineEditPasswordChars->setText(config.Characters[config.selected]);
×
1076
}
×
1077

1078
auto ConfigDialog::getPasswordConfiguration() -> PasswordConfiguration {
×
1079
  PasswordConfiguration config;
×
1080
  config.length = ui->spinBoxPasswordLength->value();
×
1081
  config.selected = static_cast<PasswordConfiguration::characterSet>(
×
1082
      ui->passwordCharTemplateSelector->currentIndex());
×
1083
  config.Characters[PasswordConfiguration::CUSTOM] =
1084
      ui->lineEditPasswordChars->text();
×
1085
  return config;
×
1086
}
×
1087

1088
/**
1089
 * @brief ConfigDialog::on_passwordCharTemplateSelector_activated sets the
1090
 * passwordChar Template
1091
 * combo box to the desired entry
1092
 * @param entry of
1093
 */
1094
void ConfigDialog::on_passwordCharTemplateSelector_activated(int index) {
×
1095
  ui->lineEditPasswordChars->setText(
×
1096
      QtPassSettings::getPasswordConfiguration().Characters[index]);
×
1097
  if (index == PasswordConfiguration::CUSTOM) {
×
1098
    ui->lineEditPasswordChars->setEnabled(true);
×
1099
  } else {
1100
    ui->lineEditPasswordChars->setEnabled(false);
×
1101
  }
1102
}
×
1103

1104
/**
1105
 * @brief ConfigDialog::on_checkBoxUseTemplate_clicked enable or disable the
1106
 * template field and options.
1107
 */
1108
void ConfigDialog::on_checkBoxUseTemplate_clicked() {
×
1109
  ui->plainTextEditTemplate->setEnabled(ui->checkBoxUseTemplate->isChecked());
×
1110
  ui->checkBoxTemplateAllFields->setEnabled(
×
1111
      ui->checkBoxUseTemplate->isChecked());
×
1112
}
×
1113

1114
void ConfigDialog::onProfileTableItemChanged(QTableWidgetItem *item) {
×
1115
  validate(item);
×
1116
}
×
1117

1118
/**
1119
 * @brief ConfigDialog::useTemplate set preference for using templates.
1120
 * @param useTemplate
1121
 */
1122
void ConfigDialog::useTemplate(bool useTemplate) {
×
1123
  ui->checkBoxUseTemplate->setChecked(useTemplate);
×
1124
  on_checkBoxUseTemplate_clicked();
×
1125
}
×
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