Skip to content

Commit 4485b11

Browse files
authored
Merge pull request #2 from derenv/subprocess
Subprocess
2 parents 8c33dbe + 94f444d commit 4485b11

File tree

3 files changed

+218
-13
lines changed

3 files changed

+218
-13
lines changed

Cargo.toml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ version = "0.1.0"
88
edition = "2021"
99

1010
[dependencies]
11-
#adwaita = { version = "0.1.1", package = "libadwaita"}
12-
gtk = { version = "0.4.8", package = "gtk4" }
13-
#glib = { version = "0.15.12", package = "glib" }
11+
#adwaita = { version = "^0.1.1", package = "libadwaita"}
12+
gtk = { version = "^0.4.8", package = "gtk4" }
13+
#glib = { version = "^0.15.12", package = "glib" }
1414

15-
#gobject = { version = "0.15.10", package = "gobject-sys" }
16-
libappindicator = { version = "0.7.1", package = "libappindicator" }
15+
#gobject = { version = "^0.15.10", package = "gobject-sys" }
16+
libappindicator = { version = "^0.7.1", package = "libappindicator" }

src/main.rs

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,16 @@
2121
// Modules
2222
mod custom_button;
2323
//use custom_button::CustomButton;
24+
mod subprocess;
25+
26+
use std::ffi::OsStr;
2427

