QImageTagger/mainwindow.cpp
2024-06-11 14:31:52 +02:00

174 lines
4.4 KiB
C++

#include "mainwindow.h"
#include "./ui_mainwindow.h"
#include <QFileDialog>
#include <QMessageBox>
#include <QJsonDocument>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->actionOpen, &QAction::triggered, this, [this](bool){open();});
connect(ui->nextButton, &QPushButton::clicked, this, [this](bool){setImage(index+1);});
connect(ui->prevButton, &QPushButton::clicked, this, [this](bool){setImage(index-1);});
connect(ui->actionSave, &QAction::triggered, this, [this](bool){save();});
connect(ui->actionQuit, &QAction::triggered, this, [this](bool){close();});
ui->verticalLayout->addWidget(&status);
ui->imageLabel->setScaledContents( true );
ui->imageLabel->setSizePolicy( QSizePolicy::Ignored, QSizePolicy::Ignored );
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::open()
{
QString dirpath = QFileDialog::getExistingDirectory(this, "Choose a directory with images", "", QFlags<QFileDialog::Option>());
if(dirpath.isEmpty())
return;
openDir(dirpath.toStdString());
}
void MainWindow::openDir(const std::filesystem::path& path)
{
imageMetas.clear();
QDir dir(path);
bool hasMetadata = false;
std::vector<std::filesystem::path> imagePaths;
for(QString filename : dir.entryList(QDir::Files))
{
if(filename == "metadata.jsonl")
hasMetadata = true;
else if(filename.endsWith(".jpg") || filename.endsWith(".png"))
imagePaths.push_back(path/filename.toStdString());
}
if(imagePaths.empty())
{
QMessageBox::warning(this, "No images found", "No valid images found in this directory");
return;
}
if(hasMetadata)
{
if(!loadMetadata(path/"metadata.jsonl"))
QMessageBox::warning(this, "Could not read",
(std::string("Could not read ") + path.string() + std::string("/metadata.jsonl, file contains errors")).c_str());
}
for(const std::filesystem::path &path : imagePaths)
{
if(imageIsKnown(path))
continue;
qDebug()<<path.c_str()<<"not in existing metadata.jsonl";
imageMetas.push_back(ImageMeta(path));
}
this->dir = path;
ui->textEdit->document()->setPlainText(imageMetas[0].text);
setImage(0);
}
void MainWindow::setImage(ssize_t index)
{
if(imageMetas.empty())
return;
else if(index > imageMetas.size()-1)
return;
else if(index < 0)
return;
imageMetas[this->index].text = ui->textEdit->document()->toPlainText();
this->index = index;
ui->counterLabel->setText(QString::asprintf("%04zu/%04zu", index, imageMetas.size()-1));
ui->textEdit->document()->setPlainText(imageMetas[index].text);
QPixmap image;
bool ret = image.load(imageMetas[index].path.string().c_str());
if(!ret)
{
ui->imageLabel->setPixmap(QPixmap());
ui->imageLabel->setText(("Unable to load " + imageMetas[index].path.string()).c_str());
ui->imageLabel->setText("No image loaded");
}
else
{
ui->imageLabel->setPixmap(image);
}
ui->imageLabel->setText("");
}
bool MainWindow::loadMetadata(const std::filesystem::path& path)
{
QFile meta(path);
meta.open(QIODeviceBase::ReadOnly);
if(!meta.isOpen())
{
qWarning()<<("Could not open " + path.string()).c_str();
return false;
}
QByteArray line = meta.readLine();
while(!line.isEmpty())
{
QJsonParseError error;
QJsonDocument json = QJsonDocument::fromJson(line, &error);
if(json.isNull())
{
qWarning()<<error.errorString();
return false;
}
imageMetas.push_back(ImageMeta(json.object(), path.parent_path()));
line = meta.readLine();
}
return true;
}
bool MainWindow::imageIsKnown(const std::filesystem::path& path)
{
for(const ImageMeta& meta : imageMetas)
{
if(meta.path == path)
return true;
}
return false;
}
void MainWindow::save()
{
if(imageMetas.empty())
return;
QFile file(dir/"metadata.jsonl");
if(!file.open(QIODeviceBase::WriteOnly | QIODeviceBase::Truncate))
{
QMessageBox::warning(this, "Could not save",
("Could not save, can not open " + (dir/"metadata.jsonl").string() + " for writeing").c_str());
return;
}
for(const ImageMeta& meta : imageMetas)
{
QJsonObject obj;
obj["file_name"] = std::filesystem::relative(meta.path, dir).string().c_str();
obj["text"] = meta.text;
QJsonDocument document(obj);
QByteArray json = document.toJson(QJsonDocument::Compact);
json.removeIf([](char ch){return ch == '\n';});
json.append('\n');
file.write(json);
}
file.close();
QMessageBox::information(this, "Saved", ("Saved to " + (dir/"metadata.jsonl").string()).c_str());
}