QtPass  1.2.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 #include "debughelper.h"
3 #include <QClipboard>
4 #include <QCloseEvent>
5 #include <QDesktopServices>
6 #include <QFileInfo>
7 #include <QInputDialog>
8 #include <QLabel>
9 #include <QMenu>
10 #include <QMessageBox>
11 #include <QQueue>
12 #include <QShortcut>
13 #include <QTextCodec>
14 #ifdef Q_OS_WIN
15 #define WIN32_LEAN_AND_MEAN /*_KILLING_MACHINE*/
16 #define WIN32_EXTRA_LEAN
17 #include <windows.h>
18 #include <winnetwk.h>
19 #undef DELETE
20 #endif
21 #include "configdialog.h"
22 #include "filecontent.h"
23 #include "keygendialog.h"
24 #include "passworddialog.h"
26 #include "qtpasssettings.h"
27 #include "settingsconstants.h"
28 #include "trayicon.h"
29 #include "ui_mainwindow.h"
30 #include "usersdialog.h"
31 #include "util.h"
32 
39 MainWindow::MainWindow(const QString &searchText, QWidget *parent)
40  : QMainWindow(parent), ui(new Ui::MainWindow), fusedav(this),
41  clippedText(QString()), freshStart(true), keygen(NULL),
42  startupPhase(true), tray(NULL) {
43 #ifdef __APPLE__
44  // extra treatment for mac os
45  // see http://doc.qt.io/qt-5/qkeysequence.html#qt_set_sequence_auto_mnemonic
46  qt_set_sequence_auto_mnemonic(true);
47 #endif
48  ui->setupUi(this);
49 
50  // i think this should be moved out of MainWindow (in main.cpp as example)
51  if (!checkConfig()) {
52  // no working config so this should quit without config anything
53  QApplication::quit();
54  }
55 
56  // register shortcut ctrl/cmd + Q to close the main window
57  new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q), this, SLOT(close()));
58  // register shortcut ctrl/cmd + C to copy the currently selected password
59  new QShortcut(QKeySequence(QKeySequence::StandardKey::Copy), this,
60  SLOT(copyPasswordFromTreeview()));
61 
62  // TODO(bezet): this should be reconnected dynamically when pass changes
63  connectPassSignalHandlers(QtPassSettings::getRealPass());
64  connectPassSignalHandlers(QtPassSettings::getImitatePass());
65 
66  // only for ipass
67  connect(QtPassSettings::getImitatePass(), SIGNAL(startReencryptPath()), this,
68  SLOT(startReencryptPath()));
69  connect(QtPassSettings::getImitatePass(), SIGNAL(endReencryptPath()), this,
70  SLOT(endReencryptPath()));
71 
72  clearPanelTimer.setSingleShot(true);
73  connect(&clearPanelTimer, SIGNAL(timeout()), this, SLOT(clearPanel()));
74  clearClipboardTimer.setSingleShot(true);
75  connect(&clearClipboardTimer, SIGNAL(timeout()), this,
76  SLOT(clearClipboard()));
77 
78  initToolBarButtons();
79  initStatusBar();
80 
81 #if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
82  ui->lineEdit->setClearButtonEnabled(true);
83 #endif
84 
85  enableUiElements(true);
86 
87  qsrand(static_cast<uint>(QTime::currentTime().msec()));
88 
89  QTimer::singleShot(10, this, SLOT(focusInput()));
90 
91  ui->lineEdit->setText(searchText);
92 }
93 
97 void MainWindow::initToolBarButtons() {
98  connect(ui->actionAddPassword, SIGNAL(triggered()), this,
99  SLOT(addPassword()));
100  connect(ui->actionAddFolder, SIGNAL(triggered()), this, SLOT(addFolder()));
101  connect(ui->actionEdit, SIGNAL(triggered()), this, SLOT(onEdit()));
102  connect(ui->actionDelete, SIGNAL(triggered()), this, SLOT(onDelete()));
103  connect(ui->actionPush, SIGNAL(triggered()), this, SLOT(onPush()));
104  connect(ui->actionUpdate, SIGNAL(triggered()), this, SLOT(onUpdate()));
105  connect(ui->actionUsers, SIGNAL(triggered()), this, SLOT(onUsers()));
106  connect(ui->actionConfig, SIGNAL(triggered()), this, SLOT(onConfig()));
107  connect(ui->actionOtp, SIGNAL(triggered()), this, SLOT(onOtp()));
108 
109  ui->actionAddPassword->setIcon(
110  QIcon::fromTheme("document-new", QIcon(":/icons/document-new.svg")));
111  ui->actionAddFolder->setIcon(
112  QIcon::fromTheme("folder-new", QIcon(":/icons/folder-new.svg")));
113  ui->actionEdit->setIcon(QIcon::fromTheme(
114  "document-properties", QIcon(":/icons/document-properties.svg")));
115  ui->actionDelete->setIcon(
116  QIcon::fromTheme("edit-delete", QIcon(":/icons/edit-delete.svg")));
117  ui->actionPush->setIcon(
118  QIcon::fromTheme("go-up", QIcon(":/icons/go-top.svg")));
119  ui->actionUpdate->setIcon(
120  QIcon::fromTheme("go-down", QIcon(":/icons/go-bottom.svg")));
121  ui->actionUsers->setIcon(QIcon::fromTheme(
122  "x-office-address-book", QIcon(":/icons/x-office-address-book.svg")));
123  ui->actionConfig->setIcon(QIcon::fromTheme(
124  "applications-system", QIcon(":/icons/applications-system.svg")));
125 }
126 
130 void MainWindow::initStatusBar() {
131  ui->statusBar->showMessage(tr("Welcome to QtPass %1").arg(VERSION), 2000);
132 
133  QPixmap logo = QPixmap::fromImage(QImage(":/artwork/icon.svg"))
134  .scaledToHeight(statusBar()->height());
135  QLabel *logoApp = new QLabel(statusBar());
136  logoApp->setPixmap(logo);
137  statusBar()->addPermanentWidget(logoApp);
138 }
139 
146 void MainWindow::focusInput() {
147  ui->lineEdit->selectAll();
148  ui->lineEdit->setFocus();
149 }
150 
155 #ifdef Q_OS_WIN
157  WNetCancelConnection2A(QtPassSettings::getPassStore().toUtf8().constData(),
158  0, 1);
159 #else
160  if (fusedav.state() == QProcess::Running) {
161  fusedav.terminate();
162  fusedav.waitForFinished(2000);
163  }
164 #endif
165 }
166 
171 void MainWindow::changeEvent(QEvent *event) {
172  QWidget::changeEvent(event);
173  if (event->type() == QEvent::ActivationChange) {
174  if (this->isActiveWindow()) {
175  focusInput();
176  }
177  }
178 }
179 
187 void MainWindow::connectPassSignalHandlers(Pass *pass) {
188  // TODO(bezet): this is never emitted(should be), also naming(see
189  // critical())
190  connect(pass, &Pass::error, this, &MainWindow::processError);
191  connect(pass, &Pass::startingExecuteWrapper, this,
192  &MainWindow::executeWrapperStarted);
193  connect(pass, &Pass::critical, this, &MainWindow::critical);
194  connect(pass, &Pass::statusMsg, this, &MainWindow::showStatusMessage);
195  connect(pass, &Pass::processErrorExit, this, &MainWindow::processErrorExit);
196 
197  connect(pass, &Pass::finishedGitInit, this, &MainWindow::passStoreChanged);
198  connect(pass, &Pass::finishedGitPull, this, &MainWindow::processFinished);
199  connect(pass, &Pass::finishedGitPush, this, &MainWindow::processFinished);
200  connect(pass, &Pass::finishedShow, this, &MainWindow::passShowHandler);
201  connect(pass, &Pass::finishedOtpGenerate, this, &MainWindow::passOtpHandler);
202  connect(pass, &Pass::finishedInsert, this, &MainWindow::finishedInsert);
203  connect(pass, &Pass::finishedRemove, this, &MainWindow::passStoreChanged);
204  connect(pass, &Pass::finishedInit, this, &MainWindow::passStoreChanged);
205  connect(pass, &Pass::finishedMove, this, &MainWindow::passStoreChanged);
206  connect(pass, &Pass::finishedCopy, this, &MainWindow::passStoreChanged);
207 
208  connect(pass, &Pass::finishedGenerateGPGKeys, this,
209  &MainWindow::keyGenerationComplete);
210 }
211 
215 void MainWindow::mountWebDav() {
216 #ifdef Q_OS_WIN
217  char dst[20] = {0};
218  NETRESOURCEA netres;
219  memset(&netres, 0, sizeof(netres));
220  netres.dwType = RESOURCETYPE_DISK;
221  netres.lpLocalName = 0;
222  netres.lpRemoteName = QtPassSettings::getWebDavUrl().toUtf8().data();
223  DWORD size = sizeof(dst);
224  DWORD r = WNetUseConnectionA(
225  reinterpret_cast<HWND>(effectiveWinId()), &netres,
226  QtPassSettings::getWebDavPassword().toUtf8().constData(),
227  QtPassSettings::getWebDavUser().toUtf8().constData(),
228  CONNECT_TEMPORARY | CONNECT_INTERACTIVE | CONNECT_REDIRECT, dst, &size,
229  0);
230  if (r == NO_ERROR) {
232  } else {
233  char message[256] = {0};
234  FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, 0, r, 0, message,
235  sizeof(message), 0);
236  ui->textBrowser->setTextColor(Qt::red);
237  ui->textBrowser->setText(tr("Failed to connect WebDAV:\n") + message +
238  " (0x" + QString::number(r, 16) + ")");
239  ui->textBrowser->setTextColor(Qt::black);
240  }
241 #else
242  fusedav.start("fusedav -o nonempty -u \"" + QtPassSettings::getWebDavUser() +
243  "\" " + QtPassSettings::getWebDavUrl() + " \"" +
245  fusedav.waitForStarted();
246  if (fusedav.state() == QProcess::Running) {
247  QString pwd = QtPassSettings::getWebDavPassword();
248  bool ok = true;
249  if (pwd.isEmpty()) {
250  pwd = QInputDialog::getText(this, tr("QtPass WebDAV password"),
251  tr("Enter password to connect to WebDAV:"),
252  QLineEdit::Password, "", &ok);
253  }
254  if (ok && !pwd.isEmpty()) {
255  fusedav.write(pwd.toUtf8() + '\n');
256  fusedav.closeWriteChannel();
257  fusedav.waitForFinished(2000);
258  } else {
259  fusedav.terminate();
260  }
261  }
262  QString error = fusedav.readAllStandardError();
263  int prompt = error.indexOf("Password:");
264  if (prompt >= 0)
265  error.remove(0, prompt + 10);
266  if (fusedav.state() != QProcess::Running)
267  error = tr("fusedav exited unexpectedly\n") + error;
268  if (error.size() > 0) {
269  ui->textBrowser->setTextColor(Qt::red);
270  ui->textBrowser->setText(
271  tr("Failed to start fusedav to connect WebDAV:\n") + error);
272  ui->textBrowser->setTextColor(Qt::black);
273  }
274 #endif
275 }
276 
282  QString version = QtPassSettings::getVersion();
283 
284  // if (freshStart) {
285  restoreWindow();
286  //}
287 
289  QtPassSettings::setPassStore(passStore);
290 
292 
294  Qt::WindowFlags flags = windowFlags();
295  this->setWindowFlags(flags | Qt::WindowStaysOnTopHint);
296  this->show();
297  }
298 
299  if (QtPassSettings::isUseTrayIcon() && tray == NULL) {
300  initTrayIcon();
301  if (freshStart && QtPassSettings::isStartMinimized()) {
302  // since we are still in constructor, can't directly hide
303  QTimer::singleShot(10, this, SLOT(hide()));
304  }
305  } /*else if (!QtPassSettings::isUseTrayIcon() && tray != NULL) {
306  destroyTrayIcon();
307  }*/
308 
309  // dbg()<< version;
310 
311  // Config updates
312  if (version.isEmpty()) {
313  dbg() << "assuming fresh install";
318  if (!QtPassSettings::getPwgenExecutable().isEmpty())
320  else
322  QtPassSettings::setPassTemplate("login\nurl");
323  } else {
324  // QStringList ver = version.split(".");
325  // dbg()<< ver;
326  // if (ver[0] == "0" && ver[1] == "8") {
328  // }
329  if (QtPassSettings::getPassTemplate().isEmpty())
330  QtPassSettings::setPassTemplate("login\nurl");
331  }
332 
334 
335  if (Util::checkConfig()) {
336  config();
337  if (freshStart && Util::checkConfig())
338  return false;
339  }
340 
341  freshStart = false;
342 
343  // TODO(annejan): this needs to be before we try to access the store,
344  // but it would be better to do it after the Window is shown,
345  // as the long delay it can cause is irritating otherwise.
347  mountWebDav();
348 
349  model.setNameFilters(QStringList() << "*.gpg");
350  model.setNameFilterDisables(false);
351 
352  proxyModel.setSourceModel(&model);
353  proxyModel.setModelAndStore(&model, passStore);
354  selectionModel.reset(new QItemSelectionModel(&proxyModel));
355  model.fetchMore(model.setRootPath(passStore));
356  model.sort(0, Qt::AscendingOrder);
357 
358  ui->treeView->setModel(&proxyModel);
359  ui->treeView->setRootIndex(
360  proxyModel.mapFromSource(model.setRootPath(passStore)));
361  ui->treeView->setColumnHidden(1, true);
362  ui->treeView->setColumnHidden(2, true);
363  ui->treeView->setColumnHidden(3, true);
364  ui->treeView->setHeaderHidden(true);
365  ui->treeView->setIndentation(15);
366  ui->treeView->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
367  ui->treeView->setContextMenuPolicy(Qt::CustomContextMenu);
368  ui->treeView->header()->setSectionResizeMode(0, QHeaderView::Stretch);
369  connect(ui->treeView, SIGNAL(customContextMenuRequested(const QPoint &)),
370  this, SLOT(showContextMenu(const QPoint &)));
371  connect(ui->treeView, SIGNAL(emptyClicked()), this, SLOT(deselect()));
372  ui->textBrowser->setOpenExternalLinks(true);
373  ui->textBrowser->setContextMenuPolicy(Qt::CustomContextMenu);
374  connect(ui->textBrowser, SIGNAL(customContextMenuRequested(const QPoint &)),
375  this, SLOT(showBrowserContextMenu(const QPoint &)));
376 
377  updateProfileBox();
379  clearPanelTimer.setInterval(1000 *
381  clearClipboardTimer.setInterval(1000 * QtPassSettings::getAutoclearSeconds());
382  updateGitButtonVisibility();
383  updateOtpButtonVisibility();
384 
385  startupPhase = false;
386  return true;
387 }
388 
394  QScopedPointer<ConfigDialog> d(new ConfigDialog(this));
395  d->setModal(true);
396  // Automatically default to pass if it's available
397  if (freshStart && QFile(QtPassSettings::getPassExecutable()).exists()) {
399  }
400 
401  if (startupPhase)
402  d->wizard(); // does shit
403  if (d->exec()) {
404  if (d->result() == QDialog::Accepted) {
406  Qt::WindowFlags flags = windowFlags();
407  this->setWindowFlags(flags | Qt::WindowStaysOnTopHint);
408  } else {
409  this->setWindowFlags(Qt::Window);
410  }
411  this->show();
412 
413  updateProfileBox();
414  ui->treeView->setRootIndex(proxyModel.mapFromSource(
415  model.setRootPath(QtPassSettings::getPassStore())));
416 
417  if (freshStart && Util::checkConfig())
418  config();
420  clearPanelTimer.setInterval(1000 *
422  clearClipboardTimer.setInterval(1000 *
424 
425  updateGitButtonVisibility();
426  updateOtpButtonVisibility();
427  if (QtPassSettings::isUseTrayIcon() && tray == NULL)
428  initTrayIcon();
429  else if (!QtPassSettings::isUseTrayIcon() && tray != NULL) {
430  destroyTrayIcon();
431  }
432  }
433  freshStart = false;
434  }
435 }
436 
440 void MainWindow::onUpdate(bool block) {
441  ui->statusBar->showMessage(tr("Updating password-store"), 2000);
442  if (block)
444  else
446 }
447 
451 void MainWindow::onPush() {
452  if (QtPassSettings::isUseGit()) {
453  ui->statusBar->showMessage(tr("Updating password-store"), 2000);
455  }
456 }
457 
465 QString MainWindow::getFile(const QModelIndex &index, bool forPass) {
466  if (!index.isValid() ||
467  !model.fileInfo(proxyModel.mapToSource(index)).isFile())
468  return QString();
469  QString filePath = model.filePath(proxyModel.mapToSource(index));
470  if (forPass) {
471  filePath = QDir(QtPassSettings::getPassStore()).relativeFilePath(filePath);
472  filePath.replace(QRegExp("\\.gpg$"), "");
473  }
474  return filePath;
475 }
476 
481 void MainWindow::on_treeView_clicked(const QModelIndex &index) {
482  bool cleared = ui->treeView->currentIndex().flags() == Qt::NoItemFlags;
483  currentDir =
484  Util::getDir(ui->treeView->currentIndex(), false, model, proxyModel);
485  // TODO(bezet): "Could not decrypt";
486  clippedText = "";
487  QString file = getFile(index, true);
488  ui->passwordName->setText(getFile(index, true));
489  if (!file.isEmpty() && !cleared) {
490  QtPassSettings::getPass()->Show(file);
491  } else {
492  clearPanel(false);
493  ui->actionEdit->setEnabled(false);
494  ui->actionDelete->setEnabled(true);
495  }
496 }
497 
503 void MainWindow::on_treeView_doubleClicked(const QModelIndex &index) {
504  QFileInfo fileOrFolder =
505  model.fileInfo(proxyModel.mapToSource(ui->treeView->currentIndex()));
506 
507  if (fileOrFolder.isFile()) {
508  editPassword(getFile(index, true));
509  }
510 }
511 
516  currentDir = "/";
517  clearClipboard();
518  ui->passwordName->setText("");
519  clearPanel(false);
520 }
521 
526  dbg() << "Pass git init called";
528 }
529 
530 void MainWindow::executeWrapperStarted() {
531  clearTemplateWidgets();
532  ui->textBrowser->clear();
533  enableUiElements(false);
534  clearPanelTimer.stop();
535 }
536 
537 void MainWindow::keyGenerationComplete(const QString &p_output,
538  const QString &p_errout) {
539  // qDebug() << p_output;
540  // qDebug() << p_errout;
541  if (0 != keygen) {
542  qDebug() << "Keygen Done";
543  keygen->close();
544  keygen = 0;
545  // TODO(annejan) some sanity checking ?
546  }
547  processFinished(p_output, p_errout);
548 }
549 
550 void MainWindow::passShowHandler(const QString &p_output) {
551  QStringList templ = QtPassSettings::isUseTemplate()
552  ? QtPassSettings::getPassTemplate().split("\n")
553  : QStringList();
554  bool allFields =
556  FileContent fileContent = FileContent::parse(p_output, templ, allFields);
557  QString output = p_output;
558  QString password = fileContent.getPassword();
559 
560  // handle clipboard
562  !p_output.isEmpty()) {
563  clippedText = password;
565  copyTextToClipboard(password);
566  }
567 
568  // first clear the current view:
569  clearTemplateWidgets();
570 
571  // show what is needed:
573  output = "***" + tr("Content hidden") + "***";
574  } else {
575  if (!password.isEmpty()) {
576  // set the password, it is hidden if needed in addToGridLayout
577  addToGridLayout(0, tr("Password"), password);
578  }
579 
580  NamedValues namedValues = fileContent.getNamedValues();
581  for (int j = 0; j < namedValues.length(); ++j) {
582  NamedValue nv = namedValues.at(j);
583  addToGridLayout(j + 1, nv.name, nv.value);
584  }
585  if (ui->gridLayout->count() == 0)
586  ui->verticalLayoutPassword->setSpacing(0);
587  else
588  ui->verticalLayoutPassword->setSpacing(6);
589  output = fileContent.getRemainingData();
590  }
591 
593  clearPanelTimer.start();
594  }
595 
596  DisplayInTextBrowser(output);
597  enableUiElements(true);
598 }
599 
600 void MainWindow::passOtpHandler(const QString &p_output) {
601  if (!p_output.isEmpty()) {
602  addToGridLayout(ui->gridLayout->count() + 1, tr("OTP Code"), p_output);
603  copyTextToClipboard(p_output);
604  }
606  clearPanelTimer.start();
607  }
608  enableUiElements(true);
609 }
610 
611 void MainWindow::passStoreChanged(const QString &p_out, const QString &p_err) {
612  processFinished(p_out, p_err);
613  doGitPush();
614 }
615 
616 void MainWindow::doGitPush() {
618  onPush();
619 }
620 
621 void MainWindow::finishedInsert(const QString &p_output,
622  const QString &p_errout) {
623  processFinished(p_output, p_errout);
624  doGitPush();
625  on_treeView_clicked(ui->treeView->currentIndex());
626 }
627 
628 void MainWindow::DisplayInTextBrowser(QString output, QString prefix,
629  QString postfix) {
630  output.replace(QRegExp("<"), "&lt;");
631  output.replace(QRegExp(">"), "&gt;");
632  output.replace(QRegExp(" "), "&nbsp;");
633 
634  output.replace(
635  QRegExp("((?:https?|ftp|ssh|sftp|ftps|webdav|webdavs)://\\S+)"),
636  "<a href=\"\\1\">\\1</a>");
637  output.replace(QRegExp("\n"), "<br />");
638  output = prefix + output + postfix;
639  if (!ui->textBrowser->toPlainText().isEmpty())
640  output = ui->textBrowser->toHtml() + output;
641  ui->textBrowser->setHtml(output);
642 }
643 
644 void MainWindow::processErrorExit(int exitCode, const QString &p_error) {
645  if (!p_error.isEmpty()) {
646  QString output;
647  QString error = p_error;
648  error.replace(QRegExp("<"), "&lt;");
649  error.replace(QRegExp(">"), "&gt;");
650  error.replace(QRegExp(" "), "&nbsp;");
651  if (exitCode == 0) {
652  // https://github.com/IJHack/qtpass/issues/111
653  output = "<span style=\"color: darkgray;\">" + error + "</span><br />";
654  } else {
655  output = "<span style=\"color: red;\">" + error + "</span><br />";
656  }
657 
658  output.replace(
659  QRegExp("((?:https?|ftp|ssh|sftp|ftps|webdav|webdavs)://\\S+)"),
660  "<a href=\"\\1\">\\1</a>");
661  output.replace(QRegExp("\n"), "<br />");
662  if (!ui->textBrowser->toPlainText().isEmpty())
663  output = ui->textBrowser->toHtml() + output;
664  ui->textBrowser->setHtml(output);
665  }
666  enableUiElements(true);
667 }
668 
672 void MainWindow::clearClipboard() {
673  QClipboard *clipboard = QApplication::clipboard();
674  bool cleared = false;
675  if (this->clippedText == clipboard->text(QClipboard::Selection)) {
676  clipboard->clear(QClipboard::Clipboard);
677  cleared = true;
678  }
679  if (this->clippedText == clipboard->text(QClipboard::Clipboard)) {
680  clipboard->clear(QClipboard::Clipboard);
681  cleared = true;
682  }
683  if (cleared) {
684  ui->statusBar->showMessage(tr("Clipboard cleared"), 2000);
685  } else {
686  ui->statusBar->showMessage(tr("Clipboard not cleared"), 2000);
687  }
688  this->clippedText.clear();
689 }
690 
694 void MainWindow::clearPanel(bool notify) {
695  while (ui->gridLayout->count() > 0) {
696  QLayoutItem *item = ui->gridLayout->takeAt(0);
697  delete item->widget();
698  delete item;
699  }
700  if (notify) {
701  QString output = "***" + tr("Password and Content hidden") + "***";
702  ui->textBrowser->setHtml(output);
703  } else {
704  ui->textBrowser->setHtml("");
705  }
706 }
707 
715 void MainWindow::processFinished(const QString &p_output,
716  const QString &p_errout) {
717  DisplayInTextBrowser(p_output);
718  // Sometimes there is error output even with 0 exit code, which is
719  // assumed in this function
720  processErrorExit(0, p_errout);
721  enableUiElements(true);
722 }
723 
729 void MainWindow::enableUiElements(bool state) {
730  ui->treeView->setEnabled(state);
731  ui->lineEdit->setEnabled(state);
732  ui->lineEdit->installEventFilter(this);
733  ui->actionAddPassword->setEnabled(state);
734  ui->actionAddFolder->setEnabled(state);
735  ui->actionUsers->setEnabled(state);
736  ui->actionConfig->setEnabled(state);
737  // is a file selected?
738  state &= ui->treeView->currentIndex().isValid();
739  ui->actionDelete->setEnabled(state);
740  ui->actionEdit->setEnabled(state);
741  updateGitButtonVisibility();
742  updateOtpButtonVisibility();
743 }
744 
745 void MainWindow::restoreWindow() {
746  QByteArray geometry = QtPassSettings::getGeometry(saveGeometry());
747  restoreGeometry(geometry);
748  QByteArray savestate = QtPassSettings::getSavestate(saveState());
749  restoreState(savestate);
750  QPoint position = QtPassSettings::getPos(pos());
751  move(position);
752  QSize newSize = QtPassSettings::getSize(size());
753  resize(newSize);
754  if (QtPassSettings::isMaximized(isMaximized())) {
755  showMaximized();
756  }
757 }
758 
763 void MainWindow::processError(QProcess::ProcessError error) {
764  QString errorString;
765  switch (error) {
766  case QProcess::FailedToStart:
767  errorString = tr("QProcess::FailedToStart");
768  break;
769  case QProcess::Crashed:
770  errorString = tr("QProcess::Crashed");
771  break;
772  case QProcess::Timedout:
773  errorString = tr("QProcess::Timedout");
774  break;
775  case QProcess::ReadError:
776  errorString = tr("QProcess::ReadError");
777  break;
778  case QProcess::WriteError:
779  errorString = tr("QProcess::WriteError");
780  break;
781  case QProcess::UnknownError:
782  errorString = tr("QProcess::UnknownError");
783  break;
784  }
785  ui->textBrowser->setTextColor(Qt::red);
786  ui->textBrowser->setText(errorString);
787  ui->textBrowser->setTextColor(Qt::black);
788  enableUiElements(true);
789 }
790 
794 void MainWindow::onConfig() { config(); }
795 
801 void MainWindow::on_lineEdit_textChanged(const QString &arg1) {
802  ui->treeView->expandAll();
803  ui->statusBar->showMessage(tr("Looking for: %1").arg(arg1), 1000);
804  QString query = arg1;
805  query.replace(QRegExp(" "), ".*");
806  QRegExp regExp(query, Qt::CaseInsensitive);
807  proxyModel.setFilterRegExp(regExp);
808  ui->treeView->setRootIndex(proxyModel.mapFromSource(
809  model.setRootPath(QtPassSettings::getPassStore())));
810  selectFirstFile();
811 }
812 
818 void MainWindow::on_lineEdit_returnPressed() {
819  dbg() << "on_lineEdit_returnPressed";
820  selectFirstFile();
821  on_treeView_clicked(ui->treeView->currentIndex());
822 }
823 
828 void MainWindow::selectFirstFile() {
829  QModelIndex index = proxyModel.mapFromSource(
830  model.setRootPath(QtPassSettings::getPassStore()));
831  index = firstFile(index);
832  ui->treeView->setCurrentIndex(index);
833 }
834 
840 QModelIndex MainWindow::firstFile(QModelIndex parentIndex) {
841  QModelIndex index = parentIndex;
842  int numRows = proxyModel.rowCount(parentIndex);
843  for (int row = 0; row < numRows; ++row) {
844  index = proxyModel.index(row, 0, parentIndex);
845  if (model.fileInfo(proxyModel.mapToSource(index)).isFile())
846  return index;
847  if (proxyModel.hasChildren(index))
848  return firstFile(index);
849  }
850  return index;
851 }
852 
858 void MainWindow::setPassword(QString file, bool isNew) {
859  PasswordDialog d(file, isNew, this);
862 
863  if (!d.exec()) {
864  this->ui->treeView->setFocus();
865  }
866 }
867 
872 void MainWindow::addPassword() {
873  bool ok;
874  QString dir =
875  Util::getDir(ui->treeView->currentIndex(), true, model, proxyModel);
876  QString file =
877  QInputDialog::getText(this, tr("New file"),
878  tr("New password file: \n(Will be placed in %1 )")
880  Util::getDir(ui->treeView->currentIndex(),
881  true, model, proxyModel)),
882  QLineEdit::Normal, "", &ok);
883  if (!ok || file.isEmpty())
884  return;
885  file = dir + file;
886  setPassword(file);
887 }
888 
893 void MainWindow::onDelete() {
894  QFileInfo fileOrFolder =
895  model.fileInfo(proxyModel.mapToSource(ui->treeView->currentIndex()));
896  QString file = "";
897  bool isDir = false;
898 
899  if (fileOrFolder.isFile()) {
900  file = getFile(ui->treeView->currentIndex(), true);
901  } else {
902  file = Util::getDir(ui->treeView->currentIndex(), true, model, proxyModel);
903  isDir = true;
904  }
905 
906  QString dirMessage = tr(" and the whole content?");
907  if (isDir) {
908  QDirIterator it(model.rootPath() + "/" + file,
909  QDirIterator::Subdirectories);
910  bool okDir = true;
911  while (it.hasNext() && okDir) {
912  it.next();
913  if (QFileInfo(it.filePath()).isFile()) {
914  if (QFileInfo(it.filePath()).suffix() != "gpg") {
915  okDir = false;
916  dirMessage = tr(" and the whole content? <br><strong>Attention: "
917  "there are unexpected files in the given folder, "
918  "check them before continue.</strong>");
919  }
920  }
921  }
922  }
923 
924  if (QMessageBox::question(
925  this, isDir ? tr("Delete folder?") : tr("Delete password?"),
926  tr("Are you sure you want to delete %1%2")
927  .arg(QDir::separator() + file)
928  .arg(isDir ? dirMessage : "?"),
929  QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)
930  return;
931 
932  QtPassSettings::getPass()->Remove(file, isDir);
933 }
934 
938 void MainWindow::onOtp() {
939  QString file = getFile(ui->treeView->currentIndex(), true);
940  if (!file.isEmpty()) {
943  }
944 }
945 
949 void MainWindow::onEdit() {
950  QString file = getFile(ui->treeView->currentIndex(), true);
951  editPassword(file);
952 }
953 
958 void MainWindow::userDialog(QString dir) {
959  if (!dir.isEmpty())
960  currentDir = dir;
961  onUsers();
962 }
963 
969 void MainWindow::onUsers() {
970  QList<UserInfo> users = QtPassSettings::getPass()->listKeys();
971  if (users.size() == 0) {
972  QMessageBox::critical(this, tr("Can not get key list"),
973  tr("Unable to get list of available gpg keys"));
974  return;
975  }
976  QList<UserInfo> secret_keys = QtPassSettings::getPass()->listKeys("", true);
977  foreach (const UserInfo &sec, secret_keys) {
978  for (QList<UserInfo>::iterator it = users.begin(); it != users.end(); ++it)
979  if (sec.key_id == it->key_id)
980  it->have_secret = true;
981  }
982  QList<UserInfo> selected_users;
983  QString dir =
984  currentDir.isEmpty()
985  ? Util::getDir(ui->treeView->currentIndex(), false, model, proxyModel)
986  : currentDir;
987  int count = 0;
988  QStringList recipients = QtPassSettings::getPass()->getRecipientString(
989  dir.isEmpty() ? "" : dir, " ", &count);
990  if (!recipients.isEmpty())
991  selected_users = QtPassSettings::getPass()->listKeys(recipients);
992  foreach (const UserInfo &sel, selected_users) {
993  for (QList<UserInfo>::iterator it = users.begin(); it != users.end(); ++it)
994  if (sel.key_id == it->key_id)
995  it->enabled = true;
996  }
997  if (count > selected_users.size()) {
998  // Some keys seem missing from keyring, add them separately
999  QStringList recipients =
1000  QtPassSettings::getPass()->getRecipientList(dir.isEmpty() ? "" : dir);
1001  foreach (const QString recipient, recipients) {
1002  if (QtPassSettings::getPass()->listKeys(recipient).size() < 1) {
1003  UserInfo i;
1004  i.enabled = true;
1005  i.key_id = recipient;
1006  i.name = " ?? " + tr("Key not found in keyring");
1007  users.append(i);
1008  }
1009  }
1010  }
1011  UsersDialog d(this);
1012  d.setUsers(&users);
1013  if (!d.exec()) {
1014  d.setUsers(NULL);
1015  return;
1016  }
1017  d.setUsers(NULL);
1018 
1019  QtPassSettings::getPass()->Init(dir, users);
1020 }
1021 
1026 void MainWindow::messageAvailable(QString message) {
1027  if (message.isEmpty()) {
1028  focusInput();
1029  } else {
1030  ui->treeView->expandAll();
1031  ui->lineEdit->setText(message);
1032  on_lineEdit_returnPressed();
1033  }
1034  show();
1035  raise();
1036 }
1037 
1043  QList<UserInfo> keys = QtPassSettings::getPass()->listKeys("", true);
1044  QStringList names;
1045 
1046  if (keys.size() == 0)
1047  return names;
1048 
1049  foreach (const UserInfo &sec, keys)
1050  names << sec.name;
1051 
1052  return names;
1053 }
1054 
1060 void MainWindow::generateKeyPair(QString batch, QDialog *keygenWindow) {
1061  keygen = keygenWindow;
1062  ui->statusBar->showMessage(tr("Generating GPG key pair"), 60000);
1064 }
1065 
1070 void MainWindow::updateProfileBox() {
1071  QHash<QString, QString> profiles = QtPassSettings::getProfiles();
1072 
1073  if (profiles.isEmpty()) {
1074  ui->profileWidget->hide();
1075  } else {
1076  ui->profileWidget->show();
1077  ui->profileBox->setEnabled(profiles.size() > 1);
1078  ui->profileBox->clear();
1079  QHashIterator<QString, QString> i(profiles);
1080  while (i.hasNext()) {
1081  i.next();
1082  if (!i.key().isEmpty())
1083  ui->profileBox->addItem(i.key());
1084  }
1085  }
1086  int index = ui->profileBox->findText(QtPassSettings::getProfile());
1087  if (index != -1) // -1 for not found
1088  ui->profileBox->setCurrentIndex(index);
1089 }
1090 
1096 void MainWindow::on_profileBox_currentIndexChanged(QString name) {
1097  if (startupPhase || name == QtPassSettings::getProfile())
1098  return;
1100 
1102  ui->statusBar->showMessage(tr("Profile changed to %1").arg(name), 2000);
1103 
1105 
1106  ui->treeView->setRootIndex(proxyModel.mapFromSource(
1107  model.setRootPath(QtPassSettings::getPassStore())));
1108 }
1109 
1115 void MainWindow::initTrayIcon() {
1116  this->tray = new TrayIcon(this);
1117  // Setup tray icon
1118 
1119  if (tray == NULL)
1120  dbg() << "Allocating tray icon failed.";
1121 
1122  if (!tray->getIsAllocated()) {
1123  destroyTrayIcon();
1124  }
1125 }
1126 
1130 void MainWindow::destroyTrayIcon() {
1131  delete this->tray;
1132  tray = NULL;
1133 }
1134 
1139 void MainWindow::closeEvent(QCloseEvent *event) {
1141  this->hide();
1142  event->ignore();
1143  } else {
1144  clearClipboard();
1145  QtPassSettings::setGeometry(saveGeometry());
1146  QtPassSettings::setSavestate(saveState());
1147  QtPassSettings::setMaximized(isMaximized());
1148  if (!isMaximized()) {
1149  QtPassSettings::setPos(pos());
1150  QtPassSettings::setSize(size());
1151  }
1152  // QtPassSettings::setSplitterLeft(ui->splitter->sizes()[0]);
1153  // QtPassSettings::setSplitterRight(ui->splitter->sizes()[1]);
1154  event->accept();
1155  }
1156 }
1157 
1165 bool MainWindow::eventFilter(QObject *obj, QEvent *event) {
1166  if (obj == ui->lineEdit && event->type() == QEvent::KeyPress) {
1167  QKeyEvent *key = static_cast<QKeyEvent *>(event);
1168  if (key->key() == Qt::Key_Down) {
1169  ui->treeView->setFocus();
1170  }
1171  }
1172  return QObject::eventFilter(obj, event);
1173 }
1174 
1179 void MainWindow::keyPressEvent(QKeyEvent *event) {
1180  switch (event->key()) {
1181  case Qt::Key_Delete:
1182  onDelete();
1183  break;
1184  case Qt::Key_Return:
1185  case Qt::Key_Enter:
1186  on_treeView_clicked(ui->treeView->currentIndex());
1187  break;
1188  case Qt::Key_Escape:
1189  ui->lineEdit->clear();
1190  break;
1191  default:
1192  break;
1193  }
1194 }
1195 
1201 void MainWindow::showContextMenu(const QPoint &pos) {
1202  QModelIndex index = ui->treeView->indexAt(pos);
1203  bool selected = true;
1204  if (!index.isValid()) {
1205  ui->treeView->clearSelection();
1206  ui->actionDelete->setEnabled(false);
1207  ui->actionEdit->setEnabled(false);
1208  currentDir = "";
1209  selected = false;
1210  }
1211 
1212  ui->treeView->setCurrentIndex(index);
1213 
1214  QPoint globalPos = ui->treeView->viewport()->mapToGlobal(pos);
1215 
1216  QFileInfo fileOrFolder =
1217  model.fileInfo(proxyModel.mapToSource(ui->treeView->currentIndex()));
1218 
1219  QMenu contextMenu;
1220  if (!selected || fileOrFolder.isDir()) {
1221  QAction *openFolder =
1222  contextMenu.addAction(tr("Open folder with file manager"));
1223  QAction *addFolder = contextMenu.addAction(tr("Add folder"));
1224  QAction *addPassword = contextMenu.addAction(tr("Add password"));
1225  QAction *users = contextMenu.addAction(tr("Users"));
1226  connect(openFolder, SIGNAL(triggered()), this, SLOT(openFolder()));
1227  connect(addFolder, SIGNAL(triggered()), this, SLOT(addFolder()));
1228  connect(addPassword, SIGNAL(triggered()), this, SLOT(addPassword()));
1229  connect(users, SIGNAL(triggered()), this, SLOT(onUsers()));
1230  } else if (fileOrFolder.isFile()) {
1231  QAction *edit = contextMenu.addAction(tr("Edit"));
1232  connect(edit, SIGNAL(triggered()), this, SLOT(onEdit()));
1233  }
1234  if (selected) {
1235  // if (useClipboard != CLIPBOARD_NEVER) {
1236  // contextMenu.addSeparator();
1237  // QAction* copyItem = contextMenu.addAction(tr("Copy Password"));
1238  // if (getClippedPassword().length() == 0) copyItem->setEnabled(false);
1239  // connect(copyItem, SIGNAL(triggered()), this,
1240  // SLOT(copyPasswordToClipboard()));
1241  // }
1242  contextMenu.addSeparator();
1243  QAction *deleteItem = contextMenu.addAction(tr("Delete"));
1244  connect(deleteItem, SIGNAL(triggered()), this, SLOT(onDelete()));
1245  }
1246  contextMenu.exec(globalPos);
1247 }
1248 
1254 void MainWindow::showBrowserContextMenu(const QPoint &pos) {
1255  QMenu *contextMenu = ui->textBrowser->createStandardContextMenu(pos);
1256  QPoint globalPos = ui->textBrowser->viewport()->mapToGlobal(pos);
1257 
1258  contextMenu->exec(globalPos);
1259 }
1260 
1264 void MainWindow::openFolder() {
1265  QString dir =
1266  Util::getDir(ui->treeView->currentIndex(), false, model, proxyModel);
1267 
1268  QString path = QDir::toNativeSeparators(dir);
1269  QDesktopServices::openUrl(QUrl::fromLocalFile(path));
1270 }
1271 
1275 void MainWindow::addFolder() {
1276  bool ok;
1277  QString dir =
1278  Util::getDir(ui->treeView->currentIndex(), false, model, proxyModel);
1279  QString newdir =
1280  QInputDialog::getText(this, tr("New file"),
1281  tr("New Folder: \n(Will be placed in %1 )")
1283  Util::getDir(ui->treeView->currentIndex(),
1284  true, model, proxyModel)),
1285  QLineEdit::Normal, "", &ok);
1286  if (!ok || newdir.isEmpty())
1287  return;
1288  newdir.prepend(dir);
1289  // dbg()<< newdir;
1290  QDir().mkdir(newdir);
1291 }
1292 
1297 void MainWindow::editPassword(const QString &file) {
1298  if (!file.isEmpty()) {
1300  onUpdate(true);
1301  setPassword(file, false);
1302  }
1303 }
1304 
1309 void MainWindow::clearTemplateWidgets() {
1310  while (ui->gridLayout->count() > 0) {
1311  QLayoutItem *item = ui->gridLayout->takeAt(0);
1312  delete item->widget();
1313  delete item;
1314  }
1315  ui->verticalLayoutPassword->setSpacing(0);
1316 }
1317 
1322 void MainWindow::copyTextToClipboard(const QString &text) {
1323  QClipboard *clip = QApplication::clipboard();
1325  clip->setText(text, QClipboard::Clipboard);
1326  } else {
1327  clip->setText(text, QClipboard::Selection);
1328  }
1329  clippedText = text;
1330  ui->statusBar->showMessage(tr("Copied to clipboard"), 2000);
1332  clearClipboardTimer.start();
1333  }
1334 }
1335 
1336 void MainWindow::copyPasswordFromTreeview() {
1337  QFileInfo fileOrFolder =
1338  model.fileInfo(proxyModel.mapToSource(ui->treeView->currentIndex()));
1339 
1340  if (fileOrFolder.isFile()) {
1341  QString file = getFile(ui->treeView->currentIndex(), true);
1342  connect(QtPassSettings::getPass(), &Pass::finishedShow, this,
1343  &MainWindow::passwordFromFileToClipboard);
1344  QtPassSettings::getPass()->Show(file);
1345  }
1346 }
1347 
1348 void MainWindow::passwordFromFileToClipboard(const QString &text) {
1349  QStringList tokens = text.split('\n');
1350  copyTextToClipboard(tokens[0]);
1351 }
1352 
1359 void MainWindow::addToGridLayout(int position, const QString &field,
1360  const QString &value) {
1361  QString trimmedField = field.trimmed();
1362  QString trimmedValue = value.trimmed();
1363 
1364  // Combine the Copy button and the line edit in one widget
1365  QFrame *frame = new QFrame();
1366  QLayout *ly = new QHBoxLayout();
1367  ly->setContentsMargins(5, 2, 2, 2);
1368  frame->setLayout(ly);
1370  QPushButtonWithClipboard *fieldLabel =
1371  new QPushButtonWithClipboard(trimmedValue, this);
1372  connect(fieldLabel, SIGNAL(clicked(QString)), this,
1373  SLOT(copyTextToClipboard(QString)));
1374 
1375  fieldLabel->setStyleSheet("border-style: none ; background: transparent;");
1376  // fieldLabel->setContentsMargins(0,5,5,0);
1377  frame->layout()->addWidget(fieldLabel);
1378  }
1379 
1380  // set the echo mode to password, if the field is "password"
1381  if (QtPassSettings::isHidePassword() && trimmedField == tr("Password")) {
1382  QLineEdit *line = new QLineEdit();
1383  line->setObjectName(trimmedField);
1384  line->setText(trimmedValue);
1385  line->setReadOnly(true);
1386  line->setStyleSheet("border-style: none ; background: transparent;");
1387  line->setContentsMargins(0, 0, 0, 0);
1388  line->setEchoMode(QLineEdit::Password);
1389  frame->layout()->addWidget(line);
1390  } else {
1391  QTextBrowser *line = new QTextBrowser();
1392  line->setOpenExternalLinks(true);
1393  line->setOpenLinks(true);
1394  line->setMaximumHeight(26);
1395  line->setMinimumHeight(26);
1396  line->setSizePolicy(
1397  QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum));
1398  line->setObjectName(trimmedField);
1399  trimmedValue.replace(
1400  QRegExp("((?:https?|ftp|ssh|sftp|ftps|webdav|webdavs)://\\S+)"),
1401  "<a href=\"\\1\">\\1</a>");
1402  line->setText(trimmedValue);
1403  line->setReadOnly(true);
1404  line->setStyleSheet("border-style: none ; background: transparent;");
1405  line->setContentsMargins(0, 0, 0, 0);
1406  frame->layout()->addWidget(line);
1407  }
1408 
1409  frame->setStyleSheet(
1410  ".QFrame{border: 1px solid lightgrey; border-radius: 5px;}");
1411 
1412  // set into the layout
1413  ui->gridLayout->addWidget(new QLabel(trimmedField), position, 0);
1414  ui->gridLayout->addWidget(frame, position, 1);
1415 }
1416 
1423 void MainWindow::showStatusMessage(QString msg, int timeout) {
1424  ui->statusBar->showMessage(msg, timeout);
1425 }
1426 
1430 void MainWindow::startReencryptPath() {
1431  enableUiElements(false);
1432  ui->treeView->setDisabled(true);
1433 }
1434 
1438 void MainWindow::endReencryptPath() { enableUiElements(true); }
1439 
1445 void MainWindow::critical(QString title, QString msg) {
1446  QMessageBox::critical(this, title, msg);
1447 }
1448 
1449 void MainWindow::updateGitButtonVisibility() {
1450  if (!QtPassSettings::isUseGit() ||
1451  (QtPassSettings::getGitExecutable().isEmpty() &&
1452  QtPassSettings::getPassExecutable().isEmpty())) {
1453  enableGitButtons(false);
1454  } else {
1455  enableGitButtons(true);
1456  }
1457 }
1458 
1459 void MainWindow::updateOtpButtonVisibility() {
1460 #if defined(Q_OS_WIN) || defined(__APPLE__)
1461  ui->actionOtp->setVisible(false);
1462 #endif
1463  if (!QtPassSettings::isUseOtp())
1464  ui->actionOtp->setEnabled(false);
1465  else
1466  ui->actionOtp->setEnabled(true);
1467 }
1468 
1469 void MainWindow::enableGitButtons(const bool &state) {
1470  // Following GNOME guidelines is preferable disable buttons instead of hide
1471  ui->actionPush->setEnabled(state);
1472  ui->actionUpdate->setEnabled(state);
1473 }
The NamedValues class is mostly a list of NamedValue but also has a method to take a specific NamedVa...
Definition: filecontent.h:17
void finishedMove(const QString &, const QString &)
static void setAutoclearSeconds(const int &autoClearSeconds)
static int getAutoclearSeconds(const int &defaultValue=QVariant().toInt())
static void setUsePwgen(const bool &usePwgen)
static bool isStartMinimized(const bool &defaultValue=QVariant().toBool())
static bool isMaximized(const bool &defaultValue=QVariant().toBool())
static void setUsePass(const bool &usePass)
void finishedCopy(const QString &, const QString &)
void GenerateGPGKeys(QString batch)
Pass::GenerateGPGKeys internal gpg keypair generator . .
Definition: pass.cpp:106
void finishedGenerateGPGKeys(const QString &, const QString &)
QList< UserInfo > listKeys(QStringList keystring, bool secret=false)
Pass::listKeys list users.
Definition: pass.cpp:120
Stylish widget to allow copying of password and account details.
bool enabled
UserInfo::enabled.
Definition: userinfo.h:50
void finishedGitPush(const QString &, const QString &)
void error(QProcess::ProcessError)
#define dbg()
Definition: debughelper.h:7
static bool isAlwaysOnTop(const bool &defaultValue=QVariant().toBool())
static QPoint getPos(const QPoint &defaultValue=QVariant().toPoint())
NamedValues getNamedValues() const
Definition: filecontent.cpp:30
Definition: configdialog.h:9
static bool isUseSelection(const bool &defaultValue=QVariant().toBool())
QString key_id
UserInfo::key_id hexadecimal representation.
Definition: userinfo.h:36
static void setPassTemplate(const QString &passTemplate)
void finishedInsert(const QString &, const QString &)
~MainWindow()
MainWindow::~MainWindow destroy!
Definition: mainwindow.cpp:154
static void setPos(const QPoint &pos)
static ImitatePass * getImitatePass()
static bool isUseAutoclearPanel(const bool &defaultValue=QVariant().toBool())
static bool isUseWebDav(const bool &defaultValue=QVariant().toBool())
static void setSize(const QSize &size)
void finishedRemove(const QString &, const QString &)
QString value
Definition: filecontent.h:10
static bool isUseAutoclear(const bool &defaultValue=QVariant().toBool())
virtual void GitInit()=0
static bool isHideOnClose(const bool &defaultValue=QVariant().toBool())
bool eventFilter(QObject *obj, QEvent *event)
MainWindow::eventFilter filter out some events and focus the treeview.
static bool isUseGit(const bool &defaultValue=QVariant().toBool())
void config()
MainWindow::config pops up the configuration screen and handles all inter-window communication.
Definition: mainwindow.cpp:393
Acts as an abstraction for pass or pass imitation.
Definition: pass.h:25
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:3
static QString getPassStore(const QString &defaultValue=QVariant().toString())
static void setProfile(const QString &profile)
void userDialog(QString="")
MainWindow::userDialog see MainWindow::onUsers()
Definition: mainwindow.cpp:958
virtual void Remove(QString file, bool isDir)=0
static void setMaximized(const bool &maximized)
static QString getGitExecutable(const QString &defaultValue=QVariant().toString())
void finishedGitPull(const QString &, const QString &)
virtual void Show(QString file)=0
static QStringList getRecipientString(QString for_file, QString separator=" ", int *count=NULL)
Pass::getRecipientString formated string for use with GPG.
Definition: pass.cpp:283
static void setAutoclearPanelSeconds(const int &autoClearPanelSeconds)
void critical(QString, QString)
void setModelAndStore(QFileSystemModel *sourceModel, QString passStore)
StoreModel::setModelAndStore update the source model and store.
Definition: storemodel.cpp:80
PasswordDialog Handles the inserting and editing of passwords.
static bool isUseTrayIcon(const bool &defaultValue=QVariant().toBool())
static bool isUseOtp(const bool &defaultValue=QVariant().toBool())
void closeEvent(QCloseEvent *event)
MainWindow::closeEvent hide or quit.
MainWindow(const QString &searchText=QString(), QWidget *parent=nullptr)
MainWindow::MainWindow handles all of the main functionality and also the main window.
Definition: mainwindow.cpp:39
Handles listing and editing of GPG users.
Definition: usersdialog.h:22
virtual void GitPull_b()=0
void changeEvent(QEvent *event)
MainWindow::changeEvent sets focus to the search box.
Definition: mainwindow.cpp:171
static QString getPassExecutable(const QString &defaultValue=QVariant().toString())
Handles the systemtray icon and menu.
Definition: trayicon.h:14
void keyPressEvent(QKeyEvent *event)
MainWindow::keyPressEvent did anyone press return, enter or escape?
static QString getVersion(const QString &defaultValue=QVariant().toString())
void executePassGitInit()
MainWindow::executePassGitInit git init wrapper.
Definition: mainwindow.cpp:525
static QStringList getRecipientList(QString for_file)
Pass::getRecipientList return list of gpg-id&#39;s to encrypt for.
Definition: pass.cpp:247
static QByteArray getSavestate(const QByteArray &defaultValue=QVariant().toByteArray())
static QSize getSize(const QSize &defaultValue=QVariant().toSize())
virtual void GitPush()=0
QString getRemainingData() const
Definition: filecontent.cpp:32
static Pass * getPass()
void statusMsg(QString, int)
virtual void GitPull()=0
static QString getWebDavUser(const QString &defaultValue=QVariant().toString())
void finishedInit(const QString &, const QString &)
static void setSavestate(const QByteArray &saveState)
static QString getPassTemplate(const QString &defaultValue=QVariant().toString())
static Enums::clipBoardType getClipBoardType(const Enums::clipBoardType &defaultvalue=Enums::CLIPBOARD_NEVER)
static QString getWebDavUrl(const QString &defaultValue=QVariant().toString())
static QString getPwgenExecutable(const QString &defaultValue=QVariant().toString())
void updateEnv()
Pass::updateEnv update the execution environment (used when switching profiles)
Definition: pass.cpp:226
The ConfigDialog handles the configuration interface.
Definition: configdialog.h:23
QString name
UserInfo::name full name.
Definition: userinfo.h:32
bool checkConfig()
MainWindow::checkConfig make sure we are ready to go as soon as possible.
Definition: mainwindow.cpp:281
Stores key info lines including validity, creation date and more.
Definition: userinfo.h:11
static QByteArray getGeometry(const QByteArray &defaultValue=QVariant().toByteArray())
static int getAutoclearPanelSeconds(const int &defaultValue=QVariant().toInt())
void finishedShow(const QString &)
static bool isUseTemplate(const bool &defaultValue=QVariant().toBool())
static QString getWebDavPassword(const QString &defaultValue=QVariant().toString())
static bool isTemplateAllFields(const bool &defaultValue=QVariant().toBool())
QStringList getSecretKeys()
MainWindow::getSecretKeys get list of secret/private keys.
static void initExecutables()
static QString getDir(const QModelIndex &index, bool forPass, const QFileSystemModel &model, const StoreModel &storeModel)
Util::getDir get selectd folder path.
Definition: util.cpp:132
void finishedGitInit(const QString &, const QString &)
static QHash< QString, QString > getProfiles()
void deselect()
MainWindow::deselect clear the selection, password and copy buffer.
Definition: mainwindow.cpp:515
static void setGeometry(const QByteArray &geometry)
void generateKeyPair(QString, QDialog *)
MainWindow::generateKeyPair internal gpg keypair generator . .
virtual void Init(QString path, const QList< UserInfo > &users)=0
void startingExecuteWrapper()
void processErrorExit(int exitCode, const QString &err)
void setPass(const QString &output)
void finishedOtpGenerate(const QString &)
The MainWindow class does way too much, not only is it a switchboard, configuration handler and more...
Definition: mainwindow.h:38
static RealPass * getRealPass()
static bool isHidePassword(const bool &defaultValue=QVariant().toBool())
QString getPassword() const
Definition: filecontent.cpp:28
static QString findPasswordStore()
Util::findPasswordStore look for common .password-store folder location.
Definition: util.cpp:41
static bool isHideContent(const bool &defaultValue=QVariant().toBool())
static bool checkConfig()
Util::checkConfig do we have prequisite settings?
Definition: util.cpp:117
virtual void OtpGenerate(QString file)=0
static QString getProfile(const QString &defaultValue=QVariant().toString())
static void setVersion(const QString &version)
bool getIsAllocated()
TrayIcon::getIsAllocated return if TrayIcon is allocated.
Definition: trayicon.cpp:60
QString name
Definition: filecontent.h:9
static void setPassStore(const QString &passStore)
static bool isAutoPull(const bool &defaultValue=QVariant().toBool())
static bool isAutoPush(const bool &defaultValue=QVariant().toBool())