1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <stdio.h>
#include <gtk/gtk.h>
#include <unistd.h>
#include "mozilla/Sprintf.h"
#include "progressui.h"
#include "readstrings.h"
#include "errors.h"
#define TIMER_INTERVAL 100
static float sProgressVal; // between 0 and 100
static gboolean sQuit = FALSE;
static gboolean sEnableUI;
static guint sTimerID;
static GtkWidget *sWin;
static GtkWidget *sLabel;
static GtkWidget *sProgressBar;
static const char *sProgramPath;
static gboolean
UpdateDialog(gpointer data)
{
if (sQuit)
{
gtk_widget_hide(sWin);
gtk_main_quit();
}
float progress = sProgressVal;
gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(sProgressBar),
progress / 100.0);
return TRUE;
}
static gboolean
OnDeleteEvent(GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
return TRUE;
}
int
InitProgressUI(int *pargc, char ***pargv)
{
sProgramPath = (*pargv)[0];
sEnableUI = gtk_init_check(pargc, pargv);
return 0;
}
int
ShowProgressUI()
{
if (!sEnableUI)
return -1;
// Only show the Progress UI if the process is taking a significant amount of
// time where a significant amount of time is defined as .5 seconds after
// ShowProgressUI is called sProgress is less than 70.
usleep(500000);
if (sQuit || sProgressVal > 70.0f)
return 0;
char ini_path[PATH_MAX];
SprintfLiteral(ini_path, "%s.ini", sProgramPath);
StringTable strings;
if (ReadStrings(ini_path, &strings) != OK)
return -1;
sWin = gtk_window_new(GTK_WINDOW_TOPLEVEL);
if (!sWin)
return -1;
static GdkPixbuf *pixbuf;
char icon_path[PATH_MAX];
SprintfLiteral(icon_path, "%s.png", sProgramPath);
g_signal_connect(G_OBJECT(sWin), "delete_event",
G_CALLBACK(OnDeleteEvent), nullptr);
gtk_window_set_title(GTK_WINDOW(sWin), strings.title);
gtk_window_set_type_hint(GTK_WINDOW(sWin), GDK_WINDOW_TYPE_HINT_DIALOG);
gtk_window_set_position(GTK_WINDOW(sWin), GTK_WIN_POS_CENTER_ALWAYS);
gtk_window_set_resizable(GTK_WINDOW(sWin), FALSE);
gtk_window_set_decorated(GTK_WINDOW(sWin), TRUE);
gtk_window_set_deletable(GTK_WINDOW(sWin),FALSE);
pixbuf = gdk_pixbuf_new_from_file (icon_path, nullptr);
gtk_window_set_icon(GTK_WINDOW(sWin), pixbuf);
g_object_unref(pixbuf);
GtkWidget *vbox = gtk_vbox_new(TRUE, 6);
sLabel = gtk_label_new(strings.info);
gtk_misc_set_alignment(GTK_MISC(sLabel), 0.0f, 0.0f);
sProgressBar = gtk_progress_bar_new();
gtk_box_pack_start(GTK_BOX(vbox), sLabel, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox), sProgressBar, TRUE, TRUE, 0);
sTimerID = g_timeout_add(TIMER_INTERVAL, UpdateDialog, nullptr);
gtk_container_set_border_width(GTK_CONTAINER(sWin), 10);
gtk_container_add(GTK_CONTAINER(sWin), vbox);
gtk_widget_show_all(sWin);
gtk_main();
return 0;
}
// Called on a background thread
void
QuitProgressUI()
{
sQuit = TRUE;
}
// Called on a background thread
void
UpdateProgressUI(float progress)
{
sProgressVal = progress; // 32-bit writes are atomic
}
|