diff --git a/src/config.rs b/src/config.rs index 26d7061..d72245f 100644 --- a/src/config.rs +++ b/src/config.rs @@ -118,19 +118,19 @@ pub fn coord_to_san(board: &Board, coords: String, lang: &lang::Language) -> Opt san_str.push_str(&coords[0..1]); san_localized.push_str(&coords[0..1]); } Piece::Bishop => { - san_str.push_str("B"); + san_str.push('B'); san_localized.push_str(&lang::tr(lang, "bishop")); } Piece::Knight => { - san_str.push_str("N"); + san_str.push('N'); san_localized.push_str(&lang::tr(lang, "knight")); } Piece::Rook => { - san_str.push_str("R"); + san_str.push('R'); san_localized.push_str(&lang::tr(lang, "rook")); } Piece::Queen => { - san_str.push_str("Q"); + san_str.push('Q'); san_localized.push_str(&lang::tr(lang, "queen")); } Piece::King => { - san_str.push_str("K"); + san_str.push('K'); san_localized.push_str(&lang::tr(lang, "king")); } } @@ -138,54 +138,52 @@ pub fn coord_to_san(board: &Board, coords: String, lang: &lang::Language) -> Opt if is_en_passant { san_localized.push_str(&(String::from("x") + &coords[2..4] + " e.p.")); } else if is_normal_capture { - let simple_capture = san_str.clone() + &"x" + &coords[2..]; - let try_move = ChessMove::from_san(&board, &simple_capture); - if let Ok(_) = try_move { + let simple_capture = san_str.clone() + "x" + &coords[2..]; + let try_move = ChessMove::from_san(board, &simple_capture); + if try_move.is_ok() { san_str.push_str(&(String::from("x") + &coords[2..])); san_localized.push_str(&(String::from("x") + &coords[2..])); } else { //the simple notation can only fail because of ambiguity, so we try to specify //either the file or the rank - let capture_with_file = san_str.clone() + &coords[0..1] + &"x" + &coords[2..]; - let try_move_file = ChessMove::from_san(&board, &capture_with_file); - if let Ok(_) = try_move_file { - san_localized.push_str(&(String::from(&coords[0..1]) + &"x" + &coords[2..])); + let capture_with_file = san_str.clone() + &coords[0..1] + "x" + &coords[2..]; + let try_move_file = ChessMove::from_san(board, &capture_with_file); + if try_move_file.is_ok() { + san_localized.push_str(&(String::from(&coords[0..1]) + "x" + &coords[2..])); } else { - san_localized.push_str(&(String::from(&coords[1..2]) + &"x" + &coords[2..])); + san_localized.push_str(&(String::from(&coords[1..2]) + "x" + &coords[2..])); } } // And now the regular moves + } else if piece==Piece::Pawn { + san_localized = String::from(&coords[2..]); } else { - if piece==Piece::Pawn { - san_localized = String::from(&coords[2..]); + let move_with_regular_notation = san_str.clone() + &coords[2..]; + let move_to_try = ChessMove::from_san(board, &move_with_regular_notation); + if move_to_try.is_ok() { + san_str.push_str(&coords[2..]); + san_localized.push_str(&coords[2..]); } else { - let move_with_regular_notation = san_str.clone() + &coords[2..]; - let move_to_try = ChessMove::from_san(&board, &move_with_regular_notation); - if let Ok(_) = move_to_try { - san_str.push_str(&coords[2..]); - san_localized.push_str(&coords[2..]); + //the simple notation can only fail because of ambiguity, so we try to specify + //either the file or the rank + let move_notation_with_file = san_str.clone() + &coords[0..1] + &coords[2..]; + let try_move_file = ChessMove::from_san(board, &move_notation_with_file); + if try_move_file.is_ok() { + san_localized.push_str(&(String::from(&coords[0..1]) + &coords[2..])); } else { - //the simple notation can only fail because of ambiguity, so we try to specify - //either the file or the rank - let move_notation_with_file = san_str.clone() + &coords[0..1] + &coords[2..]; - let try_move_file = ChessMove::from_san(&board, &move_notation_with_file); - if let Ok(_) = try_move_file { - san_localized.push_str(&(String::from(&coords[0..1]) + &coords[2..])); - } else { - san_localized.push_str(&(String::from(&coords[1..2]) + &coords[2..])); - } + san_localized.push_str(&(String::from(&coords[1..2]) + &coords[2..])); } } } - let chess_move = ChessMove::from_san(&board, &san_localized); + let chess_move = ChessMove::from_san(board, &san_localized); // Note: It can indeed return Err for a moment when using the engine (and quickly taking // back moves), I guess for a sec the engine & board may get desynced, so we can't just unwrap it. if let Ok(chess_move) = chess_move { let current_board = board.make_move_new(chess_move); if current_board.status() == chess::BoardStatus::Checkmate { - san_localized.push_str("#"); + san_localized.push('#'); } else if current_board.checkers().popcnt() != 0 { - san_localized.push_str("+"); + san_localized.push('+'); } } san = Some(san_localized); diff --git a/src/db.rs b/src/db.rs index 4cba4f7..31f850b 100644 --- a/src/db.rs +++ b/src/db.rs @@ -36,7 +36,7 @@ pub fn get_favorites(min_rating: i32, max_rating: i32, theme: TacticalThemes, op } else { opening.get_field_name() }; - let opening_filter = opening_tags.like(String::from("%") + &opening_tag + "%"); + let opening_filter = opening_tags.like(String::from("%") + opening_tag + "%"); let side = match op_side { None => OpeningSide::Any, Some(x) => x @@ -74,10 +74,8 @@ pub fn is_favorite(id: &str) -> bool { let results = favs .filter(puzzle_id.eq(id)) .first::(&mut conn); - if results.is_ok() { - return true; - } - return false; + + results.is_ok() } pub fn toggle_favorite(puzzle: Puzzle) { diff --git a/src/eval.rs b/src/eval.rs index 2c17c3f..948b1b5 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -65,7 +65,7 @@ impl Engine { let mut child = cmd.spawn().expect("Error calling engine"); let pos = String::from("position fen ") + &engine.position + &String::from("\n"); - let limit = String::from("go ") + &engine.search_up_to + &"\n"; + let limit = String::from("go ") + &engine.search_up_to + "\n"; let mut uciok = false; let mut readyok = false; @@ -76,13 +76,11 @@ impl Engine { let uciok_timeout = timeout(Duration::from_millis(7000), reader.read_line(&mut buf_str) ).await; - if let Err(_) = uciok_timeout { + if uciok_timeout.is_err() { + break; + } else if buf_str.contains("uciok") { + uciok = true; break; - } else { - if buf_str.contains("uciok") { - uciok = true; - break; - } } } if uciok { @@ -93,13 +91,11 @@ impl Engine { let readyok_timeout = timeout(Duration::from_millis(7000), reader.read_line(&mut buf_str) ).await; - if let Err(_) = readyok_timeout { + if readyok_timeout.is_err() { + break; + } else if buf_str.contains("readyok") { + readyok = true; break; - } else { - if buf_str.contains("readyok") { - readyok = true; - break; - } } } if readyok { @@ -118,8 +114,9 @@ impl Engine { let terminate_timeout = timeout(Duration::from_millis(1000), child.wait() ).await; - if let Err(_) = terminate_timeout { - eprintln!("Engine didn't quit, killing the process now..."); + if let Err(e) = terminate_timeout { + eprintln!("Error: {e}"); + eprintln!("Engine didn't quit, killing the process now... "); let kill_result = timeout(Duration::from_millis(500), child.kill() ).await; @@ -132,14 +129,15 @@ impl Engine { } EngineState::Thinking(child, search_up_to, receiver) => { let msg = receiver.try_recv(); if let Ok(msg) = msg { - if &msg == STOP_COMMAND || &msg == EXIT_APP_COMMAND { + if msg == STOP_COMMAND || msg == EXIT_APP_COMMAND { child.stdin.as_mut().unwrap().write_all(b"stop\n").await.expect("Error communicating with engine"); child.stdin.as_mut().unwrap().write_all(b"quit\n").await.expect("Error communicating with engine"); let terminate_timeout = timeout(Duration::from_millis(1000), child.wait() ).await; - if let Err(_) = terminate_timeout { - eprintln!("Engine didn't quit, killing the process now..."); + if let Err(e) = terminate_timeout { + eprintln!("Error: {e}"); + eprintln!("Engine didn't quit, killing the process now... "); let kill_result = timeout(Duration::from_millis(500), child.kill() ).await; @@ -147,12 +145,12 @@ impl Engine { eprintln!("Error killing the engine process: {e}"); } } - output.send(Message::EngineStopped(&msg == EXIT_APP_COMMAND)).await.expect("Error on the mpsc channel in the engine subscription"); + output.send(Message::EngineStopped(msg == EXIT_APP_COMMAND)).await.expect("Error on the mpsc channel in the engine subscription"); state = EngineState::TurnedOff; continue; } else { let pos = String::from("position fen ") + &msg + &String::from("\n"); - let limit = String::from("go ") + &search_up_to + &"\n"; + let limit = String::from("go ") + &search_up_to + "\n"; child.stdin.as_mut().unwrap().write_all(b"stop\n").await.expect("Error communicating with engine"); //child.stdin.as_mut().unwrap().write_all(b"setoption name UCI_AnalyseMode value true\n").await.expect("Error communicating with engine"); //child.stdin.as_mut().unwrap().write_all(b"ucinewgame\n").await.expect("Error communicating with engine"); @@ -170,38 +168,34 @@ impl Engine { let read_timeout = timeout(Duration::from_millis(50), reader.read_line(&mut buf_str) ).await; - if let Ok(timeout) = read_timeout { - if let Ok(read_result) = timeout { - if read_result == 0 { - break; - } - let vector: Vec<&str> = buf_str.split_whitespace().collect::>(); - if let Some(index) = vector.iter().position(|&x| x == "score") { - let eval_num = vector.get(index+2).unwrap().parse::().ok(); - if let Some(e) = eval_num { - if vector.get(index+1).unwrap() == &"mate" { - eval = Some(String::from("Mate in ") + &e.to_string()); - } else { - eval = Some(format!("{:.2}",(e / 100.))); - } + if let Ok(Ok(read_result)) = read_timeout { + if read_result == 0 { + break; + } + let vector: Vec<&str> = buf_str.split_whitespace().collect::>(); + if let Some(index) = vector.iter().position(|&x| x == "score") { + let eval_num = vector.get(index+2).unwrap().parse::().ok(); + if let Some(e) = eval_num { + if vector.get(index+1).unwrap() == &"mate" { + eval = Some(String::from("Mate in ") + &e.to_string()); + } else { + eval = Some(format!("{:.2}",(e / 100.))); } - for i in (index + 3)..vector.len() { - if let Some(token) = vector.get(i) { - if token == &"pv" { - // I thought we could just unwrap, but at least Koivisto sometimes - // returns lines with nothing in the pv - if let Some(best) = vector.get(i+1) { - best_move = Some(best.to_string()); - break; - } + } + for i in (index + 3)..vector.len() { + if let Some(token) = vector.get(i) { + if token == &"pv" { + // I thought we could just unwrap, but at least Koivisto sometimes + // returns lines with nothing in the pv + if let Some(best) = vector.get(i+1) { + best_move = Some(best.to_string()); + break; } } } } - buf_str.clear(); - } else { - break; } + buf_str.clear(); } else { break; } diff --git a/src/export.rs b/src/export.rs index 7de2408..71f5e7a 100644 --- a/src/export.rs +++ b/src/export.rs @@ -84,7 +84,7 @@ pub fn to_pdf(puzzles: &Vec, number_of_pages: i32, lang: &lang:: //let number_of_pages: i64 = 100;//(puzzles.len() / 6).try_into().unwrap(); let mut page_ids = vec![]; let mut puzzle_index = 0; - for _ in 0..num_of_pages.into() { + for _ in 0..num_of_pages { let mut ops: Vec = vec![]; let mut pos_x = 750; let mut pos_y = 75; @@ -132,11 +132,10 @@ pub fn to_pdf(puzzles: &Vec, number_of_pages: i32, lang: &lang:: let mut ops: Vec = vec![]; let mut pos_x = 800; let pos_y = 75; - let mut num_pages_of_solution = 1; - for puzzle_number in 0..num_of_puzzles_to_print { + for (puzzle_number, puzzle) in puzzles.iter().enumerate().take(num_of_puzzles_to_print) { // need to start by making the 1st move in the list, because it's only then that // the puzzle starts. - let mut board = Board::from_str(&puzzles[puzzle_number].fen).unwrap(); + let mut board = Board::from_str(&puzzle.fen).unwrap(); let mut puzzle_moves: VecDeque<&str> = puzzles[puzzle_number].moves.split_whitespace().collect(); let movement = ChessMove::new( Square::from_str(&String::from(&puzzle_moves[0][..2])).unwrap(), @@ -156,16 +155,16 @@ pub fn to_pdf(puzzles: &Vec, number_of_pages: i32, lang: &lang:: } for chess_move in puzzle_moves { if half_move_number % 2 == 0 { - solution.push_str(" "); + solution.push(' '); solution.push_str(&config::coord_to_san(&board, String::from(chess_move), lang).unwrap()); } else { - solution.push_str(" "); + solution.push(' '); solution.push_str(&move_label.to_string()); solution.push_str(". "); solution.push_str(&config::coord_to_san(&board, String::from(chess_move), lang).unwrap()); - move_label = move_label + 1; + move_label += 1; } - half_move_number = half_move_number + 1; + half_move_number += 1; // Apply move, so we have the updated board to generate the SAN for the next move. let movement = ChessMove::new( Square::from_str(&String::from(&chess_move[..2])).unwrap(), @@ -180,12 +179,11 @@ pub fn to_pdf(puzzles: &Vec, number_of_pages: i32, lang: &lang:: Operation::new("Tj", vec![Object::string_literal(solution)]), Operation::new("ET", vec![]), ]); - pos_x = pos_x - 18; + pos_x -= 18; // We need a page break if pos_x < 18 { pos_x = 800; - num_pages_of_solution = num_pages_of_solution + 1; let content = Content { operations: ops, @@ -318,12 +316,10 @@ fn gen_diagram_operations(index: usize, puzzle: &config::Puzzle, start_x:i32, st new_piece = new_piece.to_lowercase().collect::>()[0]; } } + } else if light_square { + new_piece = ' '; } else { - if light_square { - new_piece = ' '; - } else { - new_piece = '+'; - } + new_piece = '+'; } rank_string.push(new_piece); } diff --git a/src/lang.rs b/src/lang.rs index 37d35ad..5087adf 100644 --- a/src/lang.rs +++ b/src/lang.rs @@ -58,7 +58,7 @@ pub fn tr(lang: &Language, key: &str) -> String { let msg = bundle.get_message(key).expect(&("Missing translation key ".to_owned() + key)); let mut errors = vec![]; let pattern = msg.value().expect("Missing Value."); - bundle.format_pattern(&pattern, None, &mut errors).to_string() + bundle.format_pattern(pattern, None, &mut errors).to_string() } #[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)] diff --git a/src/main.rs b/src/main.rs index 86e2f3d..8e4596d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -198,7 +198,7 @@ impl Default for OfflinePuzzles { engine_sender: None, engine_move: String::new(), - puzzle_status: String::from(lang::tr(&config::SETTINGS.lang, "use_search")), + puzzle_status: lang::tr(&config::SETTINGS.lang, "use_search"), search_tab: SearchTab::new(), settings_tab: SettingsTab::new(), puzzle_tab: PuzzleTab::new(), @@ -579,7 +579,7 @@ impl Application for OfflinePuzzles { height: self.settings_tab.window_height - 110} ); if let Ok (screenshot) = crop { - let img = RgbaImage::from_raw(screenshot.size.width, screenshot.size.height, (&screenshot.bytes).to_vec()); + let img = RgbaImage::from_raw(screenshot.size.width, screenshot.size.height, screenshot.bytes.to_vec()); if let Some(image) = img { let _ = image.save_with_format(path, image::ImageFormat::Jpeg); } @@ -595,10 +595,10 @@ impl Application for OfflinePuzzles { if let Event::Window(window::Id::MAIN, window::Event::CloseRequested) = event { match self.engine_state { EngineStatus::TurnedOff => { - return iced::window::fetch_maximized( + iced::window::fetch_maximized( window::Id::MAIN, - |maximized| Message::SaveMaximizedStatusAndExit(maximized) - ); + Message::SaveMaximizedStatusAndExit + ) } _ => { if let Some(sender) = &self.engine_sender { sender.blocking_send(String::from(eval::EXIT_APP_COMMAND)).expect("Error stopping engine."); @@ -663,12 +663,11 @@ impl Application for OfflinePuzzles { if eval_str.contains("Mate") { let tokens: Vec<&str> = eval_str.split_whitespace().collect(); let distance_to_mate_num = tokens[2].parse::().unwrap(); - self.engine_eval = if distance_to_mate_num < 0 { - lang::tr(&self.lang, "mate_in") + &(distance_to_mate_num * -1).to_string() - } else if distance_to_mate_num > 0 { - lang::tr(&self.lang, "mate_in") + &distance_to_mate_num.to_string() - } else { - lang::tr(&self.lang, "mate") + self.engine_eval = match distance_to_mate_num { + 1.. => { lang::tr(&self.lang, "mate_in") + &distance_to_mate_num.to_string() } + 0 => { lang::tr(&self.lang, "mate") } + _ => { lang::tr(&self.lang, "mate_in") + &(-distance_to_mate_num).to_string() } + }; } else if self.analysis.side_to_move() == Color::White { self.engine_eval = eval_str; @@ -716,7 +715,7 @@ impl Application for OfflinePuzzles { ) } (_, Message::HandleDropZones(from, zones)) => { if !zones.is_empty() { - let id: &GenericId = &zones[0].0.clone().into(); + let id: &GenericId = &zones[0].0.clone(); if let Some(to) = self.square_ids.get(id) { self.verify_and_make_move(from, *to); } @@ -793,12 +792,8 @@ impl Application for OfflinePuzzles { } pub async fn screenshot_save_dialog(img: Screenshot) -> Option<(Screenshot, String)> { - let file_path = AsyncFileDialog::new().add_filter("jpg", &["jpg", "jpeg"]).save_file(); - if let Some(file_path) = file_path.await { - Some((img, file_path.path().display().to_string())) - } else { - None - } + let file_path = AsyncFileDialog::new().add_filter("jpg", &["jpg", "jpeg"]).save_file().await; + file_path.map(|file_path| (img, file_path.path().display().to_string())) } fn gen_view<'a>( @@ -843,19 +838,18 @@ fn gen_view<'a>( let is_white = (current_puzzle_side == Color::White) ^ flip_board; //Reserve more space below the board if we'll show the engine eval - let board_height = if engine_eval.is_empty() { - if show_coordinates { - ((size.height - 120.) / 8.) as u16 - } else { - ((size.height - 110.) / 8.) as u16 - } - } else { - if show_coordinates { + let board_height = + if engine_eval.is_empty() { + if show_coordinates { + ((size.height - 120.) / 8.) as u16 + } else { + ((size.height - 110.) / 8.) as u16 + } + } else if show_coordinates { ((size.height - 150.) / 8.) as u16 } else { ((size.height - 140.) / 8.) as u16 - } - }; + }; let ranks; let files; @@ -923,13 +917,12 @@ fn gen_view<'a>( if light_square { text = text.to_lowercase(); } + } else if light_square { + text = String::from(" "); } else { - if light_square { - text = String::from(" "); - } else { - text = String::from("+"); - } + text = String::from("+"); } + board_row = board_row.push(Button::new( Text::new(text) @@ -960,9 +953,8 @@ fn gen_view<'a>( } }; if let Some(piece) = piece { - let text; - if color.unwrap() == Color::White { - text = match piece { + let text = if color.unwrap() == Color::White { + match piece { Piece::Pawn => "/wP.svg", Piece::Rook => "/wR.svg", Piece::Knight => "/wN.svg", @@ -971,15 +963,15 @@ fn gen_view<'a>( Piece::King => "/wK.svg" } } else { - text = match piece { + match piece { Piece::Pawn => "/bP.svg", Piece::Rook => "/bR.svg", Piece::Knight => "/bN.svg", Piece::Bishop => "/bB.svg", Piece::Queen => "/bQ.svg", Piece::King => "/bK.svg" - }; - } + } + }; board_row = board_row.push( container( @@ -1097,8 +1089,8 @@ fn gen_view<'a>( if !engine_eval.is_empty() { board_col = board_col.push( row![ - Text::new(String::from(lang::tr(lang, "eval")) + &engine_eval), - Text::new(String::from(lang::tr(lang, "best_move")) + &engine_move) + Text::new(lang::tr(lang, "eval") + engine_eval), + Text::new(lang::tr(lang, "best_move") + engine_move) ].padding(5).spacing(15) ); } diff --git a/src/puzzles.rs b/src/puzzles.rs index ab870e8..94e436f 100644 --- a/src/puzzles.rs +++ b/src/puzzles.rs @@ -63,12 +63,8 @@ impl PuzzleTab { } pub async fn export() -> Option { - let file_path = AsyncFileDialog::new().save_file(); - if let Some(file_path) = file_path.await { - Some(file_path.path().display().to_string()) - } else { - None - } + let file_path = AsyncFileDialog::new().save_file().await; + file_path.map(|file_path| file_path.path().display().to_string()) } // Checks if the notation indicates a promotion and return the piece @@ -122,10 +118,10 @@ impl Tab for PuzzleTab { ).on_input(PuzzleMessage::ChangeTextInputs), Button::new(Text::new(lang::tr(&self.lang, "copy"))).on_press(PuzzleMessage::CopyText(self.current_puzzle_fen.clone())), ], - Text::new(String::from(lang::tr(&self.lang, "rating")) + &self.puzzles[self.current_puzzle].rating.to_string()), - Text::new(String::from(lang::tr(&self.lang, "rd")) + &self.puzzles[self.current_puzzle].rating_deviation.to_string()), - Text::new(String::from(lang::tr(&self.lang, "popularity")) + &self.puzzles[self.current_puzzle].popularity.to_string()), - Text::new(String::from(lang::tr(&self.lang, "times_played")) + &self.puzzles[self.current_puzzle].nb_plays.to_string()), + Text::new(lang::tr(&self.lang, "rating") + &self.puzzles[self.current_puzzle].rating.to_string()), + Text::new(lang::tr(&self.lang, "rd") + &self.puzzles[self.current_puzzle].rating_deviation.to_string()), + Text::new(lang::tr(&self.lang, "popularity") + &self.puzzles[self.current_puzzle].popularity.to_string()), + Text::new(lang::tr(&self.lang, "times_played") + &self.puzzles[self.current_puzzle].nb_plays.to_string()), Text::new(lang::tr(&self.lang, "themes")), Text::new(&self.puzzles[self.current_puzzle].themes), Text::new(lang::tr(&self.lang, "url")), diff --git a/src/search_tab.rs b/src/search_tab.rs index 0cc1175..43f91ac 100644 --- a/src/search_tab.rs +++ b/src/search_tab.rs @@ -31,7 +31,7 @@ impl PickListWrapper { for theme in TacticalThemes::ALL { themes_wrapper.push( PickListWrapper:: { - lang: lang, + lang, item: theme, } ); @@ -44,8 +44,9 @@ impl PickListWrapper { } } -#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Default, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)] pub enum TacticalThemes { + #[default] All, Opening, Middlegame, Endgame, RookEndgame, BishopEndgame, PawnEndgame, KnightEndgame, QueenEndgame, QueenRookEndgame, AdvancedPawn, AtackingF2F7, CapturingDefender, DiscoveredAttack, DoubleCheck, ExposedKing, Fork, HangingPiece, KingsideAttack, Pin, QueensideAttack, Sacrifice, Skewer, TrappedPiece, @@ -175,12 +176,6 @@ impl DisplayTranslated for TacticalThemes { } } -impl Default for TacticalThemes { - fn default() -> TacticalThemes { - TacticalThemes::Mate - } -} - #[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)] pub enum OpeningSide { Any, White, Black @@ -426,19 +421,19 @@ impl Tab for SearchTab { ].width(Length::Fill), Text::new(lang::tr(&self.lang, "theme_label")), PickList::new( - PickListWrapper::get_themes(self.lang.clone()), + PickListWrapper::get_themes(self.lang), Some(self.theme.clone()), SearchMesssage::SelectTheme ), Text::new(lang::tr(&self.lang, "in_opening")), PickList::new( - PickListWrapper::get_openings(self.lang.clone()), + PickListWrapper::get_openings(self.lang), Some(self.opening.clone()), SearchMesssage::SelectOpening ), Text::new(lang::tr(&self.lang, "in_the_variation")), PickList::new( - PickListWrapper::get_variations(self.lang.clone(), Some(&self.opening.item)), + PickListWrapper::get_variations(self.lang, Some(&self.opening.item)), Some(self.variation.clone()), SearchMesssage::SelectVariation ) diff --git a/src/settings.rs b/src/settings.rs index 7b66f74..5fa7eeb 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -122,9 +122,9 @@ impl SettingsTab { Command::none() } SettingsMessage::ChangePDFExportPgs(value) => { - if let Ok(_) = value.parse::() { + if value.parse::().is_ok() { self.export_pgs = value; - } else if value == "" { + } else if value.is_empty() { self.export_pgs = String::from("0"); } Command::none() @@ -174,11 +174,7 @@ impl SettingsTab { async fn open_engine_exe() -> Option { let engine_exe = AsyncFileDialog::new().pick_file().await; - if let Some(engine_path) = engine_exe { - Some(engine_path.path().display().to_string()) - } else { - None - } + engine_exe.map(|engine_path| engine_path.path().display().to_string()) } pub fn save_window_size(&self) { @@ -189,7 +185,7 @@ impl SettingsTab { let file = std::fs::File::create("settings.json"); match file { Ok(file) => { - if !serde_json::to_writer_pretty(file, &config).is_ok() { + if serde_json::to_writer_pretty(file, &config).is_err() { println!("Error saving config file."); } } Err(_) => println!("Error opening settings file") @@ -247,7 +243,7 @@ impl Tab for SettingsTab { row![ Text::new(lang::tr(&self.lang.lang, "language")), PickList::new( - PickListWrapper::get_langs(self.lang.lang.clone()), + PickListWrapper::get_langs(self.lang.lang), Some(self.lang.clone()), SettingsMessage::SelectLanguage )