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