updating cards

This commit is contained in:
leca 2024-04-14 12:12:18 +03:00
parent 4ec6e32357
commit 47fd5b3b9d
14 changed files with 87 additions and 32 deletions

View File

@ -1,11 +1,11 @@
<mxfile host="app.diagrams.net" modified="2024-04-05T22:47:36.373Z" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36" etag="5XWwemJAtwHYlzdHloKA" version="24.2.2" type="device"> <mxfile host="app.diagrams.net" modified="2024-04-14T07:14:49.035Z" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36" etag="fvixqLn8GSK1Vul1DARw" version="24.2.5" type="device">
<diagram id="R2lEEEUBdFMjLlhIrx00" name="Page-1"> <diagram id="R2lEEEUBdFMjLlhIrx00" name="Page-1">
<mxGraphModel dx="1434" dy="748" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0" extFonts="Permanent Marker^https://fonts.googleapis.com/css?family=Permanent+Marker"> <mxGraphModel dx="1434" dy="748" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0" extFonts="Permanent Marker^https://fonts.googleapis.com/css?family=Permanent+Marker">
<root> <root>
<mxCell id="0" /> <mxCell id="0" />
<mxCell id="1" parent="0" /> <mxCell id="1" parent="0" />
<mxCell id="C-vyLk0tnHw3VtMMgP7b-23" value="cards&#xa;" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;" parent="1" vertex="1"> <mxCell id="C-vyLk0tnHw3VtMMgP7b-23" value="cards&#xa;" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;" parent="1" vertex="1">
<mxGeometry x="125" y="123" width="330" height="150" as="geometry" /> <mxGeometry x="125" y="111" width="330" height="180" as="geometry" />
</mxCell> </mxCell>
<mxCell id="C-vyLk0tnHw3VtMMgP7b-24" value="" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" parent="C-vyLk0tnHw3VtMMgP7b-23" vertex="1"> <mxCell id="C-vyLk0tnHw3VtMMgP7b-24" value="" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" parent="C-vyLk0tnHw3VtMMgP7b-23" vertex="1">
<mxGeometry y="30" width="330" height="30" as="geometry" /> <mxGeometry y="30" width="330" height="30" as="geometry" />
@ -41,20 +41,33 @@
<mxRectangle width="30" height="30" as="alternateBounds" /> <mxRectangle width="30" height="30" as="alternateBounds" />
</mxGeometry> </mxGeometry>
</mxCell> </mxCell>
<mxCell id="B8Iv1AbKk0bG_LbG7-Me-13" value="hieroglyph VARCHAR(2)" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;" parent="B8Iv1AbKk0bG_LbG7-Me-11" vertex="1"> <mxCell id="B8Iv1AbKk0bG_LbG7-Me-13" value="hieroglyph VARCHAR(64)" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;" parent="B8Iv1AbKk0bG_LbG7-Me-11" vertex="1">
<mxGeometry x="30" width="300" height="30" as="geometry">
<mxRectangle width="300" height="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="BE118a502lDT9OyVwVR6-1" value="" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="C-vyLk0tnHw3VtMMgP7b-23">
<mxGeometry y="120" width="330" height="30" as="geometry" />
</mxCell>
<mxCell id="BE118a502lDT9OyVwVR6-2" value="                    " style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;" vertex="1" parent="BE118a502lDT9OyVwVR6-1">
<mxGeometry width="30" height="30" as="geometry">
<mxRectangle width="30" height="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="BE118a502lDT9OyVwVR6-3" value="reading VARCHAR(64)" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;" vertex="1" parent="BE118a502lDT9OyVwVR6-1">
<mxGeometry x="30" width="300" height="30" as="geometry"> <mxGeometry x="30" width="300" height="30" as="geometry">
<mxRectangle width="300" height="30" as="alternateBounds" /> <mxRectangle width="300" height="30" as="alternateBounds" />
</mxGeometry> </mxGeometry>
</mxCell> </mxCell>
<mxCell id="B8Iv1AbKk0bG_LbG7-Me-14" value="" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="C-vyLk0tnHw3VtMMgP7b-23" vertex="1"> <mxCell id="B8Iv1AbKk0bG_LbG7-Me-14" value="" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="C-vyLk0tnHw3VtMMgP7b-23" vertex="1">
<mxGeometry y="120" width="330" height="30" as="geometry" /> <mxGeometry y="150" width="330" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="B8Iv1AbKk0bG_LbG7-Me-15" value="" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;" parent="B8Iv1AbKk0bG_LbG7-Me-14" vertex="1"> <mxCell id="B8Iv1AbKk0bG_LbG7-Me-15" value="" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;" parent="B8Iv1AbKk0bG_LbG7-Me-14" vertex="1">
<mxGeometry width="30" height="30" as="geometry"> <mxGeometry width="30" height="30" as="geometry">
<mxRectangle width="30" height="30" as="alternateBounds" /> <mxRectangle width="30" height="30" as="alternateBounds" />
</mxGeometry> </mxGeometry>
</mxCell> </mxCell>
<mxCell id="B8Iv1AbKk0bG_LbG7-Me-16" value="reading VARCHAR(128)" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;" parent="B8Iv1AbKk0bG_LbG7-Me-14" vertex="1"> <mxCell id="B8Iv1AbKk0bG_LbG7-Me-16" value="translation VARCHAR(128)" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;" parent="B8Iv1AbKk0bG_LbG7-Me-14" vertex="1">
<mxGeometry x="30" width="300" height="30" as="geometry"> <mxGeometry x="30" width="300" height="30" as="geometry">
<mxRectangle width="300" height="30" as="alternateBounds" /> <mxRectangle width="300" height="30" as="alternateBounds" />
</mxGeometry> </mxGeometry>

