1 // Copyright (c) 2017 Matthew Brennan Jones <matthew.brennan.jones@gmail.com>
2 // Boost Software License - Version 1.0
3 // A simple progress dialog for the D programming language
4 // https://github.com/workhorsy/d-progress-dialog
5 
6 
7 module progress_dialog_zenity;
8 
9 import progress_dialog : ProgressDialogBase, use_log;
10 
11 
12 class ProgressDialogZenity : ProgressDialogBase {
13 	import std.process : ProcessPipes;
14 
15 	this(string title, string message) {
16 		super(title, message);
17 	}
18 
19 	override void show(void delegate() cb) {
20 		import std.process : ProcessPipes, ProcessException, pipeProcess, Redirect, tryWait;
21 		import progress_dialog_helpers : programPaths, logProgramOutput;
22 
23 		string[] paths = programPaths(["zenity"]);
24 		if (paths.length < 1) {
25 			this.fireOnError(new Exception("Failed to find zenity"));
26 			return;
27 		}
28 
29 		string[] args = [
30 			paths[0],
31 			"--progress",
32 			"--title=" ~ _title,
33 			"--text=" ~ _message,
34 			"--percentage=0",
35 			"--auto-close",
36 			"--no-cancel",
37 			"--modal",
38 		];
39 		ProcessPipes pipes;
40 		try {
41 			pipes = pipeProcess(args, Redirect.stdin | Redirect.stdout | Redirect.stderr);
42 		} catch (ProcessException err) {
43 			this.fireOnError(err);
44 			return;
45 		}
46 
47 		// Make sure the program did not terminate
48 		if (tryWait(pipes.pid).terminated) {
49 			this.fireOnError(new Exception("Failed to run zenity"));
50 			return;
51 		}
52 
53 		_pipes = pipes;
54 
55 		try {
56 			cb();
57 			if (use_log) {
58 				logProgramOutput(pipes);
59 			}
60 		} catch (Throwable err) {
61 			this.fireOnError(err);
62 		}
63 	}
64 
65 	override void setPercent(int percent) {
66 		import std..string : format;
67 		_pipes.stdin.writef("%s\n".format(percent));
68 		_pipes.stdin.flush();
69 	}
70 
71 	override void close() {
72 		import std.process : wait;
73 		import progress_dialog_helpers : logProgramOutput;
74 
75 		this.setPercent(100);
76 
77 		if (wait(_pipes.pid) != 0) {
78 			throw new Exception("Failed to close dialog");
79 		}
80 
81 		if (use_log) {
82 			logProgramOutput(_pipes);
83 		}
84 	}
85 
86 	static bool isSupported() {
87 		import progress_dialog_helpers : programPaths;
88 		return programPaths(["zenity"]).length > 0;
89 	}
90 
91 	ProcessPipes _pipes;
92 }