Page MenuHome GnuPG

No OneTemporary

diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 227e3df..0a9d5fd 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -1,1019 +1,1023 @@
#include "mainwindow.h"
#ifdef QT_DEBUG
#include "debughelper.h"
#endif
#ifndef VERSION
#include <qtpass_version.h>
#define VERSION QTPASS_VERSION_STRING
#endif
#include "configdialog.h"
#include "filecontent.h"
#include "passworddialog.h"
#include "qpushbuttonfactory.h"
#include "qtpass.h"
#include "qtpasssettings.h"
#include "trayicon.h"
#include "ui_mainwindow.h"
#include "usersdialog.h"
#include "util.h"
#include <QCloseEvent>
#include <QDialog>
#include <QFileInfo>
#include <QInputDialog>
#include <QLabel>
#include <QMenu>
#include <QMessageBox>
#include <QShortcut>
#include <QTimer>
static QString directoryName(const QString& dirOrFile) {
QFileInfo fi{dirOrFile};
if (fi.isDir()) {
return fi.absoluteFilePath();
} else {
return fi.absolutePath();
}
}
/**
* @brief MainWindow::MainWindow handles all of the main functionality and also
* the main window.
* @param searchText for searching from cli
* @param parent pointer
*/
MainWindow::MainWindow(const QString &searchText, QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow), keygen(nullptr),
tray(nullptr) {
#ifdef __APPLE__
// extra treatment for mac os
// see http://doc.qt.io/qt-5/qkeysequence.html#qt_set_sequence_auto_mnemonic
qt_set_sequence_auto_mnemonic(true);
#endif
ui->setupUi(this);
m_qtPass = new QtPass(this);
// register shortcut ctrl/cmd + Q to close the main window
new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_Q), this, SLOT(close()));
model.setNameFilters(QStringList() << QStringLiteral("*.gpg"));
model.setNameFilterDisables(false);
/*
* I added this to solve Windows bug but now on GNU/Linux the main folder,
* if hidden, disappear
*
* model.setFilter(QDir::NoDot);
*/
QString passStore = QtPassSettings::getPassStore(Util::findPasswordStore());
QModelIndex rootDir = model.setRootPath(passStore);
model.fetchMore(rootDir);
proxyModel.setModelAndStore(&model, passStore);
selectionModel.reset(new QItemSelectionModel(&proxyModel));
ui->treeView->setModel(&proxyModel);
ui->treeView->setRootIndex(proxyModel.mapFromSource(rootDir));
ui->treeView->setColumnHidden(1, true);
ui->treeView->setColumnHidden(2, true);
ui->treeView->setColumnHidden(3, true);
ui->treeView->setHeaderHidden(true);
ui->treeView->setIndentation(15);
ui->treeView->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
ui->treeView->setContextMenuPolicy(Qt::CustomContextMenu);
ui->treeView->header()->setSectionResizeMode(0, QHeaderView::Stretch);
ui->treeView->sortByColumn(0, Qt::AscendingOrder);
connect(ui->treeView, &QWidget::customContextMenuRequested, this,
&MainWindow::showContextMenu);
connect(ui->treeView, &DeselectableTreeView::emptyClicked, this,
&MainWindow::deselect);
if (QtPassSettings::isNoLineWrapping()) {
ui->textBrowser->setLineWrapMode(QTextBrowser::NoWrap);
}
ui->textBrowser->setOpenExternalLinks(true);
ui->textBrowser->setContextMenuPolicy(Qt::DefaultContextMenu);
updateProfileBox();
clearPanelTimer.setInterval(1000 *
QtPassSettings::getAutoclearPanelSeconds());
clearPanelTimer.setSingleShot(true);
connect(&clearPanelTimer, SIGNAL(timeout()), this, SLOT(clearPanel()));
searchTimer.setInterval(350);
searchTimer.setSingleShot(true);
connect(&searchTimer, &QTimer::timeout, this, &MainWindow::onTimeoutSearch);
initToolBarButtons();
initStatusBar();
ui->lineEdit->setClearButtonEnabled(true);
setUiElementsEnabled(true);
QTimer::singleShot(10, this, SLOT(focusInput()));
ui->lineEdit->setText(searchText);
if (!m_qtPass->init())
// no working config so this should just quit
QApplication::quit();
}
MainWindow::~MainWindow() { delete m_qtPass; }
/**
* @brief MainWindow::focusInput selects any text (if applicable) in the search
* box and sets focus to it. Allows for easy searching, called at application
* start and when receiving empty message in MainWindow::messageAvailable when
* compiled with SINGLE_APP=1 (default).
*/
void MainWindow::focusInput() {
ui->lineEdit->selectAll();
ui->lineEdit->setFocus();
}
/**
* @brief MainWindow::changeEvent sets focus to the search box
* @param event
*/
void MainWindow::changeEvent(QEvent *event) {
QWidget::changeEvent(event);
if (event->type() == QEvent::ActivationChange) {
if (isActiveWindow()) {
focusInput();
}
}
}
/**
* @brief MainWindow::initToolBarButtons init main ToolBar and connect actions
*/
void MainWindow::initToolBarButtons() {
connect(ui->actionAddPassword, &QAction::triggered, this,
&MainWindow::addPassword);
connect(ui->actionAddFolder, &QAction::triggered, this,
&MainWindow::addFolder);
connect(ui->actionEdit, &QAction::triggered, this, &MainWindow::onEdit);
connect(ui->actionDelete, &QAction::triggered, this, &MainWindow::onDelete);
connect(ui->actionUsers, &QAction::triggered, this, &MainWindow::onUsers);
connect(ui->actionConfig, &QAction::triggered, this, &MainWindow::onConfig);
connect(ui->treeView, &QTreeView::clicked, this, &MainWindow::selectTreeItem);
connect(ui->treeView, &QTreeView::doubleClicked, this, &MainWindow::editTreeItem);
connect(ui->profileBox, &QComboBox::currentTextChanged, this, &MainWindow::selectProfile);
connect(ui->lineEdit, &QLineEdit::textChanged, this, &MainWindow::filterList);
connect(ui->lineEdit, &QLineEdit::returnPressed, this, &MainWindow::selectFromSearch);
ui->actionAddPassword->setIcon(
QIcon::fromTheme(QStringLiteral("document-new"), QIcon(QStringLiteral(":/icons/document-new.svg"))));
ui->actionAddFolder->setIcon(
QIcon::fromTheme(QStringLiteral("folder-new"), QIcon(QStringLiteral(":/icons/folder-new.svg"))));
ui->actionEdit->setIcon(QIcon::fromTheme(
QStringLiteral("document-properties"), QIcon(QStringLiteral(":/icons/document-properties.svg"))));
ui->actionDelete->setIcon(
QIcon::fromTheme(QStringLiteral("edit-delete"), QIcon(QStringLiteral(":/icons/edit-delete.svg"))));
ui->actionUsers->setIcon(QIcon::fromTheme(
QStringLiteral("x-office-address-book"), QIcon(QStringLiteral(":/icons/x-office-address-book.svg"))));
ui->actionConfig->setIcon(QIcon::fromTheme(
QStringLiteral("applications-system"), QIcon(QStringLiteral(":/icons/applications-system.svg"))));
}
/**
* @brief MainWindow::initStatusBar init statusBar with default message and logo
*/
void MainWindow::initStatusBar() {
ui->statusBar->showMessage(tr("Welcome to QtPass %1").arg(QString::fromLocal8Bit(VERSION)), 2000);
QPixmap logo = QPixmap::fromImage(QImage(QStringLiteral(":/artwork/icon.svg")))
.scaledToHeight(statusBar()->height());
QLabel *logoApp = new QLabel(statusBar());
logoApp->setPixmap(logo);
statusBar()->addPermanentWidget(logoApp);
}
const QModelIndex MainWindow::getCurrentTreeViewIndex() {
return ui->treeView->currentIndex();
}
void MainWindow::cleanKeygenDialog() {
this->keygen->realDone(QDialog::Accepted);
this->keygen = nullptr;
}
void MainWindow::flashText(const QString &text, const bool isError,
const bool isHtml) {
if (isError)
ui->textBrowser->setTextColor(Qt::red);
if (isHtml) {
QString _text = text;
if (!ui->textBrowser->toPlainText().isEmpty())
_text = ui->textBrowser->toHtml() + _text;
ui->textBrowser->setHtml(_text);
} else {
ui->textBrowser->setText(text);
ui->textBrowser->setTextColor(Qt::black);
}
}
/**
* @brief MainWindow::config pops up the configuration screen and handles all
* inter-window communication
*/
void MainWindow::config() {
QScopedPointer<ConfigDialog> d(new ConfigDialog(this));
d->setModal(true);
if (m_qtPass->isFreshStart())
d->wizard(); // does shit
if (d->exec()) {
if (d->result() == QDialog::Accepted) {
// Update the textBrowser line wrap mode
if (QtPassSettings::isNoLineWrapping()) {
ui->textBrowser->setLineWrapMode(QTextBrowser::NoWrap);
} else {
ui->textBrowser->setLineWrapMode(QTextBrowser::WidgetWidth);
}
this->show();
updateProfileBox();
ui->treeView->setRootIndex(proxyModel.mapFromSource(
model.setRootPath(QtPassSettings::getPassStore())));
clearPanelTimer.setInterval(1000 *
QtPassSettings::getAutoclearPanelSeconds());
m_qtPass->setClipboardTimer();
if (QtPassSettings::isUseTrayIcon() && tray == nullptr)
initTrayIcon();
else if (!QtPassSettings::isUseTrayIcon() && tray != nullptr) {
destroyTrayIcon();
}
}
m_qtPass->setFreshStart(false);
}
}
/**
* @brief MainWindow::on_treeView_clicked read the selected password file
* @param index
*/
void MainWindow::selectTreeItem(const QModelIndex &index) {
bool cleared = ui->treeView->currentIndex().flags() == Qt::NoItemFlags;
// TODO(bezet): "Could not decrypt";
m_qtPass->clearClippedText();
QString file = index.data(QFileSystemModel::FilePathRole).toString();
ui->passwordName->setText(index.data().toString());
- if (!file.isEmpty() && !cleared) {
+ if (!file.isEmpty() && QFileInfo(file).isFile() && !cleared) {
QtPassSettings::getPass()->Show(file);
} else {
clearPanel(false);
ui->actionEdit->setEnabled(false);
ui->actionDelete->setEnabled(true);
}
}
/**
* @brief MainWindow::on_treeView_doubleClicked when doubleclicked on
* TreeViewItem, open the edit Window
* @param index
*/
void MainWindow::editTreeItem(const QModelIndex &index) {
QFileInfo fileOrFolder{index.data(QFileSystemModel::Roles::FilePathRole).toString()};
if (fileOrFolder.isFile()) {
editPassword(fileOrFolder.absoluteFilePath());
}
}
/**
* @brief MainWindow::deselect clear the selection, password and copy buffer
*/
void MainWindow::deselect() {
m_qtPass->clearClipboard();
ui->treeView->clearSelection();
ui->actionEdit->setEnabled(false);
ui->actionDelete->setEnabled(false);
ui->passwordName->setText(QString{});
clearPanel(false);
}
void MainWindow::executeWrapperStarted() {
clearTemplateWidgets();
ui->textBrowser->clear();
setUiElementsEnabled(false);
clearPanelTimer.stop();
}
void MainWindow::passShowHandler(const QString &p_output) {
QStringList templ = QtPassSettings::isUseTemplate()
? QtPassSettings::getPassTemplate().split(QStringLiteral("\n"))
: QStringList();
bool allFields =
QtPassSettings::isUseTemplate() && QtPassSettings::isTemplateAllFields();
FileContent fileContent = FileContent::parse(p_output, templ, allFields);
QString output = p_output;
QString password = fileContent.getPassword();
// set clipped text
m_qtPass->setClippedText(password, p_output);
// first clear the current view:
clearTemplateWidgets();
// show what is needed:
if (QtPassSettings::isHideContent()) {
output = QStringLiteral("***") + tr("Content hidden") + QStringLiteral("***");
} else if (!QtPassSettings::isDisplayAsIs()) {
if (!password.isEmpty()) {
// set the password, it is hidden if needed in addToGridLayout
addToGridLayout(0, tr("Password"), password);
}
NamedValues namedValues = fileContent.getNamedValues();
for (int j = 0; j < namedValues.length(); ++j) {
NamedValue nv = namedValues.at(j);
addToGridLayout(j + 1, nv.name, nv.value);
}
if (ui->gridLayout->count() == 0)
ui->verticalLayoutPassword->setSpacing(0);
else
ui->verticalLayoutPassword->setSpacing(6);
output = fileContent.getRemainingDataForDisplay();
}
if (QtPassSettings::isUseAutoclearPanel()) {
clearPanelTimer.start();
}
Q_EMIT passShowHandlerFinished(output);
setUiElementsEnabled(true);
}
/**
* @brief MainWindow::clearPanel hide the information from shoulder surfers
*/
void MainWindow::clearPanel(bool notify) {
while (ui->gridLayout->count() > 0) {
QLayoutItem *item = ui->gridLayout->takeAt(0);
delete item->widget();
delete item;
}
if (notify) {
QString output = QStringLiteral("***") + tr("Password and Content hidden") + QStringLiteral("***");
ui->textBrowser->setHtml(output);
} else {
ui->textBrowser->setHtml(QString{});
}
}
/**
* @brief MainWindow::setUiElementsEnabled enable or disable the relevant UI
* elements
* @param state
*/
void MainWindow::setUiElementsEnabled(bool state) {
ui->treeView->setEnabled(state);
ui->lineEdit->setEnabled(state);
ui->lineEdit->installEventFilter(this);
ui->actionAddPassword->setEnabled(state);
ui->actionAddFolder->setEnabled(state);
ui->actionUsers->setEnabled(state);
ui->actionConfig->setEnabled(state);
// is a file selected?
state &= ui->treeView->currentIndex().isValid();
ui->actionDelete->setEnabled(state);
ui->actionEdit->setEnabled(state);
}
void MainWindow::restoreWindow() {
QByteArray geometry = QtPassSettings::getGeometry(saveGeometry());
restoreGeometry(geometry);
QByteArray savestate = QtPassSettings::getSavestate(saveState());
restoreState(savestate);
QPoint position = QtPassSettings::getPos(pos());
move(position);
QSize newSize = QtPassSettings::getSize(size());
resize(newSize);
if (QtPassSettings::isUseTrayIcon() && tray == nullptr) {
initTrayIcon();
if (QtPassSettings::isStartMinimized()) {
// since we are still in constructor, can't directly hide
QTimer::singleShot(10, this, SLOT(hide()));
}
} else if (!QtPassSettings::isUseTrayIcon() && tray != nullptr) {
destroyTrayIcon();
}
}
/**
* @brief MainWindow::on_configButton_clicked run Mainwindow::config
*/
void MainWindow::onConfig() { config(); }
/**
* @brief Executes when the string in the search box changes, collapses the
* TreeView
* @param arg1
*/
void MainWindow::filterList(const QString &arg1) {
ui->statusBar->showMessage(tr("Looking for: %1").arg(arg1), 1000);
ui->treeView->expandAll();
clearPanel(false);
ui->passwordName->setText(QString{});
ui->actionEdit->setEnabled(false);
ui->actionDelete->setEnabled(false);
searchTimer.start();
}
/**
* @brief MainWindow::onTimeoutSearch Fired when search is finished or too much
* time from two keypresses is elapsed
*/
void MainWindow::onTimeoutSearch() {
QString query = ui->lineEdit->text();
if (query.isEmpty()) {
ui->treeView->collapseAll();
deselect();
}
query.replace(QStringLiteral(" "), QStringLiteral(".*"));
QRegularExpression regExp(query, QRegularExpression::CaseInsensitiveOption);
proxyModel.setFilterRegularExpression(regExp);
ui->treeView->setRootIndex(proxyModel.mapFromSource(
model.setRootPath(QtPassSettings::getPassStore())));
if (proxyModel.rowCount() > 0 && !query.isEmpty()) {
selectFirstFile();
} else {
ui->actionEdit->setEnabled(false);
ui->actionDelete->setEnabled(false);
}
}
/**
* @brief MainWindow::on_lineEdit_returnPressed get searching
*
* Select the first possible file in the tree
*/
void MainWindow::selectFromSearch() {
#ifdef QT_DEBUG
dbg() << "on_lineEdit_returnPressed" << proxyModel.rowCount();
#endif
if (proxyModel.rowCount() > 0) {
selectFirstFile();
selectTreeItem(ui->treeView->currentIndex());
}
}
/**
* @brief MainWindow::selectFirstFile select the first possible file in the
* tree
*/
void MainWindow::selectFirstFile() {
QModelIndex index = proxyModel.mapFromSource(
model.setRootPath(QtPassSettings::getPassStore()));
index = firstFile(index);
ui->treeView->setCurrentIndex(index);
}
/**
* @brief MainWindow::firstFile return location of first possible file
* @param parentIndex
* @return QModelIndex
*/
QModelIndex MainWindow::firstFile(QModelIndex parentIndex) {
QModelIndex index = parentIndex;
int numRows = proxyModel.rowCount(parentIndex);
for (int row = 0; row < numRows; ++row) {
index = proxyModel.index(row, 0, parentIndex);
if (model.fileInfo(proxyModel.mapToSource(index)).isFile())
return index;
if (proxyModel.hasChildren(index))
return firstFile(index);
}
return index;
}
/**
* @brief MainWindow::setPassword open passworddialog
* @param file which pgp file
* @param isNew insert (not update)
*/
void MainWindow::setPassword(QString file, bool isNew) {
PasswordDialog d(file, isNew, this);
if (!d.exec()) {
ui->treeView->setFocus();
}
}
/**
* @brief MainWindow::addPassword add a new password by showing a
* number of dialogs.
*/
void MainWindow::addPassword() {
bool ok;
QString dir = directoryName(ui->treeView->currentIndex().data(QFileSystemModel::Roles::FilePathRole).toString());
QString file =
QInputDialog::getText(this, tr("New file"),
tr("New password file: \n(Will be placed in %1 )")
.arg(dir),
QLineEdit::Normal, QString{}, &ok);
if (!ok || file.isEmpty())
return;
file = QDir(dir).absoluteFilePath(file);
setPassword(file);
}
/**
* @brief MainWindow::onDelete remove password, if you are
* sure.
*/
void MainWindow::onDelete() {
QModelIndex currentIndex = ui->treeView->currentIndex();
if (!currentIndex.isValid()) {
// This fixes https://github.com/IJHack/QtPass/issues/556
// Otherwise the entire password directory would be deleted if
// nothing is selected in the tree view.
return;
}
QFileInfo fileOrFolder = currentIndex.data(QFileSystemModel::FilePathRole).toString();
QString file = QString{};
bool isDir = fileOrFolder.isDir();
file = fileOrFolder.absoluteFilePath();
QString dirMessage = tr(" and the whole content?");
if (isDir) {
QDirIterator it(model.rootPath() + QDir::separator() + file,
QDirIterator::Subdirectories);
bool okDir = true;
while (it.hasNext() && okDir) {
it.next();
if (auto fi = it.fileInfo(); fi.isFile()) {
if (fi.suffix() != QStringLiteral("gpg")) {
okDir = false;
dirMessage = tr(" and the whole content? <br><strong>Attention: "
"there are unexpected files in the given folder, "
"check them before continue.</strong>");
}
}
}
}
if (QMessageBox::question(
this, isDir ? tr("Delete folder?") : tr("Delete password?"),
tr("Are you sure you want to delete %1%2?")
.arg(QDir::separator() + file, isDir ? dirMessage : QStringLiteral("?")),
QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)
return;
QtPassSettings::getPass()->Remove(file, isDir);
}
/**
* @brief MainWindow::onEdit try and edit (selected) password.
*/
void MainWindow::onEdit() {
QString file = ui->treeView->currentIndex().data(QFileSystemModel::FilePathRole).toString();
editPassword(file);
}
/**
* @brief MainWindow::userDialog see MainWindow::onUsers()
* @param dir folder to edit users for.
*/
void MainWindow::userDialog(QString dir) {
QFileInfo fi(dir);
if (!fi.isDir()) {
dir = fi.absolutePath();
}
UsersDialog d(dir, this);
if (!d.exec()) {
ui->treeView->setFocus();
}
}
/**
* @brief MainWindow::onUsers edit users for the current
* folder,
* gets lists and opens UserDialog.
*/
void MainWindow::onUsers() {
QString dir = ui->treeView->currentIndex().data(QFileSystemModel::Roles::FilePathRole).toString();
- QFileInfo fi(dir);
- if (!fi.isDir()) {
+ if (dir.isEmpty()) {
+ dir = QtPassSettings::getPassStore();
+ } else {
+ QFileInfo fi(dir);
+ if (!fi.isDir()) {
dir = fi.absolutePath();
+ }
}
userDialog(dir);
}
/**
* @brief MainWindow::messageAvailable we have some text/message/search to do.
* @param message
*/
void MainWindow::messageAvailable(QString message) {
if (message.isEmpty()) {
focusInput();
} else {
ui->treeView->expandAll();
ui->lineEdit->setText(message);
selectFromSearch();
}
show();
raise();
}
/**
* @brief MainWindow::generateKeyPair internal gpg keypair generator . .
* @param batch
* @param keygenWindow
*/
void MainWindow::generateKeyPair(GenKeyData batch, KeygenDialog *keygenWindow) {
keygen = keygenWindow;
Q_EMIT generateGPGKeyPair(batch);
}
/**
* @brief MainWindow::updateProfileBox update the list of profiles, optionally
* select a more appropriate one to view too
*/
void MainWindow::updateProfileBox() {
QHash<QString, QString> profiles = QtPassSettings::getProfiles();
if (profiles.isEmpty()) {
ui->profileWidget->hide();
} else {
ui->profileWidget->show();
ui->profileBox->setEnabled(profiles.size() > 1);
ui->profileBox->clear();
QHashIterator<QString, QString> i(profiles);
while (i.hasNext()) {
i.next();
if (!i.key().isEmpty())
ui->profileBox->addItem(i.key());
}
ui->profileBox->model()->sort(0);
}
int index = ui->profileBox->findText(QtPassSettings::getProfile());
if (index != -1) // -1 for not found
ui->profileBox->setCurrentIndex(index);
}
/**
* @brief MainWindow::on_profileBox_currentIndexChanged make sure we show the
* correct "profile"
* @param name
*/
void MainWindow::selectProfile(QString name) {
if (m_qtPass->isFreshStart() || name == QtPassSettings::getProfile())
return;
ui->lineEdit->clear();
QtPassSettings::setProfile(name);
QtPassSettings::setPassStore(QtPassSettings::getProfiles().value(name));
ui->statusBar->showMessage(tr("Profile changed to %1").arg(name), 2000);
ui->treeView->selectionModel()->clear();
ui->treeView->setRootIndex(proxyModel.mapFromSource(
model.setRootPath(QtPassSettings::getPassStore())));
ui->actionEdit->setEnabled(false);
ui->actionDelete->setEnabled(false);
}
/**
* @brief MainWindow::initTrayIcon show a nice tray icon on systems that
* support
* it
*/
void MainWindow::initTrayIcon() {
this->tray = new TrayIcon(this);
// Setup tray icon
if (tray == nullptr) {
#ifdef QT_DEBUG
dbg() << "Allocating tray icon failed.";
#endif
}
if (!tray->getIsAllocated()) {
destroyTrayIcon();
}
}
/**
* @brief MainWindow::destroyTrayIcon remove that pesky tray icon
*/
void MainWindow::destroyTrayIcon() {
delete this->tray;
tray = nullptr;
}
/**
* @brief MainWindow::closeEvent hide or quit
* @param event
*/
void MainWindow::closeEvent(QCloseEvent *event) {
if (QtPassSettings::isHideOnClose()) {
this->hide();
event->ignore();
} else {
m_qtPass->clearClipboard();
QtPassSettings::setGeometry(saveGeometry());
QtPassSettings::setSavestate(saveState());
QtPassSettings::setPos(pos());
QtPassSettings::setSize(size());
event->accept();
}
}
/**
* @brief MainWindow::eventFilter filter out some events and focus the
* treeview
* @param obj
* @param event
* @return
*/
bool MainWindow::eventFilter(QObject *obj, QEvent *event) {
if (obj == ui->lineEdit && event->type() == QEvent::KeyPress) {
auto *key = dynamic_cast<QKeyEvent *>(event);
if (key != nullptr && key->key() == Qt::Key_Down) {
ui->treeView->setFocus();
}
}
return QObject::eventFilter(obj, event);
}
/**
* @brief MainWindow::keyPressEvent did anyone press return, enter or escape?
* @param event
*/
void MainWindow::keyPressEvent(QKeyEvent *event) {
switch (event->key()) {
case Qt::Key_Delete:
onDelete();
break;
case Qt::Key_Return:
case Qt::Key_Enter:
if (proxyModel.rowCount() > 0)
selectTreeItem(ui->treeView->currentIndex());
break;
case Qt::Key_Escape:
ui->lineEdit->clear();
break;
default:
break;
}
}
/**
* @brief MainWindow::showContextMenu show us the (file or folder) context
* menu
* @param pos
*/
void MainWindow::showContextMenu(const QPoint &pos) {
QModelIndex index = ui->treeView->indexAt(pos);
bool selected = true;
if (!index.isValid()) {
ui->treeView->clearSelection();
ui->actionDelete->setEnabled(false);
ui->actionEdit->setEnabled(false);
selected = false;
}
ui->treeView->setCurrentIndex(index);
QPoint globalPos = ui->treeView->viewport()->mapToGlobal(pos);
QFileInfo fileOrFolder =
model.fileInfo(proxyModel.mapToSource(ui->treeView->currentIndex()));
QMenu contextMenu;
if (!selected || fileOrFolder.isDir()) {
QAction *addFolder = contextMenu.addAction(tr("Add folder"));
QAction *addPassword = contextMenu.addAction(tr("Add password"));
QAction *users = contextMenu.addAction(tr("Users"));
connect(addFolder, &QAction::triggered, this, &MainWindow::addFolder);
connect(addPassword, &QAction::triggered, this, &MainWindow::addPassword);
connect(users, &QAction::triggered, this, &MainWindow::onUsers);
} else if (fileOrFolder.isFile()) {
QAction *edit = contextMenu.addAction(tr("Edit"));
connect(edit, &QAction::triggered, this, &MainWindow::onEdit);
}
if (selected) {
contextMenu.addSeparator();
if (fileOrFolder.isDir()) {
QAction *renameFolder = contextMenu.addAction(tr("Rename folder"));
connect(renameFolder, &QAction::triggered, this,
&MainWindow::renameFolder);
} else if (fileOrFolder.isFile()) {
QAction *renamePassword = contextMenu.addAction(tr("Rename password"));
connect(renamePassword, &QAction::triggered, this,
&MainWindow::renamePassword);
}
QAction *deleteItem = contextMenu.addAction(tr("Delete"));
connect(deleteItem, &QAction::triggered, this, &MainWindow::onDelete);
}
contextMenu.exec(globalPos);
}
/**
* @brief MainWindow::addFolder add a new folder to store passwords in
*/
void MainWindow::addFolder() {
bool ok;
QString dir =
directoryName(ui->treeView->currentIndex().data(QFileSystemModel::FilePathRole).toString());
QString newdir =
QInputDialog::getText(this, tr("New file"),
tr("New Folder: \n(Will be placed in %1 )")
.arg(dir),
QLineEdit::Normal, QString{}, &ok);
if (!ok || newdir.isEmpty())
return;
// dbg()<< newdir;
QDir(dir).mkdir(newdir);
}
/**
* @brief MainWindow::renameFolder rename an existing folder
*/
void MainWindow::renameFolder() {
bool ok;
QString srcDir = QDir::cleanPath(
directoryName(ui->treeView->currentIndex().data(QFileSystemModel::FilePathRole).toString()));
QString srcDirName = QDir(srcDir).dirName();
QString newName =
QInputDialog::getText(this, tr("Rename file"), tr("Rename Folder To: "),
QLineEdit::Normal, srcDirName, &ok);
if (!ok || newName.isEmpty())
return;
QString destDir = srcDir;
destDir.replace(srcDir.lastIndexOf(srcDirName), srcDirName.length(), newName);
QtPassSettings::getPass()->Move(srcDir, destDir);
}
/**
* @brief MainWindow::editPassword read password and open edit window via
* MainWindow::onEdit()
*/
void MainWindow::editPassword(const QString &file) {
if (!file.isEmpty()) {
setPassword(file, false);
}
}
/**
* @brief MainWindow::renamePassword rename an existing password
*/
void MainWindow::renamePassword() {
bool ok;
QString file = ui->treeView->currentIndex().data(QFileSystemModel::FilePathRole).toString();
QString filePath = QFileInfo(file).path();
QString fileName = QFileInfo(file).fileName();
if (fileName.endsWith(QStringLiteral(".gpg"), Qt::CaseInsensitive))
fileName.chop(4);
QString newName =
QInputDialog::getText(this, tr("Rename file"), tr("Rename File To: "),
QLineEdit::Normal, fileName, &ok);
if (!ok || newName.isEmpty())
return;
QString newFile = QDir(filePath).filePath(newName);
QtPassSettings::getPass()->Move(file, newFile);
}
/**
* @brief MainWindow::clearTemplateWidgets empty the template widget fields in
* the UI
*/
void MainWindow::clearTemplateWidgets() {
while (ui->gridLayout->count() > 0) {
QLayoutItem *item = ui->gridLayout->takeAt(0);
delete item->widget();
delete item;
}
ui->verticalLayoutPassword->setSpacing(0);
}
/**
* @brief MainWindow::addToGridLayout add a field to the template grid
* @param position
* @param field
* @param value
*/
void MainWindow::addToGridLayout(int position, const QString &field,
const QString &value) {
QString trimmedField = field.trimmed();
QString trimmedValue = value.trimmed();
// Combine the Copy button and the line edit in one widget
QFrame *frame = new QFrame();
QLayout *ly = new QHBoxLayout();
ly->setContentsMargins(5, 2, 2, 2);
ly->setSpacing(0);
frame->setLayout(ly);
auto fieldLabel = createPushButton(QIcon::fromTheme(QStringLiteral("edit-copy")), m_qtPass, [this, trimmedValue] {
m_qtPass->copyTextToClipboard(trimmedValue);
});
frame->layout()->addWidget(fieldLabel.release());
auto qrButton = createPushButton(QIcon::fromTheme(QStringLiteral("view-barcode-qr")), m_qtPass, [this, trimmedValue]() {
m_qtPass->showTextAsQRCode(trimmedValue);
});
frame->layout()->addWidget(qrButton.release());
if (trimmedField == tr("Password")) {
auto *line = new QLineEdit();
line->setObjectName(trimmedField);
line->setText(trimmedValue);
line->setReadOnly(true);
line->setContentsMargins(0, 0, 0, 0);
line->setEchoMode(QLineEdit::Password);
auto icon = QIcon::fromTheme(QStringLiteral("password-show-on"));
icon.addFile(QStringLiteral("password-show-off"),QSize(),QIcon::Normal, QIcon::Off);
auto showButton = createPushButton(icon, line, [line]() {
if (line->echoMode() == QLineEdit::Password) {
line->setEchoMode(QLineEdit::Normal);
} else {
line->setEchoMode(QLineEdit::Password);
}
});
showButton->setCheckable(true);
showButton->setContentsMargins(0, 0, 0, 0);
frame->layout()->addWidget(showButton.release());
frame->layout()->addWidget(line);
} else {
auto *line = new QTextBrowser();
line->setOpenExternalLinks(true);
line->setOpenLinks(true);
line->setMaximumHeight(26);
line->setMinimumHeight(26);
line->setSizePolicy(
QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum));
line->setObjectName(trimmedField);
trimmedValue.replace(Util::protocolRegex(), QStringLiteral(R"(<a href="\1">\1</a>)"));
line->setText(trimmedValue);
line->setReadOnly(true);
line->setContentsMargins(0, 0, 0, 0);
frame->layout()->addWidget(line);
}
// set into the layout
ui->gridLayout->addWidget(new QLabel(trimmedField), position, 0);
ui->gridLayout->addWidget(frame, position, 1);
}
/**
* @brief Displays message in status bar
*
* @param msg text to be displayed
* @param timeout time for which msg shall be visible
*/
void MainWindow::showStatusMessage(QString msg, int timeout) {
ui->statusBar->showMessage(msg, timeout);
}
/**
* @brief MainWindow::startReencryptPath disable ui elements and treeview
*/
void MainWindow::startReencryptPath() {
setUiElementsEnabled(false);
ui->treeView->setDisabled(true);
}
/**
* @brief MainWindow::endReencryptPath re-enable ui elements
*/
void MainWindow::endReencryptPath() { setUiElementsEnabled(true); }
/**
* @brief MainWindow::critical critical message popup wrapper.
* @param title
* @param msg
*/
void MainWindow::critical(QString title, QString msg) {
QMessageBox::critical(this, title, msg);
}

File Metadata

Mime Type
text/x-diff
Expires
Fri, Dec 19, 2:32 PM (1 d, 15 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
a6/44/4f49edfae4151564747ff95d7577

Event Timeline