Skip to content
API Documentation
BastionGuard™
RsyncLogBox.vala
Go to the documentation of this file.
1/*
2 * RsyncLogBox.vala
3 */
4
5using Gtk;
6using Gee;
7
13using TeeJee.System;
14using TeeJee.Misc;
15
16public class RsyncLogBox : Gtk.Box {
17 private Gtk.Box vbox_progress;
18 private Gtk.Box vbox_list;
19 private Gtk.ComboBoxText cmb_filter;
20 private Gtk.Box hbox_filter;
21 private Gtk.Entry txt_pattern;
22 private Gtk.ListBox listbox;
23
24 private string name_filter = "";
25 private string status_filter = "";
26
27 public Gtk.Label lbl_header;
28 public Gtk.Label lbl_header_progress;
29 private Gtk.Spinner spinner;
30 public Gtk.Label lbl_msg;
31 public Gtk.Label lbl_status;
32 public Gtk.Label lbl_remaining;
33 public Gtk.ProgressBar progressbar;
34
35 private uint tmr_init = 0;
36 private bool thread_is_running = false;
37
38 private string rsync_log_file;
39 private Gee.ArrayList<FileItem> loglist;
40 private Gtk.Window window;
41
42 public RsyncLogBox(Gtk.Window _window) {
43 GLib.Object(orientation: Gtk.Orientation.VERTICAL, spacing: 6);
44 this.margin_start = 6;
45 this.margin_end = 6;
46 this.margin_top = 6;
47 this.margin_bottom = 6;
48 window = _window;
49 log_debug("RsyncLogBox: RsyncLogBox()");
50 }
51
52 public void open_log(string _rsync_log_file){
53 rsync_log_file = _rsync_log_file;
54 if (App.dry_run){
55 lbl_header = add_label_header(this, _("Confirm Actions"), true);
56 lbl_header.visible = false;
57 }
61
62 cmb_filter.changed.connect(() => {
63 status_filter = cmb_filter.get_active_id() ?? "";
65 });
66
67 show();
68 tmr_init = Timeout.add(100, init_delayed);
69 log_debug("RsyncLogWindow: open_log(): exit");
70 }
71
72 private bool is_restore_log {
73 get {
74 return file_basename(rsync_log_file).contains("restore");
75 }
76 }
77
78 public bool init_delayed(){
79 if (tmr_init > 0){
80 Source.remove(tmr_init);
81 tmr_init = 0;
82 }
84 if (App.dry_run && (lbl_header != null)){
85 lbl_header.visible = true;
86 }
87 return false;
88 }
89
90 private void parse_log_file(){
91 try {
92 thread_is_running = true;
93 new Thread<void>.try ("log-file-parser", () => {parse_log_file_thread();});
94 }
95 catch (Error e) {
96 log_error (e.message);
97 }
98
99 while (thread_is_running){
100 double fraction = (App.task.prg_count_total > 0) ? ((App.task.prg_count * 1.0) / App.task.prg_count_total) : 0.0;
101 if (fraction < 0.99){
102 progressbar.fraction = fraction;
103 }
104 lbl_msg.label = _("Read %'d of %'d lines...").printf(App.task.prg_count, App.task.prg_count_total);
105 sleep(500);
107 }
108
109 lbl_msg.label = _("Populating list...");
111 refresh_rows();
112 vbox_progress.visible = false;
113 vbox_list.visible = true;
114 hbox_filter.visible = true;
115 }
116
117 private void parse_log_file_thread(){
118 App.task = new RsyncTask();
120 thread_is_running = false;
121 }
122
123 public bool is_running{
124 get { return thread_is_running; }
125 }
126
127 private void create_progressbar(){
128 vbox_progress = new Gtk.Box(Orientation.VERTICAL, 6);
129 append(vbox_progress);
130 lbl_header_progress = add_label_header(vbox_progress, _("Parsing log file..."), true);
131 var hbox_status = new Gtk.Box(Orientation.HORIZONTAL, 6);
132 vbox_progress.append(hbox_status);
133 spinner = new Gtk.Spinner();
134 spinner.spinning = true;
135 hbox_status.append(spinner);
136 lbl_msg = add_label(hbox_status, _("Preparing..."));
137 lbl_msg.hexpand = true;
138 lbl_msg.ellipsize = Pango.EllipsizeMode.END;
139 lbl_msg.max_width_chars = 50;
140 progressbar = new Gtk.ProgressBar();
142 }
143
144 private void create_filters(){
145 var hbox = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 6);
146 hbox.visible = false;
147 append(hbox);
148 hbox_filter = hbox;
149 add_search_entry(hbox);
150 add_combo(hbox);
151
152 if (!App.dry_run){
153 var label = add_label(hbox, "");
154 label.hexpand = true;
155 var button = new Gtk.Button.with_label(_("Close"));
156 button.get_style_context().add_class("btn-cancel");
157 hbox.append(button);
158 button.clicked.connect(()=>{ window.destroy(); });
159 }
160 }
161
162 private void add_search_entry(Gtk.Box hbox){
163 var txt = new Gtk.Entry();
164 txt.hexpand = true;
165 txt.placeholder_text = _("Filter by name or path");
166 hbox.append(txt);
167 txt_pattern = txt;
168 txt.changed.connect(()=>{ name_filter = txt.text.down(); apply_filters(); });
169 }
170
171 private void add_combo(Gtk.Box hbox){
172 cmb_filter = new Gtk.ComboBoxText();
173 hbox.append(cmb_filter);
174 cmb_filter.append("", _("All Files"));
175 cmb_filter.append("created", "%s".printf(App.dry_run ? _("Create") : _("Created")));
176 if (is_restore_log){
177 cmb_filter.append("deleted", "%s".printf(App.dry_run ? _("Delete") : _("Deleted")));
178 }
179 cmb_filter.append("changed", "%s".printf(App.dry_run ? _("Restore") : _("Changed")));
180 if (!App.dry_run){
181 cmb_filter.append("checksum", " └ %s".printf(_("Checksum")));
182 cmb_filter.append("size", " └ %s".printf(_("Size")));
183 cmb_filter.append("timestamp", " └ %s".printf(_("Timestamp")));
184 cmb_filter.append("permissions", " └ %s".printf(_("Permissions")));
185 cmb_filter.append("owner", " └ %s".printf(_("Owner")));
186 cmb_filter.append("group", " └ %s".printf(_("Group")));
187 }
188 cmb_filter.set_active_id("");
189 }
190
191 private void create_listview() {
192 vbox_list = new Gtk.Box(Orientation.VERTICAL, 6);
193 vbox_list.visible = false;
194 append(vbox_list);
195 listbox = new Gtk.ListBox();
196 listbox.selection_mode = Gtk.SelectionMode.NONE;
197 listbox.add_css_class("boxed-list");
198 var scrolled = new Gtk.ScrolledWindow();
199 scrolled.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC);
200 scrolled.vexpand = true;
201 scrolled.set_child(listbox);
202 vbox_list.append(scrolled);
203 }
204
205 private string display_status(FileItem item){
206 if (is_restore_log){
207 switch(item.file_status){
208 case "checksum":
209 case "size":
210 case "timestamp":
211 case "permissions":
212 case "owner":
213 case "group":
214 return App.dry_run ? _("Restore") : _("Changed");
215 case "created":
216 return App.dry_run ? _("Create") : _("Created");
217 case "deleted":
218 return App.dry_run ? _("Delete") : _("Deleted");
219 default:
220 return item.file_status;
221 }
222 }
223 switch(item.file_status){
224 case "checksum":
225 case "size":
226 case "timestamp":
227 case "permissions":
228 case "owner":
229 case "group":
230 return _("Changed");
231 case "created":
232 return _("Created");
233 case "deleted":
234 return _("Deleted");
235 default:
236 return item.file_status;
237 }
238 }
239
240 private string relpath_for(FileItem item){
241 var spath = "%s/localhost".printf(file_parent(rsync_log_file));
242 var relpath = item.file_path[spath.length:item.file_path.length];
243 if (!is_restore_log){
244 relpath = relpath[1:relpath.length];
245 }
246 return relpath;
247 }
248
249 private bool item_matches(FileItem item){
250 string relpath = relpath_for(item).down();
251 if ((name_filter.length > 0) && !relpath.contains(name_filter)){
252 return false;
253 }
254 if (status_filter.length == 0){
255 return true;
256 }
257 if (status_filter == "changed"){
258 switch(item.file_status){
259 case "checksum":
260 case "size":
261 case "timestamp":
262 case "permissions":
263 case "owner":
264 case "group":
265 return true;
266 default:
267 return false;
268 }
269 }
270 return item.file_status == status_filter;
271 }
272
273 private Gtk.Widget create_log_row(FileItem item){
274 var row = new Gtk.ListBoxRow();
275 var outer = new Gtk.Box(Gtk.Orientation.VERTICAL, 4);
276 outer.margin_start = 8;
277 outer.margin_end = 8;
278 outer.margin_top = 8;
279 outer.margin_bottom = 8;
280 row.set_child(outer);
281
282 var top = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 8);
283 outer.append(top);
284
285 var image = new Gtk.Image.from_pixbuf(item.get_icon(16, false, false));
286 top.append(image);
287
288 var status = new Gtk.Label(display_status(item));
289 status.xalign = 0.0f;
290 status.add_css_class("accent");
291 status.width_chars = 12;
292 top.append(status);
293
294 var path = new Gtk.Label(relpath_for(item));
295 path.xalign = 0.0f;
296 path.hexpand = true;
297 path.wrap = true;
298 top.append(path);
299
300 return row;
301 }
302
303 private void clear_rows(){
304 Gtk.Widget? child = listbox.get_first_child();
305 while (child != null){
306 Gtk.Widget? next = child.get_next_sibling();
307 listbox.remove(child);
308 child = next;
309 }
310 }
311
312 private void refresh_rows() {
313 clear_rows();
314 if (loglist == null){ return; }
315 foreach(var item in loglist) {
316 if (App.dry_run && (item.file_type == FileType.DIRECTORY)){
317 continue;
318 }
319 if (!item_matches(item)){
320 continue;
321 }
322 listbox.append(create_log_row(item));
323 }
324 }
325
326 private void apply_filters(){
327 status_filter = cmb_filter.get_active_id() ?? "";
328 name_filter = txt_pattern.text.down();
329 refresh_rows();
330 }
331}
Main App
#define _(s)
int64 prg_count
int64 prg_count_total
string file_status
Definition FileItem.vala:49
Gdk.? Pixbuf get_icon(int icon_size, bool add_transparency, bool add_emblems)
string file_path
Definition FileItem.vala:41
RsyncTask task
Definition Main.vala:160
bool dry_run
Definition Main.vala:100
Gtk.Box hbox_filter
string status_filter
Gtk.Label lbl_header_progress
Gtk.Box vbox_progress
Gtk.Window window
bool thread_is_running
void parse_log_file()
Gtk.ProgressBar progressbar
string display_status(FileItem item)
void open_log(string _rsync_log_file)
Gtk.Label lbl_header
string name_filter
Gtk.Box vbox_list
string rsync_log_file
Gtk.Spinner spinner
Gtk.Label lbl_status
void create_listview()
RsyncLogBox(Gtk.Window _window)
Gtk.Widget create_log_row(FileItem item)
Gtk.ComboBoxText cmb_filter
void create_progressbar()
bool init_delayed()
void add_search_entry(Gtk.Box hbox)
void add_combo(Gtk.Box hbox)
string relpath_for(FileItem item)
bool item_matches(FileItem item)
void refresh_rows()
void apply_filters()
void clear_rows()
Gtk.Entry txt_pattern
Gtk.Label lbl_msg
Gee.ArrayList< FileItem > loglist
Gtk.Label lbl_remaining
void create_filters()
bool is_restore_log
void parse_log_file_thread()
Gtk.ListBox listbox
Gee.ArrayList< FileItem > parse_log(string log_file_path)
string file_basename(string file_path)
string file_parent(string file_path)
Gtk.Label add_label(Gtk.Box box, string text, bool bold=false, bool italic=false, bool large=false)
void log_debug(string message)
void log_error(string message, bool highlight=false, bool is_warning=false)
void sleep(int milliseconds)