update_file, add multiple files, display sizes
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
#include "mainwindow.h"
|
||||
#include <QDesktopServices>
|
||||
#include <QFileDialog>
|
||||
#include <QInputDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QTemporaryFile>
|
||||
#include <iostream>
|
||||
|
||||
@@ -16,7 +18,7 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
return;
|
||||
}
|
||||
|
||||
m_vault = Vault(path.toStdString());
|
||||
m_vault = std::make_unique<Vault>(path.toStdString());
|
||||
reload_fs_tree();
|
||||
});
|
||||
|
||||
@@ -28,7 +30,7 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
return;
|
||||
}
|
||||
|
||||
m_vault = Vault(path.toStdString());
|
||||
m_vault = std::make_unique<Vault>(path.toStdString());
|
||||
reload_fs_tree();
|
||||
});
|
||||
|
||||
@@ -40,39 +42,22 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
connect(ui->fsTreeWidget, &QTreeWidget::customContextMenuRequested, this,
|
||||
&MainWindow::file_context_menu);
|
||||
|
||||
connect(ui->actionAddFile, &QAction::triggered, this, [this]() {
|
||||
connect(ui->actionAddFiles, &QAction::triggered, this, [this]() {
|
||||
if (!m_vault) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString path = QFileDialog::getOpenFileName(this, "Choose a file to add");
|
||||
if (path.isEmpty()) {
|
||||
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->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();
|
||||
});
|
||||
}
|
||||
@@ -84,7 +69,9 @@ void MainWindow::reload_fs_tree() {
|
||||
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));
|
||||
}
|
||||
ui->fsTreeWidget->resizeColumnToContents(0);
|
||||
}
|
||||
|
||||
void MainWindow::preview_file(const std::string &filename) {
|
||||
@@ -107,9 +94,15 @@ void MainWindow::edit_file(const std::string &filename) {
|
||||
}
|
||||
temp_file.flush();
|
||||
|
||||
// TODO: xdg-open or something
|
||||
std::system(("kwrite " + temp_file.fileName()).toStdString().c_str());
|
||||
// TODO: write back
|
||||
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();
|
||||
} else {
|
||||
qWarning() << "File to edit not found";
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "ui_mainwindow.h"
|
||||
#include "vault.h"
|
||||
#include <QMainWindow>
|
||||
#include <memory>
|
||||
|
||||
class MainWindow : public QMainWindow {
|
||||
Q_OBJECT
|
||||
@@ -13,7 +14,7 @@ public:
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
|
||||
std::optional<Vault> m_vault;
|
||||
std::unique_ptr<Vault> m_vault;
|
||||
|
||||
void reload_fs_tree();
|
||||
void preview_file(const std::string &filename);
|
||||
|
||||
@@ -20,11 +20,19 @@
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::ContextMenuPolicy::CustomContextMenu</enum>
|
||||
</property>
|
||||
<attribute name="headerStretchLastSection">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Name</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Size</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -52,8 +60,7 @@
|
||||
<property name="title">
|
||||
<string>Files</string>
|
||||
</property>
|
||||
<addaction name="actionCreateFile"/>
|
||||
<addaction name="actionAddFile"/>
|
||||
<addaction name="actionAddFiles"/>
|
||||
</widget>
|
||||
<addaction name="menuFile"/>
|
||||
<addaction name="menuFiles"/>
|
||||
@@ -68,7 +75,7 @@
|
||||
<string>Open</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionAddFile">
|
||||
<action name="actionAddFiles">
|
||||
<property name="text">
|
||||
<string>Add</string>
|
||||
</property>
|
||||
|
||||
69
src/vault.cc
69
src/vault.cc
@@ -1,6 +1,7 @@
|
||||
#include "vault.h"
|
||||
#include "common.h"
|
||||
#include <array>
|
||||
#include <filesystem>
|
||||
#include <iostream>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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.seekp(0, std::ios::end);
|
||||
|
||||
u64 name_size = name.size();
|
||||
u64 filename_size = filename.size();
|
||||
u64 content_size = content.size();
|
||||
m_file.write(reinterpret_cast<const char *>(&name_size), sizeof(u64));
|
||||
m_file.write(name.data(), static_cast<i64>(name_size));
|
||||
m_file.write(reinterpret_cast<const char *>(&filename_size), sizeof(u64));
|
||||
m_file.write(filename.data(), static_cast<i64>(filename_size));
|
||||
m_file.write(reinterpret_cast<const char *>(&content_size), sizeof(u64));
|
||||
m_file.write(content.data(), static_cast<i64>(content_size));
|
||||
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::optional<std::string> read_file(const std::string &name);
|
||||
void write_file(const std::string &name, const std::string &content);
|
||||
void update_file(const std::string &name, const std::string &content);
|
||||
|
||||
private:
|
||||
std::string m_path;
|
||||
|
||||
Reference in New Issue
Block a user