2528
// Imports
2629
use gtk::prelude::*;
2730
use gtk::{
2831
/* Libraries */ gio,
2932
/* Application */ Application, ApplicationWindow,
30-
/* Widgets */ Button
33+
/* Widgets */ Button,
3134
};
3235
//use std::env;
3336
//use std::path::Path;
@@ -54,18 +57,58 @@ fn main() {
5457

5558
// Build Function
5659
fn build_ui(app: &Application) {
57-
// Button Child
58-
let button = Button::builder()
59-
.label("Press me!")
60+
// Button Child 1
61+
let button1 = Button::builder()
62+
.label("Open Settings")
63+
.margin_top(12)
64+
.margin_bottom(12)
65+
.margin_start(12)
66+
.margin_end(12)
67+
.build();
68+
// Connect to "clicked" signal of `button`
69+
button1.connect_clicked(move |_| {
70+
println!("Trying to open settings!"); //DEBUG
71+
72+
// Ideally we should grab if nvidia-settings 'failed' somehow or exited normally
73+
match subprocess::exec_check(&[OsStr::new("nvidia-settings")], None::<&gio::Cancellable>) {
74+
Ok(_x) => {
75+
println!("........yay"); //DEBUG
76+
}
77+
Err(_y) => {
78+
println!("........fak"); //DEBUG
79+
}
80+
};
81+
});
82+
// Button Child 2
83+
let button2 = Button::builder()
84+
.label("Get GPU Names")
6085
.margin_top(12)
6186
.margin_bottom(12)
6287
.margin_start(12)
6388
.margin_end(12)
6489
.build();
6590
// Connect to "clicked" signal of `button`
66-
button.connect_clicked(move |button| {
67-
// Set the label to "Hello World!" after the button has been clicked on
68-
button.set_label("Hello World!");
91+
button2.connect_clicked(move |_| {
92+
println!("Trying to open settings!"); //DEBUG
93+
94+
// Ideally we should grab if nvidia-settings 'failed' somehow or exited normally
95+
match subprocess::exec_communicate(
96+
&[
97+
OsStr::new("nvidia-settings"),
98+
OsStr::new("-q"),
99+
OsStr::new("GpuUUID"),
100+
OsStr::new("-t"),
101+
],
102+
None,
103+
None::<&gio::Cancellable>,
104+
) {
105+
Ok(_x) => {
106+
println!("........yay"); //DEBUG
107+
}
108+
Err(_y) => {
109+
println!("........fak"); //DEBUG
110+
}
111+
};
69112
});
70113

71114
// Menu Child
@@ -95,7 +138,8 @@ fn build_ui(app: &Application) {
95138
window.set_show_menubar(true);
96139

97140
// Add children to window
98-
window.set_child(Some(&button));
141+
window.set_child(Some(&button1));
142+
//window.set_child(Some(&button2));
99143

100144
// Present window
101145
window.show();

src/subprocess/mod.rs

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
// SPDX-FileCopyrightText: 2022 Deren Vural
2+
// SPDX-License-Identifier: GPL-3.0-or-later
3+
4+
/*
5+
* Name:
6+
* mod.rs
7+
*
8+
* Description:
9+
* Public-facing subprocess module
10+
*
11+
* Made:
12+
* 15/09/2022
13+
*
14+
* Made by:
15+
* Deren Vural
16+
*
17+
* Notes:
18+
* https://blog.logrocket.com/a-practical-guide-to-async-in-rust/
19+
*/
20+
21+
// Imports
22+
use gtk::prelude::*;
23+
use gtk::{gio, glib};
24+
use std::ffi::OsStr;
25+
26+
/*
27+
* Name:
28+
* execCheck
29+
*
30+
* Description:
31+
* Execute a command asynchronously and check the exit status
32+
*
33+
* If given, @cancellable can be used to stop the process before it finishes.
34+
*
35+
* https://gtk-rs.org/gtk-rs-core/stable/0.14/docs/src/gio/auto/subprocess.rs.html
36+
*
37+
* Made:
38+
* 15/09/2022
39+
*
40+
* Made by:
41+
* Deren Vural
42+
*
43+
* @param {string[]} argv - a list of string arguments
44+
* @param {Gio.Cancellable} [cancellable] - optional cancellable object
45+
* @returns {Promise<boolean>} - The process success
46+
*
47+
*/
48+
pub fn exec_check(
49+
argv: &[&OsStr],
50+
cancellable: Option<&impl IsA<gio::Cancellable>>,
51+
) -> Result<(), glib::Error> {
52+
// Create subprocess
53+
println!("..creating subprocess"); //DEBUG
54+
match gio::Subprocess::newv(argv, gio::SubprocessFlags::NONE) {
55+
Err(err) => Err(err),
56+
Ok(proc) => {
57+
println!("..Subprocess successfully created!"); //DEBUG
58+
59+
// Run subprocess
60+
61+
// Define callback
62+
//This should be called when the process is done
63+
/*
64+
let callback = |q: Result<(), glib::Error>| {
65+
match q {
66+
Err(err) => {
67+
Err(err)
68+
},
69+
Ok(_out) => {
70+
println!("....process finished");//DEBUG
71+
Ok(())
72+
},
73+
}
74+
};
75+
76+
struct Listener {
77+
done: bool
78+
}
79+
impl Listener {
80+
pub fn on_call(&mut self, done: bool) { self.done = done }
81+
}
82+
struct Caller<'callback> {
83+
callback: Box<dyn FnMut(bool) + 'callback>,
84+
}
85+
impl Caller<'_> {
86+
pub fn call(&mut self) { (self.callback)(true) }
87+
}
88+
let mut listener = Listener { done: false };
89+
let mut caller = Caller { callback: Box::new(|x| listener.on_call(x)) };
90+
91+
//fn callback_fn(x: bool){println!("callback bitch!! {}", x)}
92+
//let callback_box = Box::new(|x: bool| callback_fn(x));
93+
94+
//proc.wait_future();//not sure what this does tbh
95+
*/
96+
97+
/*
98+
Do i just not use Results with callback versions?
99+
*/
100+
// This doesn't work
101+
/*
102+
match proc.wait_async(cancellable,None) {
103+
Err(err) => {
104+
Err(err)
105+
},
106+
Ok(_out) => {
107+
println!("....process finished");//DEBUG
108+
Ok(())
109+
},
110+
}
111+
*/
112+
// This also doesn't work
113+
/*
114+
match proc.wait_async(cancellable, callback) {
115+
Err(err) => {
116+
Err(err)
117+
},
118+
Ok(_out) => {
119+
println!("....process finished");//DEBUG
120+
Ok(())
121+
},
122+
}
123+
*/
124+
125+
//*
126+
// This works but holds up main thread..
127+
match proc.wait(cancellable) {
128+
Err(err) => Err(err),
129+
Ok(_out) => {
130+
println!("....process finished"); //DEBUG
131+
Ok(())
132+
}
133+
}
134+
//*/
135+
}
136+
}
137+
}
138+
139+
pub fn exec_communicate(
140+
argv: &[&OsStr],
141+
_input: Option<&str>,
142+
cancellable: Option<&impl IsA<gio::Cancellable>>,
143+
) -> Result<(), glib::Error> {
144+
// Create subprocess
145+
println!("..creating subprocess"); //DEBUG
146+
match gio::Subprocess::newv(argv, gio::SubprocessFlags::NONE) {
147+
Err(err) => Err(err),
148+
Ok(proc) => {
149+
println!("..Subprocess successfully created!"); //DEBUG
150+
151+
// Run subprocess
152+
match proc.communicate(None, cancellable) {
153+
Err(err) => Err(err),
154+
Ok(_out) => {
155+
println!("....process finished"); //DEBUG
156+
Ok(())
157+
}
158+
}
159+
}
160+
}
161+
}

0 commit comments

Comments
 (0)