Skip to content

Commit 960de83

Browse files
Merge pull request #50 from Reim-developer/dev
Implement load `background_button_color` & `foreground_button_color` via TOML with Rust FFI backend
2 parents 5967d01 + e29888f commit 960de83

13 files changed

Lines changed: 178 additions & 40 deletions

File tree

src/back_end/rustfmt.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
max_width = 80

src/back_end/src/internal/app_config.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ pub struct AppSettings {
1010
pub struct AppGuiSettings {
1111
pub background_color: String,
1212
pub foreground_color: String,
13+
pub background_button_color: String,
14+
pub foreground_button_color: String,
1315
}
1416

1517
#[derive(Deserialize, Serialize)]
@@ -28,6 +30,8 @@ impl AppConfig {
2830
let app_gui_settings = AppGuiSettings {
2931
background_color: "#2f3136".to_string(),
3032
foreground_color: "#ffffff".to_string(),
33+
background_button_color: "#2f3136".to_string(),
34+
foreground_button_color: "#ffffff".to_string(),
3135
};
3236

3337
Self {

src/back_end/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,6 @@ pub mod internal {
1111
}
1212

1313
pub mod raw_config {
14+
pub mod constant;
1415
pub mod raw_toml;
1516
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/* Application settings */
2+
pub const APP_SETTINGS: &str = "app_settings";
3+
pub const HIDE_WHEN_CLOSED: &str = "hide_when_closed";
4+
pub const NOTIFICATION: &str = "notification";
5+
6+
/* Default application settings fallback */
7+
pub const HIDE_WHEN_CLOSED_FALLBACK: bool = false;
8+
pub const NOTIFICATION_FALLBACK: bool = false;
9+
10+
/* Application GUI settings */
11+
pub const APP_GUI_SETTINGS: &str = "app_gui_settings";
12+
pub const BACKGROUND_COLOR: &str = "background_color";
13+
pub const FOREGROUND_COLOR: &str = "foreground_color";
14+
pub const BACKGROUND_COLOR_BUTTON: &str = "background_button_color";
15+
pub const FOREGROUND_COLOR_BUTTON: &str = "fore_background_color";
16+
17+
/* Default application color fallback */
18+
pub const FALLBACK_BG_COLOR: &str = "#2f3136";
19+
pub const FALLBACK_FG_COLOR: &str = "#ffffff";
20+
pub const FALLBACK_BG_BUTTON_COLOR: &str = "#2f3136";
21+
pub const FALLBACK_FG_BUTTON_COLOR: &str = "#ffffff";

src/back_end/src/raw_config/raw_toml.rs

Lines changed: 72 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
use crate::raw_config::constant::{
2+
APP_GUI_SETTINGS, APP_SETTINGS, BACKGROUND_COLOR, BACKGROUND_COLOR_BUTTON,
3+
FALLBACK_BG_BUTTON_COLOR, FALLBACK_BG_COLOR, FALLBACK_FG_BUTTON_COLOR,
4+
FALLBACK_FG_COLOR, FOREGROUND_COLOR, FOREGROUND_COLOR_BUTTON,
5+
HIDE_WHEN_CLOSED, HIDE_WHEN_CLOSED_FALLBACK, NOTIFICATION,
6+
NOTIFICATION_FALLBACK,
7+
};
18
use std::{
29
ffi::{CStr, CString, c_char},
310
fs,
@@ -14,6 +21,8 @@ pub struct RawAppSettings {
1421
pub struct RawAppGuiSettings {
1522
pub background_color: *mut c_char,
1623
pub foreground_color: *mut c_char,
24+
pub background_button_color: *mut c_char,
25+
pub foreground_button_color: *mut c_char,
1726
}
1827

1928
#[repr(C)]
@@ -29,10 +38,38 @@ pub enum RawReadAppConfigStatus {
2938
Utf8Error,
3039
ParseTomlFailed,
3140
ConvertToMutFailed,
41+
ConvertToCStringFailed,
3242
}
3343

34-
const FALLBACK_BG_COLOR: &str = "#2f3136";
35-
const FALLBACK_FG_COLOR: &str = "#ffffff";
44+
fn color_by_settings(
45+
toml_value: &Value,
46+
field_name: &str,
47+
fallback: &str,
48+
) -> String {
49+
let color = toml_value
50+
.get(APP_GUI_SETTINGS)
51+
.and_then(|value| value.get(field_name))
52+
.and_then(Value::as_str)
53+
.unwrap_or(fallback);
54+
55+
color.to_string()
56+
}
57+
58+
fn raw_app_settings(toml_value: &Value) -> RawAppSettings {
59+
RawAppSettings {
60+
hide_when_closed: toml_value
61+
.get(APP_SETTINGS)
62+
.and_then(|value| value.get(HIDE_WHEN_CLOSED))
63+
.and_then(Value::as_bool)
64+
.unwrap_or(HIDE_WHEN_CLOSED_FALLBACK),
65+
66+
notification: toml_value
67+
.get(APP_SETTINGS)
68+
.and_then(|value| value.get(NOTIFICATION))
69+
.and_then(Value::as_bool)
70+
.unwrap_or(NOTIFICATION_FALLBACK),
71+
}
72+
}
3673

3774
/// # Safety
3875
/// Careful with raw pointers.
@@ -56,45 +93,48 @@ pub unsafe extern "C" fn raw_exists_config(
5693
return Status::ParseTomlFailed;
5794
};
5895

59-
let app_settings = RawAppSettings {
60-
hide_when_closed: toml_value
61-
.get("app_settings")
62-
.and_then(|value| value.get("hide_when_closed"))
63-
.and_then(Value::as_bool)
64-
.unwrap_or(false),
96+
let app_settings = raw_app_settings(&toml_value);
97+
98+
let bg_color =
99+
color_by_settings(&toml_value, BACKGROUND_COLOR, FALLBACK_BG_COLOR);
100+
let fg_color =
101+
color_by_settings(&toml_value, FOREGROUND_COLOR, FALLBACK_FG_COLOR);
102+
let bg_button_color = color_by_settings(
103+
&toml_value,
104+
BACKGROUND_COLOR_BUTTON,
105+
FALLBACK_BG_BUTTON_COLOR,
106+
);
107+
let fg_button_color = color_by_settings(
108+
&toml_value,
109+
FOREGROUND_COLOR_BUTTON,
110+
FALLBACK_FG_BUTTON_COLOR,
111+
);
65112

66-
notification: toml_value
67-
.get("app_settings")
68-
.and_then(|value| value.get("notification"))
69-
.and_then(Value::as_bool)
70-
.unwrap_or(false),
113+
let Ok(bg_cstr) = CString::new(bg_color) else {
114+
return Status::ConvertToCStringFailed;
71115
};
72116

73-
let bg_color = toml_value
74-
.get("app_gui_settings")
75-
.and_then(|value| value.get("background_color"))
76-
.and_then(Value::as_str)
77-
.unwrap_or(FALLBACK_BG_COLOR);
78-
79-
let fg_color = toml_value
80-
.get("app_gui_settings")
81-
.and_then(|value| value.get("foreground_color"))
82-
.and_then(Value::as_str)
83-
.unwrap_or(FALLBACK_FG_COLOR);
117+
let Ok(fg_cstr) = CString::new(fg_color) else {
118+
return Status::ConvertToCStringFailed;
119+
};
84120

85-
let Ok(bg_cstr) = CString::new(bg_color) else {
86-
return Status::ParseTomlFailed;
121+
let Ok(bg_btn_cstr) = CString::new(bg_button_color) else {
122+
return Status::ConvertToCStringFailed;
87123
};
88124

89-
let Ok(fg_cstr) = CString::new(fg_color) else {
90-
return Status::ParseTomlFailed;
125+
let Ok(fg_btn_cstr) = CString::new(fg_button_color) else {
126+
return Status::ConvertToCStringFailed;
91127
};
92128

93129
if let Some(config) = unsafe { raw_cfg_out.as_mut() } {
94130
config.app_settings.hide_when_closed = app_settings.hide_when_closed;
95131
config.app_settings.notification = app_settings.notification;
96132
config.app_gui_settings.background_color = bg_cstr.into_raw();
97133
config.app_gui_settings.foreground_color = fg_cstr.into_raw();
134+
config.app_gui_settings.background_button_color =
135+
bg_btn_cstr.into_raw();
136+
config.app_gui_settings.foreground_button_color =
137+
fg_btn_cstr.into_raw();
98138

99139
return RawReadAppConfigStatus::Ok;
100140
}
@@ -110,6 +150,10 @@ pub unsafe extern "C" fn raw_free_cstr_app_config(config: *mut RawAppConfig) {
110150
if let Some(cfg) = config.as_mut() {
111151
let _ = CString::from_raw(cfg.app_gui_settings.background_color);
112152
let _ = CString::from_raw(cfg.app_gui_settings.foreground_color);
153+
let _ =
154+
CString::from_raw(cfg.app_gui_settings.background_button_color);
155+
let _ =
156+
CString::from_raw(cfg.app_gui_settings.foreground_button_color);
113157
}
114158
}
115159
}

src/back_end/src/utils/browser.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ pub enum OpenBrowserStatus {
1414
/// # Safety
1515
/// Be careful with raw pointers.
1616
#[unsafe(no_mangle)]
17-
pub unsafe extern "C" fn raw_open_browser(url: *const c_char) -> OpenBrowserStatus {
17+
pub unsafe extern "C" fn raw_open_browser(
18+
url: *const c_char,
19+
) -> OpenBrowserStatus {
1820
unsafe {
1921
use OpenBrowserStatus as Status;
2022

src/back_end/src/utils/fs_utils.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ pub enum CreateFileSystemStatus {
1919
/// Be careful with raw pointers.
2020
#[must_use]
2121
#[unsafe(no_mangle)]
22-
pub unsafe extern "C" fn raw_new_folder(folder_path: *const c_char) -> CreateFileSystemStatus {
22+
pub unsafe extern "C" fn raw_new_folder(
23+
folder_path: *const c_char,
24+
) -> CreateFileSystemStatus {
2325
unsafe {
2426
use CreateFileSystemStatus as Status;
2527
let (c_str, is_ok) = raw_from_ptr(folder_path);

src/back_end/src/utils/memory.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use std::ffi::{CStr, CString, c_char};
22

3-
pub(crate) const unsafe fn raw_from_ptr(url: *const c_char) -> (&'static str, bool) {
3+
pub(crate) const unsafe fn raw_from_ptr(
4+
url: *const c_char,
5+
) -> (&'static str, bool) {
46
unsafe {
57
let Ok(c_str) = CStr::from_ptr(url).to_str() else {
68
return ("", false);

src/ffi/raw/config.hxx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ enum RawReadAppConfigStatus : uint8_t {
2828
UTF_8_ERROR,
2929
PARSE_TOML_FAILED,
3030
CONVERT_TO_MUT_FAILED,
31+
CONVERT_TO_C_STR_FAILED,
3132
};
3233

3334
typedef struct {
@@ -38,6 +39,8 @@ typedef struct {
3839
typedef struct {
3940
char *background_color;
4041
char *foreground_color;
42+
char *background_button_color;
43+
char *foreground_button_color;
4144
} RawAppGuiSettings;
4245

4346
typedef struct {

src/front_end/main_window_preload.cxx

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,12 @@ void Self::on_read_exists_cfg_error(RawReadAppConfigStatus status,
8787
QMessageBox::critical(main_window, "Error",
8888
"UTF-8 error in configuration file");
8989
break;
90+
91+
case Status::CONVERT_TO_C_STR_FAILED:
92+
QMessageBox::critical(
93+
main_window, "Error",
94+
"Could not convert value configuration to C string");
95+
break;
9096
}
9197
}
9298

@@ -128,29 +134,41 @@ void Self::set_application_theme(QMainWindow *main_window,
128134
RawAppConfig *app_config) {
129135
auto bg_color = string(app_config->raw_app_gui_settings.background_color);
130136
auto fg_color = string(app_config->raw_app_gui_settings.foreground_color);
137+
auto bg_button_color =
138+
string(app_config->raw_app_gui_settings.background_button_color);
139+
auto fg_button_color =
140+
string(app_config->raw_app_gui_settings.foreground_button_color);
131141

132142
auto bg_hex = QColor(QString::fromStdString(bg_color));
133143
auto fg_hex = QColor(QString::fromStdString(fg_color));
144+
auto bg_btn_hex = QColor(QString::fromStdString(bg_button_color));
145+
auto fg_btn_hex = QColor(QString::fromStdString(fg_button_color));
134146
free_cstr_app_config(raw_app_config.get());
135147

136-
if (!bg_hex.isValid() || !fg_hex.isValid()) {
148+
if (!bg_hex.isValid() || !fg_hex.isValid() || !bg_btn_hex.isValid() ||
149+
!fg_btn_hex.isValid()) {
137150
stringstream string_stream;
138151

139152
string_stream << "Invalid HEX color, please check your configuration\n"
140153
<< "Your 'background_color' setting: " << bg_color << "\n"
141-
<< "Your 'foregounrd_color: setting: " << fg_color
142-
<< "\n";
143-
auto error_message = string_stream.str();
154+
<< "Your 'foreground_color' setting: " << fg_color << "\n"
155+
<< "Your 'background_button_color' settings: "
156+
<< bg_button_color << "\n"
157+
<< "Your 'foreground_button_color' settings: "
158+
<< fg_button_color << "\n";
144159

160+
auto error_message = string_stream.str();
145161
QMessageBox::critical(main_window, "Error", error_message.c_str());
162+
146163
// clang-format off
147164
#if defined (LAZY_DEBUG)
148165
stringstream string_stream_debug;
149166
string_stream_debug
150167
<< "[DEBUG] Found error when load TOML configuration:\n"
151168
<< "[DEBUG] Error Type: 'Invalid HEX Color'\n"
152169
<< "[DEBUG] 'bg_color' setting: " << bg_color << "\n"
153-
<< "[DEBUG] 'fg_color' setting: " << fg_color << "\n";
170+
<< "[DEBUG] 'fg_color' setting: " << fg_color << "\n"
171+
<< "[DEBUG] 'bg_button_color' setting: " << bg_button_color << "\n";
154172

155173
cout << string_stream_debug.str().c_str();
156174

@@ -163,10 +181,21 @@ void Self::set_application_theme(QMainWindow *main_window,
163181

164182
palette.setColor(QPalette::Window, bg_hex);
165183
palette.setColor(QPalette::Base, bg_hex);
166-
palette.setColor(QPalette::WindowText, fg_hex);
184+
palette.setColor(QPalette::Text, fg_hex);
185+
186+
// clang-format off
187+
auto stylesheet = QString(
188+
R"""(
189+
QPushButton {
190+
background-color: %1;
191+
qproperty-autoFillBackground: true;
192+
color: %2;
193+
}
194+
)""").arg(bg_btn_hex.name(), fg_btn_hex.name()); // clang-format on
167195

168196
main_window->setPalette(palette);
169197
main_window->setAutoFillBackground(true);
198+
main_window->setStyleSheet(stylesheet);
170199
}
171200

172201
void Self::read_if_exists_config(QMainWindow *main_window) {
@@ -183,7 +212,13 @@ void Self::read_if_exists_config(QMainWindow *main_window) {
183212

184213
cout << "[DEBUG] " << "Found config setting 'foreground_color': "
185214
<< raw_app_config->raw_app_gui_settings.foreground_color << "\n";
215+
216+
cout << "[DEBUG] " << "Found config setting 'background_button_color': "
217+
<< raw_app_config->raw_app_gui_settings.background_button_color << "\n";
218+
219+
cout << "[DEBUG] " << "Found config setting 'foreground_button_color': "
220+
<< raw_app_config->raw_app_gui_settings.foreground_color << "\n";
186221
#endif // clang-format on
187222

188223
this->set_application_theme(main_window, raw_app_config.get());
189-
}
224+
}

0 commit comments

Comments
 (0)