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_kdialog; 8 9 import progress_dialog : ProgressDialogBase, use_log; 10 11 12 class ProgressDialogKDialog : 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 std.algorithm : map; 22 import std.array : array; 23 import std.conv : to; 24 import std..string : split, strip; 25 import progress_dialog_helpers : programPaths, logProgramOutput; 26 27 string[] paths = programPaths(["kdialog"]); 28 if (paths.length < 1) { 29 this.fireOnError(new Exception("Failed to find kdialog")); 30 return; 31 } 32 33 string[] args = [ 34 paths[0], 35 "--title", 36 _title, 37 "100", 38 "--progressbar", 39 _message, 40 ]; 41 ProcessPipes pipes; 42 try { 43 pipes = pipeProcess(args, Redirect.stdin | Redirect.stdout | Redirect.stderr); 44 } catch (ProcessException err) { 45 this.fireOnError(err); 46 return; 47 } 48 49 // Make sure the program did not terminate 50 if (tryWait(pipes.pid).terminated) { 51 this.fireOnError(new Exception("Failed to run kdialog")); 52 return; 53 } 54 55 // Get the qdbus id to send messages with 56 _pipes = pipes; 57 string[] output = _pipes.stdout.byLine.map!(n => n.to!string).array(); 58 _qdbus_id = output[0].split("/ProgressDialog")[0].strip(); 59 60 try { 61 cb(); 62 if (use_log) { 63 logProgramOutput(_pipes); 64 } 65 } catch (Throwable err) { 66 this.fireOnError(err); 67 } 68 } 69 70 override void setPercent(int percent) { 71 import std.process : ProcessPipes, ProcessException, pipeProcess, Redirect, tryWait, wait; 72 import std..string : format; 73 import std.stdio; 74 import progress_dialog_helpers : programPaths, logProgramOutput; 75 76 string[] paths = programPaths(["qdbus"]); 77 if (paths.length < 1) { 78 this.fireOnError(new Exception("Failed to find qdbus")); 79 return; 80 } 81 82 string[] args = [ 83 paths[0], 84 _qdbus_id, 85 "/ProgressDialog", 86 "Set", 87 "", 88 "value", 89 "%s".format(percent), 90 ]; 91 92 ProcessPipes pipes; 93 try { 94 pipes = pipeProcess(args, Redirect.stdin | Redirect.stdout | Redirect.stderr); 95 } catch (ProcessException err) { 96 this.fireOnError(err); 97 return; 98 } 99 100 if (wait(pipes.pid) != 0) { 101 this.fireOnError(new Exception("Failed to set kdialog percent")); 102 } 103 104 if (use_log) { 105 logProgramOutput(pipes); 106 } 107 } 108 109 override void close() { 110 import std.process : ProcessPipes, ProcessException, pipeProcess, Redirect, tryWait, wait; 111 import progress_dialog_helpers : programPaths, logProgramOutput; 112 113 this.setPercent(100); 114 115 string[] paths = programPaths(["qdbus"]); 116 if (paths.length < 1) { 117 this.fireOnError(new Exception("Failed to find qdbus")); 118 return; 119 } 120 121 string[] args = [ 122 paths[0], 123 _qdbus_id, 124 "/ProgressDialog", 125 "close", 126 ]; 127 128 ProcessPipes pipes; 129 try { 130 pipes = pipeProcess(args, Redirect.stdin | Redirect.stdout | Redirect.stderr); 131 } catch (ProcessException err) { 132 this.fireOnError(err); 133 return; 134 } 135 136 if (wait(pipes.pid) != 0) { 137 this.fireOnError(new Exception("Failed to close kdialog")); 138 } 139 140 if (use_log) { 141 logProgramOutput(pipes); 142 } 143 } 144 145 static bool isSupported() { 146 import progress_dialog_helpers : programPaths; 147 return programPaths(["kdialog"]).length > 0 && programPaths(["qdbus"]).length > 0; 148 } 149 150 string _qdbus_id; 151 ProcessPipes _pipes; 152 }