View File

@ -36,6 +36,13 @@
<property name="placeholder-text">Reading</property> <property name="placeholder-text">Reading</property>
</object> </object>
</child> </child>
<child>
<object class="GtkEntry" id="translation_entry">
<property name="halign">GTK_ALIGN_CENTER</property>
<property name="valign">GTK_ALIGN_CENTER</property>
<property name="placeholder-text">Translation</property>
</object>
</child>
<child> <child>
<object class="GtkButton" id="done_button"> <object class="GtkButton" id="done_button">
<property name="halign">GTK_ALIGN_CENTER</property> <property name="halign">GTK_ALIGN_CENTER</property>

View File

@ -19,7 +19,7 @@
</object> </object>
</child> </child>
<child> <child>
<object class="GtkLabel" id="reading_label"> <object class="GtkLabel" id="translation_label">
<property name="halign">GTK_ALIGN_END</property> <property name="halign">GTK_ALIGN_END</property>
<property name="valign">GTK_ALIGN_CENTER</property> <property name="valign">GTK_ALIGN_CENTER</property>
<property name="margin-end">50</property> <property name="margin-end">50</property>

3
src/cards.rs Normal file
View File

@ -0,0 +1,3 @@
pub struct Card {
}

View File

@ -43,8 +43,9 @@ pub fn init() {
connection.execute("CREATE TABLE IF NOT EXISTS cards ( connection.execute("CREATE TABLE IF NOT EXISTS cards (
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
imagename CHAR(64), imagename CHAR(64),
hieroglyph VARCHAR(2), hieroglyph VARCHAR(64),
reading VARCHAR(128) reading VARCHAR(64),
translation VARCHAR(128)
)",()).unwrap(); )",()).unwrap();
} }

View File

