Add app document route core

This commit is contained in:
2026-06-02 22:10:50 +02:00
parent e15894e4ea
commit 0e03e5940a
10 changed files with 204 additions and 12 deletions

View File

@@ -5,6 +5,7 @@
#include "node_dialog_open.h"
#include "node_progress_bar.h"
#include "mp4enc.h"
#include "app_core/document_route.h"
#include "renderer_gl/opengl_capabilities.h"
#ifdef __APPLE__
@@ -187,15 +188,11 @@ void App::create()
void App::open_document(std::string path)
{
std::regex r(R"((.*)[\\/]([^\\/]+)\.(\w+)$)");
std::smatch m;
if (!std::regex_search(path, m, r))
const auto route = pp::app::classify_document_open_path(path);
if (!route)
return;
std::string base = m[1].str();
std::string name = m[2].str();
std::string ext = m[3].str();
if (str_iequals(ext, "abr"))
if (route.value().kind == pp::app::DocumentOpenKind::import_abr)
{
auto mb = message_box("Import ABR", "Would you like to import the brushes?", true);
mb->on_submit = [this, path] (Node* target) {
@@ -203,7 +200,7 @@ void App::open_document(std::string path)
target->destroy();
};
}
else if (str_iequals(ext, "ppbr"))
else if (route.value().kind == pp::app::DocumentOpenKind::import_ppbr)
{
auto mb = message_box("Import PPBR", "Would you like to import the brushes?", true);
mb->on_submit = [this, path] (Node* target) {
@@ -213,6 +210,8 @@ void App::open_document(std::string path)
}
else
{
const std::string base = route.value().directory;
const std::string name = route.value().name;
auto open_action = [this, path, base, name] {
doc_name = name;
doc_dir = base;

View File

@@ -0,0 +1,67 @@
#include "app_core/document_route.h"
#include <cctype>
#include <utility>
namespace pp::app {
namespace {
[[nodiscard]] bool is_extension_char(char value) noexcept
{
const auto ch = static_cast<unsigned char>(value);
return std::isalnum(ch) != 0 || value == '_';
}
[[nodiscard]] std::string lowercase_ascii(std::string_view value)
{
std::string lowered;
lowered.reserve(value.size());
for (const char ch : value) {
lowered.push_back(static_cast<char>(std::tolower(static_cast<unsigned char>(ch))));
}
return lowered;
}
}
pp::foundation::Result<DocumentOpenRoute> classify_document_open_path(std::string_view path)
{
const auto separator = path.find_last_of("/\\");
if (separator == std::string_view::npos || separator + 1U >= path.size()) {
return pp::foundation::Result<DocumentOpenRoute>::failure(
pp::foundation::Status::invalid_argument("document path must include a directory and file name"));
}
const auto dot = path.find_last_of('.');
if (dot == std::string_view::npos || dot <= separator + 1U || dot + 1U >= path.size()) {
return pp::foundation::Result<DocumentOpenRoute>::failure(
pp::foundation::Status::invalid_argument("document path must include a file extension"));
}
const std::string_view extension = path.substr(dot + 1U);
for (const char ch : extension) {
if (!is_extension_char(ch)) {
return pp::foundation::Result<DocumentOpenRoute>::failure(
pp::foundation::Status::invalid_argument("document extension contains unsupported characters"));
}
}
auto lowered_extension = lowercase_ascii(extension);
auto kind = DocumentOpenKind::open_project;
if (lowered_extension == "abr") {
kind = DocumentOpenKind::import_abr;
} else if (lowered_extension == "ppbr") {
kind = DocumentOpenKind::import_ppbr;
}
return pp::foundation::Result<DocumentOpenRoute>::success(
DocumentOpenRoute {
.kind = kind,
.path = std::string(path),
.directory = std::string(path.substr(0U, separator)),
.name = std::string(path.substr(separator + 1U, dot - separator - 1U)),
.extension = std::move(lowered_extension),
});
}
}

View File

@@ -0,0 +1,27 @@
#pragma once
#include "foundation/result.h"
#include <string>
#include <string_view>
namespace pp::app {
enum class DocumentOpenKind {
import_abr,
import_ppbr,
open_project,
};
struct DocumentOpenRoute {
DocumentOpenKind kind = DocumentOpenKind::open_project;
std::string path;
std::string directory;
std::string name;
std::string extension;
};
[[nodiscard]] pp::foundation::Result<DocumentOpenRoute> classify_document_open_path(
std::string_view path);
}