164 lines
5.1 KiB
C++
164 lines
5.1 KiB
C++
#include "mainwindow.h"
|
|
#include <QDesktopServices>
|
|
#include <QFileDialog>
|
|
#include <QInputDialog>
|
|
#include <QMessageBox>
|
|
#include <QTemporaryFile>
|
|
#include <botan/hex.h>
|
|
|
|
MainWindow::MainWindow(QWidget *parent)
|
|
: QMainWindow(parent), ui(std::make_unique<Ui::MainWindow>()) {
|
|
ui->setupUi(this);
|
|
|
|
ui->filePreview->setVisible(false);
|
|
|
|
connect(ui->actionNew, &QAction::triggered, this, [this]() {
|
|
QString path = QFileDialog::getSaveFileName(this, "Choose vault location",
|
|
QDir::currentPath(),
|
|
"Dull Vaults (*.dull)");
|
|
if (path.isEmpty()) {
|
|
return;
|
|
}
|
|
|
|
QString password = QInputDialog::getText(
|
|
this, "Choose a password", "Choose a password", QLineEdit::Password);
|
|
if (password.length() < 5) {
|
|
QMessageBox::critical(this, "Error",
|
|
"Password must be at least 5 characters long.");
|
|
return;
|
|
}
|
|
|
|
std::ofstream create(path.toStdString(), std::ios::binary);
|
|
create.write("DULL", 4);
|
|
create.write(to_char_ptr(&VERSION), sizeof(VERSION));
|
|
create.close();
|
|
|
|
m_vault =
|
|
std::make_unique<Vault>(path.toStdString(), password.toStdString());
|
|
reload_fs_tree();
|
|
});
|
|
|
|
connect(ui->actionOpen, &QAction::triggered, this, [this]() {
|
|
QString path = QFileDialog::getOpenFileName(this, "Choose vault to open",
|
|
QDir::currentPath(),
|
|
"Dull Vaults (*.dull)");
|
|
if (path.isEmpty()) {
|
|
return;
|
|
}
|
|
|
|
QString password = QInputDialog::getText(
|
|
this, "Unlock the vault", "Enter vault password", QLineEdit::Password);
|
|
if (password.length() < 5) {
|
|
QMessageBox::critical(this, "Error",
|
|
"Password must be at least 5 characters long.");
|
|
return;
|
|
}
|
|
|
|
// TODO: check if password valid
|
|
|
|
m_vault =
|
|
std::make_unique<Vault>(path.toStdString(), password.toStdString());
|
|
reload_fs_tree();
|
|
});
|
|
|
|
connect(
|
|
ui->fsTreeWidget, &QTreeWidget::itemClicked,
|
|
[this](QTreeWidgetItem *, i32) { ui->filePreview->setVisible(false); });
|
|
|
|
connect(ui->fsTreeWidget, &QTreeWidget::customContextMenuRequested, this,
|
|
&MainWindow::file_context_menu);
|
|
|
|
connect(ui->actionAddFiles, &QAction::triggered, this, [this]() {
|
|
if (!m_vault) {
|
|
return;
|
|
}
|
|
|
|
QStringList paths =
|
|
QFileDialog::getOpenFileNames(this, "Choose files to add");
|
|
for (const auto &path : paths) {
|
|
std::ifstream file(path.toStdString(), std::ios::binary);
|
|
|
|
std::string content((std::istreambuf_iterator<char>(file)),
|
|
std::istreambuf_iterator<char>());
|
|
|
|
m_vault->create_file(path_to_filename(path.toStdString()), content);
|
|
}
|
|
|
|
reload_fs_tree();
|
|
});
|
|
}
|
|
|
|
void MainWindow::reload_fs_tree() {
|
|
ui->menuFiles->setEnabled(true);
|
|
ui->fsTreeWidget->clear();
|
|
|
|
auto headers = m_vault->read_file_headers();
|
|
for (const auto &header : headers) {
|
|
auto *item = new QTreeWidgetItem(ui->fsTreeWidget);
|
|
item->setText(0, QString::fromStdString(header.name));
|
|
item->setText(1, QString::number(header.size));
|
|
item->setText(2, QString::number(header.offset));
|
|
item->setText(3, QString::fromStdString(Botan::hex_encode(header.nonce)));
|
|
}
|
|
ui->fsTreeWidget->resizeColumnToContents(0);
|
|
}
|
|
|
|
void MainWindow::preview_file(const std::string &filename) {
|
|
ui->filePreview->setVisible(true);
|
|
|
|
auto content = m_vault->read_file(filename);
|
|
if (content) {
|
|
ui->filePreview->setText(QString::fromStdString(content.value()));
|
|
} else {
|
|
qWarning() << "File to preview not found";
|
|
}
|
|
}
|
|
|
|
void MainWindow::edit_file(const std::string &filename) {
|
|
auto content = m_vault->read_file(filename);
|
|
if (content) {
|
|
QTemporaryFile temp_file;
|
|
ASSERT(temp_file.open());
|
|
{
|
|
QTextStream out(&temp_file);
|
|
out << QString::fromStdString(content.value());
|
|
}
|
|
temp_file.flush();
|
|
|
|
QDesktopServices::openUrl(QUrl::fromLocalFile(temp_file.fileName()));
|
|
QMessageBox::information(this, "Edit",
|
|
"Please edit the file in the opened editor and "
|
|
"save it. Click OK when done.");
|
|
|
|
temp_file.seek(0);
|
|
QTextStream in(&temp_file);
|
|
m_vault->update_file(filename, in.readAll().toStdString());
|
|
reload_fs_tree();
|
|
|
|
// QTemporaryFile gets deleted when it goes out of scope
|
|
} else {
|
|
qWarning() << "File to edit not found";
|
|
}
|
|
}
|
|
|
|
void MainWindow::file_context_menu(const QPoint &pos) {
|
|
QTreeWidgetItem *item = ui->fsTreeWidget->itemAt(pos);
|
|
if (item == nullptr) {
|
|
return;
|
|
}
|
|
|
|
QMenu menu(this);
|
|
|
|
QAction *preview_action = menu.addAction(
|
|
style()->standardIcon(QStyle::SP_FileDialogContentsView), "Preview");
|
|
connect(preview_action, &QAction::triggered, this,
|
|
[this, item]() { preview_file(item->text(0).toStdString()); });
|
|
|
|
QAction *edit_action = menu.addAction(
|
|
style()->standardIcon(QStyle::SP_FileDialogDetailedView), "Edit");
|
|
connect(edit_action, &QAction::triggered, this,
|
|
[this, item]() { edit_file(item->text(0).toStdString()); });
|
|
|
|
menu.exec(ui->fsTreeWidget->mapToGlobal(pos));
|
|
}
|