From 11edf080de915df3a97acdb985514e7e9d8f1b4a Mon Sep 17 00:00:00 2001 From: Federico Terzi Date: Mon, 19 Jul 2021 20:48:55 +0200 Subject: [PATCH] feat(modulo): implement troubleshooting window --- espanso-modulo/build.rs | 8 +- espanso-modulo/src/lib.rs | 1 + espanso-modulo/src/sys/interop/interop.h | 29 ++ espanso-modulo/src/sys/interop/mod.rs | 35 ++ espanso-modulo/src/sys/mod.rs | 1 + espanso-modulo/src/sys/troubleshooting/mod.rs | 176 ++++++++ .../sys/troubleshooting/troubleshooting.cpp | 188 ++++++++ .../sys/troubleshooting/troubleshooting.fbp | 421 ++++++++++++++++++ .../troubleshooting/troubleshooting_gui.cpp | 77 ++++ .../sys/troubleshooting/troubleshooting_gui.h | 57 +++ espanso-modulo/src/troubleshooting.rs | 50 +++ 11 files changed, 1042 insertions(+), 1 deletion(-) create mode 100644 espanso-modulo/src/sys/troubleshooting/mod.rs create mode 100644 espanso-modulo/src/sys/troubleshooting/troubleshooting.cpp create mode 100644 espanso-modulo/src/sys/troubleshooting/troubleshooting.fbp create mode 100644 espanso-modulo/src/sys/troubleshooting/troubleshooting_gui.cpp create mode 100644 espanso-modulo/src/sys/troubleshooting/troubleshooting_gui.h create mode 100644 espanso-modulo/src/troubleshooting.rs diff --git a/espanso-modulo/build.rs b/espanso-modulo/build.rs index 740d424..85adb6e 100644 --- a/espanso-modulo/build.rs +++ b/espanso-modulo/build.rs @@ -117,6 +117,8 @@ fn build_native() { .file("src/sys/wizard/wizard_gui.cpp") .file("src/sys/welcome/welcome.cpp") .file("src/sys/welcome/welcome_gui.cpp") + .file("src/sys/troubleshooting/troubleshooting.cpp") + .file("src/sys/troubleshooting/troubleshooting_gui.cpp") .flag("/EHsc") .include(wx_include_dir) .include(wx_include_msvc_dir) @@ -215,6 +217,8 @@ fn build_native() { .file("src/sys/wizard/wizard_gui.cpp") .file("src/sys/welcome/welcome.cpp") .file("src/sys/welcome/welcome_gui.cpp") + .file("src/sys/troubleshooting/troubleshooting.cpp") + .file("src/sys/troubleshooting/troubleshooting_gui.cpp") .file("src/sys/common/mac.mm"); build.flag("-std=c++17"); @@ -353,7 +357,9 @@ fn build_native() { .file("src/sys/wizard/wizard.cpp") .file("src/sys/wizard/wizard_gui.cpp") .file("src/sys/welcome/welcome.cpp") - .file("src/sys/welcome/welcome_gui.cpp"); + .file("src/sys/welcome/welcome_gui.cpp") + .file("src/sys/troubleshooting/troubleshooting.cpp") + .file("src/sys/troubleshooting/troubleshooting_gui.cpp"); build.flag("-std=c++17"); for flag in cpp_flags { diff --git a/espanso-modulo/src/lib.rs b/espanso-modulo/src/lib.rs index 2eb870a..b139690 100644 --- a/espanso-modulo/src/lib.rs +++ b/espanso-modulo/src/lib.rs @@ -22,6 +22,7 @@ extern crate lazy_static; pub mod form; pub mod search; +pub mod troubleshooting; pub mod welcome; pub mod wizard; mod sys; \ No newline at end of file diff --git a/espanso-modulo/src/sys/interop/interop.h b/espanso-modulo/src/sys/interop/interop.h index 351646a..1fd0e9f 100644 --- a/espanso-modulo/src/sys/interop/interop.h +++ b/espanso-modulo/src/sys/interop/interop.h @@ -120,6 +120,8 @@ typedef struct WizardMetadata { void (*on_completed)(); } WizardMetadata; +// WELCOME + typedef struct WelcomeMetadata { const char *window_icon_path; const char *tray_image_path; @@ -128,3 +130,30 @@ typedef struct WelcomeMetadata { int (*dont_show_again_changed)(int); } WelcomeMetadata; +// TROUBLESHOOTING + +const int ERROR_METADATA_LEVEL_ERROR = 1; +const int ERROR_METADATA_LEVEL_WARNING = 2; +typedef struct ErrorMetadata { + const int level; + const char *message; +} ErrorMetadata; + +typedef struct ErrorSetMetadata { + const char *file_path; + const ErrorMetadata * errors; + const int errors_count; +} ErrorSetMetadata; + +typedef struct TroubleshootingMetadata { + const char *window_icon_path; + + const int is_fatal_error; + + const ErrorSetMetadata * error_sets; + const int error_sets_count; + + // METHODS + int (*dont_show_again_changed)(int); + int (*open_file)(const char * file_name); +} TroubleshootingMetadata; diff --git a/espanso-modulo/src/sys/interop/mod.rs b/espanso-modulo/src/sys/interop/mod.rs index 07f4e08..7d8b06d 100644 --- a/espanso-modulo/src/sys/interop/mod.rs +++ b/espanso-modulo/src/sys/interop/mod.rs @@ -146,6 +146,38 @@ pub struct WelcomeMetadata { pub dont_show_again_changed: extern fn(c_int), } +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct TroubleshootingMetadata { + pub window_icon_path: *const c_char, + pub is_fatal_error: c_int, + + pub error_sets: *const ErrorSetMetadata, + pub error_sets_count: c_int, + + pub dont_show_again_changed: extern fn(c_int), + pub open_file: extern fn(*const c_char), +} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct ErrorSetMetadata { + pub file_path: *const c_char, + + pub errors: *const ErrorMetadata, + pub errors_count: c_int, +} + +pub const ERROR_METADATA_LEVEL_ERROR: c_int = 1; +pub const ERROR_METADATA_LEVEL_WARNING: c_int = 2; + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct ErrorMetadata { + pub level: c_int, + pub message: *const c_char, +} + // Native bindings #[allow(improper_ctypes)] @@ -174,4 +206,7 @@ extern "C" { // WELCOME pub(crate) fn interop_show_welcome(metadata: *const WelcomeMetadata); + + // TROUBLESHOOTING + pub(crate) fn interop_show_troubleshooting(metadata: *const TroubleshootingMetadata); } diff --git a/espanso-modulo/src/sys/mod.rs b/espanso-modulo/src/sys/mod.rs index dc479ff..3ac74cc 100644 --- a/espanso-modulo/src/sys/mod.rs +++ b/espanso-modulo/src/sys/mod.rs @@ -19,6 +19,7 @@ pub mod form; pub mod search; +pub mod troubleshooting; pub mod wizard; pub mod welcome; diff --git a/espanso-modulo/src/sys/troubleshooting/mod.rs b/espanso-modulo/src/sys/troubleshooting/mod.rs new file mode 100644 index 0000000..f8c27e6 --- /dev/null +++ b/espanso-modulo/src/sys/troubleshooting/mod.rs @@ -0,0 +1,176 @@ +/* + * This file is part of modulo. + * + * Copyright (C) 2020-2021 Federico Terzi + * + * modulo is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * modulo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with modulo. If not, see . + */ + +use std::ffi::CStr; +use std::os::raw::{c_char, c_int}; +use std::path::PathBuf; +use std::sync::Mutex; + +use crate::sys::interop::{ErrorSetMetadata, TroubleshootingMetadata}; +use crate::sys::troubleshooting::interop::{OwnedErrorSet}; +use crate::sys::util::convert_to_cstring_or_null; +use crate::troubleshooting::{TroubleshootingHandlers, TroubleshootingOptions}; +use anyhow::Result; + +lazy_static! { + static ref HANDLERS: Mutex> = Mutex::new(None); +} + +#[allow(dead_code)] +mod interop { + use crate::troubleshooting::{ErrorRecord, ErrorSet}; + + use super::interop::{ErrorMetadata, ErrorSetMetadata}; + + use super::super::interop::*; + use std::{ + ffi::{CString}, + os::raw::c_int, + }; + + pub(crate) struct OwnedErrorSet { + file_path: Option, + errors: Vec, + pub(crate) _interop_errors: Vec, + } + + impl OwnedErrorSet { + pub fn to_error_set_metadata(&self) -> ErrorSetMetadata { + let file_path_ptr = if let Some(file_path) = self.file_path.as_ref() { + file_path.as_ptr() + } else { + std::ptr::null() + }; + + ErrorSetMetadata { + file_path: file_path_ptr, + errors: self._interop_errors.as_ptr(), + errors_count: self._interop_errors.len() as c_int, + } + } + } + + impl From<&ErrorSet> for OwnedErrorSet { + fn from(error_set: &ErrorSet) -> Self { + let file_path = if let Some(file_path) = &error_set.file { + Some(CString::new(file_path.to_string_lossy().to_string()) + .expect("unable to convert file_path to CString")) + } else { + None + }; + + let errors: Vec = + error_set.errors.iter().map(|item| item.into()).collect(); + + let _interop_errors: Vec = + errors.iter().map(|item| item.to_error_metadata()).collect(); + + Self { + file_path, + errors, + _interop_errors, + } + } + } + + pub(crate) struct OwnedErrorMetadata { + level: c_int, + message: CString, + } + + impl OwnedErrorMetadata { + fn to_error_metadata(&self) -> ErrorMetadata { + ErrorMetadata { + level: self.level, + message: self.message.as_ptr(), + } + } + } + + impl From<&ErrorRecord> for OwnedErrorMetadata { + fn from(item: &ErrorRecord) -> Self { + let message = + CString::new(item.message.clone()).expect("unable to convert item message to CString"); + + Self { + level: match item.level { + crate::troubleshooting::ErrorLevel::Error => ERROR_METADATA_LEVEL_ERROR, + crate::troubleshooting::ErrorLevel::Warning => ERROR_METADATA_LEVEL_WARNING, + }, + message, + } + } + } +} + +pub fn show(options: TroubleshootingOptions) -> Result<()> { + let (_c_window_icon_path, c_window_icon_path_ptr) = + convert_to_cstring_or_null(options.window_icon_path); + + let owned_error_sets: Vec = + options.error_sets.iter().map(|set| set.into()).collect(); + let error_sets: Vec = owned_error_sets + .iter() + .map(|set| set.to_error_set_metadata()) + .collect(); + + extern "C" fn dont_show_again_changed(dont_show: c_int) { + let lock = HANDLERS + .lock() + .expect("unable to acquire lock in dont_show_again_changed method"); + let handlers_ref = (*lock).as_ref().expect("unable to unwrap handlers"); + if let Some(handler_ref) = handlers_ref.dont_show_again_changed.as_ref() { + let value = if dont_show == 1 { true } else { false }; + (*handler_ref)(value); + } + } + + extern "C" fn open_file(file_path: *const c_char) { + let lock = HANDLERS + .lock() + .expect("unable to acquire lock in open_file method"); + let handlers_ref = (*lock).as_ref().expect("unable to unwrap handlers"); + if let Some(handler_ref) = handlers_ref.open_file.as_ref() { + let c_string = unsafe { CStr::from_ptr(file_path) }; + let string = c_string.to_string_lossy(); + let path = PathBuf::from(string.to_string()); + (*handler_ref)(&path); + } + } + + { + let mut lock = HANDLERS.lock().expect("unable to acquire handlers lock"); + *lock = Some(options.handlers) + } + + let troubleshooting_metadata = TroubleshootingMetadata { + window_icon_path: c_window_icon_path_ptr, + is_fatal_error: if options.is_fatal_error { 1 } else { 0 }, + error_sets: error_sets.as_ptr(), + error_sets_count: error_sets.len() as c_int, + dont_show_again_changed, + open_file, + }; + + unsafe { + super::interop::interop_show_troubleshooting(&troubleshooting_metadata); + } + + Ok(()) +} diff --git a/espanso-modulo/src/sys/troubleshooting/troubleshooting.cpp b/espanso-modulo/src/sys/troubleshooting/troubleshooting.cpp new file mode 100644 index 0000000..4471b6f --- /dev/null +++ b/espanso-modulo/src/sys/troubleshooting/troubleshooting.cpp @@ -0,0 +1,188 @@ +/* + * This file is part of modulo. + * + * Copyright (C) 2020-2021 Federico Terzi + * + * modulo is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * modulo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with modulo. If not, see . + */ + +#define _UNICODE + +#include "../common/common.h" +#include "../interop/interop.h" +#include "./troubleshooting_gui.h" + +#include +#include +#include + +TroubleshootingMetadata *troubleshooting_metadata = nullptr; + +// App Code + +class TroubleshootingApp : public wxApp +{ +public: + virtual bool OnInit(); +}; + +// Custom controller to display an ErrorSet + +class ErrorSetPanel : public wxPanel +{ +private: +protected: + wxStaticText *filename_label; + wxButton *open_file_btn; + wxTextCtrl *error_text_ctrl; + const ErrorSetMetadata * error_set_metadata; + +public: + ErrorSetPanel(wxWindow *parent, const ErrorSetMetadata * error_set_metadata) : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL) + { + this->error_set_metadata = error_set_metadata; + + wxBoxSizer *main_file_sizer; + main_file_sizer = new wxBoxSizer(wxVERTICAL); + main_file_sizer->SetMinSize(0, 150); + + wxBoxSizer *header_sizer; + header_sizer = new wxBoxSizer(wxHORIZONTAL); + + wxString path = wxString::FromUTF8(error_set_metadata->file_path); + wxString filename = wxString::Format(wxT("%s (%i errors)"), path, error_set_metadata->errors_count); + filename_label = new wxStaticText(this, wxID_ANY, filename, wxDefaultPosition, wxDefaultSize, 0); + filename_label->Wrap(-1); + filename_label->SetFont(wxFont(wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString)); + + header_sizer->Add(filename_label, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); + + header_sizer->Add(0, 0, 1, wxEXPAND, 5); + + open_file_btn = new wxButton(this, wxID_ANY, wxT("Open file"), wxDefaultPosition, wxDefaultSize, 0); + header_sizer->Add(open_file_btn, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); + + main_file_sizer->Add(header_sizer, 0, wxEXPAND, 5); + + wxString errors_text = wxEmptyString; + for (int i = 0; ierrors_count; i++) { + wxString level = wxT("ERROR"); + if (error_set_metadata->errors[i].level == ERROR_METADATA_LEVEL_WARNING) { + level = wxT("WARNING"); + } + wxString error_text = wxString::Format(wxT("[%s] %s\n"), level, error_set_metadata->errors[i].message); + errors_text.Append(error_text); + } + + error_text_ctrl = new wxTextCtrl(this, wxID_ANY, errors_text, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY); + + main_file_sizer->Add(error_text_ctrl, 1, wxALL | wxEXPAND, 5); + + this->SetSizer(main_file_sizer); + this->Layout(); + main_file_sizer->Fit(this); + + if (!this->error_set_metadata->file_path) { + filename_label->Hide(); + open_file_btn->Hide(); + } + + open_file_btn->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(ErrorSetPanel::on_open_file), NULL, this); + } + + void ErrorSetPanel::on_open_file(wxCommandEvent &event) + { + if (troubleshooting_metadata->open_file && this->error_set_metadata->file_path) { + troubleshooting_metadata->open_file(this->error_set_metadata->file_path); + } + } + + ~ErrorSetPanel() + { + open_file_btn->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(ErrorSetPanel::on_open_file), NULL, this); + } +}; + +// Frame + +class DerivedTroubleshootingFrame : public TroubleshootingFrame +{ +protected: + void on_dont_show_change(wxCommandEvent &event); + void on_ignore(wxCommandEvent &event); + +public: + DerivedTroubleshootingFrame(wxWindow *parent); +}; + +DerivedTroubleshootingFrame::DerivedTroubleshootingFrame(wxWindow *parent) + : TroubleshootingFrame(parent) +{ + if (troubleshooting_metadata->is_fatal_error) { + dont_show_checkbox->Hide(); + ignore_button->Hide(); + info_label->SetLabel(wxT("Espanso couldn't load some files due to configuration errors and won't be able to start until you fix them.")); + title_label->SetLabel(wxT("Errors detected, action needed")); + } + + for (int i = 0; ierror_sets_count; i++) { + const ErrorSetMetadata * metadata = &troubleshooting_metadata->error_sets[i]; + ErrorSetPanel *panel = new ErrorSetPanel(scrollview, metadata); + this->scrollview_sizer->Add(panel, 0, wxEXPAND | wxALL, 5); + } +} + +void DerivedTroubleshootingFrame::on_dont_show_change(wxCommandEvent &event) +{ + if (troubleshooting_metadata->dont_show_again_changed) + { + int value = this->dont_show_checkbox->IsChecked() ? 1 : 0; + troubleshooting_metadata->dont_show_again_changed(value); + } +} + +void DerivedTroubleshootingFrame::on_ignore(wxCommandEvent &event) +{ + Close(true); +} + +bool TroubleshootingApp::OnInit() +{ + DerivedTroubleshootingFrame *frame = new DerivedTroubleshootingFrame(NULL); + + if (troubleshooting_metadata->window_icon_path) + { + setFrameIcon(troubleshooting_metadata->window_icon_path, frame); + } + + frame->Show(true); + + Activate(frame); + + return true; +} + +extern "C" void interop_show_troubleshooting(TroubleshootingMetadata *_metadata) +{ +// Setup high DPI support on Windows +#ifdef __WXMSW__ + SetProcessDPIAware(); +#endif + + troubleshooting_metadata = _metadata; + + wxApp::SetInstance(new TroubleshootingApp()); + int argc = 0; + wxEntry(argc, (char **)nullptr); +} \ No newline at end of file diff --git a/espanso-modulo/src/sys/troubleshooting/troubleshooting.fbp b/espanso-modulo/src/sys/troubleshooting/troubleshooting.fbp new file mode 100644 index 0000000..c54271f --- /dev/null +++ b/espanso-modulo/src/sys/troubleshooting/troubleshooting.fbp @@ -0,0 +1,421 @@ + + + + + ; + C++ + 1 + source_name + 0 + 0 + res + UTF-8 + connect + troubleshooting_gui + 1000 + none + + 0 + Troubleshooting + + . + #define _UNICODE + 1 + 1 + 1 + 1 + UI + 0 + 0 + + 0 + wxAUI_MGR_DEFAULT + wxSYS_COLOUR_WINDOW + wxBOTH + + 1 + 1 + impl_virtual + + + + 0 + wxID_ANY + + + TroubleshootingFrame + + 841,544 + wxDEFAULT_FRAME_STYLE + ; ; forward_declare + Troubleshooting + + + + wxTAB_TRAVERSAL + 1 + + + bSizer1 + wxVERTICAL + none + + 5 + wxEXPAND + 0 + + 10 + protected + 0 + + + + 10 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + ,90,92,20,70,0 + 0 + 0 + wxID_ANY + Errors detected + 0 + + 0 + + + 0 + + 1 + title_label + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 10 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Espanso couldn't load some files due to configuration errors. Some snippets or settings might not be available until you fix them. + 0 + + 0 + + + 0 + -1,-1 + 1 + info_label + 1 + + + protected + 1 + + Resizable + 1 + -1,-1 + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + wxEXPAND | wxALL + 5 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + scrollview + 1 + + + protected + 1 + + Resizable + 5 + 5 + 1 + + ; ; forward_declare + 0 + + + + wxHSCROLL|wxVSCROLL + + + scrollview_sizer + wxVERTICAL + protected + + + + + 10 + wxEXPAND + 0 + + + bSizer2 + wxHORIZONTAL + none + + 10 + wxALIGN_CENTER_VERTICAL|wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Don't show again for non-critical errors + + 0 + + + 0 + + 1 + dont_show_checkbox + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + on_dont_show_change + + + + 5 + wxEXPAND + 1 + + 0 + protected + 0 + + + + 10 + wxALIGN_CENTER_VERTICAL|wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 1 + + 1 + + + 0 + 0 + wxID_ANY + Ignore errors + + 0 + + 0 + + + 0 + + 1 + ignore_button + 1 + + + protected + 1 + + + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + on_ignore + + + + + + + + diff --git a/espanso-modulo/src/sys/troubleshooting/troubleshooting_gui.cpp b/espanso-modulo/src/sys/troubleshooting/troubleshooting_gui.cpp new file mode 100644 index 0000000..fc9f21a --- /dev/null +++ b/espanso-modulo/src/sys/troubleshooting/troubleshooting_gui.cpp @@ -0,0 +1,77 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Oct 26 2018) +// http://www.wxformbuilder.org/ +// +// PLEASE DO *NOT* EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#define _UNICODE + +#include "troubleshooting_gui.h" + +/////////////////////////////////////////////////////////////////////////// + +TroubleshootingFrame::TroubleshootingFrame( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + + wxBoxSizer* bSizer1; + bSizer1 = new wxBoxSizer( wxVERTICAL ); + + + bSizer1->Add( 0, 10, 0, wxEXPAND, 5 ); + + title_label = new wxStaticText( this, wxID_ANY, wxT("Errors detected"), wxDefaultPosition, wxDefaultSize, 0 ); + title_label->Wrap( -1 ); + title_label->SetFont( wxFont( 20, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + + bSizer1->Add( title_label, 0, wxALL, 10 ); + + info_label = new wxStaticText( this, wxID_ANY, wxT("Espanso couldn't load some files due to configuration errors. Some snippets or settings might not be available until you fix them."), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + info_label->Wrap( -1 ); + bSizer1->Add( info_label, 0, wxALL, 10 ); + + scrollview = new wxScrolledWindow( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL ); + scrollview->SetScrollRate( 5, 5 ); + scrollview_sizer = new wxBoxSizer( wxVERTICAL ); + + + scrollview->SetSizer( scrollview_sizer ); + scrollview->Layout(); + scrollview_sizer->Fit( scrollview ); + bSizer1->Add( scrollview, 5, wxEXPAND | wxALL, 5 ); + + wxBoxSizer* bSizer2; + bSizer2 = new wxBoxSizer( wxHORIZONTAL ); + + dont_show_checkbox = new wxCheckBox( this, wxID_ANY, wxT("Don't show again for non-critical errors"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer2->Add( dont_show_checkbox, 0, wxALIGN_CENTER_VERTICAL|wxALL, 10 ); + + + bSizer2->Add( 0, 0, 1, wxEXPAND, 5 ); + + ignore_button = new wxButton( this, wxID_ANY, wxT("Ignore errors"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer2->Add( ignore_button, 0, wxALIGN_CENTER_VERTICAL|wxALL, 10 ); + + + bSizer1->Add( bSizer2, 0, wxEXPAND, 10 ); + + + this->SetSizer( bSizer1 ); + this->Layout(); + + this->Centre( wxBOTH ); + + // Connect Events + dont_show_checkbox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( TroubleshootingFrame::on_dont_show_change ), NULL, this ); + ignore_button->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( TroubleshootingFrame::on_ignore ), NULL, this ); +} + +TroubleshootingFrame::~TroubleshootingFrame() +{ + // Disconnect Events + dont_show_checkbox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( TroubleshootingFrame::on_dont_show_change ), NULL, this ); + ignore_button->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( TroubleshootingFrame::on_ignore ), NULL, this ); + +} diff --git a/espanso-modulo/src/sys/troubleshooting/troubleshooting_gui.h b/espanso-modulo/src/sys/troubleshooting/troubleshooting_gui.h new file mode 100644 index 0000000..2882667 --- /dev/null +++ b/espanso-modulo/src/sys/troubleshooting/troubleshooting_gui.h @@ -0,0 +1,57 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Oct 26 2018) +// http://www.wxformbuilder.org/ +// +// PLEASE DO *NOT* EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////////////////////// +/// Class TroubleshootingFrame +/////////////////////////////////////////////////////////////////////////////// +class TroubleshootingFrame : public wxFrame +{ + private: + + protected: + wxStaticText* title_label; + wxStaticText* info_label; + wxScrolledWindow* scrollview; + wxBoxSizer* scrollview_sizer; + wxCheckBox* dont_show_checkbox; + wxButton* ignore_button; + + // Virtual event handlers, overide them in your derived class + virtual void on_dont_show_change( wxCommandEvent& event ) { event.Skip(); } + virtual void on_ignore( wxCommandEvent& event ) { event.Skip(); } + + + public: + + TroubleshootingFrame( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("Troubleshooting"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 841,544 ), long style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL ); + + ~TroubleshootingFrame(); + +}; + diff --git a/espanso-modulo/src/troubleshooting.rs b/espanso-modulo/src/troubleshooting.rs new file mode 100644 index 0000000..b19dc7d --- /dev/null +++ b/espanso-modulo/src/troubleshooting.rs @@ -0,0 +1,50 @@ +/* + * This file is part of modulo. + * + * Copyright (C) 2020-2021 Federico Terzi + * + * modulo is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * modulo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with modulo. If not, see . + */ + +use std::path::{Path, PathBuf}; + +pub use crate::sys::troubleshooting::show; + +pub struct TroubleshootingOptions { + pub window_icon_path: Option, + pub error_sets: Vec, + pub is_fatal_error: bool, + + pub handlers: TroubleshootingHandlers, +} + +pub struct ErrorSet { + pub file: Option, + pub errors: Vec, +} + +pub struct ErrorRecord { + pub level: ErrorLevel, + pub message: String, +} + +pub enum ErrorLevel { + Error, + Warning, +} + +pub struct TroubleshootingHandlers { + pub dont_show_again_changed: Option>, + pub open_file: Option>, +}