update_file, add multiple files, display sizes
This commit is contained in:
@@ -1,6 +1,8 @@
|
|||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
|
#include <QDesktopServices>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QInputDialog>
|
#include <QInputDialog>
|
||||||
|
#include <QMessageBox>
|
||||||
#include <QTemporaryFile>
|
#include <QTemporaryFile>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
@@ -16,7 +18,7 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_vault = Vault(path.toStdString());
|
m_vault = std::make_unique<Vault>(path.toStdString());
|
||||||
reload_fs_tree();
|
reload_fs_tree();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -28,7 +30,7 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_vault = Vault(path.toStdString());
|
m_vault = std::make_unique<Vault>(path.toStdString());
|
||||||
reload_fs_tree();
|
reload_fs_tree();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -40,39 +42,22 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
connect(ui->fsTreeWidget, &QTreeWidget::customContextMenuRequested, this,
|
connect(ui->fsTreeWidget, &QTreeWidget::customContextMenuRequested, this,
|
||||||
&MainWindow::file_context_menu);
|
&MainWindow::file_context_menu);
|
||||||
|
|
||||||
connect(ui->actionAddFile, &QAction::triggered, this, [this]() {
|
connect(ui->actionAddFiles, &QAction::triggered, this, [this]() {
|
||||||
if (!m_vault) {
|
if (!m_vault) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString path = QFileDialog::getOpenFileName(this, "Choose a file to add");
|
QStringList paths =
|
||||||
if (path.isEmpty()) {
|
QFileDialog::getOpenFileNames(this, "Choose files to add");
|
||||||
return;
|
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->write_file(path_to_filename(path.toStdString()), content);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ifstream file(path.toStdString(), std::ios::binary);
|
|
||||||
|
|
||||||
std::string content((std::istreambuf_iterator<char>(file)),
|
|
||||||
std::istreambuf_iterator<char>());
|
|
||||||
|
|
||||||
m_vault->write_file(path_to_filename(path.toStdString()), content);
|
|
||||||
|
|
||||||
reload_fs_tree();
|
|
||||||
});
|
|
||||||
|
|
||||||
connect(ui->actionCreateFile, &QAction::triggered, this, [this]() {
|
|
||||||
if (!m_vault) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString path =
|
|
||||||
QInputDialog::getText(this, "Create File", "Where to create the file");
|
|
||||||
if (path.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_vault->write_file(path.toStdString(), "");
|
|
||||||
|
|
||||||
reload_fs_tree();
|
reload_fs_tree();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -84,7 +69,9 @@ void MainWindow::reload_fs_tree() {
|
|||||||
for (const auto &header : headers) {
|
for (const auto &header : headers) {
|
||||||
auto *item = new QTreeWidgetItem(ui->fsTreeWidget);
|
auto *item = new QTreeWidgetItem(ui->fsTreeWidget);
|
||||||
item->setText(0, QString::fromStdString(header.name));
|
item->setText(0, QString::fromStdString(header.name));
|
||||||
|
item->setText(1, QString::number(header.size));
|
||||||
}
|
}
|
||||||
|
ui->fsTreeWidget->resizeColumnToContents(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::preview_file(const std::string &filename) {
|
void MainWindow::preview_file(const std::string &filename) {
|
||||||
@@ -107,9 +94,15 @@ void MainWindow::edit_file(const std::string &filename) {
|
|||||||
}
|
}
|
||||||
temp_file.flush();
|
temp_file.flush();
|
||||||
|
|
||||||
// TODO: xdg-open or something
|
QDesktopServices::openUrl(QUrl::fromLocalFile(temp_file.fileName()));
|
||||||
std::system(("kwrite " + temp_file.fileName()).toStdString().c_str());
|
QMessageBox::information(this, "Edit",
|
||||||
// TODO: write back
|
"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();
|
||||||
} else {
|
} else {
|
||||||
qWarning() << "File to edit not found";
|
qWarning() << "File to edit not found";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include "ui_mainwindow.h"
|
#include "ui_mainwindow.h"
|
||||||
#include "vault.h"
|
#include "vault.h"
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
class MainWindow : public QMainWindow {
|
class MainWindow : public QMainWindow {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -13,7 +14,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
Ui::MainWindow *ui;
|
Ui::MainWindow *ui;
|
||||||
|
|
||||||
std::optional<Vault> m_vault;
|
std::unique_ptr<Vault> m_vault;
|
||||||
|
|
||||||
void reload_fs_tree();
|
void reload_fs_tree();
|
||||||
void preview_file(const std::string &filename);
|
void preview_file(const std::string &filename);
|
||||||
|
|||||||
@@ -20,11 +20,19 @@
|
|||||||
<property name="contextMenuPolicy">
|
<property name="contextMenuPolicy">
|
||||||
<enum>Qt::ContextMenuPolicy::CustomContextMenu</enum>
|
<enum>Qt::ContextMenuPolicy::CustomContextMenu</enum>
|
||||||
</property>
|
</property>
|
||||||
|
<attribute name="headerStretchLastSection">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
<column>
|
<column>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Name</string>
|
<string>Name</string>
|
||||||
</property>
|
</property>
|
||||||
</column>
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>Size</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
@@ -52,8 +60,7 @@
|
|||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Files</string>
|
<string>Files</string>
|
||||||
</property>
|
</property>
|
||||||
<addaction name="actionCreateFile"/>
|
<addaction name="actionAddFiles"/>
|
||||||
<addaction name="actionAddFile"/>
|
|
||||||
</widget>
|
</widget>
|
||||||
<addaction name="menuFile"/>
|
<addaction name="menuFile"/>
|
||||||
<addaction name="menuFiles"/>
|
<addaction name="menuFiles"/>
|
||||||
@@ -68,7 +75,7 @@
|
|||||||
<string>Open</string>
|
<string>Open</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="actionAddFile">
|
<action name="actionAddFiles">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Add</string>
|
<string>Add</string>
|
||||||
</property>
|
</property>
|
||||||
|
|||||||
69
src/vault.cc
69
src/vault.cc
@@ -1,6 +1,7 @@
|
|||||||
#include "vault.h"
|
#include "vault.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <filesystem>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
Vault::Vault(std::string path) : m_path(std::move(path)) {
|
Vault::Vault(std::string path) : m_path(std::move(path)) {
|
||||||
@@ -78,15 +79,75 @@ std::optional<std::string> Vault::read_file(const std::string &filename) {
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Vault::write_file(const std::string &name, const std::string &content) {
|
void Vault::write_file(const std::string &filename,
|
||||||
|
const std::string &content) {
|
||||||
m_file.clear();
|
m_file.clear();
|
||||||
m_file.seekp(0, std::ios::end);
|
m_file.seekp(0, std::ios::end);
|
||||||
|
|
||||||
u64 name_size = name.size();
|
u64 filename_size = filename.size();
|
||||||
u64 content_size = content.size();
|
u64 content_size = content.size();
|
||||||
m_file.write(reinterpret_cast<const char *>(&name_size), sizeof(u64));
|
m_file.write(reinterpret_cast<const char *>(&filename_size), sizeof(u64));
|
||||||
m_file.write(name.data(), static_cast<i64>(name_size));
|
m_file.write(filename.data(), static_cast<i64>(filename_size));
|
||||||
m_file.write(reinterpret_cast<const char *>(&content_size), sizeof(u64));
|
m_file.write(reinterpret_cast<const char *>(&content_size), sizeof(u64));
|
||||||
m_file.write(content.data(), static_cast<i64>(content_size));
|
m_file.write(content.data(), static_cast<i64>(content_size));
|
||||||
m_file.flush();
|
m_file.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Vault::update_file(const std::string &filename,
|
||||||
|
const std::string &content) {
|
||||||
|
m_file.clear();
|
||||||
|
m_file.seekg(AFTER_HEADER_OFFSET, std::ios::beg);
|
||||||
|
|
||||||
|
i64 entry_start = -1;
|
||||||
|
u64 entry_total_size = 0;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
i64 current_pos = m_file.tellg();
|
||||||
|
|
||||||
|
u64 name_size = 0;
|
||||||
|
if (!m_file.read(reinterpret_cast<char *>(&name_size), sizeof(u64))) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
name.resize(name_size);
|
||||||
|
m_file.read(name.data(), static_cast<i64>(name_size));
|
||||||
|
|
||||||
|
u64 content_size = 0;
|
||||||
|
m_file.read(reinterpret_cast<char *>(&content_size), sizeof(u64));
|
||||||
|
|
||||||
|
if (name == filename) {
|
||||||
|
entry_start = current_pos;
|
||||||
|
entry_total_size = sizeof(u64) + name_size + sizeof(u64) + content_size;
|
||||||
|
m_file.seekg(static_cast<i64>(content_size), std::ios::cur);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_file.seekg(static_cast<i64>(content_size), std::ios::cur);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry_start != -1) {
|
||||||
|
i64 entry_end = entry_start + static_cast<i64>(entry_total_size);
|
||||||
|
|
||||||
|
m_file.clear();
|
||||||
|
m_file.seekg(entry_end, std::ios::beg);
|
||||||
|
std::string remaining;
|
||||||
|
remaining.assign(std::istreambuf_iterator<char>(m_file),
|
||||||
|
std::istreambuf_iterator<char>());
|
||||||
|
|
||||||
|
m_file.clear();
|
||||||
|
m_file.seekp(entry_start, std::ios::beg);
|
||||||
|
m_file.write(remaining.data(), static_cast<i64>(remaining.size()));
|
||||||
|
|
||||||
|
i64 new_size = entry_start + static_cast<i64>(remaining.size());
|
||||||
|
m_file.flush();
|
||||||
|
m_file.close();
|
||||||
|
|
||||||
|
std::filesystem::resize_file(m_path, new_size);
|
||||||
|
|
||||||
|
m_file.open(m_path, std::ios::in | std::ios::out | std::ios::binary);
|
||||||
|
ASSERT(m_file.good());
|
||||||
|
}
|
||||||
|
|
||||||
|
write_file(filename, content);
|
||||||
|
}
|
||||||
@@ -20,6 +20,7 @@ public:
|
|||||||
std::vector<FileHeader> read_file_headers();
|
std::vector<FileHeader> read_file_headers();
|
||||||
std::optional<std::string> read_file(const std::string &name);
|
std::optional<std::string> read_file(const std::string &name);
|
||||||
void write_file(const std::string &name, const std::string &content);
|
void write_file(const std::string &name, const std::string &content);
|
||||||
|
void update_file(const std::string &name, const std::string &content);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_path;
|
std::string m_path;
|
||||||
|
|||||||
Reference in New Issue
Block a user