Hi, after a week of using my snap in global store I’m on this error: My dump plugin files necessary being in snap are not there. I can’t read any data by compiled program in snap, result pic:
My dir struct is: ./autoskola3==reading: ./resources/en/t1o1.jpg But everything I can is to run the ./autoskola3 and as you see on the pic ^^^ upper the program inside the snap cant read anything. Why dump plugin does not work? Or what to use please?? Any ideas? Thanks.well reading here: source: ./foo
will include ALL files from foo in the snap, dumped (by dump plugin) into the base directory of the snap. link: The dump plugin - #4 by knobby and here: It is true that the target will end up be placing at the root of the snap file hierachy Then reading here: Layouts enable snap developers outside of locations referenced by $SNAP https://snapcraft.io/docs/the-snap-format
Any ideas why I can read from local file system if used:
snap install local_snap.snap --dangerous
But I can’t read from $SNAP file system on global store installation: snap install autoskola3
Thanks for any ideas.
then reading here if I wanna check current exe folder and in this folder ./resources/ folder I get this: If the executable was invoked through a symbolic link, some platforms will return the path of the symbolic link and other platforms will return the path of the symbolic link’s target. Which is unusable function… https://doc.rust-lang.org/std/env/fn.current_exe.html Thanks for any other ideas.
All right reading here:
organize:
qt5-launch: bin/qt5-launch
gonna try that… Dump Plugin - target path
All right reading also: organize: Snapcraft parts metadata | Snapcraft documentation not working just renaming Then reading how to insert files to snap: https://askubuntu.com/questions/739379/how-to-copy-source-files-into-stage-snap-with-snapcraft Also mentioned dump ./ And finally some howtos: Not working too: https://snapcraft.io/docs/snap-howto
So I’ve read also: this: How to copy just one file using the dump plugin? Then also this: Build and staging dependencies - #2 by mwhudson And also this: Parts lifecycle | Snapcraft documentation and this: https://snapcraft.io/docs/snapcraft-parts-metadata#heading--stage And finally I checked this yaml: snapd/build-aux/snap/snapcraft.yaml at master · snapcore/snapd · GitHub But stage did not help. My YAML is now:
name: autoskola3 # you probably want to 'snapcraft register <name>'
base: core22 # the base snap is the execution environment for this snap
version: '3.0' # just for humans, typically '1.2+git' or '1.3.2'
summary: Testing app for drivers with 2000 questions. # 79 char long summary
description: |
This app offers 2000 questions in Slovak and English for drivers to be tested
before main exam in Slovak Republic. More on https://hrubos.org Just download and be ready before driving exam.
grade: stable # must be 'stable' to release into candidate/stable channels
confinement: strict # use 'strict' once you have the right plugs and slots
parts:
autoskola3:
# See 'snapcraft plugins'
plugin: rust
source: ./
build-packages:
- cargo
- libssl-dev
stage-packages:
- libxkbcommon-x11-0
autoskola3-resources:
plugin: dump
source: ./
autoskola3-copy-resources:
plugin: nil
stage:
- ./*
apps:
autoskola3:
command: bin/autoskola3
common-id: org.hrubos.autoskola3
extensions: [gnome]
plugs:
- network
Still getting this pic:
All right I created revision3 with staged resources. Seems to be error of Linux. The only way how to run the app is to open folder program /snap/autoskola3/3/autoskola3 manually. Otherwise the program crashes. Resources are present in this folder with program. Some pictures of the situation:
I dont understand why this does not work, if this is truth: At that point, the path you used to get to the file doesn't matter.
https://unix.stackexchange.com/questions/26896/how-does-linux-work-with-symbolic-links The symlink points to the name of the real file (inode) in the file system.
Ok I tried to edit paths in source code of Rust and this is the fix, ok my snap should now work without crashes Pics:
Rust source code is now:
use iced::{
widget::{column, image, text, button, row},
Sandbox, Settings, Color, Alignment, Length,
};//use crates of iced framework
use rand::prelude::*; //use crate of rand
use std::fs; //use file system crate
//use std::env::current_dir;
//use std::path::PathBuf;
//function giving me random number from 1 to right_border
fn rand_range_num(right_border:i32)-> String{
let mut rng = rand::thread_rng();
let mut nums: Vec<i32> = (1..right_border).collect();
nums.shuffle(&mut rng);
nums[0].to_string()
}
//function giving me the random number from right_border to 288
fn rand_range_num2(right_border:i32)-> String{
let mut rng = rand::thread_rng();
let mut nums: Vec<i32> = (right_border..288).collect();
nums.shuffle(&mut rng);
nums[0].to_string()
}
//same like ^^^
fn rand_range_num3(right_border:i32)-> String{
let mut rng = rand::thread_rng();
let mut nums: Vec<i32> = (right_border..23).collect();
nums.shuffle(&mut rng);
nums[0].to_string()
}
//same like ^^^
fn rand_range_num4(right_border:i32)-> String{
let mut rng = rand::thread_rng();
let mut nums: Vec<i32> = (right_border..27).collect();
nums.shuffle(&mut rng);
nums[0].to_string()
}
//function returning the current directory of exe/elf
fn cur_dir1()->String{
//let path = current_dir().unwrap();
//path.display().to_string().clone()
let path = process_path::get_executable_path();
//let srcdir = PathBuf::from("./");
//fs::canonicalize(&srcdir).expect("Error returning the path from fs:: module... ").into_os_string().into_string().unwrap()
match path {
None => String::from("The process path could not be determined... "),
Some(path) => {
let len = path.clone().into_os_string().into_string().expect("Can not shorten path of 10 chars from end == minus autoskola3").chars().count() - 11;
path.clone().into_os_string().into_string().expect("Can not shorten path of 10 chars from end == minus autoskola3").drain(0..len).collect::<String>()
//path.into_os_string().into_string().unwrap()
}
}
}
//calling main function in rust language
fn main() -> iced::Result {
MyApp::run(Settings::default())
}
//enum with app signals definitions:
#[derive(Debug, Clone)]
enum MyAppMessage {
GoZakon,
GoZnacka,
GoKrizovatka,
GiveAnswer,
GoLaw,
GoSign,
GoIntersection
}
//state of the application based on iced framework documentation:
#[derive(Default)]
struct MyApp{
pic_value:String,
question_value:String,
answer_value:String,
q_num:String,
t_num:String,
q_type:String,
}
//implementation for myapp struct:
impl Sandbox for MyApp {
type Message = MyAppMessage;//type alias
//app window constructor:
fn new() -> Self {
Self{
pic_value: String::from(""),
question_value: String::from("Sem načítam otázku po kliknutí na príslušné tlačítko...\n Here I load the question after adequate button click..."),
answer_value: String::from("Sem načítam odpoveď po kliknutí na príslušné tlačítko...\n Here I load the answer after adequate button click..."),
q_num: String::from("1"), //global random number of the SLOVAK question
q_type: String::from("za"), //whether zakony za or znacky zn
t_num:String::from("1"), //just the first English test as we know t1o1.txt means test1 otazka1
}
}
//title of app window:
fn title(&self) -> String {
String::from("Autoškola3 EN+SK: 2000 questions | Mgr. Janko Hruboš | janko.hrubos@gmail.com")
}
//on the state update and signals receiving do these actions:
fn update(&mut self, message: Self::Message) {
match message {
MyAppMessage::GoZakon => {
self.pic_value = cur_dir1()+"/resources/empty.jpg";
//println!("{}",cur_dir1());
self.q_num=rand_range_num(525);
let mut s2:String=cur_dir1()+"/resources/sk/otza/za_";
let s3:String=".txt".to_owned();
s2.push_str(&self.q_num);
s2.push_str(&s3);
self.question_value = fs::read_to_string(s2)
.expect("ERROR: Cant read the file, sorry...");
self.q_type=String::from("za");
self.answer_value=String::from("");
//^^^ self explanatory
}
MyAppMessage::GoZnacka => {
self.q_num=rand_range_num(144);
let s4:String=(cur_dir1()+"/resources/sk/znackyobr/z"+&self.q_num+".jpg").to_string().clone();
self.pic_value = s4;
let mut s2:String=cur_dir1()+"/resources/sk/otzn/z_";
let s3:String=".txt".to_owned();
s2.push_str(&self.q_num);
s2.push_str(&s3);
self.question_value = fs::read_to_string(s2)
.expect("ERROR: Cant read the file, sorry...");
self.q_type=String::from("zn");
self.answer_value=String::from("");
}
MyAppMessage::GoKrizovatka => {
self.q_num=rand_range_num2(144);
let s4:String=(cur_dir1()+"/resources/sk/znackyobr/z"+&self.q_num+".jpg").to_string().clone();
self.pic_value = s4;
let mut s2:String=cur_dir1()+"/resources/sk/otzn/z_";
let s3:String=".txt".to_owned();
s2.push_str(&self.q_num);
s2.push_str(&s3);
self.question_value = fs::read_to_string(s2)
.expect("ERROR: Cant read the file, sorry...");
self.q_type=String::from("kri");
self.answer_value=String::from("");
}
MyAppMessage::GoLaw => {
self.q_num=rand_range_num(15);//generate random question from 1 to 27
self.t_num=rand_range_num(35);//generate random test from 1 to 35
//let s4:String=("resources/en/znackyobr/z".to_owned()+&self.q_num+".jpg").to_string().clone();
self.pic_value = String::from(cur_dir1()+"/resources/empty.jpg");
let mut s2:String=cur_dir1()+"/resources/en/otazkytxt/t";
let s3:String=".txt".to_owned();
let s5:String="o".to_owned();
s2.push_str(&self.t_num);
s2.push_str(&s5);
s2.push_str(&self.q_num);
s2.push_str(&s3);
self.question_value = fs::read_to_string(s2)
.expect("ERROR: Cant read the file, sorry...");
self.q_type=String::from("law");
self.answer_value=String::from("");
}
MyAppMessage::GoSign => {
self.q_num=rand_range_num3(16);//generate random question from 16 to 23
self.t_num=rand_range_num(35);//generate random test from 1 to 35
let s4:String=(cur_dir1()+"/resources/en/znackyobr/t"+&self.t_num+"o"+&self.q_num+".jpg").to_string().clone();
//println!("{}",s4); //debug printout
self.pic_value = s4;
let mut s2:String=cur_dir1()+"/resources/en/otazkytxt/t";
let s3:String=".txt".to_owned();
let s5:String="o".to_owned();
s2.push_str(&self.t_num);
s2.push_str(&s5);
s2.push_str(&self.q_num);
s2.push_str(&s3);
self.question_value = fs::read_to_string(s2)
.expect("ERROR: Cant read the file, sorry...");
self.q_type=String::from("sig");
self.answer_value=String::from("");
}
MyAppMessage::GoIntersection => {
self.q_num=rand_range_num4(24);//generate random question from 24 to 27
self.t_num=rand_range_num(35);//generate random test from 1 to 35
let s4:String=(cur_dir1()+"/resources/en/znackyobr/t"+&self.t_num+"o"+&self.q_num+".jpg").to_string().clone();
//println!("{}",s4); //debug printout
self.pic_value = s4;
let mut s2:String=cur_dir1()+"/resources/en/otazkytxt/t";
let s3:String=".txt".to_owned();
let s5:String="o".to_owned();
s2.push_str(&self.t_num);
s2.push_str(&s5);
s2.push_str(&self.q_num);
s2.push_str(&s3);
self.question_value = fs::read_to_string(s2)
.expect(&("ERROR: Cant read the file, sorry... Path: ".to_owned()+&cur_dir1()));
self.q_type=String::from("int");//question type is intersection
self.answer_value=String::from("");//answer is not visible yet, coz intersection button pressed not answer button
//^^^ self explanatory what to do on these signals receiving
}
MyAppMessage::GiveAnswer => { //on button answer click:
let qnum = self.q_num.clone();
let tnum = self.t_num.clone();
let qtype = self.q_type.clone();
if qtype == "za" { //if this is Slovak zakon you know qnum is from 1 to 525
let mut s2:String=cur_dir1()+"/resources/sk/otza/zao_";
let s3:String=".txt".to_owned();
s2.push_str(&qnum);
s2.push_str(&s3);
self.answer_value=String::from("Odpoveď na otázku zákony ");
self.answer_value.push_str(&qnum);
let s4:String=" je: ".to_owned();
self.answer_value.push_str(&s4);
self.answer_value.push_str(&fs::read_to_string(s2)
.expect("ERROR: Cant read the file, sorry..."));
}
if qtype == "zn" { //if this is Slovak znacka you know qnum is from 1 to 144
let mut s2:String=cur_dir1()+"/resources/sk/otzn/zo_";
let s3:String=".txt".to_owned();
s2.push_str(&qnum);
s2.push_str(&s3);
self.answer_value=String::from("Odpoveď na otázku značky ");
self.answer_value.push_str(&qnum);
let s4:String=" je: ".to_owned();
self.answer_value.push_str(&s4);
self.answer_value.push_str(&fs::read_to_string(s2)
.expect("ERROR: Cant read the file, sorry..."));
}
if qtype == "kri" { //if this is Slovak znacka you know qnum is from (1 to 144)+144
let mut s2:String=cur_dir1()+"/resources/sk/otzn/zo_";
let s3:String=".txt".to_owned();
s2.push_str(&qnum);
s2.push_str(&s3);
self.answer_value=String::from("Odpoveď na otázku križovatky ");
self.answer_value.push_str(&qnum);
let s4:String=" je: ".to_owned();
self.answer_value.push_str(&s4);
self.answer_value.push_str(&fs::read_to_string(s2)
.expect("ERROR: Cant read the file, sorry..."));
}
if qtype == "law" {
let mut s2:String=cur_dir1()+"/resources/en/odtxt/t";
//let s3:String=".txt".to_owned();
let s5:String="od".to_owned();
s2.push_str(&tnum);
s2.push_str(&s5);
s2.push_str(&qnum);
//s2.push_str(&s3);
self.answer_value=String::from("Answer to the question from laws ");
self.answer_value.push_str(&qnum);
let s4:String=" is: ".to_owned();
self.answer_value.push_str(&s4);
//println!("{}",s2);
self.answer_value.push_str(&fs::read_to_string(s2)
.expect("ERROR: Cant read the file, sorry..."));
}
if qtype == "sig" {
let mut s2:String=cur_dir1()+"/resources/en/odtxt/t";
//let s3:String=".txt".to_owned();
let s5:String="od".to_owned();
s2.push_str(&tnum);
s2.push_str(&s5);
s2.push_str(&qnum);
//s2.push_str(&s3);
self.answer_value=String::from("Answer to the question from signs ");
self.answer_value.push_str(&qnum);
self.answer_value.push_str(" / test ");
self.answer_value.push_str(&tnum);
let s4:String=" is: ".to_owned();
self.answer_value.push_str(&s4);
//println!("{}",s2);
self.answer_value.push_str(&fs::read_to_string(s2)
.expect("ERROR: Cant read the file, sorry..."));
}
if qtype == "int" {
let mut s2:String=cur_dir1()+"/resources/en/odtxt/t";
//let s3:String=".txt".to_owned();
let s5:String="od".to_owned();
s2.push_str(&tnum);
s2.push_str(&s5);
s2.push_str(&qnum);
//s2.push_str(&s3);
self.answer_value=String::from("Answer to the question from intersections ");
self.answer_value.push_str(&qnum);
self.answer_value.push_str(" / test ");
self.answer_value.push_str(&tnum);
let s4:String=" is: ".to_owned();
self.answer_value.push_str(&s4);
//println!("{}",s2);
self.answer_value.push_str(&fs::read_to_string(s2)
.expect(&("ERROR: Cant read the file, sorry... Path: ".to_owned()+&cur_dir1())));
}
}
}
}
//basic view definitions with slots of signals:
fn view(&self) -> iced::Element<'_, Self::Message> {
let padding1:u16=10;//padding of 10px
column![
image(self.pic_value.clone()).width(600),
row![button("Náhodný zákon").on_press(MyAppMessage::GoZakon).padding(padding1),
button("Náhodná značka").on_press(MyAppMessage::GoZnacka).padding(padding1),
button("Náhodná križovatka").on_press(MyAppMessage::GoKrizovatka).padding(padding1)],
row![button("Answer/Opoveď").on_press(MyAppMessage::GiveAnswer).padding(padding1)],
row![button("Random law").on_press(MyAppMessage::GoLaw).padding(padding1),
button("Random sign").on_press(MyAppMessage::GoSign).padding(padding1),
button("Random intersection").on_press(MyAppMessage::GoIntersection).padding(padding1),],
text(self.question_value.as_str()).style(Color::from_rgb(1., 0.0, 0.0)),
text(self.answer_value.as_str()).style(Color::from_rgb(1., 0.0, 0.0)),
].width(Length::Fill).align_items(Alignment::Center).padding(20)
.into()
}
}
And YAML file is now:
name: autoskola3 # you probably want to 'snapcraft register <name>'
base: core22 # the base snap is the execution environment for this snap
version: '3.0' # just for humans, typically '1.2+git' or '1.3.2'
summary: Testing app for drivers with 2000 questions. # 79 char long summary
description: |
This app offers 2000 questions in Slovak and English for drivers to be tested
before main exam in Slovak Republic. More on https://hrubos.org Just download and be ready before driving exam.
grade: stable # must be 'stable' to release into candidate/stable channels
confinement: strict # use 'strict' once you have the right plugs and slots
parts:
autoskola3:
# See 'snapcraft plugins'
plugin: rust
source: ./
build-packages:
- cargo
- libssl-dev
stage-packages:
- libxkbcommon-x11-0
autoskola3-resources:
plugin: dump
source: ./
autoskola3-copy-resources:
plugin: nil
stage:
- ./*
apps:
autoskola3:
command: bin/autoskola3
common-id: org.hrubos.autoskola3
extensions: [gnome]
plugs:
- network
I’ll check it in snapcraft, but elf run paths are fixed!
Finally one more problem arised and it was -11 delta of chars in rust function cur_dir1(), coz we have in path 1Byte and 2Byte chars. So final main.rs Rust code looks like:
use iced::{
widget::{column, image, text, button, row},
Sandbox, Settings, Color, Alignment, Length,
};//use crates of iced framework
use rand::prelude::*; //use crate of rand
use std::fs; //use file system crate
//use std::env::current_dir;
//use std::path::PathBuf;
//use std::path::Path;
use pathtrim::TrimmablePath;
//function giving me random number from 1 to right_border
fn rand_range_num(right_border:i32)-> String{
let mut rng = rand::thread_rng();
let mut nums: Vec<i32> = (1..right_border).collect();
nums.shuffle(&mut rng);
nums[0].to_string()
}
//function giving me the random number from right_border to 288
fn rand_range_num2(right_border:i32)-> String{
let mut rng = rand::thread_rng();
let mut nums: Vec<i32> = (right_border..288).collect();
nums.shuffle(&mut rng);
nums[0].to_string()
}
//same like ^^^
fn rand_range_num3(right_border:i32)-> String{
let mut rng = rand::thread_rng();
let mut nums: Vec<i32> = (right_border..23).collect();
nums.shuffle(&mut rng);
nums[0].to_string()
}
//same like ^^^
fn rand_range_num4(right_border:i32)-> String{
let mut rng = rand::thread_rng();
let mut nums: Vec<i32> = (right_border..27).collect();
nums.shuffle(&mut rng);
nums[0].to_string()
}
//function returning the current directory of exe/elf
fn cur_dir1()->String{
//let path = current_dir().unwrap();
//path.display().to_string().clone()
let path = process_path::get_executable_path();
//let srcdir = PathBuf::from("./");
//fs::canonicalize(&srcdir).expect("Error returning the path from fs:: module... ").into_os_string().into_string().unwrap()
match path {
None => String::from("The process path could not be determined... "),
Some(path) => {
let len = path.clone().into_os_string().into_string().expect("Can not shorten path of 10 chars from end == minus autoskola3").chars().count();
let outa_path_exe=path.clone().into_os_string().into_string().expect("Can not shorten path of 10 chars from end == minus autoskola3").drain(0..len).collect::<String>();
//let to_replace = path.trim_to_nth(1).expect("Can not trim the path. ").into_os_string().into_string().unwrap();
//let target_str = outa_path_exe.replace(to_replace.as_str(),"");
let to_replace=String::from("/");
let mut del_farther:usize=0;
if let Some(last_index) = outa_path_exe.as_str().rfind(&to_replace.as_str()) {
del_farther = last_index;
}
outa_path_exe.as_str()[0..del_farther].to_string()+"/"
//path.trim_to_nth(1).expect("Can not trim the path. ").into_os_string().into_string().unwrap()
//target_str.to_string()
}
}
}
//calling main function in rust language
fn main() -> iced::Result {
MyApp::run(Settings::default())
}
//enum with app signals definitions:
#[derive(Debug, Clone)]
enum MyAppMessage {
GoZakon,
GoZnacka,
GoKrizovatka,
GiveAnswer,
GoLaw,
GoSign,
GoIntersection
}
//state of the application based on iced framework documentation:
#[derive(Default)]
struct MyApp{
pic_value:String,
question_value:String,
answer_value:String,
q_num:String,
t_num:String,
q_type:String,
}
//implementation for myapp struct:
impl Sandbox for MyApp {
type Message = MyAppMessage;//type alias
//app window constructor:
fn new() -> Self {
Self{
pic_value: String::from(""),
question_value: String::from("Sem načítam otázku po kliknutí na príslušné tlačítko...\n Here I load the question after adequate button click..."),
answer_value: String::from("Sem načítam odpoveď po kliknutí na príslušné tlačítko...\n Here I load the answer after adequate button click..."),
q_num: String::from("1"), //global random number of the SLOVAK question
q_type: String::from("za"), //whether zakony za or znacky zn
t_num:String::from("1"), //just the first English test as we know t1o1.txt means test1 otazka1
}
}
//title of app window:
fn title(&self) -> String {
String::from("Autoškola3 EN+SK: 2000 questions | Mgr. Janko Hruboš | janko.hrubos@gmail.com")
}
//on the state update and signals receiving do these actions:
fn update(&mut self, message: Self::Message) {
match message {
MyAppMessage::GoZakon => {
self.pic_value = cur_dir1()+"/resources/empty.jpg";
//println!("{}",cur_dir1());
self.q_num=rand_range_num(525);
let mut s2:String=cur_dir1()+"/resources/sk/otza/za_";
let s3:String=".txt".to_owned();
s2.push_str(&self.q_num);
s2.push_str(&s3);
self.question_value = fs::read_to_string(s2)
.expect("ERROR: Cant read the file, sorry...");
self.q_type=String::from("za");
self.answer_value=String::from("");
//^^^ self explanatory
}
MyAppMessage::GoZnacka => {
self.q_num=rand_range_num(144);
let s4:String=(cur_dir1()+"/resources/sk/znackyobr/z"+&self.q_num+".jpg").to_string().clone();
self.pic_value = s4;
let mut s2:String=cur_dir1()+"/resources/sk/otzn/z_";
let s3:String=".txt".to_owned();
s2.push_str(&self.q_num);
s2.push_str(&s3);
self.question_value = fs::read_to_string(s2)
.expect("ERROR: Cant read the file, sorry...");
self.q_type=String::from("zn");
self.answer_value=String::from("");
}
MyAppMessage::GoKrizovatka => {
self.q_num=rand_range_num2(144);
let s4:String=(cur_dir1()+"/resources/sk/znackyobr/z"+&self.q_num+".jpg").to_string().clone();
self.pic_value = s4;
let mut s2:String=cur_dir1()+"/resources/sk/otzn/z_";
let s3:String=".txt".to_owned();
s2.push_str(&self.q_num);
s2.push_str(&s3);
self.question_value = fs::read_to_string(s2)
.expect("ERROR: Cant read the file, sorry...");
self.q_type=String::from("kri");
self.answer_value=String::from("");
}
MyAppMessage::GoLaw => {
self.q_num=rand_range_num(15);//generate random question from 1 to 27
self.t_num=rand_range_num(35);//generate random test from 1 to 35
//let s4:String=("resources/en/znackyobr/z".to_owned()+&self.q_num+".jpg").to_string().clone();
self.pic_value = String::from(cur_dir1()+"/resources/empty.jpg");
let mut s2:String=cur_dir1()+"/resources/en/otazkytxt/t";
let s3:String=".txt".to_owned();
let s5:String="o".to_owned();
s2.push_str(&self.t_num);
s2.push_str(&s5);
s2.push_str(&self.q_num);
s2.push_str(&s3);
self.question_value = fs::read_to_string(s2)
.expect("ERROR: Cant read the file, sorry...");
self.q_type=String::from("law");
self.answer_value=String::from("");
}
MyAppMessage::GoSign => {
self.q_num=rand_range_num3(16);//generate random question from 16 to 23
self.t_num=rand_range_num(35);//generate random test from 1 to 35
let s4:String=(cur_dir1()+"/resources/en/znackyobr/t"+&self.t_num+"o"+&self.q_num+".jpg").to_string().clone();
//println!("{}",s4); //debug printout
self.pic_value = s4;
let mut s2:String=cur_dir1()+"/resources/en/otazkytxt/t";
let s3:String=".txt".to_owned();
let s5:String="o".to_owned();
s2.push_str(&self.t_num);
s2.push_str(&s5);
s2.push_str(&self.q_num);
s2.push_str(&s3);
self.question_value = fs::read_to_string(s2)
.expect("ERROR: Cant read the file, sorry...");
self.q_type=String::from("sig");
self.answer_value=String::from("");
}
MyAppMessage::GoIntersection => {
self.q_num=rand_range_num4(24);//generate random question from 24 to 27
self.t_num=rand_range_num(35);//generate random test from 1 to 35
let s4:String=(cur_dir1()+"/resources/en/znackyobr/t"+&self.t_num+"o"+&self.q_num+".jpg").to_string().clone();
//println!("{}",s4); //debug printout
self.pic_value = s4;
let mut s2:String=cur_dir1()+"/resources/en/otazkytxt/t";
let s3:String=".txt".to_owned();
let s5:String="o".to_owned();
s2.push_str(&self.t_num);
s2.push_str(&s5);
s2.push_str(&self.q_num);
s2.push_str(&s3);
self.question_value = fs::read_to_string(s2)
.expect(&("ERROR: Cant read the file, sorry... Path: ".to_owned()+&cur_dir1()));
self.q_type=String::from("int");//question type is intersection
self.answer_value=String::from("");//answer is not visible yet, coz intersection button pressed not answer button
//^^^ self explanatory what to do on these signals receiving
}
MyAppMessage::GiveAnswer => { //on button answer click:
let qnum = self.q_num.clone();
let tnum = self.t_num.clone();
let qtype = self.q_type.clone();
if qtype == "za" { //if this is Slovak zakon you know qnum is from 1 to 525
let mut s2:String=cur_dir1()+"/resources/sk/otza/zao_";
let s3:String=".txt".to_owned();
s2.push_str(&qnum);
s2.push_str(&s3);
self.answer_value=String::from("Odpoveď na otázku zákony ");
self.answer_value.push_str(&qnum);
let s4:String=" je: ".to_owned();
self.answer_value.push_str(&s4);
self.answer_value.push_str(&fs::read_to_string(s2)
.expect("ERROR: Cant read the file, sorry..."));
}
if qtype == "zn" { //if this is Slovak znacka you know qnum is from 1 to 144
let mut s2:String=cur_dir1()+"/resources/sk/otzn/zo_";
let s3:String=".txt".to_owned();
s2.push_str(&qnum);
s2.push_str(&s3);
self.answer_value=String::from("Odpoveď na otázku značky ");
self.answer_value.push_str(&qnum);
let s4:String=" je: ".to_owned();
self.answer_value.push_str(&s4);
self.answer_value.push_str(&fs::read_to_string(s2)
.expect("ERROR: Cant read the file, sorry..."));
}
if qtype == "kri" { //if this is Slovak znacka you know qnum is from (1 to 144)+144
let mut s2:String=cur_dir1()+"/resources/sk/otzn/zo_";
let s3:String=".txt".to_owned();
s2.push_str(&qnum);
s2.push_str(&s3);
self.answer_value=String::from("Odpoveď na otázku križovatky ");
self.answer_value.push_str(&qnum);
let s4:String=" je: ".to_owned();
self.answer_value.push_str(&s4);
self.answer_value.push_str(&fs::read_to_string(s2)
.expect("ERROR: Cant read the file, sorry..."));
}
if qtype == "law" {
let mut s2:String=cur_dir1()+"/resources/en/odtxt/t";
//let s3:String=".txt".to_owned();
let s5:String="od".to_owned();
s2.push_str(&tnum);
s2.push_str(&s5);
s2.push_str(&qnum);
//s2.push_str(&s3);
self.answer_value=String::from("Answer to the question from laws ");
self.answer_value.push_str(&qnum);
let s4:String=" is: ".to_owned();
self.answer_value.push_str(&s4);
//println!("{}",s2);
self.answer_value.push_str(&fs::read_to_string(s2)
.expect("ERROR: Cant read the file, sorry..."));
}
if qtype == "sig" {
let mut s2:String=cur_dir1()+"/resources/en/odtxt/t";
//let s3:String=".txt".to_owned();
let s5:String="od".to_owned();
s2.push_str(&tnum);
s2.push_str(&s5);
s2.push_str(&qnum);
//s2.push_str(&s3);
self.answer_value=String::from("Answer to the question from signs ");
self.answer_value.push_str(&qnum);
self.answer_value.push_str(" / test ");
self.answer_value.push_str(&tnum);
let s4:String=" is: ".to_owned();
self.answer_value.push_str(&s4);
//println!("{}",s2);
self.answer_value.push_str(&fs::read_to_string(s2)
.expect("ERROR: Cant read the file, sorry..."));
}
if qtype == "int" {
let mut s2:String=cur_dir1()+"/resources/en/odtxt/t";
//let s3:String=".txt".to_owned();
let s5:String="od".to_owned();
s2.push_str(&tnum);
s2.push_str(&s5);
s2.push_str(&qnum);
//s2.push_str(&s3);
self.answer_value=String::from("Answer to the question from intersections ");
self.answer_value.push_str(&qnum);
self.answer_value.push_str(" / test ");
self.answer_value.push_str(&tnum);
let s4:String=" is: ".to_owned();
self.answer_value.push_str(&s4);
//println!("{}",s2);
self.answer_value.push_str(&fs::read_to_string(s2)
.expect(&("ERROR: Cant read the file, sorry... Path: ".to_owned()+&cur_dir1())));
}
}
}
}
//basic view definitions with slots of signals:
fn view(&self) -> iced::Element<'_, Self::Message> {
let padding1:u16=10;//padding of 10px
column![
image(self.pic_value.clone()).width(600),
row![button("Náhodný zákon").on_press(MyAppMessage::GoZakon).padding(padding1),
button("Náhodná značka").on_press(MyAppMessage::GoZnacka).padding(padding1),
button("Náhodná križovatka").on_press(MyAppMessage::GoKrizovatka).padding(padding1)],
row![button("Answer/Opoveď").on_press(MyAppMessage::GiveAnswer).padding(padding1)],
row![button("Random law").on_press(MyAppMessage::GoLaw).padding(padding1),
button("Random sign").on_press(MyAppMessage::GoSign).padding(padding1),
button("Random intersection").on_press(MyAppMessage::GoIntersection).padding(padding1),],
text(self.question_value.as_str()).style(Color::from_rgb(1., 0.0, 0.0)),
text(self.answer_value.as_str()).style(Color::from_rgb(1., 0.0, 0.0)),
].width(Length::Fill).align_items(Alignment::Center).padding(20)
.into()
}
}
And cargo.toml file looks like:
[package]
name = "autoskola3"
version = "3.0.0"
authors = ["Mgr. Jan Hrubos <janko.hrubos@gmail.com>"]
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
iced = { version = "0.12.1", features = ["image"] }
rand = { version = "0.8.5"}
process_path = { version = "0.1.4" }
pathtrim = "2.0.0"
Now I’m gonna test it in snapstore ^^^
All right I tested it, it didnt work, I had to snapcraft clean command and then to edit YAML file. Now this looks like this:
Now my YAML file looks like this and finally works in snapstore:
name: autoskola4 # you probably want to 'snapcraft register <name>'
base: core20 # the base snap is the execution environment for this snap
version: '4.0' # just for humans, typically '1.2+git' or '1.3.2'
summary: Testing app for drivers with 2000 questions. # 79 char long summary
description: |
This app offers 2000 questions in Slovak and English for drivers to be tested
before main exam in Slovak Republic. More on https://hrubos.org Just download and be ready before driving exam.
grade: stable # must be 'stable' to release into candidate/stable channels
confinement: strict # use 'strict' once you have the right plugs and slots
parts:
autoskola4:
# See 'snapcraft plugins'
plugin: rust
source: ./
build-packages:
- cargo
- libssl-dev
stage-packages:
- libxkbcommon-x11-0
autoskola4-resources:
plugin: dump
source: ./
organize:
resources: bin/resources/
autoskola4-copy-resources:
plugin: nil
stage:
- ./*
apps:
autoskola4:
command: bin/autoskola4
common-id: org.hrubos.autoskola4
extensions: [gnome-3-38]
plugs:
- network
- home
My cargo TOML file looks like this:
[package]
name = "autoskola4"
version = "4.0.0"
authors = ["Mgr. Jan Hrubos <janko.hrubos@gmail.com>"]
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
iced = { version = "0.12.1", features = ["image"] }
rand = { version = "0.8.5"}
process_path = { version = "0.1.4" }
pathtrim = "2.0.0"
And my Rust main.rs looks like this:
use iced::{
widget::{column, image, text, button, row},
Sandbox, Settings, Color, Alignment, Length,
};//use crates of iced framework
use rand::prelude::*; //use crate of rand
use std::fs; //use file system crate
//use std::env::current_dir;
//use std::path::PathBuf;
//use std::path::Path;
//use pathtrim::TrimmablePath;
//function giving me random number from 1 to right_border
fn rand_range_num(right_border:i32)-> String{
let mut rng = rand::thread_rng();
let mut nums: Vec<i32> = (1..right_border).collect();
nums.shuffle(&mut rng);
nums[0].to_string()
}
//function giving me the random number from right_border to 288
fn rand_range_num2(right_border:i32)-> String{
let mut rng = rand::thread_rng();
let mut nums: Vec<i32> = (right_border..288).collect();
nums.shuffle(&mut rng);
nums[0].to_string()
}
//same like ^^^
fn rand_range_num3(right_border:i32)-> String{
let mut rng = rand::thread_rng();
let mut nums: Vec<i32> = (right_border..23).collect();
nums.shuffle(&mut rng);
nums[0].to_string()
}
//same like ^^^
fn rand_range_num4(right_border:i32)-> String{
let mut rng = rand::thread_rng();
let mut nums: Vec<i32> = (right_border..27).collect();
nums.shuffle(&mut rng);
nums[0].to_string()
}
//function returning the current directory of exe/elf
fn cur_dir1()->String{
//let path = current_dir().unwrap();
//path.display().to_string().clone()
let path = process_path::get_executable_path();
//let srcdir = PathBuf::from("./");
//fs::canonicalize(&srcdir).expect("Error returning the path from fs:: module... ").into_os_string().into_string().unwrap()
match path {
None => String::from("The process path could not be determined... "),
Some(path) => {
let len = path.clone().into_os_string().into_string().expect("Can not shorten path of 10 chars from end == minus autoskola3").chars().count();
let outa_path_exe=path.clone().into_os_string().into_string().expect("Can not shorten path of 10 chars from end == minus autoskola3").drain(0..len).collect::<String>();
//let to_replace = path.trim_to_nth(1).expect("Can not trim the path. ").into_os_string().into_string().unwrap();
//let target_str = outa_path_exe.replace(to_replace.as_str(),"");
let to_replace=String::from("/");
let mut del_farther:usize=0;
if let Some(last_index) = outa_path_exe.as_str().rfind(&to_replace.as_str()) {
del_farther = last_index;
}
outa_path_exe.as_str()[0..del_farther].to_string()+"/"
//path.trim_to_nth(1).expect("Can not trim the path. ").into_os_string().into_string().unwrap()
//target_str.to_string()
}
}
}
//calling main function in rust language
fn main() -> iced::Result {
MyApp::run(Settings::default())
}
//enum with app signals definitions:
#[derive(Debug, Clone)]
enum MyAppMessage {
GoZakon,
GoZnacka,
GoKrizovatka,
GiveAnswer,
GoLaw,
GoSign,
GoIntersection
}
//state of the application based on iced framework documentation:
#[derive(Default)]
struct MyApp{
pic_value:String,
question_value:String,
answer_value:String,
q_num:String,
t_num:String,
q_type:String,
}
//implementation for myapp struct:
impl Sandbox for MyApp {
type Message = MyAppMessage;//type alias
//app window constructor:
fn new() -> Self {
Self{
pic_value: String::from(""),
question_value: String::from("Sem načítam otázku po kliknutí na príslušné tlačítko...\n Here I load the question after adequate button click..."),
answer_value: String::from("Sem načítam odpoveď po kliknutí na príslušné tlačítko...\n Here I load the answer after adequate button click..."),
q_num: String::from("1"), //global random number of the SLOVAK question
q_type: String::from("za"), //whether zakony za or znacky zn
t_num:String::from("1"), //just the first English test as we know t1o1.txt means test1 otazka1
}
}
//title of app window:
fn title(&self) -> String {
String::from("Autoškola4 EN+SK: 2000 questions | Mgr. Janko Hruboš | janko.hrubos@gmail.com")
}
//on the state update and signals receiving do these actions:
fn update(&mut self, message: Self::Message) {
match message {
MyAppMessage::GoZakon => {
self.pic_value = cur_dir1()+"/resources/empty.jpg";
//println!("{}",cur_dir1());
self.q_num=rand_range_num(525);
let mut s2:String=cur_dir1()+"/resources/sk/otza/za_";
let s3:String=".txt".to_owned();
s2.push_str(&self.q_num);
s2.push_str(&s3);
self.question_value = fs::read_to_string(s2)
.expect("ERROR: Cant read the file, sorry...");
self.q_type=String::from("za");
self.answer_value=String::from("");
//^^^ self explanatory
}
MyAppMessage::GoZnacka => {
self.q_num=rand_range_num(144);
let s4:String=(cur_dir1()+"/resources/sk/znackyobr/z"+&self.q_num+".jpg").to_string().clone();
self.pic_value = s4;
let mut s2:String=cur_dir1()+"/resources/sk/otzn/z_";
let s3:String=".txt".to_owned();
s2.push_str(&self.q_num);
s2.push_str(&s3);
self.question_value = fs::read_to_string(s2)
.expect("ERROR: Cant read the file, sorry...");
self.q_type=String::from("zn");
self.answer_value=String::from("");
}
MyAppMessage::GoKrizovatka => {
self.q_num=rand_range_num2(144);
let s4:String=(cur_dir1()+"/resources/sk/znackyobr/z"+&self.q_num+".jpg").to_string().clone();
self.pic_value = s4;
let mut s2:String=cur_dir1()+"/resources/sk/otzn/z_";
let s3:String=".txt".to_owned();
s2.push_str(&self.q_num);
s2.push_str(&s3);
self.question_value = fs::read_to_string(s2)
.expect("ERROR: Cant read the file, sorry...");
self.q_type=String::from("kri");
self.answer_value=String::from("");
}
MyAppMessage::GoLaw => {
self.q_num=rand_range_num(15);//generate random question from 1 to 27
self.t_num=rand_range_num(35);//generate random test from 1 to 35
//let s4:String=("resources/en/znackyobr/z".to_owned()+&self.q_num+".jpg").to_string().clone();
self.pic_value = String::from(cur_dir1()+"/resources/empty.jpg");
let mut s2:String=cur_dir1()+"/resources/en/otazkytxt/t";
let s3:String=".txt".to_owned();
let s5:String="o".to_owned();
s2.push_str(&self.t_num);
s2.push_str(&s5);
s2.push_str(&self.q_num);
s2.push_str(&s3);
self.question_value = fs::read_to_string(s2)
.expect("ERROR: Cant read the file, sorry...");
self.q_type=String::from("law");
self.answer_value=String::from("");
}
MyAppMessage::GoSign => {
self.q_num=rand_range_num3(16);//generate random question from 16 to 23
self.t_num=rand_range_num(35);//generate random test from 1 to 35
let s4:String=(cur_dir1()+"/resources/en/znackyobr/t"+&self.t_num+"o"+&self.q_num+".jpg").to_string().clone();
//println!("{}",s4); //debug printout
self.pic_value = s4;
let mut s2:String=cur_dir1()+"/resources/en/otazkytxt/t";
let s3:String=".txt".to_owned();
let s5:String="o".to_owned();
s2.push_str(&self.t_num);
s2.push_str(&s5);
s2.push_str(&self.q_num);
s2.push_str(&s3);
self.question_value = fs::read_to_string(s2)
.expect("ERROR: Cant read the file, sorry...");
self.q_type=String::from("sig");
self.answer_value=String::from("");
}
MyAppMessage::GoIntersection => {
self.q_num=rand_range_num4(24);//generate random question from 24 to 27
self.t_num=rand_range_num(35);//generate random test from 1 to 35
let s4:String=(cur_dir1()+"/resources/en/znackyobr/t"+&self.t_num+"o"+&self.q_num+".jpg").to_string().clone();
//println!("{}",s4); //debug printout
self.pic_value = s4;
let mut s2:String=cur_dir1()+"/resources/en/otazkytxt/t";
let s3:String=".txt".to_owned();
let s5:String="o".to_owned();
s2.push_str(&self.t_num);
s2.push_str(&s5);
s2.push_str(&self.q_num);
s2.push_str(&s3);
self.question_value = fs::read_to_string(s2)
.expect(&("ERROR: Cant read the file, sorry... Path: ".to_owned()+&cur_dir1()));
self.q_type=String::from("int");//question type is intersection
self.answer_value=String::from("");//answer is not visible yet, coz intersection button pressed not answer button
//^^^ self explanatory what to do on these signals receiving
}
MyAppMessage::GiveAnswer => { //on button answer click:
let qnum = self.q_num.clone();
let tnum = self.t_num.clone();
let qtype = self.q_type.clone();
if qtype == "za" { //if this is Slovak zakon you know qnum is from 1 to 525
let mut s2:String=cur_dir1()+"/resources/sk/otza/zao_";
let s3:String=".txt".to_owned();
s2.push_str(&qnum);
s2.push_str(&s3);
self.answer_value=String::from("Odpoveď na otázku zákony ");
self.answer_value.push_str(&qnum);
let s4:String=" je: ".to_owned();
self.answer_value.push_str(&s4);
self.answer_value.push_str(&fs::read_to_string(s2)
.expect("ERROR: Cant read the file, sorry..."));
}
if qtype == "zn" { //if this is Slovak znacka you know qnum is from 1 to 144
let mut s2:String=cur_dir1()+"/resources/sk/otzn/zo_";
let s3:String=".txt".to_owned();
s2.push_str(&qnum);
s2.push_str(&s3);
self.answer_value=String::from("Odpoveď na otázku značky ");
self.answer_value.push_str(&qnum);
let s4:String=" je: ".to_owned();
self.answer_value.push_str(&s4);
self.answer_value.push_str(&fs::read_to_string(s2)
.expect("ERROR: Cant read the file, sorry..."));
}
if qtype == "kri" { //if this is Slovak znacka you know qnum is from (1 to 144)+144
let mut s2:String=cur_dir1()+"/resources/sk/otzn/zo_";
let s3:String=".txt".to_owned();
s2.push_str(&qnum);
s2.push_str(&s3);
self.answer_value=String::from("Odpoveď na otázku križovatky ");
self.answer_value.push_str(&qnum);
let s4:String=" je: ".to_owned();
self.answer_value.push_str(&s4);
self.answer_value.push_str(&fs::read_to_string(s2)
.expect("ERROR: Cant read the file, sorry..."));
}
if qtype == "law" {
let mut s2:String=cur_dir1()+"/resources/en/odtxt/t";
//let s3:String=".txt".to_owned();
let s5:String="od".to_owned();
s2.push_str(&tnum);
s2.push_str(&s5);
s2.push_str(&qnum);
//s2.push_str(&s3);
self.answer_value=String::from("Answer to the question from laws ");
self.answer_value.push_str(&qnum);
let s4:String=" is: ".to_owned();
self.answer_value.push_str(&s4);
//println!("{}",s2);
self.answer_value.push_str(&fs::read_to_string(s2)
.expect("ERROR: Cant read the file, sorry..."));
}
if qtype == "sig" {
let mut s2:String=cur_dir1()+"/resources/en/odtxt/t";
//let s3:String=".txt".to_owned();
let s5:String="od".to_owned();
s2.push_str(&tnum);
s2.push_str(&s5);
s2.push_str(&qnum);
//s2.push_str(&s3);
self.answer_value=String::from("Answer to the question from signs ");
self.answer_value.push_str(&qnum);
self.answer_value.push_str(" / test ");
self.answer_value.push_str(&tnum);
let s4:String=" is: ".to_owned();
self.answer_value.push_str(&s4);
//println!("{}",s2);
self.answer_value.push_str(&fs::read_to_string(s2)
.expect("ERROR: Cant read the file, sorry..."));
}
if qtype == "int" {
let mut s2:String=cur_dir1()+"/resources/en/odtxt/t";
//let s3:String=".txt".to_owned();
let s5:String="od".to_owned();
s2.push_str(&tnum);
s2.push_str(&s5);
s2.push_str(&qnum);
//s2.push_str(&s3);
self.answer_value=String::from("Answer to the question from intersections ");
self.answer_value.push_str(&qnum);
self.answer_value.push_str(" / test ");
self.answer_value.push_str(&tnum);
let s4:String=" is: ".to_owned();
self.answer_value.push_str(&s4);
//println!("{}",s2);
self.answer_value.push_str(&fs::read_to_string(s2)
.expect(&("ERROR: Cant read the file, sorry... Path: ".to_owned()+&cur_dir1())));
}
}
}
}
//basic view definitions with slots of signals:
fn view(&self) -> iced::Element<'_, Self::Message> {
let padding1:u16=10;//padding of 10px
column![
image(self.pic_value.clone()).width(600),
row![button("Náhodný zákon").on_press(MyAppMessage::GoZakon).padding(padding1),
button("Náhodná značka").on_press(MyAppMessage::GoZnacka).padding(padding1),
button("Náhodná križovatka").on_press(MyAppMessage::GoKrizovatka).padding(padding1)],
row![button("Answer/Opoveď").on_press(MyAppMessage::GiveAnswer).padding(padding1)],
row![button("Random law").on_press(MyAppMessage::GoLaw).padding(padding1),
button("Random sign").on_press(MyAppMessage::GoSign).padding(padding1),
button("Random intersection").on_press(MyAppMessage::GoIntersection).padding(padding1),],
text(self.question_value.as_str()).style(Color::from_rgb(1., 0.0, 0.0)),
text(self.answer_value.as_str()).style(Color::from_rgb(1., 0.0, 0.0)),
].width(Length::Fill).align_items(Alignment::Center).padding(20)
.into()
}
}
Now everything is tested in snapstore and with local paths. Should work now ok. If you want to download it in zip it is here: https://hrubos.org/repo/autoskola4_and_snap.zip
For windows11 the code of cur_dir1() function is this:
So the code of main.rs for windows11 is:use iced::{
widget::{column, image, text, button, row},
Sandbox, Settings, Color, Alignment, Length,
};//use crates of iced framework
use rand::prelude::*; //use crate of rand
use std::fs; //use file system crate
//use std::env::current_dir;
//use std::path::PathBuf;
//use std::path::Path;
//use pathtrim::TrimmablePath;
use std::env::current_exe;
//function giving me random number from 1 to right_border
fn rand_range_num(right_border:i32)-> String{
let mut rng = rand::thread_rng();
let mut nums: Vec<i32> = (1..right_border).collect();
nums.shuffle(&mut rng);
nums[0].to_string()
}
//function giving me the random number from right_border to 288
fn rand_range_num2(right_border:i32)-> String{
let mut rng = rand::thread_rng();
let mut nums: Vec<i32> = (right_border..288).collect();
nums.shuffle(&mut rng);
nums[0].to_string()
}
//same like ^^^
fn rand_range_num3(right_border:i32)-> String{
let mut rng = rand::thread_rng();
let mut nums: Vec<i32> = (right_border..23).collect();
nums.shuffle(&mut rng);
nums[0].to_string()
}
//same like ^^^
fn rand_range_num4(right_border:i32)-> String{
let mut rng = rand::thread_rng();
let mut nums: Vec<i32> = (right_border..27).collect();
nums.shuffle(&mut rng);
nums[0].to_string()
}
//function returning the current directory of exe/elf
fn cur_dir1()->String{
//let path = current_dir().unwrap();
//path.display().to_string().clone()
// /*>>linux process only path:*/ let path = process_path::get_executable_path();
let path = current_exe(); //for windows 11
//let srcdir = PathBuf::from("./");
//fs::canonicalize(&srcdir).expect("Error returning the path from fs:: module... ").into_os_string().into_string().unwrap()
//windows path only:
match path {
Ok(exe_path) => {
let exe_path = exe_path.display().to_string();
let to_replace=String::from("\\");
let mut del_farther:usize=0;
if let Some(last_index) = exe_path.as_str().rfind(&to_replace.as_str()) {
del_farther = last_index;
}
return exe_path.as_str()[0..del_farther].to_string()+"\\"
},
Err(e) => return String::from("Failed to get current exe path {e} "),
};
//linux process only path
/*
match path {
None => String::from("The process path could not be determined... "),
Some(path) => {
let len = path.clone().into_os_string().into_string().expect("Can not shorten path of 10 chars from end == minus autoskola3").chars().count();
let outa_path_exe=path.clone().into_os_string().into_string().expect("Can not shorten path of 10 chars from end == minus autoskola3").drain(0..len).collect::<String>();
//let to_replace = path.trim_to_nth(1).expect("Can not trim the path. ").into_os_string().into_string().unwrap();
//let target_str = outa_path_exe.replace(to_replace.as_str(),"");
let to_replace=String::from("/");
let mut del_farther:usize=0;
if let Some(last_index) = outa_path_exe.as_str().rfind(&to_replace.as_str()) {
del_farther = last_index;
}
outa_path_exe.as_str()[0..del_farther].to_string()+"/"
//path.trim_to_nth(1).expect("Can not trim the path. ").into_os_string().into_string().unwrap()
//target_str.to_string()
}
} */ }
//calling main function in rust language
fn main() -> iced::Result {
MyApp::run(Settings::default())
}
//enum with app signals definitions:
#[derive(Debug, Clone)]
enum MyAppMessage {
GoZakon,
GoZnacka,
GoKrizovatka,
GiveAnswer,
GoLaw,
GoSign,
GoIntersection
}
//state of the application based on iced framework documentation:
#[derive(Default)]
struct MyApp{
pic_value:String,
question_value:String,
answer_value:String,
q_num:String,
t_num:String,
q_type:String,
}
//implementation for myapp struct:
impl Sandbox for MyApp {
type Message = MyAppMessage;//type alias
//app window constructor:
fn new() -> Self {
Self{
pic_value: String::from(""),
question_value: String::from("Sem načítam otázku po kliknutí na príslušné tlačítko...\n Here I load the question after adequate button click..."),
answer_value: String::from("Sem načítam odpoveď po kliknutí na príslušné tlačítko...\n Here I load the answer after adequate button click..."),
q_num: String::from("1"), //global random number of the SLOVAK question
q_type: String::from("za"), //whether zakony za or znacky zn
t_num:String::from("1"), //just the first English test as we know t1o1.txt means test1 otazka1
}
}
//title of app window:
fn title(&self) -> String {
String::from("Autoškola2023 EN+SK: 2000 questions | Mgr. Janko Hruboš | janko.hrubos@gmail.com")
}
//on the state update and signals receiving do these actions:
fn update(&mut self, message: Self::Message) {
match message {
MyAppMessage::GoZakon => {
self.pic_value = cur_dir1()+"/resources/empty.jpg";
//println!("{}",cur_dir1());
self.q_num=rand_range_num(525);
let mut s2:String=cur_dir1()+"/resources/sk/otza/za_";
let s3:String=".txt".to_owned();
s2.push_str(&self.q_num);
s2.push_str(&s3);
self.question_value = fs::read_to_string(s2)
.expect("ERROR: Cant read the file, sorry...");
self.q_type=String::from("za");
self.answer_value=String::from("");
//^^^ self explanatory
}
MyAppMessage::GoZnacka => {
self.q_num=rand_range_num(144);
let s4:String=(cur_dir1()+"/resources/sk/znackyobr/z"+&self.q_num+".jpg").to_string().clone();
self.pic_value = s4;
let mut s2:String=cur_dir1()+"/resources/sk/otzn/z_";
let s3:String=".txt".to_owned();
s2.push_str(&self.q_num);
s2.push_str(&s3);
self.question_value = fs::read_to_string(s2)
.expect("ERROR: Cant read the file, sorry...");
self.q_type=String::from("zn");
self.answer_value=String::from("");
}
MyAppMessage::GoKrizovatka => {
self.q_num=rand_range_num2(144);
let s4:String=(cur_dir1()+"/resources/sk/znackyobr/z"+&self.q_num+".jpg").to_string().clone();
self.pic_value = s4;
let mut s2:String=cur_dir1()+"/resources/sk/otzn/z_";
let s3:String=".txt".to_owned();
s2.push_str(&self.q_num);
s2.push_str(&s3);
self.question_value = fs::read_to_string(s2)
.expect("ERROR: Cant read the file, sorry...");
self.q_type=String::from("kri");
self.answer_value=String::from("");
}
MyAppMessage::GoLaw => {
self.q_num=rand_range_num(15);//generate random question from 1 to 27
self.t_num=rand_range_num(35);//generate random test from 1 to 35
//let s4:String=("resources/en/znackyobr/z".to_owned()+&self.q_num+".jpg").to_string().clone();
self.pic_value = String::from(cur_dir1()+"/resources/empty.jpg");
let mut s2:String=cur_dir1()+"/resources/en/otazkytxt/t";
let s3:String=".txt".to_owned();
let s5:String="o".to_owned();
s2.push_str(&self.t_num);
s2.push_str(&s5);
s2.push_str(&self.q_num);
s2.push_str(&s3);
self.question_value = fs::read_to_string(s2)
.expect("ERROR: Cant read the file, sorry...");
self.q_type=String::from("law");
self.answer_value=String::from("");
}
MyAppMessage::GoSign => {
self.q_num=rand_range_num3(16);//generate random question from 16 to 23
self.t_num=rand_range_num(35);//generate random test from 1 to 35
let s4:String=(cur_dir1()+"/resources/en/znackyobr/t"+&self.t_num+"o"+&self.q_num+".jpg").to_string().clone();
//println!("{}",s4); //debug printout
self.pic_value = s4;
let mut s2:String=cur_dir1()+"/resources/en/otazkytxt/t";
let s3:String=".txt".to_owned();
let s5:String="o".to_owned();
s2.push_str(&self.t_num);
s2.push_str(&s5);
s2.push_str(&self.q_num);
s2.push_str(&s3);
self.question_value = fs::read_to_string(s2)
.expect("ERROR: Cant read the file, sorry...");
self.q_type=String::from("sig");
self.answer_value=String::from("");
}
MyAppMessage::GoIntersection => {
self.q_num=rand_range_num4(24);//generate random question from 24 to 27
self.t_num=rand_range_num(35);//generate random test from 1 to 35
let s4:String=(cur_dir1()+"/resources/en/znackyobr/t"+&self.t_num+"o"+&self.q_num+".jpg").to_string().clone();
//println!("{}",s4); //debug printout
self.pic_value = s4;
let mut s2:String=cur_dir1()+"/resources/en/otazkytxt/t";
let s3:String=".txt".to_owned();
let s5:String="o".to_owned();
s2.push_str(&self.t_num);
s2.push_str(&s5);
s2.push_str(&self.q_num);
s2.push_str(&s3);
self.question_value = fs::read_to_string(s2)
.expect(&("ERROR: Cant read the file, sorry... Path: ".to_owned()+&cur_dir1()));
self.q_type=String::from("int");//question type is intersection
self.answer_value=String::from("");//answer is not visible yet, coz intersection button pressed not answer button
//^^^ self explanatory what to do on these signals receiving
}
MyAppMessage::GiveAnswer => { //on button answer click:
let qnum = self.q_num.clone();
let tnum = self.t_num.clone();
let qtype = self.q_type.clone();
if qtype == "za" { //if this is Slovak zakon you know qnum is from 1 to 525
let mut s2:String=cur_dir1()+"/resources/sk/otza/zao_";
let s3:String=".txt".to_owned();
s2.push_str(&qnum);
s2.push_str(&s3);
self.answer_value=String::from("Odpoveď na otázku zákony ");
self.answer_value.push_str(&qnum);
let s4:String=" je: ".to_owned();
self.answer_value.push_str(&s4);
self.answer_value.push_str(&fs::read_to_string(s2)
.expect("ERROR: Cant read the file, sorry..."));
}
if qtype == "zn" { //if this is Slovak znacka you know qnum is from 1 to 144
let mut s2:String=cur_dir1()+"/resources/sk/otzn/zo_";
let s3:String=".txt".to_owned();
s2.push_str(&qnum);
s2.push_str(&s3);
self.answer_value=String::from("Odpoveď na otázku značky ");
self.answer_value.push_str(&qnum);
let s4:String=" je: ".to_owned();
self.answer_value.push_str(&s4);
self.answer_value.push_str(&fs::read_to_string(s2)
.expect("ERROR: Cant read the file, sorry..."));
}
if qtype == "kri" { //if this is Slovak znacka you know qnum is from (1 to 144)+144
let mut s2:String=cur_dir1()+"/resources/sk/otzn/zo_";
let s3:String=".txt".to_owned();
s2.push_str(&qnum);
s2.push_str(&s3);
self.answer_value=String::from("Odpoveď na otázku križovatky ");
self.answer_value.push_str(&qnum);
let s4:String=" je: ".to_owned();
self.answer_value.push_str(&s4);
self.answer_value.push_str(&fs::read_to_string(s2)
.expect("ERROR: Cant read the file, sorry..."));
}
if qtype == "law" {
let mut s2:String=cur_dir1()+"/resources/en/odtxt/t";
//let s3:String=".txt".to_owned();
let s5:String="od".to_owned();
s2.push_str(&tnum);
s2.push_str(&s5);
s2.push_str(&qnum);
//s2.push_str(&s3);
self.answer_value=String::from("Answer to the question from laws ");
self.answer_value.push_str(&qnum);
let s4:String=" is: ".to_owned();
self.answer_value.push_str(&s4);
//println!("{}",s2);
self.answer_value.push_str(&fs::read_to_string(s2)
.expect("ERROR: Cant read the file, sorry..."));
}
if qtype == "sig" {
let mut s2:String=cur_dir1()+"/resources/en/odtxt/t";
//let s3:String=".txt".to_owned();
let s5:String="od".to_owned();
s2.push_str(&tnum);
s2.push_str(&s5);
s2.push_str(&qnum);
//s2.push_str(&s3);
self.answer_value=String::from("Answer to the question from signs ");
self.answer_value.push_str(&qnum);
self.answer_value.push_str(" / test ");
self.answer_value.push_str(&tnum);
let s4:String=" is: ".to_owned();
self.answer_value.push_str(&s4);
//println!("{}",s2);
self.answer_value.push_str(&fs::read_to_string(s2)
.expect("ERROR: Cant read the file, sorry..."));
}
if qtype == "int" {
let mut s2:String=cur_dir1()+"/resources/en/odtxt/t";
//let s3:String=".txt".to_owned();
let s5:String="od".to_owned();
s2.push_str(&tnum);
s2.push_str(&s5);
s2.push_str(&qnum);
//s2.push_str(&s3);
self.answer_value=String::from("Answer to the question from intersections ");
self.answer_value.push_str(&qnum);
self.answer_value.push_str(" / test ");
self.answer_value.push_str(&tnum);
let s4:String=" is: ".to_owned();
self.answer_value.push_str(&s4);
//println!("{}",s2);
self.answer_value.push_str(&fs::read_to_string(s2)
.expect(&("ERROR: Cant read the file, sorry... Path: ".to_owned()+&cur_dir1())));
}
}
}
}
//basic view definitions with slots of signals:
fn view(&self) -> iced::Element<'_, Self::Message> {
let padding1:u16=10;//padding of 10px
column![
image(self.pic_value.clone()).width(600),
row![button("Náhodný zákon").on_press(MyAppMessage::GoZakon).padding(padding1),
button("Náhodná značka").on_press(MyAppMessage::GoZnacka).padding(padding1),
button("Náhodná križovatka").on_press(MyAppMessage::GoKrizovatka).padding(padding1)],
row![button("Answer/Opoveď").on_press(MyAppMessage::GiveAnswer).padding(padding1)],
row![button("Random law").on_press(MyAppMessage::GoLaw).padding(padding1),
button("Random sign").on_press(MyAppMessage::GoSign).padding(padding1),
button("Random intersection").on_press(MyAppMessage::GoIntersection).padding(padding1),],
text(self.question_value.as_str()).style(Color::from_rgb(1., 0.0, 0.0)),
text(self.answer_value.as_str()).style(Color::from_rgb(1., 0.0, 0.0)),
].width(Length::Fill).align_items(Alignment::Center).padding(20)
.into()
}
}
The pack for windows11 can be downloaded here: https://hrubos.org/repo/autoskola2023_win11.64_pack.zip