@ -1,5 +1,8 @@
use rusqlite::Connection;
use std::fs; use std::fs;
use crate::db::get_db_path;
#[derive(PartialEq)] #[derive(PartialEq)]
pub struct DictionaryEntry { pub struct DictionaryEntry {
hieroglyph: String, hieroglyph: String,
@ -9,7 +12,11 @@ pub struct DictionaryEntry {
impl std::clone::Clone for DictionaryEntry { impl std::clone::Clone for DictionaryEntry {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self { hieroglyph: self.hieroglyph.clone(), reading: self.reading.clone(), translation: self.translation.clone() } Self {
hieroglyph: self.hieroglyph.clone(),
reading: self.reading.clone(),
translation: self.translation.clone(),
}
} }
} }
@ -70,9 +77,8 @@ fn read_and_parse(path: &String) -> Vec<DictionaryEntry> {
result result
} }
fn deduplicate (entries: &Vec<DictionaryEntry>) -> Vec<DictionaryEntry>{ fn deduplicate(entries: &Vec<DictionaryEntry>) -> Vec<DictionaryEntry> {
let mut deduplicated: Vec<DictionaryEntry> = Vec::new();
let mut deduplicated:Vec<DictionaryEntry> = Vec::new();
for entry in entries.iter() { for entry in entries.iter() {
let mut is_dup = false; let mut is_dup = false;
@ -85,8 +91,11 @@ fn deduplicate (entries: &Vec<DictionaryEntry>) -> Vec<DictionaryEntry>{
} }
if is_dup { if is_dup {
let pos = deduplicated.iter().position(|x| x.hieroglyph == entry.hieroglyph).unwrap(); let pos = deduplicated
deduplicated[pos].translation += &(String::from(" ; ") + &entry.translation); .iter()
.position(|x| x.hieroglyph == entry.hieroglyph)
.unwrap();
deduplicated[pos].translation += &(String::from(";") + &entry.translation);
} else { } else {
deduplicated.push(entry.clone()); deduplicated.push(entry.clone());
} }
@ -95,10 +104,24 @@ fn deduplicate (entries: &Vec<DictionaryEntry>) -> Vec<DictionaryEntry>{
deduplicated deduplicated
} }
pub fn import(path: &String) -> Vec<DictionaryEntry>{ fn write_to_database(dict: &Vec<DictionaryEntry>) {
let conn = Connection::open(get_db_path()).unwrap();
for line in dict.iter() {
match conn.execute("INSERT OR REPLACE INTO cards (id, hieroglyph, reading, translation) VALUES ((SELECT id FROM cards WHERE hieroglyph = ?1), ?1, ?2, ?3)", [&line.hieroglyph, &line.reading, &line.translation]) {
Ok(_) => (),
Err(e) => {
println!("{e}" );
panic!("Cannot update database with words form dictionary")
}
};
}
}
pub fn import(path: &String) {
let dictionary = read_and_parse(path); let dictionary = read_and_parse(path);
let dictionary = deduplicate(&dictionary); let dictionary = deduplicate(&dictionary);
dictionary // write_to_database(&dictionary);
} }
// pub fn write_to_file(path: &String, dict: &Vec<Entry>) { // pub fn write_to_file(path: &String, dict: &Vec<Entry>) {

View File

@ -1,4 +1,3 @@
use rand::Rng; use rand::Rng;
const VOWELS: usize = 5; const VOWELS: usize = 5;

View File

@ -41,7 +41,7 @@ fn main() -> glib::ExitCode {
db::init(); // Create database if not exists, create program's home if not exists, etc... db::init(); // Create database if not exists, create program's home if not exists, etc...
dictionary::import(&String::from("./reparsed.txt")); // dictionary::import(&String::from("./dictionary.txt")); // Read file, parse it, deduplicate and append to the database.
let app: Application = Application::builder().application_id(APP_ID).build(); let app: Application = Application::builder().application_id(APP_ID).build();

View File

@ -80,7 +80,7 @@ impl ObjectImpl for MemoryCardsEditScene {
"" => None, "" => None,
_ => { _ => {
let search_option = e.text().to_string(); let search_option = e.text().to_string();
let conditions = format!("hieroglyph LIKE '%{}%' OR reading LIKE '%{}%'", search_option, search_option); let conditions = format!("hieroglyph LIKE '%{}%'", search_option);
Some(conditions) Some(conditions)
} }
} }
@ -108,7 +108,7 @@ impl MemoryCardsEditScene {
None => "".to_owned() None => "".to_owned()
}; };
let sql = format!("SELECT imagename, hieroglyph, reading FROM cards {selector}"); let sql = format!("SELECT imagename, hieroglyph, reading, translation FROM cards {selector}");
let mut stmt = conn let mut stmt = conn
.prepare(sql.as_str()) .prepare(sql.as_str())
.unwrap(); .unwrap();
@ -118,7 +118,9 @@ impl MemoryCardsEditScene {
let image_path: String = get_images_store_path() + &image_path; let image_path: String = get_images_store_path() + &image_path;
let hieroglyph: String = row.get(1).unwrap(); let hieroglyph: String = row.get(1).unwrap();
let reading: String = row.get(2).unwrap(); let reading: String = row.get(2).unwrap();
let entry = CardEntry::new(&image_path, &hieroglyph, &reading); let hieroglyph = format!("{} ({})", hieroglyph, reading);
let translation: String = row.get(3).unwrap();
let entry = CardEntry::new(&image_path, &hieroglyph, &translation);
Ok(entry) Ok(entry)
}) })
.unwrap(); .unwrap();
@ -188,10 +190,11 @@ async fn file_choose_dialog<W: IsA<gtk::Window>>(window: Rc<W>) {
let hieroglyph = w.get_hieroglyph_input(); let hieroglyph = w.get_hieroglyph_input();
let reading = w.get_reading_input(); let reading = w.get_reading_input();
let translation = w.get_translation_input();
let conn = Connection::open(get_db_path()).unwrap(); let conn = Connection::open(get_db_path()).unwrap();
let query = "INSERT INTO cards (imagename, hieroglyph, reading) VALUES(?1, ?2, ?3)"; let query = "INSERT INTO cards (imagename, hieroglyph, reading, translation) VALUES(?1, ?2, ?3, ?4)";
conn.execute(query, (&new_filename, &hieroglyph, &reading)).unwrap(); conn.execute(query, (&new_filename, &hieroglyph, &reading, &translation)).unwrap();
w.close(); w.close();
}), }),
); );

