QtPass  1.3.3
Multi-platform GUI for pass, the standard unix password manager.
mainwindow.cpp
Go to the documentation of this file.
1 #include "mainwindow.h"
2 
3 #ifdef QT_DEBUG
4 #include "debughelper.h"
5 #endif
6 
7 #include "configdialog.h"
8 #include "filecontent.h"
9 #include "keygendialog.h"
10 #include "passworddialog.h"
11 #include "qpushbuttonasqrcode.h"
13 #include "qtpass.h"
14 #include "qtpasssettings.h"
15 #include "settingsconstants.h"
16 #include "trayicon.h"
17 #include "ui_mainwindow.h"
18 #include "usersdialog.h"
19 #include "util.h"
20 #include <QCloseEvent>
21 #include <QDesktopServices>
22 #include <QDialog>
23 #include <QFileInfo>
24 #include <QInputDialog>
25 #include <QLabel>
26 #include <QMenu>
27 #include <QMessageBox>
28 #include <QShortcut>
29 #include <QTimer>
30 
37 MainWindow::MainWindow(const QString &searchText, QWidget *parent)
38  : QMainWindow(parent), ui(new Ui::MainWindow), keygen(nullptr),
39  tray(nullptr) {
40 #ifdef __APPLE__
41  // extra treatment for mac os
42  // see http://doc.qt.io/qt-5/qkeysequence.html#qt_set_sequence_auto_mnemonic
43  qt_set_sequence_auto_mnemonic(true);
44 #endif
45  ui->setupUi(this);
46 
47  m_qtPass = new QtPass(this);
48 
49  // register shortcut ctrl/cmd + Q to close the main window
50  new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q), this, SLOT(close()));
51  // register shortcut ctrl/cmd + C to copy the currently selected password
52  new QShortcut(QKeySequence(QKeySequence::StandardKey::Copy), this,
53  SLOT(copyPasswordFromTreeview()));
54 
55  model.setNameFilters(QStringList() << "*.gpg");
56  model.setNameFilterDisables(false);
57 
58  /*
59  * I added this to solve Windows bug but now on GNU/Linux the main folder,
60  * if hidden, disappear
61  *
62  * model.setFilter(QDir::NoDot);
63  */
64 
66 
67  QModelIndex rootDir = model.setRootPath(passStore);
68  model.fetchMore(rootDir);
69 
70  proxyModel.setModelAndStore(&model, passStore);
71  selectionModel.reset(new QItemSelectionModel(&proxyModel));
72 
73  ui->treeView->setModel(&proxyModel);
74  ui->treeView->setRootIndex(proxyModel.mapFromSource(rootDir));
75  ui->treeView->setColumnHidden(1, true);
76  ui->treeView->setColumnHidden(2, true);
77  ui->treeView->setColumnHidden(3, true);
78  ui->treeView->setHeaderHidden(true);
79  ui->treeView->setIndentation(15);
80  ui->treeView->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
81  ui->treeView->setContextMenuPolicy(Qt::CustomContextMenu);
82  ui->treeView->header()->setSectionResizeMode(0, QHeaderView::Stretch);
83  ui->treeView->sortByColumn(0, Qt::AscendingOrder);
84  connect(ui->treeView, &QWidget::customContextMenuRequested, this,
85  &MainWindow::showContextMenu);
86  connect(ui->treeView, &DeselectableTreeView::emptyClicked, this,
88 
89  ui->textBrowser->setOpenExternalLinks(true);
90  ui->textBrowser->setContextMenuPolicy(Qt::CustomContextMenu);
91  connect(ui->textBrowser, &QWidget::customContextMenuRequested, this,
92  &MainWindow::showBrowserContextMenu);
93 
94  updateProfileBox();
95 
97  clearPanelTimer.setInterval(1000 *
99  clearPanelTimer.setSingleShot(true);
100  connect(&clearPanelTimer, SIGNAL(timeout()), this, SLOT(clearPanel()));
101 
102  searchTimer.setInterval(350);
103  searchTimer.setSingleShot(true);
104 
105  connect(&searchTimer, &QTimer::timeout, this, &MainWindow::onTimeoutSearch);
106 
107  initToolBarButtons();
108  initStatusBar();
109 
110 #if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
111  ui->lineEdit->setClearButtonEnabled(true);
112 #endif
113 
114  setUiElementsEnabled(true);
115 
116  qsrand(static_cast<uint>(QTime::currentTime().msec()));
117  QTimer::singleShot(10, this, SLOT(focusInput()));
118 
119  ui->lineEdit->setText(searchText);
120 
121  if (!m_qtPass->init())
122  // no working config so this should just quit
123  QApplication::quit();
124 }
125 
126 MainWindow::~MainWindow() { delete m_qtPass; }
127 
134 void MainWindow::focusInput() {
135  ui->lineEdit->selectAll();
136  ui->lineEdit->setFocus();
137 }
138 
143 void MainWindow::changeEvent(QEvent *event) {
144  QWidget::changeEvent(event);
145  if (event->type() == QEvent::ActivationChange) {
146  if (isActiveWindow()) {
147  focusInput();
148  }
149  }
150 }
151 
155 void MainWindow::initToolBarButtons() {
156  connect(ui->actionAddPassword, &QAction::triggered, this,
157  &MainWindow::addPassword);
158  connect(ui->actionAddFolder, &QAction::triggered, this,
159  &MainWindow::addFolder);
160  connect(ui->actionEdit, &QAction::triggered, this, &MainWindow::onEdit);
161  connect(ui->actionDelete, &QAction::triggered, this, &MainWindow::onDelete);
162  connect(ui->actionPush, &QAction::triggered, this, &MainWindow::onPush);
163  connect(ui->actionUpdate, &QAction::triggered, this, &MainWindow::onUpdate);
164  connect(ui->actionUsers, &QAction::triggered, this, &MainWindow::onUsers);
165  connect(ui->actionConfig, &QAction::triggered, this, &MainWindow::onConfig);
166  connect(ui->actionOtp, &QAction::triggered, this, &MainWindow::onOtp);
167 
168  ui->actionAddPassword->setIcon(
169  QIcon::fromTheme("document-new", QIcon(":/icons/document-new.svg")));
170  ui->actionAddFolder->setIcon(
171  QIcon::fromTheme("folder-new", QIcon(":/icons/folder-new.svg")));
172  ui->actionEdit->setIcon(QIcon::fromTheme(
173  "document-properties", QIcon(":/icons/document-properties.svg")));
174  ui->actionDelete->setIcon(
175  QIcon::fromTheme("edit-delete", QIcon(":/icons/edit-delete.svg")));
176  ui->actionPush->setIcon(
177  QIcon::fromTheme("go-up", QIcon(":/icons/go-top.svg")));
178  ui->actionUpdate->setIcon(
179  QIcon::fromTheme("go-down", QIcon(":/icons/go-bottom.svg")));
180  ui->actionUsers->setIcon(QIcon::fromTheme(
181  "x-office-address-book", QIcon(":/icons/x-office-address-book.svg")));
182  ui->actionConfig->setIcon(QIcon::fromTheme(
183  "applications-system", QIcon(":/icons/applications-system.svg")));
184 }
185 
189 void MainWindow::initStatusBar() {
190  ui->statusBar->showMessage(tr("Welcome to QtPass %1").arg(VERSION), 2000);
191 
192  QPixmap logo = QPixmap::fromImage(QImage(":/artwork/icon.svg"))
193  .scaledToHeight(statusBar()->height());
194  QLabel *logoApp = new QLabel(statusBar());
195  logoApp->setPixmap(logo);
196  statusBar()->addPermanentWidget(logoApp);
197 }
198 
200  return ui->treeView->currentIndex();
201 }
202 
204  this->keygen->close();
205  this->keygen = nullptr;
206 }
207 
208 void MainWindow::flashText(const QString &text, const bool isError,
209  const bool isHtml) {
210  if (isError)
211  ui->textBrowser->setTextColor(Qt::red);
212 
213  if (isHtml) {
214  QString _text = text;
215  if (!ui->textBrowser->toPlainText().isEmpty())
216  _text = ui->textBrowser->toHtml() + _text;
217  ui->textBrowser->setHtml(_text);
218  } else {
219  ui->textBrowser->setText(text);
220  ui->textBrowser->setTextColor(Qt::black);
221  }
222 }
223 
229  QScopedPointer<ConfigDialog> d(new ConfigDialog(this));
230  d->setModal(true);
231  // Automatically default to pass if it's available
232  if (m_qtPass->isFreshStart() &&
233  QFile(QtPassSettings::getPassExecutable()).exists()) {
235  }
236 
237  if (m_qtPass->isFreshStart())
238  d->wizard(); // does shit
239  if (d->exec()) {
240  if (d->result() == QDialog::Accepted) {
242  Qt::WindowFlags flags = windowFlags();
243  this->setWindowFlags(flags | Qt::WindowStaysOnTopHint);
244  } else {
245  this->setWindowFlags(Qt::Window);
246  }
247  this->show();
248 
249  updateProfileBox();
250  ui->treeView->setRootIndex(proxyModel.mapFromSource(
251  model.setRootPath(QtPassSettings::getPassStore())));
252 
253  if (m_qtPass->isFreshStart() && Util::checkConfig())
254  config();
256  clearPanelTimer.setInterval(1000 *
258  m_qtPass->setClipboardTimer();
259 
260  updateGitButtonVisibility();
261  updateOtpButtonVisibility();
262  if (QtPassSettings::isUseTrayIcon() && tray == nullptr)
263  initTrayIcon();
264  else if (!QtPassSettings::isUseTrayIcon() && tray != nullptr) {
265  destroyTrayIcon();
266  }
267  }
268 
269  m_qtPass->setFreshStart(false);
270  }
271 }
272 
276 void MainWindow::onUpdate(bool block) {
277  ui->statusBar->showMessage(tr("Updating password-store"), 2000);
278  if (block)
280  else
282 }
283 
288  if (QtPassSettings::isUseGit()) {
289  ui->statusBar->showMessage(tr("Updating password-store"), 2000);
291  }
292 }
293 
301 QString MainWindow::getFile(const QModelIndex &index, bool forPass) {
302  if (!index.isValid() ||
303  !model.fileInfo(proxyModel.mapToSource(index)).isFile())
304  return QString();
305  QString filePath = model.filePath(proxyModel.mapToSource(index));
306  if (forPass) {
307  filePath = QDir(QtPassSettings::getPassStore()).relativeFilePath(filePath);
308  filePath.replace(QRegExp("\\.gpg$"), "");
309  }
310  return filePath;
311 }
312 
317 void MainWindow::on_treeView_clicked(const QModelIndex &index) {
318  bool cleared = ui->treeView->currentIndex().flags() == Qt::NoItemFlags;
319  currentDir =
320  Util::getDir(ui->treeView->currentIndex(), false, model, proxyModel);
321  // TODO(bezet): "Could not decrypt";
322  m_qtPass->clearClippedText();
323  QString file = getFile(index, true);
324  ui->passwordName->setText(getFile(index, true));
325  if (!file.isEmpty() && !cleared) {
326  QtPassSettings::getPass()->Show(file);
327  } else {
328  clearPanel(false);
329  ui->actionEdit->setEnabled(false);
330  ui->actionDelete->setEnabled(true);
331  }
332 }
333 
339 void MainWindow::on_treeView_doubleClicked(const QModelIndex &index) {
340  QFileInfo fileOrFolder =
341  model.fileInfo(proxyModel.mapToSource(ui->treeView->currentIndex()));
342 
343  if (fileOrFolder.isFile()) {
344  editPassword(getFile(index, true));
345  }
346 }
347 
352  currentDir = "";
353  m_qtPass->clearClipboard();
354  ui->treeView->clearSelection();
355  ui->actionEdit->setEnabled(false);
356  ui->actionDelete->setEnabled(false);
357  ui->passwordName->setText("");
358  ui->actionDelete->setEnabled(false);
359  ui->actionEdit->setEnabled(false);
360  clearPanel(false);
361 }
362 
364  clearTemplateWidgets();
365  ui->textBrowser->clear();
366  setUiElementsEnabled(false);
367  clearPanelTimer.stop();
368 }
369 
370 void MainWindow::passShowHandler(const QString &p_output) {
371  QStringList templ = QtPassSettings::isUseTemplate()
372  ? QtPassSettings::getPassTemplate().split("\n")
373  : QStringList();
374  bool allFields =
376  FileContent fileContent = FileContent::parse(p_output, templ, allFields);
377  QString output = p_output;
378  QString password = fileContent.getPassword();
379 
380  // set clipped text
381  m_qtPass->setClippedText(password, p_output);
382 
383  // first clear the current view:
384  clearTemplateWidgets();
385 
386  // show what is needed:
388  output = "***" + tr("Content hidden") + "***";
389  } else {
390  if (!password.isEmpty()) {
391  // set the password, it is hidden if needed in addToGridLayout
392  addToGridLayout(0, tr("Password"), password);
393  }
394 
395  NamedValues namedValues = fileContent.getNamedValues();
396  for (int j = 0; j < namedValues.length(); ++j) {
397  NamedValue nv = namedValues.at(j);
398  addToGridLayout(j + 1, nv.name, nv.value);
399  }
400  if (ui->gridLayout->count() == 0)
401  ui->verticalLayoutPassword->setSpacing(0);
402  else
403  ui->verticalLayoutPassword->setSpacing(6);
404 
405  output = fileContent.getRemainingDataForDisplay();
406  }
407 
409  clearPanelTimer.start();
410  }
411 
412  emit passShowHandlerFinished(output);
413  setUiElementsEnabled(true);
414 }
415 
416 void MainWindow::passOtpHandler(const QString &p_output) {
417  if (!p_output.isEmpty()) {
418  addToGridLayout(ui->gridLayout->count() + 1, tr("OTP Code"), p_output);
419  m_qtPass->copyTextToClipboard(p_output);
420  }
422  clearPanelTimer.start();
423  }
424  setUiElementsEnabled(true);
425 }
426 
430 void MainWindow::clearPanel(bool notify) {
431  while (ui->gridLayout->count() > 0) {
432  QLayoutItem *item = ui->gridLayout->takeAt(0);
433  delete item->widget();
434  delete item;
435  }
436  if (notify) {
437  QString output = "***" + tr("Password and Content hidden") + "***";
438  ui->textBrowser->setHtml(output);
439  } else {
440  ui->textBrowser->setHtml("");
441  }
442 }
443 
450  ui->treeView->setEnabled(state);
451  ui->lineEdit->setEnabled(state);
452  ui->lineEdit->installEventFilter(this);
453  ui->actionAddPassword->setEnabled(state);
454  ui->actionAddFolder->setEnabled(state);
455  ui->actionUsers->setEnabled(state);
456  ui->actionConfig->setEnabled(state);
457  // is a file selected?
458  state &= ui->treeView->currentIndex().isValid();
459  ui->actionDelete->setEnabled(state);
460  ui->actionEdit->setEnabled(state);
461  updateGitButtonVisibility();
462  updateOtpButtonVisibility();
463 }
464 
466  QByteArray geometry = QtPassSettings::getGeometry(saveGeometry());
467  restoreGeometry(geometry);
468  QByteArray savestate = QtPassSettings::getSavestate(saveState());
469  restoreState(savestate);
470  QPoint position = QtPassSettings::getPos(pos());
471  move(position);
472  QSize newSize = QtPassSettings::getSize(size());
473  resize(newSize);
474  if (QtPassSettings::isMaximized(isMaximized())) {
475  showMaximized();
476  }
477 
479  Qt::WindowFlags flags = windowFlags();
480  setWindowFlags(flags | Qt::WindowStaysOnTopHint);
481  show();
482  }
483 
484  if (QtPassSettings::isUseTrayIcon() && tray == nullptr) {
485  initTrayIcon();
487  // since we are still in constructor, can't directly hide
488  QTimer::singleShot(10, this, SLOT(hide()));
489  }
490  } else if (!QtPassSettings::isUseTrayIcon() && tray != nullptr) {
491  destroyTrayIcon();
492  }
493 }
494 
498 void MainWindow::onConfig() { config(); }
499 
505 void MainWindow::on_lineEdit_textChanged(const QString &arg1) {
506  ui->statusBar->showMessage(tr("Looking for: %1").arg(arg1), 1000);
507  ui->treeView->expandAll();
508 
509  searchTimer.start();
510 }
511 
516 void MainWindow::onTimeoutSearch() {
517  QString query = ui->lineEdit->text();
518 
519  if (query.isEmpty()) {
520  ui->treeView->collapseAll();
521  deselect();
522  }
523 
524  query.replace(QRegExp(" "), ".*");
525  QRegExp regExp(query, Qt::CaseInsensitive);
526  proxyModel.setFilterRegExp(regExp);
527  ui->treeView->setRootIndex(proxyModel.mapFromSource(
528  model.setRootPath(QtPassSettings::getPassStore())));
529 
530  if (proxyModel.rowCount() > 0 && !query.isEmpty()) {
531  selectFirstFile();
532  } else {
533  ui->actionEdit->setEnabled(false);
534  ui->actionDelete->setEnabled(false);
535  }
536 }
537 
543 void MainWindow::on_lineEdit_returnPressed() {
544 #ifdef QT_DEBUG
545  dbg() << "on_lineEdit_returnPressed" << proxyModel.rowCount();
546 #endif
547 
548  if (proxyModel.rowCount() > 0) {
549  selectFirstFile();
550  on_treeView_clicked(ui->treeView->currentIndex());
551  }
552 }
553 
558 void MainWindow::selectFirstFile() {
559  QModelIndex index = proxyModel.mapFromSource(
560  model.setRootPath(QtPassSettings::getPassStore()));
561  index = firstFile(index);
562  ui->treeView->setCurrentIndex(index);
563 }
564 
570 QModelIndex MainWindow::firstFile(QModelIndex parentIndex) {
571  QModelIndex index = parentIndex;
572  int numRows = proxyModel.rowCount(parentIndex);
573  for (int row = 0; row < numRows; ++row) {
574  index = proxyModel.index(row, 0, parentIndex);
575  if (model.fileInfo(proxyModel.mapToSource(index)).isFile())
576  return index;
577  if (proxyModel.hasChildren(index))
578  return firstFile(index);
579  }
580  return index;
581 }
582 
588 void MainWindow::setPassword(QString file, bool isNew) {
589  PasswordDialog d(file, isNew, this);
590 
591  if (!d.exec()) {
592  ui->treeView->setFocus();
593  }
594 }
595 
600 void MainWindow::addPassword() {
601  bool ok;
602  QString dir =
603  Util::getDir(ui->treeView->currentIndex(), true, model, proxyModel);
604  QString file =
605  QInputDialog::getText(this, tr("New file"),
606  tr("New password file: \n(Will be placed in %1 )")
608  Util::getDir(ui->treeView->currentIndex(),
609  true, model, proxyModel)),
610  QLineEdit::Normal, "", &ok);
611  if (!ok || file.isEmpty())
612  return;
613  file = dir + file;
614  setPassword(file);
615 }
616 
621 void MainWindow::onDelete() {
622  QFileInfo fileOrFolder =
623  model.fileInfo(proxyModel.mapToSource(ui->treeView->currentIndex()));
624  QString file = "";
625  bool isDir = false;
626 
627  if (fileOrFolder.isFile()) {
628  file = getFile(ui->treeView->currentIndex(), true);
629  } else {
630  file = Util::getDir(ui->treeView->currentIndex(), true, model, proxyModel);
631  isDir = true;
632  }
633 
634  QString dirMessage = tr(" and the whole content?");
635  if (isDir) {
636  QDirIterator it(model.rootPath() + QDir::separator() + file,
637  QDirIterator::Subdirectories);
638  bool okDir = true;
639  while (it.hasNext() && okDir) {
640  it.next();
641  if (QFileInfo(it.filePath()).isFile()) {
642  if (QFileInfo(it.filePath()).suffix() != "gpg") {
643  okDir = false;
644  dirMessage = tr(" and the whole content? <br><strong>Attention: "
645  "there are unexpected files in the given folder, "
646  "check them before continue.</strong>");
647  }
648  }
649  }
650  }
651 
652  if (QMessageBox::question(
653  this, isDir ? tr("Delete folder?") : tr("Delete password?"),
654  tr("Are you sure you want to delete %1%2?")
655  .arg(QDir::separator() + file)
656  .arg(isDir ? dirMessage : "?"),
657  QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)
658  return;
659 
660  QtPassSettings::getPass()->Remove(file, isDir);
661 }
662 
666 void MainWindow::onOtp() {
667  QString file = getFile(ui->treeView->currentIndex(), true);
668  if (!file.isEmpty()) {
671  }
672 }
673 
677 void MainWindow::onEdit() {
678  QString file = getFile(ui->treeView->currentIndex(), true);
679  editPassword(file);
680 }
681 
686 void MainWindow::userDialog(QString dir) {
687  if (!dir.isEmpty())
688  currentDir = dir;
689  onUsers();
690 }
691 
697 void MainWindow::onUsers() {
698  QString dir =
699  currentDir.isEmpty()
700  ? Util::getDir(ui->treeView->currentIndex(), false, model, proxyModel)
701  : currentDir;
702 
703  UsersDialog d(dir, this);
704  if (!d.exec()) {
705  ui->treeView->setFocus();
706  }
707 }
708 
713 void MainWindow::messageAvailable(QString message) {
714  if (message.isEmpty()) {
715  focusInput();
716  } else {
717  ui->treeView->expandAll();
718  ui->lineEdit->setText(message);
719  on_lineEdit_returnPressed();
720  }
721  show();
722  raise();
723 }
724 
730 void MainWindow::generateKeyPair(QString batch, QDialog *keygenWindow) {
731  keygen = keygenWindow;
732  emit generateGPGKeyPair(batch);
733 }
734 
739 void MainWindow::updateProfileBox() {
740  QHash<QString, QString> profiles = QtPassSettings::getProfiles();
741 
742  if (profiles.isEmpty()) {
743  ui->profileWidget->hide();
744  } else {
745  ui->profileWidget->show();
746  ui->profileBox->setEnabled(profiles.size() > 1);
747  ui->profileBox->clear();
748  QHashIterator<QString, QString> i(profiles);
749  while (i.hasNext()) {
750  i.next();
751  if (!i.key().isEmpty())
752  ui->profileBox->addItem(i.key());
753  }
754  ui->profileBox->model()->sort(0);
755  }
756  int index = ui->profileBox->findText(QtPassSettings::getProfile());
757  if (index != -1) // -1 for not found
758  ui->profileBox->setCurrentIndex(index);
759 }
760 
766 void MainWindow::on_profileBox_currentIndexChanged(QString name) {
767  if (m_qtPass->isFreshStart() || name == QtPassSettings::getProfile())
768  return;
770 
772  ui->statusBar->showMessage(tr("Profile changed to %1").arg(name), 2000);
773 
775 
776  ui->treeView->selectionModel()->clear();
777  ui->treeView->setRootIndex(proxyModel.mapFromSource(
778  model.setRootPath(QtPassSettings::getPassStore())));
779 
780  ui->actionEdit->setEnabled(false);
781  ui->actionDelete->setEnabled(false);
782 }
783 
789 void MainWindow::initTrayIcon() {
790  this->tray = new TrayIcon(this);
791  // Setup tray icon
792 
793  if (tray == nullptr) {
794 #ifdef QT_DEBUG
795  dbg() << "Allocating tray icon failed.";
796 #endif
797  }
798 
799  if (!tray->getIsAllocated()) {
800  destroyTrayIcon();
801  }
802 }
803 
807 void MainWindow::destroyTrayIcon() {
808  delete this->tray;
809  tray = nullptr;
810 }
811 
816 void MainWindow::closeEvent(QCloseEvent *event) {
818  this->hide();
819  event->ignore();
820  } else {
821  m_qtPass->clearClipboard();
822 
823  QtPassSettings::setGeometry(saveGeometry());
824  QtPassSettings::setSavestate(saveState());
825  QtPassSettings::setMaximized(isMaximized());
826  if (!isMaximized()) {
827  QtPassSettings::setPos(pos());
828  QtPassSettings::setSize(size());
829  }
830  event->accept();
831  }
832 }
833 
841 bool MainWindow::eventFilter(QObject *obj, QEvent *event) {
842  if (obj == ui->lineEdit && event->type() == QEvent::KeyPress) {
843  auto *key = dynamic_cast<QKeyEvent *>(event);
844  if (key != NULL && key->key() == Qt::Key_Down) {
845  ui->treeView->setFocus();
846  }
847  }
848  return QObject::eventFilter(obj, event);
849 }
850 
855 void MainWindow::keyPressEvent(QKeyEvent *event) {
856  switch (event->key()) {
857  case Qt::Key_Delete:
858  onDelete();
859  break;
860  case Qt::Key_Return:
861  case Qt::Key_Enter:
862  if (proxyModel.rowCount() > 0)
863  on_treeView_clicked(ui->treeView->currentIndex());
864  break;
865  case Qt::Key_Escape:
866  ui->lineEdit->clear();
867  break;
868  default:
869  break;
870  }
871 }
872 
878 void MainWindow::showContextMenu(const QPoint &pos) {
879  QModelIndex index = ui->treeView->indexAt(pos);
880  bool selected = true;
881  if (!index.isValid()) {
882  ui->treeView->clearSelection();
883  ui->actionDelete->setEnabled(false);
884  ui->actionEdit->setEnabled(false);
885  currentDir = "";
886  selected = false;
887  }
888 
889  ui->treeView->setCurrentIndex(index);
890 
891  QPoint globalPos = ui->treeView->viewport()->mapToGlobal(pos);
892 
893  QFileInfo fileOrFolder =
894  model.fileInfo(proxyModel.mapToSource(ui->treeView->currentIndex()));
895 
896  QMenu contextMenu;
897  if (!selected || fileOrFolder.isDir()) {
898  QAction *openFolder =
899  contextMenu.addAction(tr("Open folder with file manager"));
900  QAction *addFolder = contextMenu.addAction(tr("Add folder"));
901  QAction *addPassword = contextMenu.addAction(tr("Add password"));
902  QAction *users = contextMenu.addAction(tr("Users"));
903  connect(openFolder, &QAction::triggered, this, &MainWindow::openFolder);
904  connect(addFolder, &QAction::triggered, this, &MainWindow::addFolder);
905  connect(addPassword, &QAction::triggered, this, &MainWindow::addPassword);
906  connect(users, &QAction::triggered, this, &MainWindow::onUsers);
907  } else if (fileOrFolder.isFile()) {
908  QAction *edit = contextMenu.addAction(tr("Edit"));
909  connect(edit, &QAction::triggered, this, &MainWindow::onEdit);
910  }
911  if (selected) {
912  // if (useClipboard != CLIPBOARD_NEVER) {
913  // contextMenu.addSeparator();
914  // QAction* copyItem = contextMenu.addAction(tr("Copy Password"));
915  // if (getClippedPassword().length() == 0) copyItem->setEnabled(false);
916  // connect(copyItem, SIGNAL(triggered()), this,
917  // SLOT(copyPasswordToClipboard()));
918  // }
919  contextMenu.addSeparator();
920  if (fileOrFolder.isDir()) {
921  QAction *renameFolder = contextMenu.addAction(tr("Rename folder"));
922  connect(renameFolder, &QAction::triggered, this,
923  &MainWindow::renameFolder);
924  } else if (fileOrFolder.isFile()) {
925  QAction *renamePassword = contextMenu.addAction(tr("Rename password"));
926  connect(renamePassword, &QAction::triggered, this,
927  &MainWindow::renamePassword);
928  }
929  QAction *deleteItem = contextMenu.addAction(tr("Delete"));
930  connect(deleteItem, &QAction::triggered, this, &MainWindow::onDelete);
931  }
932  contextMenu.exec(globalPos);
933 }
934 
940 void MainWindow::showBrowserContextMenu(const QPoint &pos) {
941  QMenu *contextMenu = ui->textBrowser->createStandardContextMenu(pos);
942  QPoint globalPos = ui->textBrowser->viewport()->mapToGlobal(pos);
943 
944  contextMenu->exec(globalPos);
945 }
946 
950 void MainWindow::openFolder() {
951  QString dir =
952  Util::getDir(ui->treeView->currentIndex(), false, model, proxyModel);
953 
954  QString path = QDir::toNativeSeparators(dir);
955  QDesktopServices::openUrl(QUrl::fromLocalFile(path));
956 }
957 
961 void MainWindow::addFolder() {
962  bool ok;
963  QString dir =
964  Util::getDir(ui->treeView->currentIndex(), false, model, proxyModel);
965  QString newdir =
966  QInputDialog::getText(this, tr("New file"),
967  tr("New Folder: \n(Will be placed in %1 )")
969  Util::getDir(ui->treeView->currentIndex(),
970  true, model, proxyModel)),
971  QLineEdit::Normal, "", &ok);
972  if (!ok || newdir.isEmpty())
973  return;
974  newdir.prepend(dir);
975  // dbg()<< newdir;
976  QDir().mkdir(newdir);
977 }
978 
982 void MainWindow::renameFolder() {
983  bool ok;
984  QString srcDir = QDir::cleanPath(
985  Util::getDir(ui->treeView->currentIndex(), false, model, proxyModel));
986  QString srcDirName = QDir(srcDir).dirName();
987  QString newName =
988  QInputDialog::getText(this, tr("Rename file"), tr("Rename Folder To: "),
989  QLineEdit::Normal, srcDirName, &ok);
990  if (!ok || newName.isEmpty())
991  return;
992  QString destDir = srcDir;
993  destDir.replace(srcDir.lastIndexOf(srcDirName), srcDirName.length(), newName);
994  QtPassSettings::getPass()->Move(srcDir, destDir);
995 }
996 
1001 void MainWindow::editPassword(const QString &file) {
1002  if (!file.isEmpty()) {
1004  onUpdate(true);
1005  setPassword(file, false);
1006  }
1007 }
1008 
1012 void MainWindow::renamePassword() {
1013  bool ok;
1014  QString file = getFile(ui->treeView->currentIndex(), false);
1015  QString fileName = QFileInfo(file).baseName();
1016  QString newName =
1017  QInputDialog::getText(this, tr("Rename file"), tr("Rename File To: "),
1018  QLineEdit::Normal, fileName, &ok);
1019  if (!ok || newName.isEmpty())
1020  return;
1021  QString newFile = file;
1022  newFile.replace(file.lastIndexOf(fileName), fileName.length(), newName);
1023  newFile.replace(QRegExp("\\.gpg$"), "");
1024  QtPassSettings::getPass()->Move(file, newFile);
1025 }
1026 
1031 void MainWindow::clearTemplateWidgets() {
1032  while (ui->gridLayout->count() > 0) {
1033  QLayoutItem *item = ui->gridLayout->takeAt(0);
1034  delete item->widget();
1035  delete item;
1036  }
1037  ui->verticalLayoutPassword->setSpacing(0);
1038 }
1039 
1040 void MainWindow::copyPasswordFromTreeview() {
1041  QFileInfo fileOrFolder =
1042  model.fileInfo(proxyModel.mapToSource(ui->treeView->currentIndex()));
1043 
1044  if (fileOrFolder.isFile()) {
1045  QString file = getFile(ui->treeView->currentIndex(), true);
1046  connect(QtPassSettings::getPass(), &Pass::finishedShow, this,
1047  &MainWindow::passwordFromFileToClipboard);
1048  QtPassSettings::getPass()->Show(file);
1049  }
1050 }
1051 
1052 void MainWindow::passwordFromFileToClipboard(const QString &text) {
1053  QStringList tokens = text.split('\n');
1054  m_qtPass->copyTextToClipboard(tokens[0]);
1055 }
1056 
1063 void MainWindow::addToGridLayout(int position, const QString &field,
1064  const QString &value) {
1065  QString trimmedField = field.trimmed();
1066  QString trimmedValue = value.trimmed();
1067 
1068  // Combine the Copy button and the line edit in one widget
1069  QFrame *frame = new QFrame();
1070  QLayout *ly = new QHBoxLayout();
1071  ly->setContentsMargins(5, 2, 2, 2);
1072  frame->setLayout(ly);
1074  auto *fieldLabel = new QPushButtonWithClipboard(trimmedValue, this);
1075  connect(fieldLabel, &QPushButtonWithClipboard::clicked, m_qtPass,
1077 
1078  fieldLabel->setStyleSheet("border-style: none ; background: transparent;");
1079  // fieldLabel->setContentsMargins(0,5,5,0);
1080  frame->layout()->addWidget(fieldLabel);
1081  }
1082 
1084  QPushButtonAsQRCode *qrbutton = new QPushButtonAsQRCode(trimmedValue, this);
1085  connect(qrbutton, &QPushButtonAsQRCode::clicked, m_qtPass,
1087  qrbutton->setStyleSheet("border-style: none ; background: transparent;");
1088 
1089  frame->layout()->addWidget(qrbutton);
1090  }
1091 
1092  // set the echo mode to password, if the field is "password"
1093  if (QtPassSettings::isHidePassword() && trimmedField == tr("Password")) {
1094  auto *line = new QLineEdit();
1095  line->setObjectName(trimmedField);
1096  line->setText(trimmedValue);
1097  line->setReadOnly(true);
1098  line->setStyleSheet("border-style: none ; background: transparent;");
1099  line->setContentsMargins(0, 0, 0, 0);
1100  line->setEchoMode(QLineEdit::Password);
1101  frame->layout()->addWidget(line);
1102  } else {
1103  auto *line = new QTextBrowser();
1104  line->setOpenExternalLinks(true);
1105  line->setOpenLinks(true);
1106  line->setMaximumHeight(26);
1107  line->setMinimumHeight(26);
1108  line->setSizePolicy(
1109  QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum));
1110  line->setObjectName(trimmedField);
1111  trimmedValue.replace(
1112  QRegExp("((?:https?|ftp|ssh|sftp|ftps|webdav|webdavs)://\\S+)"),
1113  R"(<a href="\1">\1</a>)");
1114  line->setText(trimmedValue);
1115  line->setReadOnly(true);
1116  line->setStyleSheet("border-style: none ; background: transparent;");
1117  line->setContentsMargins(0, 0, 0, 0);
1118  frame->layout()->addWidget(line);
1119  }
1120 
1121  frame->setStyleSheet(
1122  ".QFrame{border: 1px solid lightgrey; border-radius: 5px;}");
1123 
1124  // set into the layout
1125  ui->gridLayout->addWidget(new QLabel(trimmedField), position, 0);
1126  ui->gridLayout->addWidget(frame, position, 1);
1127 }
1128 
1135 void MainWindow::showStatusMessage(QString msg, int timeout) {
1136  ui->statusBar->showMessage(msg, timeout);
1137 }
1138 
1143  setUiElementsEnabled(false);
1144  ui->treeView->setDisabled(true);
1145 }
1146 
1151 
1152 void MainWindow::updateGitButtonVisibility() {
1153  if (!QtPassSettings::isUseGit() ||
1154  (QtPassSettings::getGitExecutable().isEmpty() &&
1155  QtPassSettings::getPassExecutable().isEmpty())) {
1156  enableGitButtons(false);
1157  } else {
1158  enableGitButtons(true);
1159  }
1160 }
1161 
1162 void MainWindow::updateOtpButtonVisibility() {
1163 #if defined(Q_OS_WIN) || defined(__APPLE__)
1164  ui->actionOtp->setVisible(false);
1165 #endif
1166  if (!QtPassSettings::isUseOtp())
1167  ui->actionOtp->setEnabled(false);
1168  else
1169  ui->actionOtp->setEnabled(true);
1170 }
1171 
1172 void MainWindow::enableGitButtons(const bool &state) {
1173  // Following GNOME guidelines is preferable disable buttons instead of hide
1174  ui->actionPush->setEnabled(state);
1175  ui->actionUpdate->setEnabled(state);
1176 }
1177 
1183 void MainWindow::critical(QString title, QString msg) {
1184  QMessageBox::critical(this, title, msg);
1185 }
QtPassSettings::getGitExecutable
static QString getGitExecutable(const QString &defaultValue=QVariant().toString())
Definition: qtpasssettings.cpp:305
QPushButtonWithClipboard
Stylish widget to allow copying of password and account details.
Definition: qpushbuttonwithclipboard.h:11
UsersDialog
Handles listing and editing of GPG users.
Definition: usersdialog.h:23
Pass::Move
virtual void Move(const QString srcDir, const QString dest, const bool force=false)=0
MainWindow::eventFilter
bool eventFilter(QObject *obj, QEvent *event)
MainWindow::eventFilter filter out some events and focus the treeview.
Definition: mainwindow.cpp:841
QtPassSettings::setUsePass
static void setUsePass(const bool &usePass)
Definition: qtpasssettings.cpp:154
QtPassSettings::getSize
static QSize getSize(const QSize &defaultValue=QVariant().toSize())
Definition: qtpasssettings.cpp:133
QPushButtonAsQRCode
Stylish widget to display the field as QR Code.
Definition: qpushbuttonasqrcode.h:11
NamedValue::value
QString value
Definition: filecontent.h:10
MainWindow::getCurrentTreeViewIndex
const QModelIndex getCurrentTreeViewIndex()
Definition: mainwindow.cpp:199
keygendialog.h
MainWindow::userDialog
void userDialog(QString="")
MainWindow::userDialog see MainWindow::onUsers()
Definition: mainwindow.cpp:686
QtPassSettings::isHideOnClose
static bool isHideOnClose(const bool &defaultValue=QVariant().toBool())
Definition: qtpasssettings.cpp:484
MainWindow::passShowHandler
void passShowHandler(const QString &)
Definition: mainwindow.cpp:370
QtPassSettings::getPos
static QPoint getPos(const QPoint &defaultValue=QVariant().toPoint())
Definition: qtpasssettings.cpp:126
QtPassSettings::getPassTemplate
static QString getPassTemplate(const QString &defaultValue=QVariant().toString())
Definition: qtpasssettings.cpp:529
QtPassSettings::isUseTrayIcon
static bool isUseTrayIcon(const bool &defaultValue=QVariant().toBool())
Definition: qtpasssettings.cpp:475
QtPass::isFreshStart
bool isFreshStart()
Definition: qtpass.h:21
QtPassSettings::getPassExecutable
static QString getPassExecutable(const QString &defaultValue=QVariant().toString())
Definition: qtpasssettings.cpp:296
MainWindow::deselect
void deselect()
MainWindow::deselect clear the selection, password and copy buffer.
Definition: mainwindow.cpp:351
MainWindow::MainWindow
MainWindow(const QString &searchText=QString(), QWidget *parent=nullptr)
MainWindow::MainWindow handles all of the main functionality and also the main window.
Definition: mainwindow.cpp:37
QtPass
Definition: qtpass.h:10
QtPass::clearClipboard
void clearClipboard()
MainWindow::clearClipboard remove clipboard contents.
Definition: qtpass.cpp:369
MainWindow::restoreWindow
void restoreWindow()
Definition: mainwindow.cpp:465
FileContent::getNamedValues
NamedValues getNamedValues() const
Definition: filecontent.cpp:38
QtPassSettings::isMaximized
static bool isMaximized(const bool &defaultValue=QVariant().toBool())
Definition: qtpasssettings.cpp:140
QtPass::clearClippedText
void clearClippedText()
Definition: qtpass.cpp:360
MainWindow::on_treeView_clicked
void on_treeView_clicked(const QModelIndex &index)
MainWindow::on_treeView_clicked read the selected password file.
Definition: mainwindow.cpp:317
MainWindow::critical
void critical(QString, QString)
MainWindow::critical critical message popup wrapper.
Definition: mainwindow.cpp:1183
NamedValues
The NamedValues class is mostly a list of NamedValue but also has a method to take a specific NamedVa...
Definition: filecontent.h:17
debughelper.h
QtPass::showTextAsQRCode
void showTextAsQRCode(const QString &text)
displays the text as qrcode
Definition: qtpass.cpp:412
Pass::Show
virtual void Show(QString file)=0
filecontent.h
MainWindow::generateGPGKeyPair
void generateGPGKeyPair(QString batch)
QtPassSettings::isUseAutoclearPanel
static bool isUseAutoclearPanel(const bool &defaultValue=QVariant().toBool())
Definition: qtpasssettings.cpp:206
QtPass::setClipboardTimer
void setClipboardTimer()
Definition: qtpass.cpp:362
QtPassSettings::setSavestate
static void setSavestate(const QByteArray &saveState)
Definition: qtpasssettings.cpp:122
TrayIcon
Handles the systemtray icon and menu.
Definition: trayicon.h:14
settingsconstants.h
QtPassSettings::isTemplateAllFields
static bool isTemplateAllFields(const bool &defaultValue=QVariant().toBool())
Definition: qtpasssettings.cpp:547
MainWindow::config
void config()
MainWindow::config pops up the configuration screen and handles all inter-window communication.
Definition: mainwindow.cpp:228
MainWindow::setUiElementsEnabled
void setUiElementsEnabled(bool state)
MainWindow::setUiElementsEnabled enable or disable the relevant UI elements.
Definition: mainwindow.cpp:449
TrayIcon::getIsAllocated
bool getIsAllocated()
TrayIcon::getIsAllocated return if TrayIcon is allocated.
Definition: trayicon.cpp:57
QtPassSettings::setMaximized
static void setMaximized(const bool &maximized)
Definition: qtpasssettings.cpp:145
FileContent
Definition: filecontent.h:25
MainWindow::messageAvailable
void messageAvailable(QString message)
MainWindow::messageAvailable we have some text/message/search to do.
Definition: mainwindow.cpp:713
NamedValue::name
QString name
Definition: filecontent.h:9
MainWindow::startReencryptPath
void startReencryptPath()
MainWindow::startReencryptPath disable ui elements and treeview.
Definition: mainwindow.cpp:1142
qpushbuttonwithclipboard.h
ConfigDialog
The ConfigDialog handles the configuration interface.
Definition: configdialog.h:24
QtPassSettings::getPass
static Pass * getPass()
Definition: qtpasssettings.cpp:87
QtPassSettings::isStartMinimized
static bool isStartMinimized(const bool &defaultValue=QVariant().toBool())
Definition: qtpasssettings.cpp:493
QtPassSettings::isHideContent
static bool isHideContent(const bool &defaultValue=QVariant().toBool())
Definition: qtpasssettings.cpp:236
Pass::Remove
virtual void Remove(QString file, bool isDir)=0
MainWindow::closeEvent
void closeEvent(QCloseEvent *event)
MainWindow::closeEvent hide or quit.
Definition: mainwindow.cpp:816
trayicon.h
QPushButtonAsQRCode::clicked
void clicked(QString)
QtPassSettings::getProfile
static QString getProfile(const QString &defaultValue=QVariant().toString())
Definition: qtpasssettings.cpp:374
qpushbuttonasqrcode.h
QtPassSettings::isUseTemplate
static bool isUseTemplate(const bool &defaultValue=QVariant().toBool())
Definition: qtpasssettings.cpp:538
MainWindow::passShowHandlerFinished
void passShowHandlerFinished(QString output)
MainWindow::passOtpHandler
void passOtpHandler(const QString &)
Definition: mainwindow.cpp:416
QtPass::init
bool init()
QtPass::init make sure we are ready to go as soon as possible.
Definition: qtpass.cpp:60
MainWindow::onPush
void onPush()
MainWindow::onPush do a git push.
Definition: mainwindow.cpp:287
Pass::GitPush
virtual void GitPush()=0
Pass::updateEnv
void updateEnv()
Pass::updateEnv update the execution environment (used when switching profiles)
Definition: pass.cpp:238
MainWindow::showStatusMessage
void showStatusMessage(QString msg, int timeout=2000)
Displays message in status bar.
Definition: mainwindow.cpp:1135
MainWindow::generateKeyPair
void generateKeyPair(QString, QDialog *)
MainWindow::generateKeyPair internal gpg keypair generator . .
Definition: mainwindow.cpp:730
MainWindow::flashText
void flashText(const QString &text, const bool isError, const bool isHtml=false)
Definition: mainwindow.cpp:208
QtPassSettings::getGeometry
static QByteArray getGeometry(const QByteArray &defaultValue=QVariant().toByteArray())
Definition: qtpasssettings.cpp:108
Pass::GitPull
virtual void GitPull()=0
StoreModel::setModelAndStore
void setModelAndStore(QFileSystemModel *sourceModel, QString passStore)
StoreModel::setModelAndStore update the source model and store.
Definition: storemodel.cpp:81
QtPassSettings::isUseGit
static bool isUseGit(const bool &defaultValue=QVariant().toBool())
Definition: qtpasssettings.cpp:383
usersdialog.h
QPushButtonWithClipboard::clicked
void clicked(QString)
QtPassSettings::isAutoPull
static bool isAutoPull(const bool &defaultValue=QVariant().toBool())
Definition: qtpasssettings.cpp:511
QtPass::copyTextToClipboard
void copyTextToClipboard(const QString &text)
MainWindow::copyTextToClipboard copies text to your clipboard.
Definition: qtpass.cpp:393
QtPassSettings::isUseQrencode
static bool isUseQrencode(const bool &defaultValue=QVariant().toBool())
Definition: qtpasssettings.cpp:398
QtPassSettings::setGeometry
static void setGeometry(const QByteArray &geometry)
Definition: qtpasssettings.cpp:113
QtPassSettings::getClipBoardType
static Enums::clipBoardType getClipBoardType(const Enums::clipBoardType &defaultvalue=Enums::CLIPBOARD_NEVER)
Definition: qtpasssettings.cpp:171
MainWindow::cleanKeygenDialog
void cleanKeygenDialog()
Definition: mainwindow.cpp:203
QtPassSettings::setPos
static void setPos(const QPoint &pos)
Definition: qtpasssettings.cpp:129
QtPassSettings::setSize
static void setSize(const QSize &size)
Definition: qtpasssettings.cpp:136
Pass::GitPull_b
virtual void GitPull_b()=0
QtPassSettings::getAutoclearPanelSeconds
static int getAutoclearPanelSeconds(const int &defaultValue=QVariant().toInt())
Definition: qtpasssettings.cpp:216
Ui
Definition: configdialog.h:9
FileContent::getRemainingDataForDisplay
QString getRemainingDataForDisplay() const
Definition: filecontent.cpp:42
PasswordDialog
PasswordDialog Handles the inserting and editing of passwords.
Definition: passworddialog.h:20
Util::checkConfig
static bool checkConfig()
Util::checkConfig do we have prequisite settings?
Definition: util.cpp:142
configdialog.h
QtPass::setClippedText
void setClippedText(const QString &, const QString &p_output=QString())
Definition: qtpass.cpp:352
QtPassSettings::setPassStore
static void setPassStore(const QString &passStore)
Definition: qtpasssettings.cpp:275
MainWindow::executeWrapperStarted
void executeWrapperStarted()
Definition: mainwindow.cpp:363
QtPass::setFreshStart
void setFreshStart(const bool &fs)
Definition: qtpass.h:22
passworddialog.h
DeselectableTreeView::emptyClicked
void emptyClicked()
emptyClicked event
QtPassSettings::getSavestate
static QByteArray getSavestate(const QByteArray &defaultValue=QVariant().toByteArray())
Definition: qtpasssettings.cpp:117
QtPassSettings::setProfile
static void setProfile(const QString &profile)
Definition: qtpasssettings.cpp:379
Enums::CLIPBOARD_NEVER
@ CLIPBOARD_NEVER
Definition: enums.h:11
NamedValue
Definition: filecontent.h:8
QtPassSettings::getProfiles
static QHash< QString, QString > getProfiles()
Definition: qtpasssettings.cpp:61
qtpass.h
dbg
#define dbg()
Definition: debughelper.h:7
FileContent::getPassword
QString getPassword() const
Definition: filecontent.cpp:36
Util::findPasswordStore
static QString findPasswordStore()
Util::findPasswordStore look for common .password-store folder location.
Definition: util.cpp:56
MainWindow::keyPressEvent
void keyPressEvent(QKeyEvent *event)
MainWindow::keyPressEvent did anyone press return, enter or escape?
Definition: mainwindow.cpp:855
Util::getDir
static QString getDir(const QModelIndex &index, bool forPass, const QFileSystemModel &model, const StoreModel &storeModel)
Util::getDir get selectd folder path.
Definition: util.cpp:160
FileContent::parse
static FileContent parse(const QString &fileContent, const QStringList &templateFields, bool allFields)
parse parses the given fileContent in a FileContent object. The password is accessible through getPas...
Definition: filecontent.cpp:7
Pass::OtpGenerate
virtual void OtpGenerate(QString file)=0
MainWindow::changeEvent
void changeEvent(QEvent *event)
MainWindow::changeEvent sets focus to the search box.
Definition: mainwindow.cpp:143
QtPassSettings::isUseOtp
static bool isUseOtp(const bool &defaultValue=QVariant().toBool())
Definition: qtpasssettings.cpp:390
MainWindow
The MainWindow class does way too much, not only is it a switchboard, configuration handler and more,...
Definition: mainwindow.h:39
MainWindow::endReencryptPath
void endReencryptPath()
MainWindow::endReencryptPath re-enable ui elements.
Definition: mainwindow.cpp:1150
QtPassSettings::getPassStore
static QString getPassStore(const QString &defaultValue=QVariant().toString())
Definition: qtpasssettings.cpp:254
Pass::finishedShow
void finishedShow(const QString &)
util.h
QtPassSettings::isHidePassword
static bool isHidePassword(const bool &defaultValue=QVariant().toBool())
Definition: qtpasssettings.cpp:227
mainwindow.h
QtPassSettings::isAlwaysOnTop
static bool isAlwaysOnTop(const bool &defaultValue=QVariant().toBool())
Definition: qtpasssettings.cpp:502
MainWindow::~MainWindow
~MainWindow()
Definition: mainwindow.cpp:126
qtpasssettings.h