1
0
Fork 0
This repository has been archived on 2023-11-15. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
comicinfo-editor/src/main.rs

457 lines
16 KiB
Rust

use std::iter::Enumerate;
use egui::{widgets, TextStyle};
use metadata::{AgeRating, LanguageISO, Metadata};
use eframe::egui;
use parsers::Parsers;
use strum::IntoEnumIterator;
mod metadata;
mod parsers;
const TEXT_SIZE_SMALL: f32 = 1.0;
const TEXT_SIZE_MEDIUM: f32 = 1.2;
const TEXT_SIZE_LARGE: f32 = 1.4;
fn main() -> Result<(), eframe::Error> {
env_logger::init();
let options = eframe::NativeOptions {
initial_window_size: Some(egui::vec2(1280.0, 720.0)),
..Default::default()
};
eframe::run_native(
"Metadata Generator",
options,
Box::new(|cc| {
cc.egui_ctx.set_pixels_per_point(TEXT_SIZE_MEDIUM);
Box::<Generator>::default()
}),
)
}
struct Generator<'a> {
show_all: bool,
metadata: Vec<Metadata<'a>>,
selected_parser: Parsers,
use_file: bool,
meta_path: Option<String>,
bundle: bool,
bundle_source: Option<String>,
bundle_path: Option<String>,
footer_height: f32,
}
impl Default for Generator<'_> {
fn default() -> Self {
Self {
show_all: false,
metadata: vec![Metadata::default()],
selected_parser: Parsers::JNovel,
use_file: true,
meta_path: None,
bundle: false,
bundle_source: None,
bundle_path: None,
footer_height: 0.0,
}
}
}
impl eframe::App for Generator<'_> {
fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) {
// Non-Metadata Options
egui::SidePanel::right("Options")
.resizable(false)
.min_width(ctx.screen_rect().width() / 3.0)
.max_width(ctx.screen_rect().width() / 3.0)
.show(ctx, |panel| {
panel.heading("Options");
panel.horizontal(|row| {
row.label("Parser: ");
egui::containers::ComboBox::from_label("")
.selected_text(self.selected_parser.to_string())
.show_ui(row, |ui| {
for rating in Parsers::iter() {
let text = rating.to_string().clone();
if ui
.selectable_value(&mut self.selected_parser, rating, text)
.clicked()
{
match self.selected_parser {
Parsers::Fakku | Parsers::Irodori => {
self.use_file = false; // TODO change to use Parser default
}
Parsers::JNovel => {
self.use_file = true; // TODO change to use Parser default
}
}
};
}
});
});
panel.horizontal(|row| {
row.label("Parser Source: ");
if row
.add(widgets::SelectableLabel::new(self.use_file, "File"))
.clicked()
{
self.use_file = true;
}
if row
.add(widgets::SelectableLabel::new(!self.use_file, "URL"))
.clicked()
{
self.use_file = false;
}
});
let file_label;
if self.use_file {
file_label = "File Path";
} else {
file_label = "URL";
}
text_input_option(panel, &mut self.meta_path, file_label, self.use_file);
// TODO this feels wrong, there must be a better way
panel.add_space(self.footer_height * 0.1);
panel.separator();
panel.add_space(self.footer_height * 0.1);
panel.horizontal(|row| {
row.label("Perform Bundle: ");
row.add(widgets::Checkbox::new(&mut self.bundle, ""));
});
if self.bundle {
text_input_option(panel, &mut self.bundle_source, "Images Folder", true);
text_input_option(panel, &mut self.bundle_path, "Output Path", true);
}
panel.add_space(self.footer_height * 2.0);
panel.horizontal(|elem| {
elem.vertical_centered(|centered| {
if centered.button("Generate Metadata").clicked() {
// Run Metadata Generation
// DO NOT SAVE RESULTS YET ONLY POPULATE DATA
println!("Ran Generation (not yet)");
}
})
});
panel.add_space(panel.available_height() - self.footer_height);
self.footer_height = panel
.horizontal(|row| {
let ppp = ctx.pixels_per_point();
row.label("Text Size:");
if row
.add(widgets::RadioButton::new(ppp == TEXT_SIZE_SMALL, "Small"))
.clicked()
{
ctx.set_pixels_per_point(TEXT_SIZE_SMALL);
}
if row
.add(widgets::RadioButton::new(ppp == TEXT_SIZE_MEDIUM, "Medium"))
.clicked()
{
ctx.set_pixels_per_point(TEXT_SIZE_MEDIUM);
}
if row
.add(widgets::RadioButton::new(ppp == TEXT_SIZE_LARGE, "Large"))
.clicked()
{
ctx.set_pixels_per_point(TEXT_SIZE_LARGE);
}
})
.response
.rect
.height();
});
// Metadata Options
egui::CentralPanel::default().show(ctx, |ui| {
ui.heading("Metadata");
// Title & Series
text_input(ui, &mut self.metadata[0].series, "Series", false);
text_input(ui, &mut self.metadata[0].title, "Title", false);
// Volume and Chapter Info
ui.horizontal(|row| {
row.label("Volume:");
if row.button("-").clicked() {
self.metadata[0].volume -= 1;
}
row.label(format!("{}", self.metadata[0].volume));
if row.button("+").clicked() {
self.metadata[0].volume += 1;
}
row.label("Chapter:");
if row.button("-").clicked() {
self.metadata[0].number -= 1;
}
row.label(format!("{}", self.metadata[0].number));
if row.button("+").clicked() {
self.metadata[0].number += 1;
}
});
ui.horizontal(|row| {
row.label("Series Chapter Count:");
if row.button("-").clicked() {
self.metadata[0].count -= 1;
}
row.label(format!("{}", self.metadata[0].count));
if row.button("+").clicked() {
self.metadata[0].count += 1;
}
});
// TODO Multiline Summary
ui.label("TODO: Summary Edit");
if let Some(summary) = &self.metadata[0].summary {
ui.label(summary);
}
// Date Inputs
let glyph_width = ctx
.fonts(|f| -> f32 { f.glyph_width(&TextStyle::Body.resolve(ui.style()), '0') });
let mut year_text = self.metadata[0].year.to_string();
ui.horizontal(|row| {
row.label("Release Date:");
if row
.add(
widgets::text_edit::TextEdit::singleline(&mut year_text)
.desired_width(5.0 * glyph_width),
)
.changed()
{
let trimmed = year_text.trim();
if trimmed == "0" {
self.metadata[0].year = -1;
self.metadata[0].month = -1;
self.metadata[0].day = -1;
} else {
self.metadata[0].year =
trimmed.parse::<i16>().unwrap_or(self.metadata[0].year);
}
};
if self.metadata[0].year >= 1970 {
let mut month_text = self.metadata[0].month.to_string();
if row
.add(
widgets::text_edit::TextEdit::singleline(&mut month_text)
.desired_width(3.0 * glyph_width),
)
.changed()
{
let trimmed = month_text.trim();
if trimmed == "0" {
self.metadata[0].month = -1;
self.metadata[0].day = -1;
} else {
self.metadata[0].month = month_text
.trim()
.parse::<i8>()
.unwrap_or(self.metadata[0].month);
}
};
if self.metadata[0].month >= 0 {
let mut day_text = self.metadata[0].day.to_string();
if row
.add(
widgets::text_edit::TextEdit::singleline(&mut day_text)
.desired_width(3.0 * glyph_width),
)
.changed()
{
let trimmed = day_text.trim();
if trimmed == "0" {
self.metadata[0].day = -1;
} else {
self.metadata[0].day = day_text
.trim()
.parse::<i8>()
.unwrap_or(self.metadata[0].day);
}
};
}
}
});
// People involved
text_input_option(ui, &mut self.metadata[0].writer, "Author", false);
text_input_option(ui, &mut self.metadata[0].letterer, "Typesetter", false);
text_input_option(ui, &mut self.metadata[0].editor, "Editor", false);
text_input_option(ui, &mut self.metadata[0].translator, "Translator", false);
text_input_option(ui, &mut self.metadata[0].publisher, "Publisher", false);
/*
tags: Vec<String>,
characters: Vec<String>,
*/
text_input(ui, &mut self.metadata[0].genre, "Genre", false);
// TODO tag list (List of bordered labels with plus that opens a new text edit)
ui.horizontal(|row| {
row.label("Page Count:");
if row.button("-").clicked() {
self.metadata[0].page_count -= 1;
}
row.label(format!("{}", self.metadata[0].page_count));
if row.button("+").clicked() {
self.metadata[0].page_count += 1;
}
});
//text_input(ui, &mut self.metadata[0].page_count, "Page Count", false);
// Lang Drop Down
ui.horizontal(|row| {
row.label("Language: ");
egui::containers::ComboBox::from_label("a")
.selected_text(self.metadata[0].language.to_string())
.show_ui(row, |ui| {
for language in LanguageISO::iter() {
let text = language.to_string().clone();
ui.selectable_value(&mut self.metadata[0].language, language, text);
}
});
});
// TODO same as with Tags but for characters
// Age Rating Drop Down
ui.horizontal(|row| {
row.label("Age Rating: ");
egui::containers::ComboBox::from_label("b")
.selected_text(self.metadata[0].age_rating.to_string())
.show_ui(row, |ui| {
for rating in AgeRating::iter() {
let text = rating.to_string().clone();
ui.selectable_value(&mut self.metadata[0].age_rating, rating, text);
}
});
});
ui.horizontal(|elem| {
elem.vertical_centered(|centered| {
if centered.button("Save Metadata").clicked() {
// Run Metadata Generation
// DO NOT SAVE RESULTS YET ONLY POPULATE DATA
self.metadata[0].save_to_xml("/home/neshura/Repositories/manga-hentai-metadata-generator/ComicInfo.xml")
}
})
});
if self.show_all {
ui.label(format!("Not Implemented yet."));
}
});
}
}
pub(crate) fn text_input_option(
ui: &mut egui::Ui,
option: &mut Option<String>,
label: &str,
file_picker: bool,
) -> egui::InnerResponse<()> {
let zero_width =
2.0 * ui.fonts(|f| -> f32 { f.glyph_width(&TextStyle::Body.resolve(ui.style()), '0') });
ui.horizontal(|row| {
row.label(format!("{}:", label));
if let Some(ref mut text) = option {
let dynamic_width = zero_width
+ text
.chars()
.map(|c| {
row.fonts(|f| -> f32 {
f.glyph_width(&TextStyle::Body.resolve(row.style()), c)
})
})
.sum::<f32>();
row.add(
widgets::text_edit::TextEdit::singleline(text).desired_width(
if dynamic_width >= zero_width * 3.0 {
dynamic_width
} else {
zero_width * 3.0
},
),
);
if text == "" {
*option = None;
}
} else {
let mut init = "".to_string();
row.add(
widgets::text_edit::TextEdit::singleline(&mut init).desired_width(zero_width * 3.0),
);
if init != "" {
*option = Some(init);
}
}
if file_picker {
if row.button("...").clicked() {
if let Some(path) = rfd::FileDialog::new().pick_file() {
*option = Some(path.display().to_string());
}
}
}
})
}
pub(crate) fn text_input(
ui: &mut egui::Ui,
option: &mut String,
label: &str,
file_picker: bool,
) -> egui::InnerResponse<()> {
let zero_width =
2.0 * ui.fonts(|f| -> f32 { f.glyph_width(&TextStyle::Body.resolve(ui.style()), '0') });
ui.horizontal(|row| {
row.label(format!("{}:", label));
let dynamic_width = zero_width
+ option
.chars()
.map(|c| {
row.fonts(|f| -> f32 {
f.glyph_width(&TextStyle::Body.resolve(row.style()), c)
})
})
.sum::<f32>();
row.add(
widgets::text_edit::TextEdit::singleline(option).desired_width(
if dynamic_width >= zero_width * 3.0 {
dynamic_width
} else {
zero_width * 3.0
},
),
);
if file_picker {
if row.button("...").clicked() {
if let Some(path) = rfd::FileDialog::new().pick_file() {
*option = path.display().to_string();
}
}
}
})
}