View File

@ -14,6 +14,8 @@ pub struct MemoryCardsNewScene {
#[template_child] #[template_child]
pub reading_entry: TemplateChild<Entry>, pub reading_entry: TemplateChild<Entry>,
#[template_child] #[template_child]
pub translation_entry: TemplateChild<Entry>,
#[template_child]
pub done_button: TemplateChild<Button>, pub done_button: TemplateChild<Button>,
} }

View File

@ -33,6 +33,10 @@ impl MemoryCardsNewScene {
self.imp().reading_entry.text().to_string() self.imp().reading_entry.text().to_string()
} }
pub fn get_translation_input(&self) -> String {
self.imp().translation_entry.text().to_string()
}
pub fn get_done_button(&self) -> &Button { pub fn get_done_button(&self) -> &Button {
self.imp().done_button.as_ref() self.imp().done_button.as_ref()
} }

View File

@ -25,7 +25,7 @@ impl CardDisplay {
Object::builder() Object::builder()
.property("imagepath", image_path) .property("imagepath", image_path)
.property("hieroglyph", hieroglyph) .property("hieroglyph", hieroglyph)
// .property("reading", reading) // .property("translation", translation)
.build() .build()
} }

View File

@ -14,7 +14,7 @@ pub struct CardEntry {
#[template_child] #[template_child]
pub hieroglyph_label: TemplateChild<Label>, pub hieroglyph_label: TemplateChild<Label>,
#[template_child] #[template_child]
pub reading_label: TemplateChild<Label>, pub translation_label: TemplateChild<Label>,
#[template_child] #[template_child]
pub delete_button: TemplateChild<Button>, pub delete_button: TemplateChild<Button>,
#[property(get, set)] #[property(get, set)]
@ -22,7 +22,7 @@ pub struct CardEntry {
#[property(get, set)] #[property(get, set)]
hieroglyph: RefCell<String>, hieroglyph: RefCell<String>,
#[property(get, set)] #[property(get, set)]
reading: RefCell<String>, translation: RefCell<String>,
} }
#[glib::object_subclass] #[glib::object_subclass]
@ -51,9 +51,9 @@ impl ObjectImpl for CardEntry {
.sync_create() .sync_create()
.build(); .build();
let reading_label_binding: &Label = self.reading_label.as_ref(); let translation_label_binding: &Label = self.translation_label.as_ref();
self.obj() self.obj()
.bind_property("reading", reading_label_binding, "label") .bind_property("translation", translation_label_binding, "label")
.sync_create() .sync_create()
.build(); .build();
} }

View File

@ -15,11 +15,11 @@ glib::wrapper! {
} }
impl CardEntry { impl CardEntry {
pub fn new(image_path: &String, hieroglyph: &String, reading: &String) -> Self { pub fn new(image_path: &String, hieroglyph: &String, translation: &String) -> Self {
Object::builder() Object::builder()
.property("imagepath", image_path) .property("imagepath", image_path)
.property("hieroglyph", hieroglyph) .property("hieroglyph", hieroglyph)
.property("reading", reading) .property("translation", translation)
.build() .build()
} }