File indexing completed on 2024-05-12 17:08:23

0001 // SPDX-FileCopyrightText: 2018 Daniel Vrátil <dvratil@kde.org>
0002 //
0003 // SPDX-License-Identifier: LGPL-2.1-or-later
0004 
0005 #include "mainwindow.h"
0006 #include "passwordfiltermodel.h"
0007 #include "passwordprovider.h"
0008 #include "passwordsmodel.h"
0009 
0010 #include <QFormLayout>
0011 #include <QLabel>
0012 #include <QLineEdit>
0013 #include <QListView>
0014 #include <QProgressBar>
0015 #include <QPushButton>
0016 #include <QSplitter>
0017 #include <QStackedWidget>
0018 #include <QTreeView>
0019 #include <QVBoxLayout>
0020 
0021 using namespace PlasmaPass;
0022 
0023 MainWindow::MainWindow(QWidget *parent)
0024     : QMainWindow(parent)
0025 {
0026     resize(900, 350); // NOLINT(cppcoreguidelines-avoid-magic-numbers)
0027 
0028     auto w = new QWidget;
0029     setCentralWidget(w);
0030 
0031     auto h = new QHBoxLayout(w);
0032 
0033     auto splitter = new QSplitter;
0034     h->addWidget(splitter);
0035 
0036     w = new QWidget;
0037     splitter->addWidget(w);
0038 
0039     auto v = new QVBoxLayout(w);
0040 
0041     auto input = new QLineEdit;
0042     input->setClearButtonEnabled(true);
0043     input->setPlaceholderText(QStringLiteral("Search ..."));
0044     connect(input, &QLineEdit::textChanged, this, &MainWindow::onSearchChanged);
0045     v->addWidget(input);
0046 
0047     mStack = new QStackedWidget;
0048     v->addWidget(mStack);
0049 
0050     auto treeView = new QTreeView;
0051     treeView->setHeaderHidden(true);
0052     treeView->setModel(new PasswordsModel(this));
0053     connect(treeView, &QTreeView::clicked, this, &MainWindow::onPasswordClicked);
0054     mStack->addWidget(treeView);
0055 
0056     auto listView = new QListView;
0057     mFilterModel = new PasswordFilterModel(listView);
0058     mFilterModel->setSourceModel(treeView->model());
0059     listView->setModel(mFilterModel);
0060     connect(listView, &QListView::clicked, this, &MainWindow::onPasswordClicked);
0061     mStack->addWidget(listView);
0062 
0063     mStack->setCurrentIndex(0);
0064 
0065     w = new QWidget;
0066     splitter->addWidget(w);
0067 
0068     v = new QVBoxLayout(w);
0069 
0070     v->addWidget(mTitle = new QLabel);
0071     auto font = mTitle->font();
0072     font.setBold(true);
0073     mTitle->setFont(font);
0074 
0075     auto g = new QFormLayout;
0076     v->addLayout(g);
0077     g->addRow(QStringLiteral("Path:"), mPath = new QLabel());
0078     g->addRow(QStringLiteral("Type:"), mType = new QLabel());
0079     g->addRow(QStringLiteral("Password:"), mPassword = new QLabel());
0080     g->addRow(QStringLiteral("Expiration:"), mPassProgress = new QProgressBar());
0081     g->addRow(QStringLiteral("Error:"), mError = new QLabel());
0082     mPassProgress->setTextVisible(false);
0083 
0084     v->addWidget(mPassBtn = new QPushButton(QStringLiteral("Display Password")));
0085     connect(mPassBtn, &QPushButton::clicked, this, [this]() {
0086         setProvider(mCurrent.data(PasswordsModel::PasswordRole).value<PasswordProvider *>());
0087     });
0088 
0089     v->addStretch(2.0); // NOLINT(cppcoreguidelines-avoid-magic-numbers)
0090 
0091     onPasswordClicked({});
0092 }
0093 
0094 MainWindow::~MainWindow() = default;
0095 
0096 void MainWindow::setProvider(ProviderBase *provider)
0097 {
0098     mProvider = provider;
0099     if (provider->isValid()) {
0100         mPassBtn->setVisible(false);
0101         mPassword->setVisible(true);
0102         mPassword->setText(provider->secret());
0103     }
0104     if (provider->hasError()) {
0105         mError->setVisible(true);
0106         mError->setText(provider->error());
0107     }
0108 
0109     connect(provider, &ProviderBase::secretChanged, this, [this, provider]() {
0110         const auto pass = provider->secret();
0111         if (!pass.isEmpty()) {
0112             mPassword->setVisible(true);
0113             mPassword->setText(provider->secret());
0114         } else {
0115             onPasswordClicked(mCurrent);
0116         }
0117     });
0118     connect(provider, &ProviderBase::timeoutChanged, this, [this, provider]() {
0119         mPassProgress->setVisible(true);
0120         mPassProgress->setMaximum(provider->defaultTimeout());
0121         mPassProgress->setValue(provider->timeout());
0122     });
0123     connect(provider, &ProviderBase::errorChanged, this, [this, provider]() {
0124         mError->setVisible(true);
0125         mError->setText(provider->error());
0126     });
0127 }
0128 
0129 void MainWindow::onPasswordClicked(const QModelIndex &idx)
0130 {
0131     if (mProvider != nullptr) {
0132         mProvider->disconnect(this);
0133     }
0134     mCurrent = idx;
0135     mTitle->setText(idx.data(PasswordsModel::NameRole).toString());
0136     mPath->setText(idx.data(PasswordsModel::PathRole).toString());
0137     const auto type = idx.isValid() ? static_cast<PasswordsModel::EntryType>(idx.data(PasswordsModel::EntryTypeRole).toInt()) : PasswordsModel::FolderEntry;
0138     mType->setText(type == PasswordsModel::PasswordEntry ? QStringLiteral("Password") : QStringLiteral("Folder"));
0139     mPassword->setVisible(false);
0140     mPassword->clear();
0141     mPassBtn->setEnabled(type == PasswordsModel::PasswordEntry);
0142     mPassBtn->setVisible(true);
0143     mPassProgress->setVisible(false);
0144     mError->clear();
0145     mError->setVisible(false);
0146 
0147     const auto hasProvider = mCurrent.data(PasswordsModel::HasPasswordRole).toBool();
0148     if (hasProvider) {
0149         setProvider(mCurrent.data(PasswordsModel::PasswordRole).value<PasswordProvider*>());
0150     }
0151 }
0152 
0153 void MainWindow::onSearchChanged(const QString &text)
0154 {
0155     mStack->setCurrentIndex(text.isEmpty() ? 0 : 1);
0156     mFilterModel->setPasswordFilter(text);
0157 }
0158 
0159 #include "moc_mainwindow.cpp"